Skip to content

Commit 57cd256

Browse files
dougqhclaude
andcommitted
Reuse trace context parsing on the span link path
When a trace context's trace id doesn't match, build it from the interpreter the merge already ran instead of interpreting its headers again, and reuse the propagation tags parse result rather than allocating one per tracestate. Also drop a duplicate empty check and a pass-through overload. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 427a607 commit 57cd256

5 files changed

Lines changed: 26 additions & 13 deletions

File tree

‎dd-trace-core/src/main/java/datadog/trace/core/propagation/HttpCodec.java‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -223,11 +223,13 @@ public <C> TagContext extract(
223223
ExtractionCache<C> extractionCache = new ExtractionCache<>(carrier, getter);
224224

225225
for (final Extractor extractor : this.extractors) {
226+
TagContext extracted;
226227
if (context != null && extractor instanceof W3CHttpCodec.TraceContextExtractor) {
227228
// Merging a trace context only needs a few of its parts, so skip building it whole
229+
W3CHttpCodec.TraceContextExtractor traceContextExtractor =
230+
(W3CHttpCodec.TraceContextExtractor) extractor;
228231
W3CHttpCodec.TraceContextMerge merge =
229-
((W3CHttpCodec.TraceContextExtractor) extractor)
230-
.extractForMerge(extractionCache, extractionCache);
232+
traceContextExtractor.extractForMerge(extractionCache, extractionCache);
231233
if (merge == null) {
232234
continue;
233235
}
@@ -236,8 +238,10 @@ public <C> TagContext extract(
236238
continue;
237239
}
238240
// A mismatched trace context becomes a span link, which needs all of it
241+
extracted = traceContextExtractor.completeExtraction();
242+
} else {
243+
extracted = extractor.extract(extractionCache, extractionCache);
239244
}
240-
TagContext extracted = extractor.extract(extractionCache, extractionCache);
241245
// Check if context is valid
242246
if (extracted instanceof ExtractedContext) {
243247
ExtractedContext extractedContext = (ExtractedContext) extracted;

‎dd-trace-core/src/main/java/datadog/trace/core/propagation/TagContextExtractor.java‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ public <C> TagContext extract(final C carrier, final AgentPropagation.ContextVis
2121
return interpret(carrier, getter).build();
2222
}
2323

24+
/** This thread's interpreter, as the last {@link #interpret} left it. */
25+
protected final ContextInterpreter interpreter() {
26+
return this.ctxInterpreter.get();
27+
}
28+
2429
/** Runs this thread's interpreter over the carrier, ready to build. */
2530
protected final <C> ContextInterpreter interpret(
2631
final C carrier, final AgentPropagation.ContextVisitor<C> getter) {

‎dd-trace-core/src/main/java/datadog/trace/core/propagation/W3CHttpCodec.java‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,11 @@ <C> TraceContextMerge extractForMerge(
164164
final C carrier, final AgentPropagation.ContextVisitor<C> getter) {
165165
return ((W3CContextInterpreter) interpret(carrier, getter)).buildForMerge();
166166
}
167+
168+
/** Builds the whole context that {@link #extractForMerge} last returned the merge parts of. */
169+
TagContext completeExtraction() {
170+
return interpreter().build();
171+
}
167172
}
168173

169174
private static class W3CContextInterpreter extends ContextInterpreter {

‎dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/W3CPTagsCodec.java‎

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,16 @@ public class W3CPTagsCodec extends PTagsCodec {
3333
private static final int MAX_ALLOWED_CHAR = 126;
3434
@VisibleForTesting public static final int MAX_MEMBER_COUNT = 32;
3535

36+
/** Reused across parses; the codec belongs to one factory, so this is set once. */
37+
private volatile PTagsResult ptagsResult;
38+
3639
@Override
3740
PropagationTags fromHeaderValue(PTagsFactory tagsFactory, String value) {
38-
return parse(value, new PTagsResult(tagsFactory));
41+
PTagsResult result = ptagsResult;
42+
if (result == null || result.tagsFactory != tagsFactory) {
43+
ptagsResult = result = new PTagsResult(tagsFactory);
44+
}
45+
return parse(value, result);
3946
}
4047

4148
/**
@@ -1152,12 +1159,7 @@ public W3CTracestate parsed(
11521159

11531160
/** Creates tags that preserve unmanaged W3C tracestate members without sampling state. */
11541161
static W3CPTags empty(PTagsFactory factory, String original) {
1155-
return empty(factory, original, null);
1156-
}
1157-
1158-
private static W3CPTags empty(
1159-
PTagsFactory factory, String original, OtelTraceState otelTraceState) {
1160-
return empty(factory, original, 0, -1, -1, otelTraceState);
1162+
return empty(factory, original, 0, -1, -1, null);
11611163
}
11621164

11631165
private static W3CPTags empty(

‎dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/W3CTracestate.java‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,6 @@ public final class W3CTracestate {
3131

3232
/** Parses a {@code tracestate} header value, which may be null. */
3333
public static W3CTracestate parse(String value) {
34-
if (value == null || value.isEmpty()) {
35-
return NONE;
36-
}
3734
return W3CPTagsCodec.parseForMerge(value);
3835
}
3936

0 commit comments

Comments
 (0)