2
2
// SPDX-License-Identifier: Apache-2.0
3
3
4
4
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' ;
6
6
import { OTLPMetricExporter as OTLPGrpcOTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-grpc' ;
7
7
import { OTLPMetricExporter as OTLPHttpOTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http' ;
8
8
import { OTLPTraceExporter as OTLPGrpcTraceExporter } from '@opentelemetry/exporter-trace-otlp-grpc' ;
@@ -63,6 +63,7 @@ import {
63
63
import { OTLPAwsLogExporter } from '../src/exporter/otlp/aws/logs/otlp-aws-log-exporter' ;
64
64
import { OTLPAwsSpanExporter } from '../src/exporter/otlp/aws/traces/otlp-aws-span-exporter' ;
65
65
import { AwsCloudWatchOtlpBatchLogRecordProcessor } from '../src/exporter/otlp/aws/logs/aws-cw-otlp-batch-log-record-processor' ;
66
+ import { TRACE_PARENT_HEADER } from '@opentelemetry/core' ;
66
67
67
68
// Tests AwsOpenTelemetryConfigurator after running Environment Variable setup in register.ts
68
69
describe ( 'AwsOpenTelemetryConfiguratorTest' , ( ) => {
@@ -90,6 +91,12 @@ describe('AwsOpenTelemetryConfiguratorTest', () => {
90
91
( awsOtelConfigurator as any ) . spanProcessors . forEach ( ( spanProcessor : SpanProcessor ) => {
91
92
spanProcessor . shutdown ( ) ;
92
93
} ) ;
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 ;
93
100
} ) ;
94
101
95
102
// The probability of this passing once without correct IDs is low, 20 times is inconceivable.
@@ -110,6 +117,152 @@ describe('AwsOpenTelemetryConfiguratorTest', () => {
110
117
}
111
118
} ) ;
112
119
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
+
113
266
// Sanity check that the trace ID ratio sampler works fine with the x-ray generator.
114
267
it ( 'TraceIdRatioSamplerTest' , ( ) => {
115
268
process . env . OTEL_AWS_APPLICATION_SIGNALS_ENABLED = 'True' ;
@@ -604,14 +757,14 @@ describe('AwsOpenTelemetryConfiguratorTest', () => {
604
757
605
758
function validateConfiguratorEnviron ( ) {
606
759
// 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' ) ;
609
762
610
763
// 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' ) ;
615
768
}
616
769
617
770
it ( 'OtelTracesSamplerInputValidationTest' , ( ) => {
0 commit comments