From cf376316bc4863b98223bac9c81697c2245341ae Mon Sep 17 00:00:00 2001 From: Paulo Castro Date: Fri, 9 Oct 2020 13:06:09 +0100 Subject: [PATCH] Support BALENARC_NO_SENTRY env var to disable Sentry.io error reporting Change-type: minor --- lib/app-common.ts | 7 ++++++- lib/app.ts | 7 +------ lib/errors.ts | 23 +++++++++++++++-------- lib/events.ts | 23 ++++++++++++++--------- lib/utils/bootstrap.ts | 33 +++++++++++++++++++++++++++++++++ 5 files changed, 69 insertions(+), 24 deletions(-) create mode 100644 lib/utils/bootstrap.ts diff --git a/lib/app-common.ts b/lib/app-common.ts index 2ae011d4..054498ea 100644 --- a/lib/app-common.ts +++ b/lib/app-common.ts @@ -229,7 +229,12 @@ export function setMaxListeners(maxListeners: number) { } export async function globalInit() { - await setupSentry(); + (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(); diff --git a/lib/app.ts b/lib/app.ts index 433aff03..22f33578 100644 --- a/lib/app.ts +++ b/lib/app.ts @@ -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. diff --git a/lib/errors.ts b/lib/errors.ts index 66e108c0..f4da8aca 100644 --- a/lib/errors.ts +++ b/lib/errors.ts @@ -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(); diff --git a/lib/events.ts b/lib/events.ts index a12e2de1..b427465a 100644 --- a/lib/events.ts +++ b/lib/events.ts @@ -49,10 +49,13 @@ interface CachedUsername { */ export async function trackCommand(commandSignature: string) { try { - const Sentry = await import('@sentry/node'); - Sentry.configureScope((scope) => { - scope.setExtra('command', commandSignature); - }); + 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) => { - scope.setUser({ - id: username, - username, + 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}`, { diff --git a/lib/utils/bootstrap.ts b/lib/utils/bootstrap.ts new file mode 100644 index 00000000..baaa3c4a --- /dev/null +++ b/lib/utils/bootstrap.ts @@ -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' : ''; +}