diff --git a/plugins/node/opentelemetry-instrumentation-aws-lambda/README.md b/plugins/node/opentelemetry-instrumentation-aws-lambda/README.md index 22a6095920..d4e090b46d 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-lambda/README.md +++ b/plugins/node/opentelemetry-instrumentation-aws-lambda/README.md @@ -50,7 +50,7 @@ In your Lambda function configuration, add or update the `NODE_OPTIONS` environm | --- | --- | --- | | `requestHook` | `RequestHook` (function) | Hook for adding custom attributes before lambda starts handling the request. Receives params: `span, { event, context }` | | `responseHook` | `ResponseHook` (function) | Hook for adding custom attributes before lambda returns the response. Receives params: `span, { err?, res? }` | -| `disableAwsContextPropagation` | `boolean` | By default, this instrumentation will try to read the context from the `_X_AMZN_TRACE_ID` environment variable set by Lambda, set this to `true` to disable this behavior | +| `disableAwsContextPropagation` | `boolean` | By default, this instrumentation will try to read the context from the `_X_AMZN_TRACE_ID` environment variable set by Lambda, set this to `true` or set the environment variable `OTEL_LAMBDA_DISABLE_AWS_CONTEXT_PROPAGATION=true` to disable this behavior | | `eventContextExtractor` | `EventContextExtractor` (function) | Function for providing custom context extractor in order to support different event types that are handled by AWS Lambda (e.g., SQS, CloudWatch, Kinesis, API Gateway). Applied only when `disableAwsContextPropagation` is set to `true`. Receives params: `event, context` | ### Hooks Usage Example diff --git a/plugins/node/opentelemetry-instrumentation-aws-lambda/src/instrumentation.ts b/plugins/node/opentelemetry-instrumentation-aws-lambda/src/instrumentation.ts index 20d4717a04..75adb7e331 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-lambda/src/instrumentation.ts +++ b/plugins/node/opentelemetry-instrumentation-aws-lambda/src/instrumentation.ts @@ -57,6 +57,7 @@ import { import { AwsLambdaInstrumentationConfig, EventContextExtractor } from './types'; import { VERSION } from './version'; +import { env } from 'process'; import { LambdaModule } from './internal-types'; const awsPropagator = new AWSXRayPropagator(); @@ -77,6 +78,17 @@ export class AwsLambdaInstrumentation extends InstrumentationBase { constructor(protected override _config: AwsLambdaInstrumentationConfig = {}) { super('@opentelemetry/instrumentation-aws-lambda', VERSION, _config); + if (this._config.disableAwsContextPropagation == null) { + if ( + typeof env['OTEL_LAMBDA_DISABLE_AWS_CONTEXT_PROPAGATION'] === + 'string' && + env[ + 'OTEL_LAMBDA_DISABLE_AWS_CONTEXT_PROPAGATION' + ].toLocaleLowerCase() === 'true' + ) { + this._config.disableAwsContextPropagation = true; + } + } } override setConfig(config: AwsLambdaInstrumentationConfig = {}) { diff --git a/plugins/node/opentelemetry-instrumentation-aws-lambda/test/integrations/lambda-handler.test.ts b/plugins/node/opentelemetry-instrumentation-aws-lambda/test/integrations/lambda-handler.test.ts index 681922fbee..573cab8140 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-lambda/test/integrations/lambda-handler.test.ts +++ b/plugins/node/opentelemetry-instrumentation-aws-lambda/test/integrations/lambda-handler.test.ts @@ -544,6 +544,92 @@ describe('lambda handler', () => { assert.strictEqual(spans.length, 0); }); + it('ignores sampled lambda context if env OTEL_LAMBDA_DISABLE_AWS_CONTEXT_PROPAGATION is set to "true"', async () => { + process.env['OTEL_LAMBDA_DISABLE_AWS_CONTEXT_PROPAGATION'] = 'true'; + process.env[traceContextEnvironmentKey] = sampledAwsHeader; + initializeHandler('lambda-test/async.handler', {}); + + const result = await lambdaRequire('lambda-test/async').handler( + 'arg', + ctx + ); + assert.strictEqual(result, 'ok'); + const spans = memoryExporter.getFinishedSpans(); + const [span] = spans; + assert.strictEqual(spans.length, 1); + assertSpanSuccess(span); + assert.notDeepStrictEqual( + span.spanContext().traceId, + sampledAwsSpanContext.traceId + ); + assert.strictEqual(span.parentSpanId, undefined); + }); + + it('ignores sampled lambda context if env OTEL_LAMBDA_DISABLE_AWS_CONTEXT_PROPAGATION is set to "TRUE"', async () => { + process.env['OTEL_LAMBDA_DISABLE_AWS_CONTEXT_PROPAGATION'] = 'TRUE'; + process.env[traceContextEnvironmentKey] = sampledAwsHeader; + initializeHandler('lambda-test/async.handler', {}); + + const result = await lambdaRequire('lambda-test/async').handler( + 'arg', + ctx + ); + assert.strictEqual(result, 'ok'); + const spans = memoryExporter.getFinishedSpans(); + const [span] = spans; + assert.strictEqual(spans.length, 1); + assertSpanSuccess(span); + assert.notDeepStrictEqual( + span.spanContext().traceId, + sampledAwsSpanContext.traceId + ); + assert.strictEqual(span.parentSpanId, undefined); + }); + + it('ignores sampled lambda context if env OTEL_LAMBDA_DISABLE_AWS_CONTEXT_PROPAGATION is set to "True"', async () => { + process.env['OTEL_LAMBDA_DISABLE_AWS_CONTEXT_PROPAGATION'] = 'True'; + process.env[traceContextEnvironmentKey] = sampledAwsHeader; + initializeHandler('lambda-test/async.handler', {}); + + const result = await lambdaRequire('lambda-test/async').handler( + 'arg', + ctx + ); + assert.strictEqual(result, 'ok'); + const spans = memoryExporter.getFinishedSpans(); + const [span] = spans; + assert.strictEqual(spans.length, 1); + assertSpanSuccess(span); + assert.notDeepStrictEqual( + span.spanContext().traceId, + sampledAwsSpanContext.traceId + ); + assert.strictEqual(span.parentSpanId, undefined); + }); + + it('ignores OTEL_LAMBDA_DISABLE_AWS_CONTEXT_PROPAGATION if `config.disableAwsContextPropagation` is set', async () => { + process.env['OTEL_LAMBDA_DISABLE_AWS_CONTEXT_PROPAGATION'] = 'true'; + process.env[traceContextEnvironmentKey] = sampledAwsHeader; + initializeHandler('lambda-test/async.handler', { + disableAwsContextPropagation: false, + }); + + const result = await lambdaRequire('lambda-test/async').handler( + 'arg', + ctx + ); + assert.strictEqual(result, 'ok'); + const spans = memoryExporter.getFinishedSpans(); + const [span] = spans; + assert.strictEqual(spans.length, 1); + assertSpanSuccess(span); + assert.strictEqual( + span.spanContext().traceId, + sampledAwsSpanContext.traceId + ); + assert.strictEqual(span.parentSpanId, sampledAwsSpanContext.spanId); + }); + it('ignores sampled lambda context if "disableAwsContextPropagation" config option is true', async () => { process.env[traceContextEnvironmentKey] = sampledAwsHeader; initializeHandler('lambda-test/async.handler', {