Skip to content

Commit

Permalink
Removes corvus in favor of sentry and analytics client
Browse files Browse the repository at this point in the history
Change-type: patch
Signed-off-by: Otavio Jacobi
  • Loading branch information
otaviojacobi committed Dec 2, 2022
1 parent 30c4baa commit 7a835c3
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 91 deletions.
1 change: 0 additions & 1 deletion .github/actions/publish/action.yml
Expand Up @@ -172,7 +172,6 @@ runs:
for target in ${TARGETS}; do
electron-builder ${ELECTRON_BUILDER_OS} ${target} ${ARCHITECTURE_FLAGS} \
--c.extraMetadata.analytics.sentry.token='${{ steps.sentry.outputs.dsn }}' \
--c.extraMetadata.analytics.mixpanel.token='balena-etcher' \
--c.extraMetadata.packageType="${target}"
find dist -type f -maxdepth 1
Expand Down
3 changes: 1 addition & 2 deletions docs/MAINTAINERS.md
Expand Up @@ -31,7 +31,7 @@ Releasing
- [Post release note to forums](https://forums.balena.io/c/etcher)
- [Submit Windows binaries to Symantec for whitelisting](#submitting-binaries-to-symantec)
- [Update the website](https://github.com/balena-io/etcher-homepage)
- Wait 2-3 hours for analytics (Sentry, Mixpanel) to trickle in and check for elevated error rates, or regressions
- Wait 2-3 hours for analytics (Sentry, amplitude) to trickle in and check for elevated error rates, or regressions
- If regressions arise; pull the release, and release a patched version, else:
- [Upload deb & rpm packages to Bintray](#uploading-packages-to-bintray)
- [Upload build artifacts to Amazon S3](#uploading-binaries-to-amazon-s3)
Expand All @@ -48,7 +48,6 @@ Make sure to set the analytics tokens when generating production release binarie

```bash
export ANALYTICS_SENTRY_TOKEN="xxxxxx"
export ANALYTICS_MIXPANEL_TOKEN="xxxxxx"
```

#### Linux
Expand Down
2 changes: 1 addition & 1 deletion docs/MANUAL-TESTING.md
Expand Up @@ -112,4 +112,4 @@ Analytics
- [ ] Disable analytics, open DevTools Network pane or a packet sniffer, and
check that no request is sent
- [ ] **Disable analytics, refresh application from DevTools (using Cmd-R or
F5), and check that initial events are not sent to Mixpanel**
F5), and check that initial events are not sent to Amplitude**
92 changes: 24 additions & 68 deletions lib/gui/app/modules/analytics.ts
Expand Up @@ -15,86 +15,40 @@
*/

import * as _ from 'lodash';
import * as resinCorvus from 'resin-corvus/browser';

import * as packageJSON from '../../../../package.json';
import { getConfig } from '../../../shared/utils';
import { Client, createClient, createNoopClient } from 'analytics-client';
import * as Sentry from '@sentry/electron';
import * as settings from '../models/settings';
import { store } from '../models/store';

const DEFAULT_PROBABILITY = 0.1;

async function installCorvus(): Promise<void> {
const sentryToken =
(await settings.get('analyticsSentryToken')) ||
_.get(packageJSON, ['analytics', 'sentry', 'token']);
const mixpanelToken =
(await settings.get('analyticsMixpanelToken')) ||
_.get(packageJSON, ['analytics', 'mixpanel', 'token']);
resinCorvus.install({
services: {
sentry: sentryToken,
mixpanel: mixpanelToken,
},
options: {
release: packageJSON.version,
shouldReport: () => {
return settings.getSync('errorReporting');
},
mixpanelDeferred: true,
},
});
}

let mixpanelSample = DEFAULT_PROBABILITY;

let analyticsClient: Client;
/**
* @summary Init analytics configurations
*/
async function initConfig() {
await installCorvus();
let validatedConfig = null;
// TODO: should sentry (public) key come from some variable?
Sentry.init({});
try {
const configUrl = await settings.get('configUrl');
const config = await getConfig(configUrl);
const mixpanel = _.get(config, ['analytics', 'mixpanel'], {});
mixpanelSample = mixpanel.probability || DEFAULT_PROBABILITY;
if (isClientEligible(mixpanelSample)) {
validatedConfig = validateMixpanelConfig(mixpanel);
}
const shouldReportAnalytics = await settings.get('errorReporting');

// TODO: should this config come from somewhere? Where?
const clientConfig = {
endpoint: 'data.balena-cloud.com',
projectName: 'balena-etcher',
componentName: 'etcher',
componentVersion: packageJSON.version,
};
analyticsClient = shouldReportAnalytics
? createClient(clientConfig)
: createNoopClient();
} catch (err) {
resinCorvus.logException(err);
console.error('Failed to initialize analytics', err);
Sentry.captureException(err);
}
resinCorvus.setConfigs({
mixpanel: validatedConfig,
});
}

initConfig();

/**
* @summary Check that the client is eligible for analytics
*/
function isClientEligible(probability: number) {
return Math.random() < probability;
}

/**
* @summary Check that config has at least HTTP_PROTOCOL and api_host
*/
function validateMixpanelConfig(config: {
api_host?: string;
HTTP_PROTOCOL?: string;
}) {
const mixpanelConfig = {
api_host: 'https://api.mixpanel.com',
};
if (config.HTTP_PROTOCOL !== undefined && config.api_host !== undefined) {
mixpanelConfig.api_host = `${config.HTTP_PROTOCOL}://${config.api_host}`;
}
return mixpanelConfig;
}

/**
* @summary Log an event
*
Expand All @@ -105,9 +59,8 @@ export function logEvent(message: string, data: _.Dictionary<any> = {}) {
const { applicationSessionUuid, flashingWorkflowUuid } = store
.getState()
.toJS();
resinCorvus.logEvent(message, {
analyticsClient.track(message, {
...data,
sample: mixpanelSample,
applicationSessionUuid,
flashingWorkflowUuid,
});
Expand All @@ -119,4 +72,7 @@ export function logEvent(message: string, data: _.Dictionary<any> = {}) {
* @description
* This function logs an exception to error reporting services.
*/
export const logException = resinCorvus.logException;
export const logException = (error: any) => {
console.error(error);
Sentry.captureException(error);
};
3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -53,6 +53,7 @@
"@balena/lint": "5.4.2",
"@balena/sudo-prompt": "9.2.1-workaround-windows-amperstand-in-username-0849e215b947987a643fe5763902aea201255534",
"@fortawesome/fontawesome-free": "5.15.4",
"@sentry/electron": "^4.1.2",
"@svgr/webpack": "5.5.0",
"@types/chai": "4.2.7",
"@types/copy-webpack-plugin": "6.4.3",
Expand All @@ -68,6 +69,7 @@
"@types/terser-webpack-plugin": "5.0.2",
"@types/tmp": "0.2.3",
"@types/webpack-node-externals": "2.5.3",
"analytics-client": "^2.0.1",
"aws4-axios": "2.4.9",
"chai": "4.2.0",
"copy-webpack-plugin": "7.0.0",
Expand Down Expand Up @@ -100,7 +102,6 @@
"react-dom": "16.8.5",
"redux": "4.0.5",
"rendition": "19.2.0",
"resin-corvus": "2.0.5",
"semver": "7.3.8",
"simple-progress-webpack-plugin": "1.1.2",
"sinon": "9.0.2",
Expand Down
33 changes: 15 additions & 18 deletions webpack.config.ts
Expand Up @@ -29,7 +29,7 @@ import * as PnpWebpackPlugin from 'pnp-webpack-plugin';
import * as tsconfigRaw from './tsconfig.webpack.json';

/**
* Don't webpack package.json as mixpanel & sentry tokens
* Don't webpack package.json as sentry tokens
* will be inserted in it after webpacking
*/
function externalPackageJson(packageJsonPath: string) {
Expand Down Expand Up @@ -78,24 +78,24 @@ function renameNodeModules(resourcePath: string) {
}

function findUsbPrebuild(): string[] {
const usbPrebuildsFolder = path.join('node_modules', 'usb', 'prebuilds')
const usbPrebuildsFolder = path.join('node_modules', 'usb', 'prebuilds');
const prebuildFolders = readdirSync(usbPrebuildsFolder);
let bindingFile: string | undefined = 'node.napi.node';
const platformFolder = prebuildFolders.find(
(f) =>
f.startsWith(os.platform()) &&
f.indexOf(os.arch()) > -1,
(f) => f.startsWith(os.platform()) && f.indexOf(os.arch()) > -1,
);
if (platformFolder === undefined) {
throw new Error('Could not find usb prebuild. Should try fallback to node-gyp and use /build/Release instead of /prebuilds');
throw new Error(
'Could not find usb prebuild. Should try fallback to node-gyp and use /build/Release instead of /prebuilds',
);
}

const bindingFiles = readdirSync(
path.join(usbPrebuildsFolder, platformFolder)
)
path.join(usbPrebuildsFolder, platformFolder),
);

if (!bindingFiles.length) {
throw new Error('Could not find usb prebuild for platform')
throw new Error('Could not find usb prebuild for platform');
}

if (bindingFiles.length === 1) {
Expand All @@ -107,25 +107,22 @@ function findUsbPrebuild(): string[] {
if (bindingFiles.length > 1) {
bindingFile = bindingFiles.find((file) => {
if (bindingFiles.indexOf('arm') > -1) {
const process = require('process')
return file.indexOf(process.config.variables.arm_version) > -1
const process = require('process');
return file.indexOf(process.config.variables.arm_version) > -1;
} else {
return file.indexOf('glibc') > -1
return file.indexOf('glibc') > -1;
}
})
});
}

if (bindingFile === undefined) {
throw new Error('Could not find usb prebuild for platform')
throw new Error('Could not find usb prebuild for platform');
}

return [platformFolder, bindingFile];
}

const [
USB_BINDINGS_FOLDER,
USB_BINDINGS_FILE,
] = findUsbPrebuild();
const [USB_BINDINGS_FOLDER, USB_BINDINGS_FILE] = findUsbPrebuild();

function findLzmaNativeBindingsFolder(): string {
const files = readdirSync(
Expand Down

0 comments on commit 7a835c3

Please sign in to comment.