@@ -27,7 +27,8 @@ import {
2727 isValidTraceId ,
2828 INVALID_TRACEID ,
2929 INVALID_SPANID ,
30- INVALID_SPAN_CONTEXT ,
30+ propagation ,
31+ Baggage ,
3132} from '@opentelemetry/api' ;
3233
3334export const AWSXRAY_TRACE_ID_HEADER = 'x-amzn-trace-id' ;
@@ -49,6 +50,8 @@ const SAMPLED_FLAG_KEY = 'Sampled';
4950const IS_SAMPLED = '1' ;
5051const NOT_SAMPLED = '0' ;
5152
53+ const LINEAGE_KEY = "Lineage" ;
54+
5255/**
5356 * Implementation of the AWS X-Ray Trace Header propagation protocol. See <a href=
5457 * https://https://docs.aws.amazon.com/xray/latest/devguide/xray-concepts.html#xray-concepts-tracingheader>AWS
@@ -66,48 +69,73 @@ export class AWSXRayPropagator implements TextMapPropagator {
6669 const timestamp = otTraceId . substring ( 0 , TRACE_ID_FIRST_PART_LENGTH ) ;
6770 const randomNumber = otTraceId . substring ( TRACE_ID_FIRST_PART_LENGTH ) ;
6871
72+ const xrayTraceId = `${ TRACE_ID_VERSION } ${ TRACE_ID_DELIMITER } ${ timestamp } ${ TRACE_ID_DELIMITER } ${ randomNumber } ` ;
73+
6974 const parentId = spanContext . spanId ;
7075 const samplingFlag =
7176 ( TraceFlags . SAMPLED & spanContext . traceFlags ) === TraceFlags . SAMPLED
7277 ? IS_SAMPLED
7378 : NOT_SAMPLED ;
7479 // TODO: Add OT trace state to the X-Ray trace header
7580
76- const traceHeader = `Root=1-${ timestamp } -${ randomNumber } ;Parent=${ parentId } ;Sampled=${ samplingFlag } ` ;
81+ let traceHeader =
82+ `${ TRACE_ID_KEY } ` +
83+ `${ KV_DELIMITER } ` +
84+ `${ xrayTraceId } ` +
85+ `${ TRACE_HEADER_DELIMITER } ` +
86+ `${ PARENT_ID_KEY } ` +
87+ `${ KV_DELIMITER } ` +
88+ `${ parentId } ` +
89+ `${ TRACE_HEADER_DELIMITER } ` +
90+ `${ SAMPLED_FLAG_KEY } ` +
91+ `${ KV_DELIMITER } ` +
92+ `${ samplingFlag } ` ;
93+
94+ const baggage = propagation . getBaggage ( context ) ;
95+ const lineageV2Header = baggage ?. getEntry ( LINEAGE_KEY ) ?. value ;
96+
97+ if ( lineageV2Header ) {
98+ traceHeader +=
99+ `${ TRACE_HEADER_DELIMITER } ` +
100+ `${ LINEAGE_KEY } ` +
101+ `${ KV_DELIMITER } ` +
102+ `${ lineageV2Header } ` ;
103+ }
104+
77105 setter . set ( carrier , AWSXRAY_TRACE_ID_HEADER , traceHeader ) ;
78106 }
79107
80108 extract ( context : Context , carrier : unknown , getter : TextMapGetter ) : Context {
81- const spanContext = this . getSpanContextFromHeader ( carrier , getter ) ;
82- if ( ! isSpanContextValid ( spanContext ) ) return context ;
83-
84- return trace . setSpan ( context , trace . wrapSpanContext ( spanContext ) ) ;
109+ return this . getContextFromHeader ( context , carrier , getter ) ;
85110 }
86111
87112 fields ( ) : string [ ] {
88113 return [ AWSXRAY_TRACE_ID_HEADER ] ;
89114 }
90115
91- private getSpanContextFromHeader (
116+ private getContextFromHeader (
117+ context : Context ,
92118 carrier : unknown ,
93119 getter : TextMapGetter
94- ) : SpanContext {
120+ ) : Context {
95121 const headerKeys = getter . keys ( carrier ) ;
96122 const relevantHeaderKey = headerKeys . find ( e => {
97123 return e . toLowerCase ( ) === AWSXRAY_TRACE_ID_HEADER ;
98124 } ) ;
99125 if ( ! relevantHeaderKey ) {
100- return INVALID_SPAN_CONTEXT ;
126+ return context ;
101127 }
102128 const rawTraceHeader = getter . get ( carrier , relevantHeaderKey ) ;
103129 const traceHeader = Array . isArray ( rawTraceHeader )
104130 ? rawTraceHeader [ 0 ]
105131 : rawTraceHeader ;
106132
107133 if ( ! traceHeader || typeof traceHeader !== 'string' ) {
108- return INVALID_SPAN_CONTEXT ;
134+ return context ;
109135 }
110136
137+ let baggage : Baggage = propagation . getBaggage ( context ) || propagation . createBaggage ( ) ;
138+
111139 let pos = 0 ;
112140 let trimmedPart : string ;
113141 let parsedTraceId = INVALID_TRACEID ;
@@ -133,21 +161,27 @@ export class AWSXRayPropagator implements TextMapPropagator {
133161 parsedSpanId = AWSXRayPropagator . _parseSpanId ( value ) ;
134162 } else if ( trimmedPart . startsWith ( SAMPLED_FLAG_KEY ) ) {
135163 parsedTraceFlags = AWSXRayPropagator . _parseTraceFlag ( value ) ;
164+ } else if ( trimmedPart . startsWith ( LINEAGE_KEY ) ) {
165+ baggage = baggage . setEntry ( LINEAGE_KEY , { value} ) ;
136166 }
137167 }
138168 if ( parsedTraceFlags === null ) {
139- return INVALID_SPAN_CONTEXT ;
169+ return context ;
140170 }
141171 const resultSpanContext : SpanContext = {
142172 traceId : parsedTraceId ,
143173 spanId : parsedSpanId ,
144174 traceFlags : parsedTraceFlags ,
145175 isRemote : true ,
146176 } ;
147- if ( ! isSpanContextValid ( resultSpanContext ) ) {
148- return INVALID_SPAN_CONTEXT ;
177+ if ( isSpanContextValid ( resultSpanContext ) ) {
178+ context = trace . setSpan ( context , trace . wrapSpanContext ( resultSpanContext ) ) ;
149179 }
150- return resultSpanContext ;
180+ if ( baggage . getAllEntries ( ) . length > 0 ) {
181+ context = propagation . setBaggage ( context , baggage ) ;
182+ }
183+
184+ return context ;
151185 }
152186
153187 private static _parseTraceId ( xrayTraceId : string ) : string {
0 commit comments