Skip to content

Commit e5b50a9

Browse files
authored
Update default OTEL_PROPAGATORS setting to be 'baggage,xray,tracecontext' (#210)
*Issue #, if available:* *Description of changes:* - Update default `OTEL_PROPAGATORS` setting to be `'baggage,xray,tracecontext'` By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.
1 parent 9b0a538 commit e5b50a9

File tree

5 files changed

+167
-12
lines changed

5 files changed

+167
-12
lines changed

aws-distro-opentelemetry-node-autoinstrumentation/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,6 @@ export OTEL_TRACES_SAMPLER_ARG=endpoint=http://localhost:2000,polling_interval=3
3030
| Environment Variable | Description | Example |
3131
| -------------------- | ----------- | ------- |
3232
| `OTEL_EXPORTER_OTLP_PROTOCOL` | Leave unset so that ADOT JS will use a recommended OTLP protocol | `http/protobuf` |
33-
| `OTEL_PROPAGATORS` | Leave unset so that ADOT JS will use a recommended list of propagators | `xray,tracecontext,b3,b3multi` |
33+
| `OTEL_PROPAGATORS` | Leave unset so that ADOT JS will use a recommended list of propagators | `baggage,xray,tracecontext` |
3434
| `OTEL_NODE_DISABLED_INSTRUMENTATIONS` | Leave unset so that ADOT JS will disable a recommended list of instrumentations | `fs,dns` |
3535
| `OTEL_NODE_RESOURCE_DETECTORS` | Leave unset so that ADOT JS will use a recommended list of Resource Detectors. If set, `env` should be at the end of the list | `aws,env` |

aws-distro-opentelemetry-node-autoinstrumentation/src/register.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ export function setAwsDefaultEnvironmentVariables() {
4242
process.env.OTEL_EXPORTER_OTLP_PROTOCOL = 'http/protobuf';
4343
}
4444
if (!process.env.OTEL_PROPAGATORS) {
45-
process.env.OTEL_PROPAGATORS = 'xray,tracecontext';
45+
// Propagators are run in the order they are configured.
46+
// xray is set after baggage in case xray propagator depends on the result of the baggage header extraction.
47+
process.env.OTEL_PROPAGATORS = 'baggage,xray,tracecontext';
4648
}
4749
if (!process.env.OTEL_NODE_DISABLED_INSTRUMENTATIONS) {
4850
if (isAgentObservabilityEnabled()) {

aws-distro-opentelemetry-node-autoinstrumentation/test/aws-opentelemetry-configurator.test.ts

Lines changed: 160 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// SPDX-License-Identifier: Apache-2.0
33

44
import { AWSCloudWatchEMFExporter } from '../src/exporter/aws/metrics/aws-cloudwatch-emf-exporter';
5-
import { Span, TraceFlags, Tracer } from '@opentelemetry/api';
5+
import { propagation, ROOT_CONTEXT, Span, TextMapGetter, trace, TraceFlags, Tracer } from '@opentelemetry/api';
66
import { OTLPMetricExporter as OTLPGrpcOTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-grpc';
77
import { OTLPMetricExporter as OTLPHttpOTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http';
88
import { OTLPTraceExporter as OTLPGrpcTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc';
@@ -63,6 +63,7 @@ import {
6363
import { OTLPAwsLogExporter } from '../src/exporter/otlp/aws/logs/otlp-aws-log-exporter';
6464
import { OTLPAwsSpanExporter } from '../src/exporter/otlp/aws/traces/otlp-aws-span-exporter';
6565
import { AwsCloudWatchOtlpBatchLogRecordProcessor } from '../src/exporter/otlp/aws/logs/aws-cw-otlp-batch-log-record-processor';
66+
import { TRACE_PARENT_HEADER } from '@opentelemetry/core';
6667

6768
// Tests AwsOpenTelemetryConfigurator after running Environment Variable setup in register.ts
6869
describe('AwsOpenTelemetryConfiguratorTest', () => {
@@ -90,6 +91,12 @@ describe('AwsOpenTelemetryConfiguratorTest', () => {
9091
(awsOtelConfigurator as any).spanProcessors.forEach((spanProcessor: SpanProcessor) => {
9192
spanProcessor.shutdown();
9293
});
94+
95+
delete process.env.OTEL_TRACES_EXPORTER;
96+
delete process.env.OTEL_METRICS_EXPORTER;
97+
delete process.env.OTEL_LOGS_EXPORTER;
98+
delete process.env.OTEL_TRACES_SAMPLER;
99+
delete process.env.OTEL_TRACES_SAMPLER_ARG;
93100
});
94101

95102
// The probability of this passing once without correct IDs is low, 20 times is inconceivable.
@@ -110,6 +117,152 @@ describe('AwsOpenTelemetryConfiguratorTest', () => {
110117
}
111118
});
112119

120+
describe('Propagator Extraction', () => {
121+
const envVarsToRestore: NodeJS.ProcessEnv = {};
122+
beforeEach(() => {
123+
for (const [key, value] of Object.entries(process.env)) {
124+
if (key.startsWith('OTEL_')) {
125+
envVarsToRestore[key] = value;
126+
delete process.env[key];
127+
}
128+
}
129+
});
130+
131+
afterEach(() => {
132+
// Clean-up
133+
for (const [key, value] of Object.entries(envVarsToRestore)) {
134+
process.env[key] = value;
135+
}
136+
});
137+
138+
it('Default Propagator extraction of Trace Context works if only X-Ray Trace Header is set', () => {
139+
const carrier: Record<string, string> = {
140+
'X-Amzn-Trace-Id':
141+
'Root=1-5759e988-bd862e3fe1bf46a994270000;Parent=53945c3f42cd0000;Sampled=1;Lineage=a87bd80c:1|68fd508a:5|c512fbe3:2',
142+
};
143+
const textMapGetter: TextMapGetter = {
144+
keys: (carrier: Record<string, string>): string[] => {
145+
return Object.keys(carrier);
146+
},
147+
get: (carrier: Record<string, string>, key: string) => {
148+
return carrier?.[key];
149+
},
150+
};
151+
152+
// Create configurator with default settings and AgentObservability enabled for this test case
153+
setAwsDefaultEnvironmentVariables();
154+
const customAwsOtelConfigurator = new AwsOpentelemetryConfigurator([]);
155+
const customAwsOtelConfiguration = customAwsOtelConfigurator.configure();
156+
157+
const tracerProvider: NodeTracerProvider = new NodeTracerProvider(customAwsOtelConfiguration);
158+
const tracer: Tracer = tracerProvider.getTracer('test');
159+
160+
const contextAfterExtraction = customAwsOtelConfiguration.textMapPropagator?.extract(
161+
ROOT_CONTEXT,
162+
carrier,
163+
textMapGetter
164+
);
165+
166+
// Test Trace Context extraction directly
167+
const spanContextAfterExtraction = trace.getSpanContext(contextAfterExtraction!);
168+
expect(spanContextAfterExtraction?.traceId).toEqual('5759e988bd862e3fe1bf46a994270000');
169+
expect(spanContextAfterExtraction?.spanId).toEqual('53945c3f42cd0000');
170+
expect(spanContextAfterExtraction?.traceFlags).toEqual(1);
171+
172+
// Test Trace Context extraction indirectly through span creation
173+
const span: Span = tracer.startSpan('test', undefined, contextAfterExtraction);
174+
span.end();
175+
const spanContext = span.spanContext();
176+
177+
expect(spanContext.traceId).toEqual('5759e988bd862e3fe1bf46a994270000');
178+
expect((span as any).parentSpanId).toEqual('53945c3f42cd0000');
179+
expect(spanContext.traceFlags).toEqual(1);
180+
});
181+
182+
it('Default Propagator extraction of Trace Context prioritizes W3C Trace Header over X-Ray Trace Header for span context if they mismatch', () => {
183+
const carrier: Record<string, string> = {
184+
'X-Amzn-Trace-Id':
185+
'Root=1-5759e988-bd862e3fe1bf46a994270000;Parent=53945c3f42cd0000;Sampled=0;Lineage=a87bd80c:1|68fd508a:5|c512fbe3:2',
186+
[TRACE_PARENT_HEADER]: '00-11111111222222223333333344444444-5555555566666666-01',
187+
};
188+
const textMapGetter: TextMapGetter = {
189+
keys: (carrier: Record<string, string>): string[] => {
190+
return Object.keys(carrier);
191+
},
192+
get: (carrier: Record<string, string>, key: string) => {
193+
return carrier?.[key];
194+
},
195+
};
196+
197+
// Create configurator with default settings and AgentObservability enabled for this test case
198+
setAwsDefaultEnvironmentVariables();
199+
const customAwsOtelConfigurator = new AwsOpentelemetryConfigurator([]);
200+
const customAwsOtelConfiguration = customAwsOtelConfigurator.configure();
201+
202+
const tracerProvider: NodeTracerProvider = new NodeTracerProvider(customAwsOtelConfiguration);
203+
const tracer: Tracer = tracerProvider.getTracer('test');
204+
205+
const contextAfterExtraction = customAwsOtelConfiguration.textMapPropagator?.extract(
206+
ROOT_CONTEXT,
207+
carrier,
208+
textMapGetter
209+
);
210+
211+
// Test Trace Context extraction directly
212+
const spanContextAfterExtraction = trace.getSpanContext(contextAfterExtraction!);
213+
expect(spanContextAfterExtraction?.traceId).toEqual('11111111222222223333333344444444');
214+
expect(spanContextAfterExtraction?.spanId).toEqual('5555555566666666');
215+
expect(spanContextAfterExtraction?.traceFlags).toEqual(1);
216+
217+
// Test Trace Context extraction indirectly through span creation
218+
const span: Span = tracer.startSpan('test', undefined, contextAfterExtraction);
219+
span.end();
220+
const spanContext = span.spanContext();
221+
222+
expect(spanContext.traceId).toEqual('11111111222222223333333344444444');
223+
expect((span as any).parentSpanId).toEqual('5555555566666666');
224+
expect(spanContext.traceFlags).toEqual(1);
225+
});
226+
227+
it('Propagator extracts session.id baggage header attribute into to span attributes when Agent Observability is enabled', () => {
228+
// Create configurator with default settings and AgentObservability enabled for this test case
229+
setAwsDefaultEnvironmentVariables();
230+
process.env.AGENT_OBSERVABILITY_ENABLED = 'true';
231+
const customAwsOtelConfigurator = new AwsOpentelemetryConfigurator([]);
232+
const customAwsOtelConfiguration = customAwsOtelConfigurator.configure();
233+
234+
const tracerProvider: NodeTracerProvider = new NodeTracerProvider(customAwsOtelConfiguration);
235+
const tracer: Tracer = tracerProvider.getTracer('test');
236+
237+
const carrier: Record<string, string> = {
238+
baggage: 'session.id=test-adot-js-dev',
239+
};
240+
const textMapGetter: TextMapGetter = {
241+
keys: (carrier: Record<string, string>): string[] => {
242+
return Object.keys(carrier);
243+
},
244+
get: (carrier: Record<string, string>, key: string) => {
245+
return carrier?.[key];
246+
},
247+
};
248+
const contextAfterExtraction = customAwsOtelConfiguration.textMapPropagator?.extract(
249+
ROOT_CONTEXT,
250+
carrier,
251+
textMapGetter
252+
);
253+
254+
// Test baggage is set directly
255+
const baggageAfterExtraction = propagation.getBaggage(contextAfterExtraction!);
256+
expect(baggageAfterExtraction?.getAllEntries().length).toEqual(1);
257+
expect(baggageAfterExtraction?.getEntry('session.id')?.value).toEqual('test-adot-js-dev');
258+
259+
// Test baggage is set indirectly through span creation
260+
const span: Span = tracer.startSpan('test', undefined, contextAfterExtraction);
261+
span.end();
262+
expect((span as any).attributes['session.id']).toEqual('test-adot-js-dev');
263+
});
264+
});
265+
113266
// Sanity check that the trace ID ratio sampler works fine with the x-ray generator.
114267
it('TraceIdRatioSamplerTest', () => {
115268
process.env.OTEL_AWS_APPLICATION_SIGNALS_ENABLED = 'True';
@@ -604,14 +757,14 @@ describe('AwsOpenTelemetryConfiguratorTest', () => {
604757

605758
function validateConfiguratorEnviron() {
606759
// Set by register.ts
607-
expect('http/protobuf').toEqual(process.env.OTEL_EXPORTER_OTLP_PROTOCOL);
608-
expect('xray,tracecontext').toEqual(process.env.OTEL_PROPAGATORS);
760+
expect(process.env).toHaveProperty('OTEL_EXPORTER_OTLP_PROTOCOL', 'http/protobuf');
761+
expect(process.env).toHaveProperty('OTEL_PROPAGATORS', 'baggage,xray,tracecontext');
609762

610763
// Not set
611-
expect(undefined).toEqual(process.env.OTEL_TRACES_SAMPLER);
612-
expect(undefined).toEqual(process.env.OTEL_TRACES_SAMPLER_ARG);
613-
expect(undefined).toEqual(process.env.OTEL_TRACES_EXPORTER);
614-
expect(undefined).toEqual(process.env.OTEL_METRICS_EXPORTER);
764+
expect(process.env).not.toHaveProperty('OTEL_TRACES_SAMPLER');
765+
expect(process.env).not.toHaveProperty('OTEL_TRACES_SAMPLER_ARG');
766+
expect(process.env).not.toHaveProperty('OTEL_TRACES_EXPORTER');
767+
expect(process.env).not.toHaveProperty('OTEL_METRICS_EXPORTER');
615768
}
616769

617770
it('OtelTracesSamplerInputValidationTest', () => {

aws-distro-opentelemetry-node-autoinstrumentation/test/register.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ describe('Register', function () {
4646
it('sets AWS Default Environment Variables', () => {
4747
setAwsDefaultEnvironmentVariables();
4848
expect(process.env.OTEL_EXPORTER_OTLP_PROTOCOL).toEqual('http/protobuf');
49-
expect(process.env.OTEL_PROPAGATORS).toEqual('xray,tracecontext');
49+
expect(process.env.OTEL_PROPAGATORS).toEqual('baggage,xray,tracecontext');
5050
expect(process.env.OTEL_NODE_DISABLED_INSTRUMENTATIONS).toEqual('fs,dns');
5151
});
5252

@@ -167,7 +167,7 @@ describe('Register', function () {
167167

168168
assert.ok(proc.stdout.includes('AWS Distro of OpenTelemetry automatic instrumentation started successfully'));
169169
assert.ok(proc.stdout.includes("Environment variable OTEL_EXPORTER_OTLP_PROTOCOL is set to 'http/protobuf'"));
170-
assert.ok(proc.stdout.includes("Environment variable OTEL_PROPAGATORS is set to 'xray,tracecontext'"));
170+
assert.ok(proc.stdout.includes("Environment variable OTEL_PROPAGATORS is set to 'baggage,xray,tracecontext'"));
171171

172172
// Check a span has been generated for the GET request done in app.js
173173
assert.ok(proc.stdout.includes("name: 'GET'"), 'console span output in stdout - validate Span Name');

lambda-layer/packages/layer/scripts/otel-instrument

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ fi
6868

6969
# - Set the propagators
7070
if [[ -z "$OTEL_PROPAGATORS" ]]; then
71-
export OTEL_PROPAGATORS="xray,tracecontext,baggage"
71+
export OTEL_PROPAGATORS="baggage,xray,tracecontext"
7272
fi
7373

7474
# - Set Application Signals configuration

0 commit comments

Comments
 (0)