Skip to content
58 changes: 52 additions & 6 deletions packages/auto-instrumentations-node/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,50 @@ export type InstrumentationConfigMap = {
>;
};

function shouldDisableInstrumentation(
name: string,
userConfig: any,
enabledInstrumentationsFromEnv: string[],
disabledInstrumentationsFromEnv: string[]
): boolean {
// Priority 1: Programmatic config
if (userConfig.enabled === false) {
diag.debug(
`Disabling instrumentation for ${name} - disabled by user config`
);
return true;
}

if (userConfig.enabled === true) {
diag.debug(
`Enabling instrumentation for ${name} - explicitly enabled by user config`
);
return false;
}

// Priority 2: Environment variables
if (disabledInstrumentationsFromEnv.includes(name)) {
diag.debug(`Disabling instrumentation for ${name} - disabled by env var`);
return true;
}

const isEnabledEnvSet = !!process.env.OTEL_NODE_ENABLED_INSTRUMENTATIONS;
if (isEnabledEnvSet && !enabledInstrumentationsFromEnv.includes(name)) {
diag.debug(
`Disabling instrumentation for ${name} - not in enabled env var list`
);
return true;
}

// Priority 3: Default exclusions
if (!isEnabledEnvSet && defaultExcludedInstrumentations.includes(name)) {
diag.debug(`Disabling instrumentation for ${name} - excluded by default`);
return true;
}

return false;
}

export function getNodeAutoInstrumentations(
inputConfigs: InstrumentationConfigMap = {}
): Instrumentation[] {
Expand All @@ -168,12 +212,14 @@ export function getNodeAutoInstrumentations(
// Defaults are defined by the instrumentation itself
const userConfig: any = inputConfigs[name] ?? {};

if (
userConfig.enabled === false ||
!enabledInstrumentationsFromEnv.includes(name) ||
disabledInstrumentationsFromEnv.includes(name)
) {
diag.debug(`Disabling instrumentation for ${name}`);
const shouldDisable = shouldDisableInstrumentation(
name,
userConfig,
enabledInstrumentationsFromEnv,
disabledInstrumentationsFromEnv
);

if (shouldDisable) {
continue;
}

Expand Down
86 changes: 86 additions & 0 deletions packages/auto-instrumentations-node/test/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,92 @@ describe('utils', () => {

spy.restore();
});

it('should enable fs instrumentation when explicitly enabled and OTEL_NODE_ENABLED_INSTRUMENTATIONS is not set', () => {
const instrumentations = getNodeAutoInstrumentations({
'@opentelemetry/instrumentation-fs': {
enabled: true,
},
});
const fsInstrumentation = instrumentations.find(
instr =>
instr.instrumentationName === '@opentelemetry/instrumentation-fs'
);
assert.notStrictEqual(
fsInstrumentation,
undefined,
'fs instrumentation should be included when explicitly enabled in config and env var is not set'
);
});

it('should respect programmatic config over OTEL_NODE_ENABLED_INSTRUMENTATIONS - user config overrides env var', () => {
process.env.OTEL_NODE_ENABLED_INSTRUMENTATIONS = 'fs,http';
try {
const instrumentations = getNodeAutoInstrumentations({
'@opentelemetry/instrumentation-fs': {
enabled: false, // User explicitly disables - should override env var
},
'@opentelemetry/instrumentation-express': {
enabled: true, // User explicitly enables - should override env var
},
});

const fsInstrumentation = instrumentations.find(
instr =>
instr.instrumentationName === '@opentelemetry/instrumentation-fs'
);
const httpInstrumentation = instrumentations.find(
instr =>
instr.instrumentationName === '@opentelemetry/instrumentation-http'
);
const expressInstrumentation = instrumentations.find(
instr =>
instr.instrumentationName ===
'@opentelemetry/instrumentation-express'
);

assert.strictEqual(
fsInstrumentation,
undefined,
'fs should be disabled by user config despite env var'
);
assert.notStrictEqual(
httpInstrumentation,
undefined,
'http should be enabled by env var (no user override)'
);
assert.notStrictEqual(
expressInstrumentation,
undefined,
'express should be enabled by user config despite not being in env var list'
);
} finally {
delete process.env.OTEL_NODE_ENABLED_INSTRUMENTATIONS;
}
});

it('should respect programmatic config over OTEL_NODE_DISABLED_INSTRUMENTATIONS - user config overrides env var', () => {
process.env.OTEL_NODE_DISABLED_INSTRUMENTATIONS = 'http';
try {
const instrumentations = getNodeAutoInstrumentations({
'@opentelemetry/instrumentation-http': {
enabled: true, // User explicitly enables - should override env var
},
});
const httpInstrumentation = instrumentations.find(
instr =>
instr.instrumentationName === '@opentelemetry/instrumentation-http'
);

assert.notStrictEqual(
httpInstrumentation,
undefined,
'http instrumentation should be enabled by user config despite OTEL_NODE_DISABLED_INSTRUMENTATIONS'
);
} finally {
delete process.env.OTEL_NODE_DISABLED_INSTRUMENTATIONS;
}
});
});

describe('getResourceDetectorsFromEnv', () => {
Expand Down
Loading