Skip to content

Commit a926f53

Browse files
martinkubatylerbensonblumamir
authored
feat(aws-lambda)!: Remove explicit x-ray context in favor of global propagator (open-telemetry#2369)
Co-authored-by: Tyler Benson <[email protected]> Co-authored-by: Amir Blum <[email protected]>
1 parent 1ae98de commit a926f53

File tree

6 files changed

+182
-395
lines changed

6 files changed

+182
-395
lines changed

package-lock.json

Lines changed: 93 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

plugins/node/opentelemetry-instrumentation-aws-lambda/README.md

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,7 @@ In your Lambda function configuration, add or update the `NODE_OPTIONS` environm
5454
| --- | --- | --- |
5555
| `requestHook` | `RequestHook` (function) | Hook for adding custom attributes before lambda starts handling the request. Receives params: `span, { event, context }` |
5656
| `responseHook` | `ResponseHook` (function) | Hook for adding custom attributes before lambda returns the response. Receives params: `span, { err?, res? }` |
57-
| `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 |
58-
| `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` |
57+
| `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). |
5958
| `lambdaHandler` | `string` | By default, this instrumentation automatically determines the Lambda handler function to instrument. This option is used to override that behavior by explicitly specifying the Lambda handler to instrument. See [Specifying the Lambda Handler](#specifying-the-lambda-handler) for additional information. |
6059

6160
### Hooks Usage Example
@@ -86,6 +85,62 @@ The `lambdaHandler` should be specified as a string in the format `<file>.<handl
8685

8786
One way to determine if the `lambdaHandler` option should be used is to check the handler defined on your Lambda. This can be done by determining the value of the `_HANDLER` environment variable or by viewing the **Runtime Settings** of your Lambda in AWS Console. If the handler is what you expect, then the instrumentation should work without the `lambdaHandler` option. If the handler points to something else, then the `lambdaHandler` option should be used to explicitly specify the handler that should be instrumented.
8887

88+
### Context Propagation
89+
90+
AWS Active Tracing can provide a parent context for the span generated by this instrumentation. Note that the span generated by Active Tracing is always reported only to AWS X-Ray. Therefore, if the OpenTelemetry SDK is configured to export traces to a backend other than AWS X-Ray, this will result in a broken trace.
91+
92+
If you use version `<=0.46.0` of this package, then the Active Tracing context is used as the parent context by default if present. In this case, in order to prevent broken traces, set the `disableAwsContextPropagation` option to `false`.
93+
Additional propagators can be added in the TracerProvider configuration.
94+
95+
If you use version `>0.46.0`, the Active Tracing context is no longer used by default. In order to enable it, include the [AWSXRayLambdaPropagator](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/propagators/propagator-aws-xray-lambda) propagator in the list of propagators provided to the TracerProvider via its configuration, or by including `xray-lambda` in the OTEL_PROPAGATORS environment variable (see the example below on using the env variable).
96+
97+
Note that there are two AWS-related propagators: [AWSXRayPropagator](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/propagators/propagator-aws-xray) and [AWSXRayLambdaPropagator](https://github.com/open-telemetry/opentelemetry-js-contrib/tree/main/propagators/propagator-aws-xray-lambda). Here is a guideline for when to use one or the other:
98+
99+
- If you export traces to AWS X-Ray, then use the `AWSXRayLambdaPropagator` or the `xray-lambda` value in the OTEL_PROPAGATORS environment variable. This will handle the active tracing lambda context as well as X-Ray HTTP headers.
100+
- If you export traces to a backend other than AWS X-Ray, then use the `AWSXrayPropagator` or `xray` in the environment variable. This propagator only handles the X-Ray HTTP headers.
101+
102+
Examples:
103+
104+
1. Active Tracing is enabled and the OpenTelemetry SDK is configured to export traces to AWS X-Ray. In this case, configure the SDK to use the `AWSXRayLambdaPropagator`.
105+
106+
```js
107+
const { NodeTracerProvider } = require('@opentelemetry/sdk-trace-node');
108+
const { AWSXRayLambdaPropagator } = require('@opentelemetry/propagator-aws-xray-lambda');
109+
110+
const provider = new NodeTracerProvider();
111+
provider.register({
112+
propagator: new AWSXRayLambdaPropagator()
113+
});
114+
```
115+
116+
Alternatively, use the `getPropagators()` function from the [auto-configuration-propagators](https://github.com/open-telemetry/opentelemetry-js-contrib/blob/main/metapackages/auto-configuration-propagators/README.md) package, and set the OTEL_PROPAGATORS environment variable to `xray-lambda`.
117+
118+
```js
119+
const { NodeTracerProvider } = require('@opentelemetry/sdk-trace-node');
120+
const { getPropagator } = require('@opentelemetry/auto-configuration-propagators');
121+
122+
const provider = new NodeTracerProvider();
123+
provider.register({
124+
propagator: getPropagator()
125+
});
126+
```
127+
128+
1. The OpenTelemetry SDK is configured to export traces to a backend other than AWX X-Ray, but the lambda function is invoked by other AWS services which send the context using the X-Ray HTTP headers. In this case, include the `AWSXRayPropagator`, which extracts context from the HTTP header but not the Lambda Active Tracing context.
129+
130+
```js
131+
const { NodeTracerProvider } = require('@opentelemetry/sdk-trace-node');
132+
const { AWSXRayLambdaPropagator } = require('@opentelemetry/propagator-aws-xray-lambda');
133+
134+
const provider = new NodeTracerProvider();
135+
provider.register({
136+
propagator: new AWSXRayPropagator()
137+
});
138+
```
139+
140+
Alternatively, use the `auto-configuration-package` as in example #1 and set the OTEL_PROPAGATORS environment variable to `xray`.
141+
142+
For additional information, see the [documentation for lambda semantic conventions](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/faas/aws-lambda.md#aws-x-ray-active-tracing-considerations).
143+
89144
## Semantic Conventions
90145

91146
This package uses `@opentelemetry/semantic-conventions` version `1.22+`, which implements Semantic Convention [Version 1.7.0](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.7.0/semantic_conventions/README.md)

plugins/node/opentelemetry-instrumentation-aws-lambda/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
"devDependencies": {
4646
"@opentelemetry/api": "^1.3.0",
4747
"@opentelemetry/core": "^1.8.0",
48+
"@opentelemetry/propagator-aws-xray": "^1.25.1",
49+
"@opentelemetry/propagator-aws-xray-lambda": "^0.52.1",
4850
"@opentelemetry/sdk-metrics": "^1.8.0",
4951
"@opentelemetry/sdk-trace-base": "^1.8.0",
5052
"@opentelemetry/sdk-trace-node": "^1.8.0",
@@ -56,7 +58,6 @@
5658
},
5759
"dependencies": {
5860
"@opentelemetry/instrumentation": "^0.54.0",
59-
"@opentelemetry/propagator-aws-xray": "^1.3.1",
6061
"@opentelemetry/semantic-conventions": "^1.27.0",
6162
"@types/aws-lambda": "8.10.143"
6263
},

plugins/node/opentelemetry-instrumentation-aws-lambda/src/instrumentation.ts

Lines changed: 1 addition & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,9 @@ import {
3535
SpanKind,
3636
SpanStatusCode,
3737
TextMapGetter,
38-
TraceFlags,
3938
TracerProvider,
4039
ROOT_CONTEXT,
4140
} from '@opentelemetry/api';
42-
import {
43-
AWSXRAY_TRACE_ID_HEADER,
44-
AWSXRayPropagator,
45-
} from '@opentelemetry/propagator-aws-xray';
4641
import {
4742
SEMATTRS_FAAS_EXECUTION,
4843
SEMRESATTRS_CLOUD_ACCOUNT_ID,
@@ -60,10 +55,8 @@ import {
6055
import { AwsLambdaInstrumentationConfig, EventContextExtractor } from './types';
6156
/** @knipignore */
6257
import { PACKAGE_NAME, PACKAGE_VERSION } from './version';
63-
import { env } from 'process';
6458
import { LambdaModule } from './internal-types';
6559

66-
const awsPropagator = new AWSXRayPropagator();
6760
const headerGetter: TextMapGetter<APIGatewayProxyEventHeaders> = {
6861
keys(carrier): string[] {
6962
return Object.keys(carrier);
@@ -73,26 +66,13 @@ const headerGetter: TextMapGetter<APIGatewayProxyEventHeaders> = {
7366
},
7467
};
7568

76-
export const traceContextEnvironmentKey = '_X_AMZN_TRACE_ID';
7769
export const lambdaMaxInitInMilliseconds = 10_000;
7870

7971
export class AwsLambdaInstrumentation extends InstrumentationBase<AwsLambdaInstrumentationConfig> {
8072
private _traceForceFlusher?: () => Promise<void>;
8173
private _metricForceFlusher?: () => Promise<void>;
8274

8375
constructor(config: AwsLambdaInstrumentationConfig = {}) {
84-
if (config.disableAwsContextPropagation == null) {
85-
if (
86-
typeof env['OTEL_LAMBDA_DISABLE_AWS_CONTEXT_PROPAGATION'] ===
87-
'string' &&
88-
env[
89-
'OTEL_LAMBDA_DISABLE_AWS_CONTEXT_PROPAGATION'
90-
].toLocaleLowerCase() === 'true'
91-
) {
92-
config = { ...config, disableAwsContextPropagation: true };
93-
}
94-
}
95-
9676
super(PACKAGE_NAME, PACKAGE_VERSION, config);
9777
}
9878

@@ -230,7 +210,6 @@ export class AwsLambdaInstrumentation extends InstrumentationBase<AwsLambdaInstr
230210
const parent = AwsLambdaInstrumentation._determineParent(
231211
event,
232212
context,
233-
config.disableAwsContextPropagation === true,
234213
config.eventContextExtractor ||
235214
AwsLambdaInstrumentation._defaultEventContextExtractor
236215
);
@@ -433,32 +412,8 @@ export class AwsLambdaInstrumentation extends InstrumentationBase<AwsLambdaInstr
433412
private static _determineParent(
434413
event: any,
435414
context: Context,
436-
disableAwsContextPropagation: boolean,
437415
eventContextExtractor: EventContextExtractor
438416
): OtelContext {
439-
let parent: OtelContext | undefined = undefined;
440-
if (!disableAwsContextPropagation) {
441-
const lambdaTraceHeader = process.env[traceContextEnvironmentKey];
442-
if (lambdaTraceHeader) {
443-
parent = awsPropagator.extract(
444-
otelContext.active(),
445-
{ [AWSXRAY_TRACE_ID_HEADER]: lambdaTraceHeader },
446-
headerGetter
447-
);
448-
}
449-
if (parent) {
450-
const spanContext = trace.getSpan(parent)?.spanContext();
451-
if (
452-
spanContext &&
453-
(spanContext.traceFlags & TraceFlags.SAMPLED) === TraceFlags.SAMPLED
454-
) {
455-
// Trace header provided by Lambda only sampled if a sampled context was propagated from
456-
// an upstream cloud service such as S3, or the user is using X-Ray. In these cases, we
457-
// need to use it as the parent.
458-
return parent;
459-
}
460-
}
461-
}
462417
const extractedContext = safeExecuteInTheMiddle(
463418
() => eventContextExtractor(event, context),
464419
e => {
@@ -473,10 +428,6 @@ export class AwsLambdaInstrumentation extends InstrumentationBase<AwsLambdaInstr
473428
if (trace.getSpan(extractedContext)?.spanContext()) {
474429
return extractedContext;
475430
}
476-
if (!parent) {
477-
// No context in Lambda environment or HTTP headers.
478-
return ROOT_CONTEXT;
479-
}
480-
return parent;
431+
return ROOT_CONTEXT;
481432
}
482433
}

plugins/node/opentelemetry-instrumentation-aws-lambda/src/types.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ export type EventContextExtractor = (
3838
export interface AwsLambdaInstrumentationConfig extends InstrumentationConfig {
3939
requestHook?: RequestHook;
4040
responseHook?: ResponseHook;
41-
disableAwsContextPropagation?: boolean;
4241
eventContextExtractor?: EventContextExtractor;
4342
lambdaHandler?: string;
4443
lambdaStartTime?: number;

0 commit comments

Comments
 (0)