mirror of https://github.com/apache/superset.git
feat(telemetry): Adding Scarf based telemetry to Superset (#26011)
Co-authored-by: Michael S. Molina <70410625+michael-s-molina@users.noreply.github.com>
This commit is contained in:
parent
67468c46c0
commit
8437a235c9
|
@ -622,7 +622,7 @@ cd superset-frontend
|
|||
npm ci
|
||||
```
|
||||
|
||||
Note that Superset uses [Scarf](https://docs.scarf.sh) to capture telemetry/analytics about versions being installed, including the `scarf-js` npm package. As noted elsewhere in this documentation, Scarf gathers aggregated stats for the sake of security/release strategy, and does not capture/retain PII. [You can read here](https://docs.scarf.sh/package-analytics/) about the package, and various means to opt out of it, but one easy way to opt out is to add this setting in `superset-frontent/package.json`:
|
||||
Note that Superset uses [Scarf](https://docs.scarf.sh) to capture telemetry/analytics about versions being installed, including the `scarf-js` npm package and an analytics pixel. As noted elsewhere in this documentation, Scarf gathers aggregated stats for the sake of security/release strategy, and does not capture/retain PII. [You can read here](https://docs.scarf.sh/package-analytics/) about the `scarf-js` package, and various means to opt out of it, but you can opt out of the npm package _and_ the pixel by setting the `SCARF_ANALYTICS` envinronment variable to `false` or opt out of the pixel by adding this setting in `superset-frontent/package.json`:
|
||||
|
||||
```json
|
||||
// your-package/package.json
|
||||
|
|
|
@ -124,6 +124,8 @@ services:
|
|||
command: ["/app/docker/docker-frontend.sh"]
|
||||
env_file: docker/.env
|
||||
depends_on: *superset-depends-on
|
||||
environment:
|
||||
SCARF_ANALYTICS: "${SCARF_ANALYTICS}"
|
||||
volumes: *superset-volumes
|
||||
|
||||
superset-worker:
|
||||
|
|
|
@ -268,8 +268,10 @@ This can be used, for example, to convert UTC time to local time.
|
|||
### Does Superset collect any telemetry data?
|
||||
|
||||
Superset uses [Scarf](https://about.scarf.sh/) by default to collect basic telemetry data upon installing and/or running Superset. This data helps the maintainers of Superset better understand which versions of Superset are being used, in order to prioritize patch/minor releases and security fixes.
|
||||
We use the [Scarf Gateway](https://docs.scarf.sh/gateway/) to sit in front of container registries, and the [scarf-js](https://about.scarf.sh/package-sdks) package to track `npm` installations.
|
||||
Scarf purges PII and provides aggregated statistics. Superset users can easily opt out of analytics in various ways documented [here](https://docs.scarf.sh/gateway/#do-not-track) and [here](https://docs.scarf.sh/package-analytics/#as-a-user-of-a-package-using-scarf-js-how-can-i-opt-out-of-analytics). Additional opt-out instructions for Docker users are available on the [Docker Installation](https://superset.apache.org/docs/installation/installing-superset-using-docker-compose) page.
|
||||
We use the [Scarf Gateway](https://docs.scarf.sh/gateway/) to sit in front of container registries, the [scarf-js](https://about.scarf.sh/package-sdks) package to track `npm` installations, and a Scarf pixel to gather anonymous analytics on Superset page views.
|
||||
Scarf purges PII and provides aggregated statistics. Superset users can easily opt out of analytics in various ways documented [here](https://docs.scarf.sh/gateway/#do-not-track) and [here](https://docs.scarf.sh/package-analytics/#as-a-user-of-a-package-using-scarf-js-how-can-i-opt-out-of-analytics).
|
||||
Superset maintainers can also opt out of telemetry data collection by setting the `SCARF_ANALYTICS` environment variable to `false` in the Superset container (or anywhere Superset/webpack are run).
|
||||
Additional opt-out instructions for Docker users are available on the [Docker Installation](https://superset.apache.org/docs/installation/installing-superset-using-docker-compose) page.
|
||||
|
||||
### Does Superset have an archive panel or trash bin from which a user can recover deleted assets?
|
||||
|
||||
|
|
|
@ -124,7 +124,9 @@ Users often want to connect to other databases from Superset. Currently, the eas
|
|||
:::note
|
||||
Superset uses [Scarf Gateway](https://about.scarf.sh/scarf-gateway) to collect telemetry data. Knowing the installation counts for different Superset versions informs the project's decisions about patching and long-term support. Scarf purges personally identifiable information (PII) and provides only aggregated statistics.
|
||||
|
||||
To opt-out of this data collection in your docker compose based installation, edit the `x-superset-image:` line in your `docker-compose.yml` and `docker-compose-non-dev.yml` files, replacing `apachesuperset.docker.scarf.sh/apache/superset` with `apache/superset` to pull the image directly from Docker Hub.
|
||||
To opt-out of this data collection for packages downloaded through the Scarf Gateway by your docker compose based installation, edit the `x-superset-image:` line in your `docker-compose.yml` and `docker-compose-non-dev.yml` files, replacing `apachesuperset.docker.scarf.sh/apache/superset` with `apache/superset` to pull the image directly from Docker Hub.
|
||||
|
||||
To disable the Scarf telemetry pixel, set the `SCARF_ANALYTICS` environment variable to `False` in your terminal and/or in your `docker/.env` and `docker/.env-non-dev` files.
|
||||
:::
|
||||
|
||||
### 4. Log in to Superset
|
||||
|
|
|
@ -194,7 +194,7 @@
|
|||
"@types/js-levenshtein": "^1.1.0",
|
||||
"@types/json-bigint": "^1.0.1",
|
||||
"@types/mousetrap": "^1.6.11",
|
||||
"@types/react": "^16.9.43",
|
||||
"@types/react": "^16.9.53",
|
||||
"@types/react-dom": "^16.9.8",
|
||||
"@types/react-gravatar": "^2.6.8",
|
||||
"@types/react-json-tree": "^0.6.11",
|
||||
|
@ -19628,12 +19628,13 @@
|
|||
"devOptional": true
|
||||
},
|
||||
"node_modules/@types/react": {
|
||||
"version": "16.9.43",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.43.tgz",
|
||||
"integrity": "sha512-PxshAFcnJqIWYpJbLPriClH53Z2WlJcVZE+NP2etUtWQs2s7yIMj3/LDKZT/5CHJ/F62iyjVCDu2H3jHEXIxSg==",
|
||||
"version": "16.14.51",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.51.tgz",
|
||||
"integrity": "sha512-4T/wsDXStA5OUGTj6w2INze3ZCz22IwQiWcApgqqNRU2A6vNUIPXpNkjAMUFxx6diYPVkvz+d7gEtU7AZ+0Xqg==",
|
||||
"dependencies": {
|
||||
"@types/prop-types": "*",
|
||||
"csstype": "^2.2.0"
|
||||
"@types/scheduler": "*",
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-dom": {
|
||||
|
@ -19775,6 +19776,11 @@
|
|||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react/node_modules/csstype": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
|
||||
"integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
|
||||
},
|
||||
"node_modules/@types/redux-localstorage": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/redux-localstorage/-/redux-localstorage-1.0.8.tgz",
|
||||
|
@ -19816,6 +19822,11 @@
|
|||
"resolved": "https://registry.npmjs.org/@types/rison/-/rison-0.0.6.tgz",
|
||||
"integrity": "sha512-mE3eRK0fpTN/GnNBOIg2tGq2cFhchQXF6fCbrLxus75TgnoOECbdHikr948FGO/UAml7/ZhLMa5FbGkF5PKvmw=="
|
||||
},
|
||||
"node_modules/@types/scheduler": {
|
||||
"version": "0.16.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.6.tgz",
|
||||
"integrity": "sha512-Vlktnchmkylvc9SnwwwozTv04L/e1NykF5vgoQ0XTmI8DD+wxfjQuHuvHS3p0r2jz2x2ghPs2h1FVeDirIteWA=="
|
||||
},
|
||||
"node_modules/@types/seedrandom": {
|
||||
"version": "2.4.30",
|
||||
"resolved": "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-2.4.30.tgz",
|
||||
|
@ -79599,12 +79610,20 @@
|
|||
"devOptional": true
|
||||
},
|
||||
"@types/react": {
|
||||
"version": "16.9.43",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.43.tgz",
|
||||
"integrity": "sha512-PxshAFcnJqIWYpJbLPriClH53Z2WlJcVZE+NP2etUtWQs2s7yIMj3/LDKZT/5CHJ/F62iyjVCDu2H3jHEXIxSg==",
|
||||
"version": "16.14.51",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.51.tgz",
|
||||
"integrity": "sha512-4T/wsDXStA5OUGTj6w2INze3ZCz22IwQiWcApgqqNRU2A6vNUIPXpNkjAMUFxx6diYPVkvz+d7gEtU7AZ+0Xqg==",
|
||||
"requires": {
|
||||
"@types/prop-types": "*",
|
||||
"csstype": "^2.2.0"
|
||||
"@types/scheduler": "*",
|
||||
"csstype": "^3.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"csstype": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
|
||||
"integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@types/react-dom": {
|
||||
|
@ -79789,6 +79808,11 @@
|
|||
"resolved": "https://registry.npmjs.org/@types/rison/-/rison-0.0.6.tgz",
|
||||
"integrity": "sha512-mE3eRK0fpTN/GnNBOIg2tGq2cFhchQXF6fCbrLxus75TgnoOECbdHikr948FGO/UAml7/ZhLMa5FbGkF5PKvmw=="
|
||||
},
|
||||
"@types/scheduler": {
|
||||
"version": "0.16.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.6.tgz",
|
||||
"integrity": "sha512-Vlktnchmkylvc9SnwwwozTv04L/e1NykF5vgoQ0XTmI8DD+wxfjQuHuvHS3p0r2jz2x2ghPs2h1FVeDirIteWA=="
|
||||
},
|
||||
"@types/seedrandom": {
|
||||
"version": "2.4.30",
|
||||
"resolved": "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-2.4.30.tgz",
|
||||
|
|
|
@ -259,7 +259,7 @@
|
|||
"@types/js-levenshtein": "^1.1.0",
|
||||
"@types/json-bigint": "^1.0.1",
|
||||
"@types/mousetrap": "^1.6.11",
|
||||
"@types/react": "^16.9.43",
|
||||
"@types/react": "^16.9.53",
|
||||
"@types/react-dom": "^16.9.8",
|
||||
"@types/react-gravatar": "^2.6.8",
|
||||
"@types/react-json-tree": "^0.6.11",
|
||||
|
|
|
@ -48,14 +48,14 @@ if (defaultView != null) {
|
|||
}
|
||||
|
||||
const g = global as any;
|
||||
g.window = g.window || {};
|
||||
g.window.location = { href: 'about:blank' };
|
||||
g.window.performance = { now: () => new Date().getTime() };
|
||||
g.window.Worker = Worker;
|
||||
g.window.IntersectionObserver = IntersectionObserver;
|
||||
g.window.ResizeObserver = ResizeObserver;
|
||||
g.window.featureFlags = {};
|
||||
g.URL.createObjectURL = () => '';
|
||||
g.window ??= Object.create(window);
|
||||
g.window.location ??= { href: 'about:blank' };
|
||||
g.window.performance ??= { now: () => new Date().getTime() };
|
||||
g.window.Worker ??= Worker;
|
||||
g.window.IntersectionObserver ??= IntersectionObserver;
|
||||
g.window.ResizeObserver ??= ResizeObserver;
|
||||
g.window.featureFlags ??= {};
|
||||
g.URL.createObjectURL ??= () => '';
|
||||
g.caches = new CacheStorage();
|
||||
|
||||
Object.defineProperty(window, 'matchMedia', {
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { render } from 'spec/helpers/testing-library';
|
||||
import TelemetryPixel from '.';
|
||||
|
||||
const OLD_ENV = process.env;
|
||||
|
||||
// restor the process after messing with it!
|
||||
afterAll(() => {
|
||||
process.env = OLD_ENV;
|
||||
});
|
||||
|
||||
test('should render', () => {
|
||||
const { container } = render(<TelemetryPixel />);
|
||||
expect(container).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('should render the pixel link when FF is on', () => {
|
||||
process.env.SCARF_ANALYTICS = 'true';
|
||||
render(<TelemetryPixel />);
|
||||
|
||||
const image = document.querySelector('img[src*="scarf.sh"]');
|
||||
expect(image).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test('should NOT render the pixel link when FF is off', () => {
|
||||
process.env.SCARF_ANALYTICS = 'false';
|
||||
render(<TelemetryPixel />);
|
||||
|
||||
const image = document.querySelector('img[src*="scarf.sh"]');
|
||||
expect(image).not.toBeInTheDocument();
|
||||
});
|
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
interface TelemetryPixelProps {
|
||||
version?: string;
|
||||
sha?: string;
|
||||
build?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a telemetry pixel component to capture anonymous, aggregated telemetry via Scarf.
|
||||
* This can be disabled by setting the SCARF_ANALYTICS environment variable to false.
|
||||
*
|
||||
* @component
|
||||
* @param {TelemetryPixelProps} props - The props for the TelemetryPixel component.
|
||||
* @param {string} props.version - The version of Superset that's currently in use.
|
||||
* @param {string} props.sha - The SHA of Superset that's currently in use.
|
||||
* @param {string} props.build - The build of Superset that's currently in use.
|
||||
* @returns {JSX.Element | null} The rendered TelemetryPixel component.
|
||||
*/
|
||||
|
||||
const PIXEL_ID = '0d3461e1-abb1-4691-a0aa-5ed50de66af0';
|
||||
|
||||
const TelemetryPixel = ({
|
||||
version = 'unknownVersion',
|
||||
sha = 'unknownSHA',
|
||||
build = 'unknownBuild',
|
||||
}: TelemetryPixelProps): React.ReactElement | null => {
|
||||
const pixelPath = `https://apachesuperset.gateway.scarf.sh/pixel/${PIXEL_ID}/${version}/${sha}/${build}`;
|
||||
return process.env.SCARF_ANALYTICS === 'false' ||
|
||||
process.env.SCARF_ANALYTICS === 'false' ? null : (
|
||||
<img
|
||||
referrerPolicy="no-referrer-when-downgrade"
|
||||
src={pixelPath}
|
||||
width={0}
|
||||
height={0}
|
||||
alt=""
|
||||
/>
|
||||
);
|
||||
};
|
||||
export default TelemetryPixel;
|
|
@ -46,6 +46,7 @@ import {
|
|||
import { RootState } from 'src/dashboard/types';
|
||||
import DatabaseModal from 'src/features/databases/DatabaseModal';
|
||||
import { uploadUserPerms } from 'src/views/CRUD/utils';
|
||||
import TelemetryPixel from 'src/components/TelemetryPixel';
|
||||
import LanguagePicker from './LanguagePicker';
|
||||
import {
|
||||
ExtensionConfigs,
|
||||
|
@ -562,6 +563,11 @@ const RightMenu = ({
|
|||
{t('Login')}
|
||||
</StyledAnchor>
|
||||
)}
|
||||
<TelemetryPixel
|
||||
version={navbarRight.version_string}
|
||||
sha={navbarRight.version_sha}
|
||||
build={navbarRight.build_number}
|
||||
/>
|
||||
</StyledDiv>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -117,6 +117,7 @@ const plugins = [
|
|||
'process.env.WEBPACK_MODE': JSON.stringify(mode),
|
||||
'process.env.REDUX_DEFAULT_MIDDLEWARE':
|
||||
process.env.REDUX_DEFAULT_MIDDLEWARE,
|
||||
'process.env.SCARF_ANALYTICS': process.env.SCARF_ANALYTICS,
|
||||
}),
|
||||
|
||||
new CopyPlugin({
|
||||
|
|
|
@ -1427,7 +1427,13 @@ TALISMAN_CONFIG = {
|
|||
"content_security_policy": {
|
||||
"base-uri": ["'self'"],
|
||||
"default-src": ["'self'"],
|
||||
"img-src": ["'self'", "blob:", "data:"],
|
||||
"img-src": [
|
||||
"'self'",
|
||||
"blob:",
|
||||
"data:",
|
||||
"https://apachesuperset.gateway.scarf.sh",
|
||||
"https://static.scarf.sh/",
|
||||
],
|
||||
"worker-src": ["'self'", "blob:"],
|
||||
"connect-src": [
|
||||
"'self'",
|
||||
|
@ -1450,7 +1456,13 @@ TALISMAN_DEV_CONFIG = {
|
|||
"content_security_policy": {
|
||||
"base-uri": ["'self'"],
|
||||
"default-src": ["'self'"],
|
||||
"img-src": ["'self'", "blob:", "data:"],
|
||||
"img-src": [
|
||||
"'self'",
|
||||
"blob:",
|
||||
"data:",
|
||||
"https://apachesuperset.gateway.scarf.sh",
|
||||
"https://static.scarf.sh/",
|
||||
],
|
||||
"worker-src": ["'self'", "blob:"],
|
||||
"connect-src": [
|
||||
"'self'",
|
||||
|
|
Loading…
Reference in New Issue