From cf04993a486865f935468ffa5a1914579eab985e Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Mon, 12 Aug 2024 15:49:26 +0100 Subject: [PATCH 1/6] feat: Add support for SENTRY_SPOTLIGHT env var in Node --- packages/node/src/sdk/index.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/node/src/sdk/index.ts b/packages/node/src/sdk/index.ts index 1a20458802a0..c8cde965ec88 100644 --- a/packages/node/src/sdk/index.ts +++ b/packages/node/src/sdk/index.ts @@ -208,6 +208,9 @@ export function validateOpenTelemetrySetup(): void { } } +const FALSY_ENV_VALUES = new Set(['0', 'false', 'no']); +const TRUTHY_ENV_VALUES = new Set(['1', 'true', 'yes']); + function getClientOptions( options: NodeOptions, getDefaultIntegrationsImpl: (options: Options) => Integration[], @@ -221,6 +224,17 @@ function getClientOptions( ? true : options.autoSessionTracking; + if (options.spotlight == null && process.env.SENTRY_SPOTLIGHT) { + const spotlightEnv = process.env.SENTRY_SPOTLIGHT.toLowerCase(); + if (FALSY_ENV_VALUES.has(spotlightEnv)) { + options.spotlight = false; + } else if (TRUTHY_ENV_VALUES.has(spotlightEnv)) { + options.spotlight = true; + } else { + options.spotlight = spotlightEnv; + } + } + const tracesSampleRate = getTracesSampleRate(options.tracesSampleRate); const baseOptions = dropUndefinedKeys({ From f08ff0d07d22b694dc8e55dfcc866652f810d4b9 Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Tue, 13 Aug 2024 13:20:18 +0100 Subject: [PATCH 2/6] pull out into helper --- .vscode/settings.json | 2 +- packages/node/src/preload.ts | 7 +++--- packages/node/src/sdk/index.ts | 17 +++++-------- packages/node/src/utils/envToBool.ts | 37 ++++++++++++++++++++++++++++ 4 files changed, 48 insertions(+), 15 deletions(-) create mode 100644 packages/node/src/utils/envToBool.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index 615ca5b24472..4926554ffe4b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -42,5 +42,5 @@ "[typescript]": { "editor.defaultFormatter": "biomejs.biome" }, - "cSpell.words": ["arrayify"] + "cSpell.words": ["arrayify", "OTEL"] } diff --git a/packages/node/src/preload.ts b/packages/node/src/preload.ts index 0d62b28d9c91..0e4af146197f 100644 --- a/packages/node/src/preload.ts +++ b/packages/node/src/preload.ts @@ -1,13 +1,14 @@ import { preloadOpenTelemetry } from './sdk/initOtel'; +import { envToBool } from './utils/envToBool'; -const debug = !!process.env.SENTRY_DEBUG; +const debug = envToBool(process.env.SENTRY_DEBUG); const integrationsStr = process.env.SENTRY_PRELOAD_INTEGRATIONS; const integrations = integrationsStr ? integrationsStr.split(',').map(integration => integration.trim()) : undefined; /** - * The @sentry/node/preload export can be used with the node --import and --require args to preload the OTEL instrumentation, - * without initializing the Sentry SDK. + * The @sentry/node/preload export can be used with the node --import and --require args to preload the OTEL + * instrumentation, without initializing the Sentry SDK. * * This is useful if you cannot initialize the SDK immediately, but still want to preload the instrumentation, * e.g. if you have to load the DSN from somewhere else. diff --git a/packages/node/src/sdk/index.ts b/packages/node/src/sdk/index.ts index c8cde965ec88..e8c8b2d71fe6 100644 --- a/packages/node/src/sdk/index.ts +++ b/packages/node/src/sdk/index.ts @@ -41,6 +41,7 @@ import { getAutoPerformanceIntegrations } from '../integrations/tracing'; import { makeNodeTransport } from '../transports'; import type { NodeClientOptions, NodeOptions } from '../types'; import { isCjs } from '../utils/commonjs'; +import { envToBool } from '../utils/envToBool'; import { defaultStackParser, getSentryRelease } from './api'; import { NodeClient } from './client'; import { initOpenTelemetry, maybeInitializeEsmLoader } from './initOtel'; @@ -208,9 +209,6 @@ export function validateOpenTelemetrySetup(): void { } } -const FALSY_ENV_VALUES = new Set(['0', 'false', 'no']); -const TRUTHY_ENV_VALUES = new Set(['1', 'true', 'yes']); - function getClientOptions( options: NodeOptions, getDefaultIntegrationsImpl: (options: Options) => Integration[], @@ -224,12 +222,10 @@ function getClientOptions( ? true : options.autoSessionTracking; - if (options.spotlight == null && process.env.SENTRY_SPOTLIGHT) { - const spotlightEnv = process.env.SENTRY_SPOTLIGHT.toLowerCase(); - if (FALSY_ENV_VALUES.has(spotlightEnv)) { - options.spotlight = false; - } else if (TRUTHY_ENV_VALUES.has(spotlightEnv)) { - options.spotlight = true; + if (options.spotlight == null) { + const spotlightEnv = envToBool(process.env.SENTRY_SPOTLIGHT); + if (spotlightEnv == null) { + options.spotlight = process.env.SENTRY_SPOTLIGHT; } else { options.spotlight = spotlightEnv; } @@ -306,8 +302,7 @@ function getTracesSampleRate(tracesSampleRate: NodeOptions['tracesSampleRate']): * for more details. */ function updateScopeFromEnvVariables(): void { - const sentryUseEnvironment = (process.env.SENTRY_USE_ENVIRONMENT || '').toLowerCase(); - if (!['false', 'n', 'no', 'off', '0'].includes(sentryUseEnvironment)) { + if (envToBool(process.env.SENTRY_USE_ENVIRONMENT) !== false) { const sentryTraceEnv = process.env.SENTRY_TRACE; const baggageEnv = process.env.SENTRY_BAGGAGE; const propagationContext = propagationContextFromHeaders(sentryTraceEnv, baggageEnv); diff --git a/packages/node/src/utils/envToBool.ts b/packages/node/src/utils/envToBool.ts new file mode 100644 index 000000000000..fa10cdba529b --- /dev/null +++ b/packages/node/src/utils/envToBool.ts @@ -0,0 +1,37 @@ +export const FALSY_ENV_VALUES = new Set(['false', 'n', 'no', 'off', '0']); +export const TRUTHY_ENV_VALUES = new Set(['true', 'y', 'yes', 'on', '1']); + +export type StrictBoolCast = { + strict: true; +}; + +export type LooseBoolCast = { + strict?: false; +}; + +export type BoolCastOptions = StrictBoolCast | LooseBoolCast; + +export function envToBool(value: unknown, options?: LooseBoolCast): boolean; +export function envToBool(value: unknown, options: StrictBoolCast): boolean | null; +/** + * A helper function which casts an ENV variable value to `true` or `false` using the constants defined above. + * In strict mode, it may return `null` if the value doesn't match any of the predefined values. + * + * @param value The value of the env variable + * @param options -- Only has `strict` key for now, which requires a strict match for `true` in TRUTHY_ENV_VALUES + * @returns true/false if the lowercase value matches the predefined values above. If not, null in strict mode, + * and Boolean(value) in loose mode. + */ +export function envToBool(value: unknown, options?: BoolCastOptions): boolean | null { + const normalized = String(value).toLowerCase(); + + if (FALSY_ENV_VALUES.has(normalized)) { + return false; + } + + if (TRUTHY_ENV_VALUES.has(normalized)) { + return true; + } + + return options && options.strict ? null : Boolean(normalized); +} From 67bd976f51c8863283e2f3e760b8a72f37c7de33 Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Tue, 13 Aug 2024 13:26:40 +0100 Subject: [PATCH 3/6] forgot strict mode --- packages/node/src/sdk/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/node/src/sdk/index.ts b/packages/node/src/sdk/index.ts index e8c8b2d71fe6..7276e809875a 100644 --- a/packages/node/src/sdk/index.ts +++ b/packages/node/src/sdk/index.ts @@ -223,7 +223,7 @@ function getClientOptions( : options.autoSessionTracking; if (options.spotlight == null) { - const spotlightEnv = envToBool(process.env.SENTRY_SPOTLIGHT); + const spotlightEnv = envToBool(process.env.SENTRY_SPOTLIGHT, { strict: true }); if (spotlightEnv == null) { options.spotlight = process.env.SENTRY_SPOTLIGHT; } else { From 32c89cba441d2a6d048e9496e8440e78a00a8947 Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Tue, 13 Aug 2024 13:53:10 +0100 Subject: [PATCH 4/6] fix logic error --- packages/node/src/utils/envToBool.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/node/src/utils/envToBool.ts b/packages/node/src/utils/envToBool.ts index fa10cdba529b..537c767a7e92 100644 --- a/packages/node/src/utils/envToBool.ts +++ b/packages/node/src/utils/envToBool.ts @@ -33,5 +33,5 @@ export function envToBool(value: unknown, options?: BoolCastOptions): boolean | return true; } - return options && options.strict ? null : Boolean(normalized); + return options && options.strict ? null : Boolean(value); } From ed51040458c888128a4957004a4b5a1c6e463171 Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Tue, 13 Aug 2024 15:25:32 +0100 Subject: [PATCH 5/6] add tests --- packages/node/src/utils/envToBool.ts | 1 + packages/node/test/utils/envToBool.test.ts | 64 ++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 packages/node/test/utils/envToBool.test.ts diff --git a/packages/node/src/utils/envToBool.ts b/packages/node/src/utils/envToBool.ts index 537c767a7e92..0c8c017acd1e 100644 --- a/packages/node/src/utils/envToBool.ts +++ b/packages/node/src/utils/envToBool.ts @@ -13,6 +13,7 @@ export type BoolCastOptions = StrictBoolCast | LooseBoolCast; export function envToBool(value: unknown, options?: LooseBoolCast): boolean; export function envToBool(value: unknown, options: StrictBoolCast): boolean | null; +export function envToBool(value: unknown, options?: BoolCastOptions): boolean | null; /** * A helper function which casts an ENV variable value to `true` or `false` using the constants defined above. * In strict mode, it may return `null` if the value doesn't match any of the predefined values. diff --git a/packages/node/test/utils/envToBool.test.ts b/packages/node/test/utils/envToBool.test.ts new file mode 100644 index 000000000000..dff0a19d7872 --- /dev/null +++ b/packages/node/test/utils/envToBool.test.ts @@ -0,0 +1,64 @@ +import { envToBool } from '../../src/utils/envToBool'; + +describe('envToBool', () => { + it.each([ + ['', true, null], + ['', false, false], + ['t', true, true], + ['T', true, true], + ['t', false, true], + ['T', false, true], + ['y', true, true], + ['Y', true, true], + ['y', false, true], + ['Y', false, true], + ['1', true, true], + ['1', false, true], + ['true', true, true], + ['true', false, true], + ['tRuE', true, true], + ['tRuE', false, true], + ['Yes', true, true], + ['Yes', false, true], + ['yes', true, true], + ['yes', false, true], + ['yEs', true, true], + ['yEs', false, true], + ['On', true, true], + ['On', false, true], + ['on', true, true], + ['on', false, true], + ['oN', true, true], + ['oN', false, true], + ['f', true, false], + ['f', false, false], + ['n', true, false], + ['N', true, false], + ['n', false, false], + ['N', false, false], + ['0', true, false], + ['0', false, false], + ['false', true, false], + ['false', false, false], + ['false', true, false], + ['false', false, false], + ['FaLsE', true, false], + ['FaLsE', false, false], + ['No', true, false], + ['No', false, false], + ['no', true, false], + ['no', false, false], + ['nO', true, false], + ['nO', false, false], + ['Off', true, false], + ['Off', false, false], + ['off', true, false], + ['off', false, false], + ['oFf', true, false], + ['oFf', false, false], + ['xxx', true, null], + ['xxx', false, true], + ])('%s becomes (strict: %s): %s', (value, strict, expected) => { + expect(envToBool(value, { strict })).toBe(expected); + }); +}); From 7dcaa82cbbb96e16dd4681613f869d4239e8a53f Mon Sep 17 00:00:00 2001 From: Burak Yigit Kaya Date: Tue, 13 Aug 2024 15:45:25 +0100 Subject: [PATCH 6/6] fix tests & add undefined case --- packages/node/src/utils/envToBool.ts | 4 ++-- packages/node/test/utils/envToBool.test.ts | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/node/src/utils/envToBool.ts b/packages/node/src/utils/envToBool.ts index 0c8c017acd1e..4f7fd2201ce8 100644 --- a/packages/node/src/utils/envToBool.ts +++ b/packages/node/src/utils/envToBool.ts @@ -1,5 +1,5 @@ -export const FALSY_ENV_VALUES = new Set(['false', 'n', 'no', 'off', '0']); -export const TRUTHY_ENV_VALUES = new Set(['true', 'y', 'yes', 'on', '1']); +export const FALSY_ENV_VALUES = new Set(['false', 'f', 'n', 'no', 'off', '0']); +export const TRUTHY_ENV_VALUES = new Set(['true', 't', 'y', 'yes', 'on', '1']); export type StrictBoolCast = { strict: true; diff --git a/packages/node/test/utils/envToBool.test.ts b/packages/node/test/utils/envToBool.test.ts index dff0a19d7872..cd06ef132267 100644 --- a/packages/node/test/utils/envToBool.test.ts +++ b/packages/node/test/utils/envToBool.test.ts @@ -58,6 +58,8 @@ describe('envToBool', () => { ['oFf', false, false], ['xxx', true, null], ['xxx', false, true], + [undefined, false, false], + [undefined, true, null], ])('%s becomes (strict: %s): %s', (value, strict, expected) => { expect(envToBool(value, { strict })).toBe(expected); });