From c3afab7ddd4e86fd32478b19f64b94b33f157520 Mon Sep 17 00:00:00 2001 From: Jamie Danielson Date: Wed, 19 Jun 2024 13:10:18 -0400 Subject: [PATCH] feat(auto-instrumentations-node): disabling instrumentations via env var (#2174) * feat(auto-instr-node): disabling instrumentations via env var * create new func to reduce code duplication * fix Object is possibly undefined --------- Co-authored-by: Amir Blum --- .../auto-instrumentations-node/README.md | 11 ++++- .../auto-instrumentations-node/src/utils.ts | 43 ++++++++++++++++--- .../test/utils.test.ts | 25 +++++++++++ 3 files changed, 70 insertions(+), 9 deletions(-) diff --git a/metapackages/auto-instrumentations-node/README.md b/metapackages/auto-instrumentations-node/README.md index 221a0570a5..c32df7c437 100644 --- a/metapackages/auto-instrumentations-node/README.md +++ b/metapackages/auto-instrumentations-node/README.md @@ -77,8 +77,9 @@ For example, to enable only the `env`, `host` detectors: export OTEL_NODE_RESOURCE_DETECTORS="env,host" ``` -By default, all [Supported Instrumentations](#supported-instrumentations) are enabled, -but you can use the environment variable `OTEL_NODE_ENABLED_INSTRUMENTATIONS` to enable only certain instrumentations +By default, all [Supported Instrumentations](#supported-instrumentations) are enabled. +You can use the environment variable `OTEL_NODE_ENABLED_INSTRUMENTATIONS` to enable only certain instrumentations, +OR the environment variable `OTEL_NODE_DISABLED_INSTRUMENTATIONS` to disable only certain instrumentations, by providing a comma-separated list of the instrumentation package names without the `@opentelemetry/instrumentation-` prefix. For example, to enable only @@ -90,6 +91,12 @@ instrumentations: export OTEL_NODE_ENABLED_INSTRUMENTATIONS="http,nestjs-core" ``` +To disable only [@opentelemetry/instrumentation-fs](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/plugins/node/instrumentation-fs): + +```shell +export OTEL_NODE_DISABLED_INSTRUMENTATIONS="fs" +``` + To enable logging for troubleshooting, set the log level by setting the `OTEL_LOG_LEVEL` environment variable to one of the following: - `none` diff --git a/metapackages/auto-instrumentations-node/src/utils.ts b/metapackages/auto-instrumentations-node/src/utils.ts index 04f4c1ed50..c258dfc597 100644 --- a/metapackages/auto-instrumentations-node/src/utils.ts +++ b/metapackages/auto-instrumentations-node/src/utils.ts @@ -147,6 +147,7 @@ export function getNodeAutoInstrumentations( ): Instrumentation[] { checkManuallyProvidedInstrumentationNames(Object.keys(inputConfigs)); const enabledInstrumentationsFromEnv = getEnabledInstrumentationsFromEnv(); + const disabledInstrumentationsFromEnv = getDisabledInstrumentationsFromEnv(); const instrumentations: Instrumentation[] = []; @@ -159,7 +160,8 @@ export function getNodeAutoInstrumentations( if ( userConfig.enabled === false || - !enabledInstrumentationsFromEnv.includes(name) + !enabledInstrumentationsFromEnv.includes(name) || + disabledInstrumentationsFromEnv.includes(name) ) { diag.debug(`Disabling instrumentation for ${name}`); continue; @@ -186,6 +188,22 @@ function checkManuallyProvidedInstrumentationNames( } } +function getInstrumentationsFromEnv(envVar: string): string[] { + const envVarValue = process.env[envVar]; + if (envVarValue == null) { + return []; + } + + const instrumentationsFromEnv = envVarValue + ?.split(',') + .map( + instrumentationPkgSuffix => + `@opentelemetry/instrumentation-${instrumentationPkgSuffix.trim()}` + ); + checkManuallyProvidedInstrumentationNames(instrumentationsFromEnv); + return instrumentationsFromEnv; +} + /** * Returns the list of instrumentations that are enabled based on the environment variable. */ @@ -194,12 +212,23 @@ function getEnabledInstrumentationsFromEnv() { return Object.keys(InstrumentationMap); } - const instrumentationsFromEnv = - process.env.OTEL_NODE_ENABLED_INSTRUMENTATIONS.split(',').map( - instrumentationPkgSuffix => - `@opentelemetry/instrumentation-${instrumentationPkgSuffix.trim()}` - ); - checkManuallyProvidedInstrumentationNames(instrumentationsFromEnv); + const instrumentationsFromEnv = getInstrumentationsFromEnv( + 'OTEL_NODE_ENABLED_INSTRUMENTATIONS' + ); + return instrumentationsFromEnv; +} + +/** + * Returns the list of instrumentations that are disabled based on the environment variable. + */ +function getDisabledInstrumentationsFromEnv() { + if (!process.env.OTEL_NODE_DISABLED_INSTRUMENTATIONS) { + return []; + } + + const instrumentationsFromEnv = getInstrumentationsFromEnv( + 'OTEL_NODE_DISABLED_INSTRUMENTATIONS' + ); return instrumentationsFromEnv; } diff --git a/metapackages/auto-instrumentations-node/test/utils.test.ts b/metapackages/auto-instrumentations-node/test/utils.test.ts index 0622022f36..ceea3262a8 100644 --- a/metapackages/auto-instrumentations-node/test/utils.test.ts +++ b/metapackages/auto-instrumentations-node/test/utils.test.ts @@ -89,6 +89,31 @@ describe('utils', () => { } }); + it('should include all instrumentations except those disabled via OTEL_NODE_DISABLED_INSTRUMENTATIONS environment variable', () => { + process.env.OTEL_NODE_DISABLED_INSTRUMENTATIONS = + 'fs,aws-sdk, aws-lambda'; // separator with and without whitespaces should be allowed + try { + const instrumentations = getNodeAutoInstrumentations(); + const disabledInstrumentations = new Set([ + '@opentelemetry/instrumentation-fs', + '@opentelemetry/instrumentation-aws-sdk', + '@opentelemetry/instrumentation-aws-lambda', + ]); + const enabledInstrumentationNames = new Set( + instrumentations.map(i => i.instrumentationName) + ); + + for (const disabledInstrumentation of disabledInstrumentations) { + assert.strictEqual( + enabledInstrumentationNames.has(disabledInstrumentation), + false + ); + } + } finally { + delete process.env.OTEL_NODE_DISABLED_INSTRUMENTATIONS; + } + }); + it('should show error for none existing instrumentation', () => { const spy = sinon.stub(diag, 'error'); const name = '@opentelemetry/instrumentation-http2';