Support BALENARC_NO_SENTRY env var to disable Sentry.io error reporting

Change-type: minor
This commit is contained in:
Paulo Castro 2020-10-09 13:06:09 +01:00
parent 8f0f3bda29
commit cf376316bc
5 changed files with 69 additions and 24 deletions

View File

@ -229,7 +229,12 @@ export function setMaxListeners(maxListeners: number) {
}
export async function globalInit() {
(await import('./utils/bootstrap')).normalizeEnvVar('BALENARC_NO_SENTRY');
if (process.env.BALENARC_NO_SENTRY) {
console.error(`WARN: disabling Sentry.io error reporting`);
} else {
await setupSentry();
}
checkNodeVersion();
const settings = new CliSettings();

View File

@ -23,12 +23,7 @@ export async function run(
cliArgs = process.argv,
options: import('./preparser').AppOptions = {},
) {
// DEBUG set to falsy for negative values else is truthy
process.env.DEBUG = ['0', 'no', 'false', '', undefined].includes(
process.env.DEBUG?.toLowerCase(),
)
? ''
: '1';
(await import('./utils/bootstrap')).normalizeEnvVar('DEBUG');
// The 'pkgExec' special/internal command provides a Node.js interpreter
// for use of the standalone zip package. See pkgExec function.

View File

@ -162,6 +162,18 @@ export const getSentry = async function () {
return await import('@sentry/node');
};
async function sentryCaptureException(error: Error) {
const Sentry = await getSentry();
Sentry.captureException(error);
try {
await Sentry.close(1000);
} catch (e) {
if (process.env.DEBUG) {
console.error('Timeout reporting error to sentry.io');
}
}
}
export async function handleError(error: Error) {
// Set appropriate exitCode
process.exitCode =
@ -189,15 +201,10 @@ export async function handleError(error: Error) {
printErrorMessage(message.join('\n'));
// Report "unexpected" errors via Sentry.io
const Sentry = await getSentry();
Sentry.captureException(error);
try {
await Sentry.close(1000);
} catch (e) {
if (process.env.DEBUG) {
console.error('Timeout reporting error to sentry.io');
}
if (!process.env.BALENARC_NO_SENTRY) {
await sentryCaptureException(error);
}
// Unhandled/unexpected error: ensure that the process terminates.
// The exit error code was set above through `process.exitCode`.
process.exit();

View File

@ -49,10 +49,13 @@ interface CachedUsername {
*/
export async function trackCommand(commandSignature: string) {
try {
const Sentry = await import('@sentry/node');
let Sentry: typeof import('@sentry/node');
if (!process.env.BALENARC_NO_SENTRY) {
Sentry = await import('@sentry/node');
Sentry.configureScope((scope) => {
scope.setExtra('command', commandSignature);
});
}
const settings = await import('balena-settings-client');
const balenaUrl = settings.get('balenaUrl') as string;
@ -90,12 +93,14 @@ export async function trackCommand(commandSignature: string) {
const mixpanel = getMixpanel(balenaUrl);
Sentry.configureScope((scope) => {
if (!process.env.BALENARC_NO_SENTRY) {
Sentry!.configureScope((scope) => {
scope.setUser({
id: username,
username,
});
});
}
// Don't actually call mixpanel.track() while running test cases
if (!process.env.BALENA_CLI_TEST_TYPE) {
await mixpanel.track(`[CLI] ${commandSignature}`, {

33
lib/utils/bootstrap.ts Normal file
View File

@ -0,0 +1,33 @@
/**
* @license
* Copyright 2020 Balena Ltd.
*
* Licensed 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.
*/
/*
* THIS MODULE SHOULD NOT IMPORT / REQUIRE ANYTHING AT THE GLOBAL LEVEL.
* It is meant to contain elementary helper functions or classes that
* can be used very early on during CLI startup, before anything else
* like Sentry error reporting, preparser, oclif parser and the like.
*/
export function parseBoolEnvVar(varName: string): boolean {
return !['0', 'no', 'false', '', undefined].includes(
process.env[varName]?.toLowerCase(),
);
}
export function normalizeEnvVar(varName: string) {
process.env[varName] = parseBoolEnvVar(varName) ? '1' : '';
}