Skip to content

Commit 4b78889

Browse files
committed
add lineage to trace header injection and baggage
1 parent 3dfc7e3 commit 4b78889

File tree

1 file changed

+48
-14
lines changed

1 file changed

+48
-14
lines changed

propagators/propagator-aws-xray/src/AWSXRayPropagator.ts

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -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

3334
export const AWSXRAY_TRACE_ID_HEADER = 'x-amzn-trace-id';
@@ -49,6 +50,8 @@ const SAMPLED_FLAG_KEY = 'Sampled';
4950
const IS_SAMPLED = '1';
5051
const 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

Comments
 (0)