From c71c5adc15deedd3c5825d42967997341d2c6194 Mon Sep 17 00:00:00 2001 From: Bruce Bujon Date: Fri, 5 Jun 2026 10:28:11 +0200 Subject: [PATCH 1/8] fix(core): Manually cleaning up AI code --- .../trace/core/propagation/B3HttpCodec.java | 8 +- .../core/propagation/B3HttpExtractorTest.java | 78 ++++--- .../propagation/B3HttpInjectorPaddedTest.java | 8 - .../core/propagation/B3HttpInjectorTest.java | 177 +++++++------- .../propagation/DatadogHttpExtractorTest.java | 176 +++++++------- .../propagation/DatadogHttpInjectorTest.java | 218 ++++++++---------- .../DatadogPropagationTagsTest.java | 4 +- .../core/propagation/HttpInjectorTest.java | 4 +- .../propagation/NoneHttpExtractorTest.java | 2 +- .../propagation/W3CHttpExtractorTest.java | 4 +- .../core/propagation/W3CHttpInjectorTest.java | 2 +- .../propagation/W3CPropagationTagsTest.java | 4 +- .../propagation/XRayHttpExtractorTest.java | 2 +- .../propagation/XRayHttpInjectorTest.java | 2 +- .../core/propagation/ptags/TagKeyTest.java | 18 +- .../core/propagation/ptags/TagValueTest.java | 18 +- .../java/datadog/opentracing/OT31ApiTest.java | 6 +- .../java/datadog/opentracing/OT33ApiTest.java | 6 +- .../utils/config/WithConfigExtension.java | 1 + 19 files changed, 372 insertions(+), 366 deletions(-) delete mode 100644 dd-trace-core/src/test/java/datadog/trace/core/propagation/B3HttpInjectorPaddedTest.java diff --git a/dd-trace-core/src/main/java/datadog/trace/core/propagation/B3HttpCodec.java b/dd-trace-core/src/main/java/datadog/trace/core/propagation/B3HttpCodec.java index 493faca96bc..9a4dda687c1 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/propagation/B3HttpCodec.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/propagation/B3HttpCodec.java @@ -25,15 +25,15 @@ class B3HttpCodec { private static final Logger log = LoggerFactory.getLogger(B3HttpCodec.class); - private static final String B3_TRACE_ID = "b3.traceid"; - private static final String B3_SPAN_ID = "b3.spanid"; + static final String B3_TRACE_ID = "b3.traceid"; + static final String B3_SPAN_ID = "b3.spanid"; static final String TRACE_ID_KEY = "X-B3-TraceId"; static final String SPAN_ID_KEY = "X-B3-SpanId"; static final String SAMPLING_PRIORITY_KEY = "X-B3-Sampled"; // See https://github.com/openzipkin/b3-propagation#single-header for b3 header documentation static final String B3_KEY = "b3"; - private static final String SAMPLING_PRIORITY_ACCEPT = String.valueOf(1); - private static final String SAMPLING_PRIORITY_DROP = String.valueOf(0); + static final String SAMPLING_PRIORITY_ACCEPT = String.valueOf(1); + static final String SAMPLING_PRIORITY_DROP = String.valueOf(0); private B3HttpCodec() { // This class should not be created. This also makes code coverage checks happy. diff --git a/dd-trace-core/src/test/java/datadog/trace/core/propagation/B3HttpExtractorTest.java b/dd-trace-core/src/test/java/datadog/trace/core/propagation/B3HttpExtractorTest.java index ec939528bbd..57cafd002a1 100644 --- a/dd-trace-core/src/test/java/datadog/trace/core/propagation/B3HttpExtractorTest.java +++ b/dd-trace-core/src/test/java/datadog/trace/core/propagation/B3HttpExtractorTest.java @@ -1,7 +1,11 @@ package datadog.trace.core.propagation; +import static datadog.trace.bootstrap.ActiveSubsystems.APPSEC_ACTIVE; import static datadog.trace.bootstrap.instrumentation.api.ContextVisitors.stringValuesMap; import static datadog.trace.core.propagation.B3HttpCodec.B3_KEY; +import static datadog.trace.core.propagation.B3HttpCodec.B3_SPAN_ID; +import static datadog.trace.core.propagation.B3HttpCodec.B3_TRACE_ID; +import static datadog.trace.core.propagation.B3HttpCodec.SAMPLING_PRIORITY_ACCEPT; import static datadog.trace.core.propagation.B3HttpCodec.SAMPLING_PRIORITY_KEY; import static datadog.trace.core.propagation.B3HttpCodec.SPAN_ID_KEY; import static datadog.trace.core.propagation.B3HttpCodec.TRACE_ID_KEY; @@ -12,18 +16,15 @@ import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; import datadog.trace.api.Config; import datadog.trace.api.DDSpanId; import datadog.trace.api.DynamicConfig; -import datadog.trace.bootstrap.ActiveSubsystems; import datadog.trace.bootstrap.instrumentation.api.TagContext; import datadog.trace.junit.utils.config.WithConfig; import datadog.trace.junit.utils.tabletest.PrioritySamplingConverter; import datadog.trace.test.util.DDJavaSpecification; import java.util.HashMap; -import java.util.LinkedHashMap; import java.util.Map; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -33,7 +34,6 @@ @WithConfig(key = "propagation.extract.log_header_names.enabled", value = "true") class B3HttpExtractorTest extends DDJavaSpecification { - private static final String SOME_HEADER = "SOME_HEADER"; private static final String SOME_TAG = "some-tag"; private static final String SOME_VALUE = "my-interesting-info"; @@ -50,14 +50,14 @@ void setup() { .setHeaderTags(singletonMap(SOME_HEADER, SOME_TAG)) .setBaggageMapping(emptyMap()) .apply(); - extractor = B3HttpCodec.newExtractor(Config.get(), dynamicConfig::captureTraceConfig); - origAppSecActive = ActiveSubsystems.APPSEC_ACTIVE; - ActiveSubsystems.APPSEC_ACTIVE = true; + this.extractor = B3HttpCodec.newExtractor(Config.get(), dynamicConfig::captureTraceConfig); + this.origAppSecActive = APPSEC_ACTIVE; + APPSEC_ACTIVE = true; } @AfterEach void teardown() { - ActiveSubsystems.APPSEC_ACTIVE = origAppSecActive; + APPSEC_ACTIVE = this.origAppSecActive; } @TableTest({ @@ -72,8 +72,8 @@ void extractHttpHeaders( String traceIdHex, String spanIdHex, Integer samplingPriority, - @ConvertWith(PrioritySamplingConverter.class) int expectedSamplingPriority) { - Map headers = new LinkedHashMap<>(); + @ConvertWith(PrioritySamplingConverter.class) byte expectedSamplingPriority) { + Map headers = new HashMap<>(); headers.put("", "empty key"); headers.put(TRACE_ID_KEY.toUpperCase(), traceIdHex); headers.put(SPAN_ID_KEY.toUpperCase(), spanIdHex); @@ -103,18 +103,19 @@ void extractHttpHeadersWithB3HeaderAtTheBeginning( String b3, String expectedTraceIdHex, long expectedSpanId, - @ConvertWith(PrioritySamplingConverter.class) int expectedSamplingPriority) { + @ConvertWith(PrioritySamplingConverter.class) byte expectedSamplingPriority) { String traceIdHex = "1"; String spanIdHex = "2"; - Map headers = new LinkedHashMap<>(); + Map headers = new HashMap<>(); headers.put("", "empty key"); headers.put(B3_KEY, b3); headers.put(TRACE_ID_KEY.toUpperCase(), traceIdHex); headers.put(SPAN_ID_KEY.toUpperCase(), spanIdHex); headers.put(SOME_HEADER, SOME_VALUE); - headers.put(SAMPLING_PRIORITY_KEY, "1"); + headers.put(SAMPLING_PRIORITY_KEY, SAMPLING_PRIORITY_ACCEPT); - ExtractedContext context = (ExtractedContext) extractor.extract(headers, stringValuesMap()); + ExtractedContext context = + (ExtractedContext) this.extractor.extract(headers, stringValuesMap()); assertB3MultiOrSingleContext( context, expectedTraceIdHex, expectedSpanId, expectedSamplingPriority); @@ -131,18 +132,18 @@ void extractHttpHeadersWithB3HeaderAtTheEnd( String b3, String expectedTraceIdHex, long expectedSpanId, - @ConvertWith(PrioritySamplingConverter.class) int expectedSamplingPriority) { + @ConvertWith(PrioritySamplingConverter.class) byte expectedSamplingPriority) { String traceIdHex = "1"; String spanIdHex = "2"; - Map headers = new LinkedHashMap<>(); + Map headers = new HashMap<>(); headers.put("", "empty key"); headers.put(TRACE_ID_KEY.toUpperCase(), traceIdHex); headers.put(SPAN_ID_KEY.toUpperCase(), spanIdHex); headers.put(B3_KEY, b3); headers.put(SOME_HEADER, SOME_VALUE); - headers.put(SAMPLING_PRIORITY_KEY, "1"); + headers.put(SAMPLING_PRIORITY_KEY, SAMPLING_PRIORITY_ACCEPT); - TagContext context = extractor.extract(headers, stringValuesMap()); + TagContext context = this.extractor.extract(headers, stringValuesMap()); assertB3MultiOrSingleContext( context, expectedTraceIdHex, expectedSpanId, expectedSamplingPriority); @@ -163,8 +164,8 @@ private void assertB3MultiOrSingleContext( private Map expectedB3Tags(TagContext context) { Map expected = new HashMap<>(); - expected.put("b3.traceid", ((B3TraceId) context.getTraceId()).getOriginal()); - expected.put("b3.spanid", DDSpanId.toHexString(context.getSpanId())); + expected.put(B3_TRACE_ID, ((B3TraceId) context.getTraceId()).getOriginal()); + expected.put(B3_SPAN_ID, DDSpanId.toHexString(context.getSpanId())); expected.put(SOME_TAG, SOME_VALUE); return expected; } @@ -186,11 +187,11 @@ private Map expectedB3Tags(TagContext context) { }) void extract128BitIdTruncatesIdTo64Bit( String traceId, String spanId, String expectedTraceIdHex, Long expectedSpanId) { - Map headers = new LinkedHashMap<>(); + Map headers = new HashMap<>(); headers.put(TRACE_ID_KEY.toUpperCase(), traceId); headers.put(SPAN_ID_KEY.toUpperCase(), spanId); - TagContext context = extractor.extract(headers, stringValuesMap()); + TagContext context = this.extractor.extract(headers, stringValuesMap()); if (expectedTraceIdHex != null) { assertInstanceOf(ExtractedContext.class, context); @@ -198,19 +199,22 @@ void extract128BitIdTruncatesIdTo64Bit( assertEquals(expectedTraceId, context.getTraceId()); long spanIdValue = expectedSpanId == null ? 0L : expectedSpanId; assertEquals(spanIdValue, context.getSpanId()); - assertEquals(expectedTraceId.getOriginal(), context.getTags().get("b3.traceid")); - Object expectedSpanIdTag = - expectedSpanId == null ? null : DDSpanId.toHexString(expectedSpanId); - assertEquals(expectedSpanIdTag, context.getTags().get("b3.spanid")); - } else { - assertTrue(context == null || !(context instanceof ExtractedContext)); + assertEquals(expectedTraceId.getOriginal(), context.getTags().getString(B3_TRACE_ID)); + if (expectedSpanId == null) { + assertNull(context.getTags().getString(B3_SPAN_ID)); + } else { + assertEquals(DDSpanId.toHexString(expectedSpanId), context.getTags().getString(B3_SPAN_ID)); + } + } else if (context != null) { + assertInstanceOf(TagContext.class, context); + assertFalse(context instanceof ExtractedContext); } } @Test void extractHeaderTagsWithNoPropagation() { TagContext context = - extractor.extract(singletonMap(SOME_HEADER, SOME_VALUE), stringValuesMap()); + this.extractor.extract(singletonMap(SOME_HEADER, SOME_VALUE), stringValuesMap()); assertFalse(context instanceof ExtractedContext); assertEquals(singletonMap(SOME_TAG, SOME_VALUE), context.getTags()); @@ -220,7 +224,7 @@ void extractHeaderTagsWithNoPropagation() { void extractHeadersWithForwarding() { String forwarded = "for=" + FORWARDED_IP + ":" + FORWARDED_PORT; Map tagOnlyCtx = singletonMap("Forwarded", forwarded); - Map fullCtx = new LinkedHashMap<>(); + Map fullCtx = new HashMap<>(); fullCtx.put(TRACE_ID_KEY.toUpperCase(), "1"); fullCtx.put(SPAN_ID_KEY.toUpperCase(), "2"); fullCtx.put("Forwarded", forwarded); @@ -231,7 +235,7 @@ void extractHeadersWithForwarding() { assertFalse(context instanceof ExtractedContext); assertEquals(forwarded, context.getForwarded()); - context = extractor.extract(fullCtx, stringValuesMap()); + context = this.extractor.extract(fullCtx, stringValuesMap()); assertInstanceOf(ExtractedContext.class, context); assertEquals(1L, context.getTraceId().toLong()); @@ -241,10 +245,10 @@ void extractHeadersWithForwarding() { @Test void extractHeadersWithXForwarding() { - Map tagOnlyCtx = new LinkedHashMap<>(); + Map tagOnlyCtx = new HashMap<>(); tagOnlyCtx.put("X-Forwarded-For", FORWARDED_IP); tagOnlyCtx.put("X-Forwarded-Port", FORWARDED_PORT); - Map fullCtx = new LinkedHashMap<>(); + Map fullCtx = new HashMap<>(); fullCtx.put(TRACE_ID_KEY.toUpperCase(), "1"); fullCtx.put(SPAN_ID_KEY.toUpperCase(), "2"); fullCtx.put("x-forwarded-for", FORWARDED_IP); @@ -273,7 +277,7 @@ void extractEmptyHeadersReturnsNull() { @Test void extractHttpHeadersWithInvalidNonNumericId() { - Map headers = new LinkedHashMap<>(); + Map headers = new HashMap<>(); headers.put(TRACE_ID_KEY.toUpperCase(), "traceId"); headers.put(SPAN_ID_KEY.toUpperCase(), "spanId"); headers.put(SOME_HEADER, SOME_VALUE); @@ -286,7 +290,7 @@ void extractHttpHeadersWithInvalidNonNumericId() { @Test void extractHttpHeadersWithOutOfRangeSpanId() { - Map headers = new LinkedHashMap<>(); + Map headers = new HashMap<>(); headers.put(TRACE_ID_KEY.toUpperCase(), "0"); headers.put(SPAN_ID_KEY.toUpperCase(), "-1"); headers.put(SOME_HEADER, SOME_VALUE); @@ -309,7 +313,7 @@ void extractHttpHeadersWithOutOfRangeSpanId() { }) void extractIdsWhileRetainingTheOriginalString( String traceId, String spanId, long expectedSpanId) { - Map headers = new LinkedHashMap<>(); + Map headers = new HashMap<>(); headers.put(TRACE_ID_KEY.toUpperCase(), traceId); headers.put(SPAN_ID_KEY.toUpperCase(), spanId); B3TraceId expectedTraceId = B3TraceId.fromHex(traceId); @@ -336,7 +340,7 @@ private static String trimmed(String hex) { @Test void extractCommonHttpHeaders() { - Map headers = new LinkedHashMap<>(); + Map headers = new HashMap<>(); headers.put(HttpCodec.USER_AGENT_KEY, "some-user-agent"); headers.put(HttpCodec.X_CLUSTER_CLIENT_IP_KEY, "1.1.1.1"); headers.put(HttpCodec.X_REAL_IP_KEY, "2.2.2.2"); diff --git a/dd-trace-core/src/test/java/datadog/trace/core/propagation/B3HttpInjectorPaddedTest.java b/dd-trace-core/src/test/java/datadog/trace/core/propagation/B3HttpInjectorPaddedTest.java deleted file mode 100644 index aaed1effa98..00000000000 --- a/dd-trace-core/src/test/java/datadog/trace/core/propagation/B3HttpInjectorPaddedTest.java +++ /dev/null @@ -1,8 +0,0 @@ -package datadog.trace.core.propagation; - -class B3HttpInjectorPaddedTest extends B3HttpInjectorTest { - @Override - protected boolean tracePropagationB3Padding() { - return true; - } -} diff --git a/dd-trace-core/src/test/java/datadog/trace/core/propagation/B3HttpInjectorTest.java b/dd-trace-core/src/test/java/datadog/trace/core/propagation/B3HttpInjectorTest.java index 55c8120e199..e47fdcebb88 100644 --- a/dd-trace-core/src/test/java/datadog/trace/core/propagation/B3HttpInjectorTest.java +++ b/dd-trace-core/src/test/java/datadog/trace/core/propagation/B3HttpInjectorTest.java @@ -7,9 +7,7 @@ import static datadog.trace.core.propagation.B3HttpCodec.SPAN_ID_KEY; import static datadog.trace.core.propagation.B3HttpCodec.TRACE_ID_KEY; import static java.util.Collections.emptyMap; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.junit.jupiter.api.Assertions.assertEquals; import datadog.context.propagation.CarrierSetter; import datadog.trace.api.Config; @@ -24,54 +22,37 @@ import datadog.trace.core.DDSpanContext; import datadog.trace.junit.utils.tabletest.PrioritySamplingConverter; import java.util.HashMap; -import java.util.LinkedHashMap; import java.util.Map; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.params.converter.ConvertWith; import org.tabletest.junit.TableTest; -class B3HttpInjectorTest extends DDCoreJavaSpecification { +abstract class B3HttpInjectorTest extends DDCoreJavaSpecification { private static final CarrierSetter> MAP_SETTER = Map::put; - protected boolean tracePropagationB3Padding() { - return false; - } + private HttpCodec.Injector injector; + private HttpCodec.Extractor extractor; + private CoreTracer tracer; - private String idOrPadded(long id, int size) { - return idOrPadded(Long.toHexString(id), size); - } + protected abstract boolean tracePropagationB3Padding(); - private String idOrPadded(String id, int size) { - if (!tracePropagationB3Padding()) { - return id.toLowerCase(); - } - return padHexLower(id, size); - } + @BeforeEach + void setup() { + this.injector = B3HttpCodec.newCombinedInjector(tracePropagationB3Padding()); - private static String padHexLower(String hex, int size) { - String lower = hex.toLowerCase(); - int diff = size - lower.length(); - if (diff <= 0) { - return lower; - } - StringBuilder sb = new StringBuilder(size); - for (int i = 0; i < diff; i++) { - sb.append('0'); - } - sb.append(lower); - return sb.toString(); + DynamicConfig dynamicConfig = + DynamicConfig.create().setHeaderTags(emptyMap()).setBaggageMapping(emptyMap()).apply(); + this.extractor = B3HttpCodec.newExtractor(Config.get(), dynamicConfig::captureTraceConfig); + + ListWriter writer = new ListWriter(); + this.tracer = tracerBuilder().writer(writer).build(); } - private static String trimHex(String hex) { - int length = hex.length(); - int firstNonZero = 0; - while (firstNonZero < length && hex.charAt(firstNonZero) == '0') { - firstNonZero++; - } - if (firstNonZero == length) { - return "0"; - } - return hex.substring(firstNonZero, length); + @AfterEach + void tearDown() { + this.tracer.close(); } @TableTest({ @@ -84,32 +65,32 @@ private static String trimHex(String hex) { "uint64 max unset | -1 | -2 | PrioritySampling.UNSET | ", "uint64 max-1 keep | -2 | -1 | PrioritySampling.SAMPLER_KEEP | PrioritySampling.SAMPLER_KEEP" }) - @SuppressWarnings("unchecked") void injectHttpHeaders( long traceId, long spanId, - @ConvertWith(PrioritySamplingConverter.class) int samplingPriority, + @ConvertWith(PrioritySamplingConverter.class) byte samplingPriority, @ConvertWith(PrioritySamplingConverter.class) Byte expectedSamplingPriority) { - HttpCodec.Injector injector = B3HttpCodec.newCombinedInjector(tracePropagationB3Padding()); - ListWriter writer = new ListWriter(); - CoreTracer tracer = tracerBuilder().writer(writer).build(); - DDSpanContext mockedContext = - mockedContext(tracer, DDTraceId.from(traceId), spanId, samplingPriority); - Map carrier = mock(Map.class); + + DDSpanContext spanContext = + mockedSpanContext(DDTraceId.from(traceId), spanId, samplingPriority); + + Map carrier = new HashMap<>(); + this.injector.inject(spanContext, carrier, MAP_SETTER); + String traceIdHex = idOrPadded(traceId, 32); String spanIdHex = idOrPadded(spanId, 16); + assertEquals(traceIdHex, carrier.get(TRACE_ID_KEY)); + assertEquals(spanIdHex, carrier.get(SPAN_ID_KEY)); - injector.inject(mockedContext, carrier, MAP_SETTER); - - verify(carrier).put(TRACE_ID_KEY, traceIdHex); - verify(carrier).put(SPAN_ID_KEY, spanIdHex); if (expectedSamplingPriority != null) { - verify(carrier).put(SAMPLING_PRIORITY_KEY, expectedSamplingPriority.toString()); - verify(carrier).put(B3_KEY, traceIdHex + "-" + spanIdHex + "-" + expectedSamplingPriority); + assertEquals(4, carrier.size()); + assertEquals(expectedSamplingPriority.toString(), carrier.get(SAMPLING_PRIORITY_KEY)); + assertEquals( + traceIdHex + "-" + spanIdHex + "-" + expectedSamplingPriority, carrier.get(B3_KEY)); } else { - verify(carrier).put(B3_KEY, traceIdHex + "-" + spanIdHex); + assertEquals(3, carrier.size()); + assertEquals(traceIdHex + "-" + spanIdHex, carrier.get(B3_KEY)); } - verifyNoMoreInteractions(carrier); } @TableTest({ @@ -122,38 +103,66 @@ void injectHttpHeaders( "uint64 max spanId | '1' | 'ffffffffffffffff' ", "padded uint64 max | '1' | '000ffffffffffffffff'" }) - @SuppressWarnings("unchecked") void injectHttpHeadersWithExtractedOriginal(String traceId, String spanId) { - HttpCodec.Injector injector = B3HttpCodec.newCombinedInjector(tracePropagationB3Padding()); - ListWriter writer = new ListWriter(); - CoreTracer tracer = tracerBuilder().writer(writer).build(); - Map headers = new LinkedHashMap<>(); + Map headers = new HashMap<>(); headers.put(TRACE_ID_KEY.toUpperCase(), traceId); headers.put(SPAN_ID_KEY.toUpperCase(), spanId); - DynamicConfig dynamicConfig = - DynamicConfig.create().setHeaderTags(emptyMap()).setBaggageMapping(emptyMap()).apply(); - HttpCodec.Extractor extractor = - B3HttpCodec.newExtractor(Config.get(), () -> dynamicConfig.captureTraceConfig()); - TagContext context = extractor.extract(headers, stringValuesMap()); - DDSpanContext mockedContext = mockedContext(tracer, context); - Map carrier = mock(Map.class); + TagContext context = this.extractor.extract(headers, stringValuesMap()); + + DDSpanContext mockedContext = mockedSpanContext(context); + Map carrier = new HashMap<>(); + this.injector.inject(mockedContext, carrier, MAP_SETTER); + String traceIdHex = idOrPadded(traceId, 32); String spanIdHex = idOrPadded(trimHex(spanId), 16); + assertEquals(traceIdHex, carrier.get(TRACE_ID_KEY)); + assertEquals(spanIdHex, carrier.get(SPAN_ID_KEY)); + assertEquals(traceIdHex + "-" + spanIdHex, carrier.get(B3_KEY)); + assertEquals(3, carrier.size()); + } - injector.inject(mockedContext, carrier, MAP_SETTER); + private String idOrPadded(long id, int size) { + return idOrPadded(Long.toHexString(id), size); + } - verify(carrier).put(TRACE_ID_KEY, traceIdHex); - verify(carrier).put(SPAN_ID_KEY, spanIdHex); - verify(carrier).put(B3_KEY, traceIdHex + "-" + spanIdHex); - verifyNoMoreInteractions(carrier); + private String idOrPadded(String id, int size) { + if (!tracePropagationB3Padding()) { + return id.toLowerCase(); + } + return padHexLower(id, size); } - static DDSpanContext mockedContext(CoreTracer tracer, TagContext context) { - return mockedContext(tracer, context.getTraceId(), context.getSpanId(), UNSET); + private static String padHexLower(String hex, int size) { + String lower = hex.toLowerCase(); + int diff = size - lower.length(); + if (diff <= 0) { + return lower; + } + StringBuilder sb = new StringBuilder(size); + for (int i = 0; i < diff; i++) { + sb.append('0'); + } + sb.append(lower); + return sb.toString(); } - static DDSpanContext mockedContext( - CoreTracer tracer, DDTraceId traceId, long spanId, int samplingPriority) { + private static String trimHex(String hex) { + int length = hex.length(); + int firstNonZero = 0; + while (firstNonZero < length && hex.charAt(firstNonZero) == '0') { + firstNonZero++; + } + if (firstNonZero == length) { + return "0"; + } + return hex.substring(firstNonZero, length); + } + + private DDSpanContext mockedSpanContext(TagContext context) { + return mockedSpanContext(context.getTraceId(), context.getSpanId(), UNSET); + } + + private DDSpanContext mockedSpanContext(DDTraceId traceId, long spanId, int samplingPriority) { Map baggage = new HashMap<>(); baggage.put("k1", "v1"); baggage.put("k2", "v2"); @@ -171,11 +180,25 @@ static DDSpanContext mockedContext( false, "fakeType", 0, - tracer.createTraceCollector(DDTraceId.ONE), + this.tracer.createTraceCollector(DDTraceId.ONE), null, null, NoopPathwayContext.INSTANCE, false, PropagationTags.factory().empty()); } + + static class B3HttpInjectorNonPaddedTest extends B3HttpInjectorTest { + @Override + protected boolean tracePropagationB3Padding() { + return false; + } + } + + static class B3HttpInjectorPaddedTest extends B3HttpInjectorTest { + @Override + protected boolean tracePropagationB3Padding() { + return true; + } + } } diff --git a/dd-trace-core/src/test/java/datadog/trace/core/propagation/DatadogHttpExtractorTest.java b/dd-trace-core/src/test/java/datadog/trace/core/propagation/DatadogHttpExtractorTest.java index 2bd535cce71..d25747f41a1 100644 --- a/dd-trace-core/src/test/java/datadog/trace/core/propagation/DatadogHttpExtractorTest.java +++ b/dd-trace-core/src/test/java/datadog/trace/core/propagation/DatadogHttpExtractorTest.java @@ -1,14 +1,20 @@ package datadog.trace.core.propagation; +import static datadog.trace.api.config.TracerConfig.PROPAGATION_EXTRACT_LOG_HEADER_NAMES_ENABLED; +import static datadog.trace.api.config.TracerConfig.REQUEST_HEADER_TAGS_COMMA_ALLOWED; +import static datadog.trace.api.config.TracerConfig.TRACE_CLIENT_IP_HEADER; +import static datadog.trace.api.config.TracerConfig.TRACE_CLIENT_IP_RESOLVER_ENABLED; import static datadog.trace.api.sampling.PrioritySampling.UNSET; +import static datadog.trace.bootstrap.ActiveSubsystems.APPSEC_ACTIVE; import static datadog.trace.bootstrap.instrumentation.api.ContextVisitors.stringValuesMap; +import static datadog.trace.core.CoreTracer.TRACE_ID_MAX; import static datadog.trace.core.propagation.DatadogHttpCodec.DATADOG_TAGS_KEY; import static datadog.trace.core.propagation.DatadogHttpCodec.ORIGIN_KEY; import static datadog.trace.core.propagation.DatadogHttpCodec.OT_BAGGAGE_PREFIX; import static datadog.trace.core.propagation.DatadogHttpCodec.SAMPLING_PRIORITY_KEY; import static datadog.trace.core.propagation.DatadogHttpCodec.SPAN_ID_KEY; import static datadog.trace.core.propagation.DatadogHttpCodec.TRACE_ID_KEY; -import static datadog.trace.junit.utils.config.WithConfigExtension.injectEnvConfig; +import static java.math.BigInteger.ONE; import static java.util.Collections.singletonMap; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -22,14 +28,12 @@ import datadog.trace.api.DDSpanId; import datadog.trace.api.DDTraceId; import datadog.trace.api.DynamicConfig; -import datadog.trace.api.config.TracerConfig; import datadog.trace.api.internal.util.LongStringUtils; -import datadog.trace.bootstrap.ActiveSubsystems; import datadog.trace.bootstrap.instrumentation.api.TagContext; import datadog.trace.junit.utils.config.WithConfig; import datadog.trace.junit.utils.tabletest.PrioritySamplingConverter; import datadog.trace.test.util.DDJavaSpecification; -import java.util.LinkedHashMap; +import java.util.HashMap; import java.util.Map; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -39,9 +43,8 @@ import org.junit.jupiter.params.provider.ValueSource; import org.tabletest.junit.TableTest; -@WithConfig(key = "propagation.extract.log_header_names.enabled", value = "true") +@WithConfig(key = PROPAGATION_EXTRACT_LOG_HEADER_NAMES_ENABLED, value = "true") class DatadogHttpExtractorTest extends DDJavaSpecification { - private static final String SOME_HEADER = "SOME_HEADER"; private static final String SOME_CUSTOM_BAGGAGE_HEADER = "SOME_CUSTOM_BAGGAGE_HEADER"; private static final String SOME_CUSTOM_BAGGAGE_HEADER_2 = "SOME_CUSTOM_BAGGAGE_HEADER_2"; @@ -50,58 +53,44 @@ class DatadogHttpExtractorTest extends DDJavaSpecification { private static final String SOME_BAGGAGE = "some-baggage"; private static final String SOME_CASE_SENSITIVE_BAGGAGE = "some-CaseSensitive-baggage"; - private DynamicConfig dynamicConfig; - private HttpCodec.Extractor lazyExtractor; private boolean origAppSecActive; + private HttpCodec.Extractor extractor; @BeforeEach void setup() { - Map baggageMap = new LinkedHashMap<>(); + Map baggageMap = new HashMap<>(); baggageMap.put(SOME_CUSTOM_BAGGAGE_HEADER, SOME_BAGGAGE); baggageMap.put(SOME_CUSTOM_BAGGAGE_HEADER_2, SOME_CASE_SENSITIVE_BAGGAGE); - dynamicConfig = + DynamicConfig dynamicConfig = DynamicConfig.create() .setHeaderTags(singletonMap(SOME_HEADER, SOME_TAG)) .setBaggageMapping(baggageMap) .apply(); - origAppSecActive = ActiveSubsystems.APPSEC_ACTIVE; - ActiveSubsystems.APPSEC_ACTIVE = true; + this.extractor = DatadogHttpCodec.newExtractor(Config.get(), dynamicConfig::captureTraceConfig); + + this.origAppSecActive = APPSEC_ACTIVE; + APPSEC_ACTIVE = true; } @AfterEach void teardown() { - ActiveSubsystems.APPSEC_ACTIVE = origAppSecActive; - extractor().cleanup(); - } - - private HttpCodec.Extractor extractor() { - if (lazyExtractor == null) { - lazyExtractor = createExtractor(); - } - return lazyExtractor; - } - - private HttpCodec.Extractor createExtractor() { - return DatadogHttpCodec.newExtractor(Config.get(), () -> dynamicConfig.captureTraceConfig()); + this.extractor.cleanup(); + APPSEC_ACTIVE = this.origAppSecActive; } @TableTest({ - "scenario | traceId | spanId | samplingPriority | origin | allowComma", - "unset no origin | '1' | '2' | PrioritySampling.UNSET | | true ", - "keep with origin | '2' | '3' | PrioritySampling.SAMPLER_KEEP | 'saipan' | false ", - "uint64 max unset | '18446744073709551615' | '18446744073709551614' | PrioritySampling.UNSET | 'saipan' | true ", - "uint64 max-1 keep | '18446744073709551614' | '18446744073709551615' | PrioritySampling.SAMPLER_KEEP | 'saipan' | false " + "scenario | traceId | spanId | samplingPriority | origin ", + "unset no origin | '1' | '2' | PrioritySampling.UNSET | ", + "keep with origin | '2' | '3' | PrioritySampling.SAMPLER_KEEP | 'saipan'", + "uint64 max unset | '18446744073709551615' | '18446744073709551614' | PrioritySampling.UNSET | 'saipan'", + "uint64 max-1 keep | '18446744073709551614' | '18446744073709551615' | PrioritySampling.SAMPLER_KEEP | 'saipan'" }) void extractHttpHeaders( String traceId, String spanId, - @ConvertWith(PrioritySamplingConverter.class) int samplingPriority, - String origin, - boolean allowComma) { - injectEnvConfig( - "DD_TRACE_REQUEST_HEADER_TAGS_COMMA_ALLOWED", String.valueOf(allowComma), false); - HttpCodec.Extractor extractor = createExtractor(); - Map headers = new LinkedHashMap<>(); + @ConvertWith(PrioritySamplingConverter.class) byte samplingPriority, + String origin) { + Map headers = new HashMap<>(); headers.put("", "empty key"); headers.put(TRACE_ID_KEY.toUpperCase(), traceId); headers.put(SPAN_ID_KEY.toUpperCase(), spanId); @@ -116,33 +105,54 @@ void extractHttpHeaders( if (origin != null) { headers.put(ORIGIN_KEY, origin); } - String expectedTagValue = allowComma ? "my-interesting-info,and-more" : "my-interesting-info"; ExtractedContext context = (ExtractedContext) extractor.extract(headers, stringValuesMap()); assertEquals(DDTraceId.from(traceId), context.getTraceId()); assertEquals(DDSpanId.from(spanId), context.getSpanId()); - Map expectedBaggage = new LinkedHashMap<>(); + Map expectedBaggage = new HashMap<>(); expectedBaggage.put("k1", "v1"); expectedBaggage.put("k2", "v2"); expectedBaggage.put(SOME_BAGGAGE, "my-interesting-baggage-info"); expectedBaggage.put(SOME_CASE_SENSITIVE_BAGGAGE, "my-interesting-baggage-info-2"); assertEquals(expectedBaggage, context.getBaggage()); - assertEquals(singletonMap(SOME_TAG, expectedTagValue), context.getTags()); + assertEquals(singletonMap(SOME_TAG, "my-interesting-info,and-more"), context.getTags()); assertEquals(samplingPriority, context.getSamplingPriority()); assertEquals(origin, asString(context.getOrigin())); } + @WithConfig(key = REQUEST_HEADER_TAGS_COMMA_ALLOWED, value = "false") + @Test + void extractHttpHeadersWithoutComma() { + // Recreate extractor with the new comma config + this.extractor.cleanup(); + DynamicConfig dynamicConfig = + DynamicConfig.create().setHeaderTags(singletonMap(SOME_HEADER, SOME_TAG)).apply(); + this.extractor = DatadogHttpCodec.newExtractor(Config.get(), dynamicConfig::captureTraceConfig); + + Map headers = new HashMap<>(); + headers.put(TRACE_ID_KEY.toUpperCase(), "1"); + headers.put(SPAN_ID_KEY.toUpperCase(), "2"); + String headerWithComma = "my-interesting-info,and-more"; + headers.put(SOME_HEADER, headerWithComma); + + ExtractedContext context = + (ExtractedContext) this.extractor.extract(headers, stringValuesMap()); + + String expectedHeader = "my-interesting-info"; + assertEquals(expectedHeader, context.getTags().getString(SOME_TAG)); + } + @ParameterizedTest @ValueSource(booleans = {false, true}) void extractHeaderTagsWithNoPropagation(boolean withOrigin) { - Map headers = new LinkedHashMap<>(); + Map headers = new HashMap<>(); if (withOrigin) { headers.put(ORIGIN_KEY, "my-origin"); } headers.put(SOME_HEADER, "my-interesting-info"); - TagContext context = extractor().extract(headers, stringValuesMap()); + TagContext context = this.extractor.extract(headers, stringValuesMap()); assertFalse(context instanceof ExtractedContext); assertEquals(singletonMap(SOME_TAG, "my-interesting-info"), context.getTags()); @@ -157,18 +167,18 @@ void extractHeadersWithForwarding() { String forwardedPort = "1234"; String forwarded = "for=" + forwardedIp + ":" + forwardedPort; Map tagOnlyCtx = singletonMap("Forwarded", forwarded); - Map fullCtx = new LinkedHashMap<>(); + Map fullCtx = new HashMap<>(); fullCtx.put(TRACE_ID_KEY.toUpperCase(), "1"); fullCtx.put(SPAN_ID_KEY.toUpperCase(), "2"); fullCtx.put("Forwarded", forwarded); - TagContext context = extractor().extract(tagOnlyCtx, stringValuesMap()); + TagContext context = this.extractor.extract(tagOnlyCtx, stringValuesMap()); assertNotNull(context); assertFalse(context instanceof ExtractedContext); assertEquals(forwarded, context.getForwarded()); - context = extractor().extract(fullCtx, stringValuesMap()); + context = this.extractor.extract(fullCtx, stringValuesMap()); assertInstanceOf(ExtractedContext.class, context); assertEquals(1L, context.getTraceId().toLong()); @@ -180,22 +190,22 @@ void extractHeadersWithForwarding() { void extractHeadersWithXForwarding() { String forwardedIp = "1.2.3.4"; String forwardedPort = "1234"; - Map tagOnlyCtx = new LinkedHashMap<>(); + Map tagOnlyCtx = new HashMap<>(); tagOnlyCtx.put("X-Forwarded-For", forwardedIp); tagOnlyCtx.put("X-Forwarded-Port", forwardedPort); - Map fullCtx = new LinkedHashMap<>(); + Map fullCtx = new HashMap<>(); fullCtx.put(TRACE_ID_KEY.toUpperCase(), "1"); fullCtx.put(SPAN_ID_KEY.toUpperCase(), "2"); fullCtx.put("x-forwarded-for", forwardedIp); fullCtx.put("x-forwarded-port", forwardedPort); - TagContext context = extractor().extract(tagOnlyCtx, stringValuesMap()); + TagContext context = this.extractor.extract(tagOnlyCtx, stringValuesMap()); assertNotNull(context); assertEquals(forwardedIp, context.getXForwardedFor()); assertEquals(forwardedPort, context.getXForwardedPort()); - context = extractor().extract(fullCtx, stringValuesMap()); + context = this.extractor.extract(fullCtx, stringValuesMap()); assertInstanceOf(ExtractedContext.class, context); assertEquals(1L, context.getTraceId().toLong()); @@ -206,18 +216,18 @@ void extractHeadersWithXForwarding() { @Test void extractEmptyHeadersReturnsNull() { - assertNull( - extractor().extract(singletonMap("ignored-header", "ignored-value"), stringValuesMap())); + Map carrier = singletonMap("ignored-header", "ignored-value"); + assertNull(this.extractor.extract(carrier, stringValuesMap())); } @Test - @WithConfig(key = TracerConfig.TRACE_CLIENT_IP_RESOLVER_ENABLED, value = "false") + @WithConfig(key = TRACE_CLIENT_IP_RESOLVER_ENABLED, value = "false") void extractHeadersWithIpResolutionDisabled() { - Map tagOnlyCtx = new LinkedHashMap<>(); + Map tagOnlyCtx = new HashMap<>(); tagOnlyCtx.put("X-Forwarded-For", "::1"); tagOnlyCtx.put("User-agent", "foo/bar"); - TagContext context = extractor().extract(tagOnlyCtx, stringValuesMap()); + TagContext context = this.extractor.extract(tagOnlyCtx, stringValuesMap()); assertNotNull(context); assertNull(context.getXForwardedFor()); @@ -226,25 +236,25 @@ void extractHeadersWithIpResolutionDisabled() { @Test void extractHeadersWithIpResolutionDisabledAppsecDisabled() { - ActiveSubsystems.APPSEC_ACTIVE = false; - Map tagOnlyCtx = new LinkedHashMap<>(); + APPSEC_ACTIVE = false; + Map tagOnlyCtx = new HashMap<>(); tagOnlyCtx.put("X-Forwarded-For", "::1"); tagOnlyCtx.put("User-agent", "foo/bar"); - TagContext context = extractor().extract(tagOnlyCtx, stringValuesMap()); + TagContext context = this.extractor.extract(tagOnlyCtx, stringValuesMap()); assertNotNull(context); assertNull(context.getXForwardedFor()); } @Test - @WithConfig(key = TracerConfig.TRACE_CLIENT_IP_HEADER, value = "my-header") + @WithConfig(key = TRACE_CLIENT_IP_HEADER, value = "my-header") void customIpHeaderCollectionDoesNotDisableStandardIpHeaderCollection() { - Map tagOnlyCtx = new LinkedHashMap<>(); + Map tagOnlyCtx = new HashMap<>(); tagOnlyCtx.put("X-Forwarded-For", "::1"); tagOnlyCtx.put("My-Header", "8.8.8.8"); - TagContext context = extractor().extract(tagOnlyCtx, stringValuesMap()); + TagContext context = this.extractor.extract(tagOnlyCtx, stringValuesMap()); assertNotNull(context); assertEquals("::1", context.getXForwardedFor()); @@ -262,8 +272,8 @@ void customIpHeaderCollectionDoesNotDisableStandardIpHeaderCollection() { void extractHttpHeadersWith128BitTraceId(String hexId) { DD128bTraceId traceId = DD128bTraceId.fromHex(hexId); boolean is128bTrace = traceId.toHighOrderLong() != 0; - DDTraceId expectedTraceId = is128bTrace ? traceId : DD64bTraceId.from(traceId.toLong()); - Map headers = new LinkedHashMap<>(); + + Map headers = new HashMap<>(); headers.put(TRACE_ID_KEY.toUpperCase(), traceId.toString()); headers.put(SPAN_ID_KEY.toUpperCase(), "2"); headers.put((OT_BAGGAGE_PREFIX + "k1").toUpperCase(), "v1"); @@ -275,11 +285,13 @@ void extractHttpHeadersWith128BitTraceId(String hexId) { "_dd.p.tid=" + LongStringUtils.toHexStringPadded(traceId.toHighOrderLong(), 16)); } - ExtractedContext context = (ExtractedContext) extractor().extract(headers, stringValuesMap()); + ExtractedContext context = + (ExtractedContext) this.extractor.extract(headers, stringValuesMap()); + DDTraceId expectedTraceId = is128bTrace ? traceId : DD64bTraceId.from(traceId.toLong()); assertEquals(expectedTraceId, context.getTraceId()); assertEquals(DDSpanId.from("2"), context.getSpanId()); - Map expectedBaggage = new LinkedHashMap<>(); + Map expectedBaggage = new HashMap<>(); expectedBaggage.put("k1", "v1"); expectedBaggage.put("k2", "v2"); assertEquals(expectedBaggage, context.getBaggage()); @@ -288,42 +300,43 @@ void extractHttpHeadersWith128BitTraceId(String hexId) { @Test void extractHttpHeadersWithInvalidNonNumericId() { - Map headers = new LinkedHashMap<>(); + Map headers = new HashMap<>(); headers.put(TRACE_ID_KEY.toUpperCase(), "traceId"); headers.put(SPAN_ID_KEY.toUpperCase(), "spanId"); headers.put((OT_BAGGAGE_PREFIX + "k1").toUpperCase(), "v1"); headers.put((OT_BAGGAGE_PREFIX + "k2").toUpperCase(), "v2"); headers.put(SOME_HEADER, "my-interesting-info"); - TagContext context = extractor().extract(headers, stringValuesMap()); + TagContext context = this.extractor.extract(headers, stringValuesMap()); assertNull(context); } @Test void extractHttpHeadersWithOutOfRangeTraceId() { - Map headers = new LinkedHashMap<>(); - headers.put(TRACE_ID_KEY.toUpperCase(), "18446744073709551616"); // TRACE_ID_MAX + 1 + String outOfRangeTraceId = TRACE_ID_MAX.add(ONE).toString(); + Map headers = new HashMap<>(); + headers.put(TRACE_ID_KEY.toUpperCase(), outOfRangeTraceId); headers.put(SPAN_ID_KEY.toUpperCase(), "0"); headers.put((OT_BAGGAGE_PREFIX + "k1").toUpperCase(), "v1"); headers.put((OT_BAGGAGE_PREFIX + "k2").toUpperCase(), "v2"); headers.put(SOME_HEADER, "my-interesting-info"); - TagContext context = extractor().extract(headers, stringValuesMap()); + TagContext context = this.extractor.extract(headers, stringValuesMap()); assertNull(context); } @Test void extractHttpHeadersWithOutOfRangeSpanId() { - Map headers = new LinkedHashMap<>(); + Map headers = new HashMap<>(); headers.put(TRACE_ID_KEY.toUpperCase(), "0"); headers.put(SPAN_ID_KEY.toUpperCase(), "-1"); headers.put((OT_BAGGAGE_PREFIX + "k1").toUpperCase(), "v1"); headers.put((OT_BAGGAGE_PREFIX + "k2").toUpperCase(), "v2"); headers.put(SOME_HEADER, "my-interesting-info"); - TagContext context = extractor().extract(headers, stringValuesMap()); + TagContext context = this.extractor.extract(headers, stringValuesMap()); assertNull(context); } @@ -340,11 +353,11 @@ void extractHttpHeadersWithOutOfRangeSpanId() { "out-of-range spanId | '1' | '18446744073709551616' | false " }) void moreIdRangeValidation(String traceId, String spanId, boolean expectExtraction) { - Map headers = new LinkedHashMap<>(); + Map headers = new HashMap<>(); headers.put(TRACE_ID_KEY.toUpperCase(), traceId); headers.put(SPAN_ID_KEY.toUpperCase(), spanId); - TagContext context = extractor().extract(headers, stringValuesMap()); + TagContext context = this.extractor.extract(headers, stringValuesMap()); if (expectExtraction) { ExtractedContext extracted = assertInstanceOf(ExtractedContext.class, context); @@ -361,7 +374,7 @@ void moreIdRangeValidation(String traceId, String spanId, boolean expectExtracti "epoch 2021 | '2' | '3' | 1610001234 " }) void extractHttpHeadersWithEndToEnd(String traceId, String spanId, long endToEndStartTime) { - Map headers = new LinkedHashMap<>(); + Map headers = new HashMap<>(); headers.put("", "empty key"); headers.put(TRACE_ID_KEY.toUpperCase(), traceId); headers.put(SPAN_ID_KEY.toUpperCase(), spanId); @@ -372,11 +385,12 @@ void extractHttpHeadersWithEndToEnd(String traceId, String spanId, long endToEnd headers.put(SOME_CUSTOM_BAGGAGE_HEADER, "my-interesting-baggage-info"); headers.put(SOME_CUSTOM_BAGGAGE_HEADER_2, "my-interesting-baggage-info-2"); - ExtractedContext context = (ExtractedContext) extractor().extract(headers, stringValuesMap()); + ExtractedContext context = + (ExtractedContext) this.extractor.extract(headers, stringValuesMap()); assertEquals(DDTraceId.from(traceId), context.getTraceId()); assertEquals(DDSpanId.from(spanId), context.getSpanId()); - Map expectedBaggage = new LinkedHashMap<>(); + Map expectedBaggage = new HashMap<>(); expectedBaggage.put("k1", "v1"); expectedBaggage.put("k2", "v2"); expectedBaggage.put(SOME_BAGGAGE, "my-interesting-baggage-info"); @@ -394,7 +408,7 @@ void extractHttpHeadersWithEndToEnd(String traceId, String spanId, long endToEnd "uint64 max-1 ids | '18446744073709551614' | '18446744073709551614' | true " }) void baggageIsMappedOnContextCreation(String traceId, String spanId, boolean ctxCreated) { - Map headers = new LinkedHashMap<>(); + Map headers = new HashMap<>(); headers.put(TRACE_ID_KEY.toUpperCase(), traceId); headers.put(SPAN_ID_KEY.toUpperCase(), spanId); headers.put(SOME_CUSTOM_BAGGAGE_HEADER, "mappedBaggageValue"); @@ -402,11 +416,11 @@ void baggageIsMappedOnContextCreation(String traceId, String spanId, boolean ctx headers.put((OT_BAGGAGE_PREFIX + "k2").toUpperCase(), "v2"); headers.put(SOME_ARBITRARY_HEADER, "my-interesting-info"); - TagContext context = extractor().extract(headers, stringValuesMap()); + TagContext context = this.extractor.extract(headers, stringValuesMap()); if (ctxCreated) { assertNotNull(context); - Map expectedBaggage = new LinkedHashMap<>(); + Map expectedBaggage = new HashMap<>(); expectedBaggage.put(SOME_BAGGAGE, "mappedBaggageValue"); expectedBaggage.put("k1", "v1"); expectedBaggage.put("k2", "v2"); @@ -418,7 +432,7 @@ void baggageIsMappedOnContextCreation(String traceId, String spanId, boolean ctx @Test void extractCommonHttpHeaders() { - Map headers = new LinkedHashMap<>(); + Map headers = new HashMap<>(); headers.put(HttpCodec.USER_AGENT_KEY, "some-user-agent"); headers.put(HttpCodec.X_CLUSTER_CLIENT_IP_KEY, "1.1.1.1"); headers.put(HttpCodec.X_REAL_IP_KEY, "2.2.2.2"); @@ -430,7 +444,7 @@ void extractCommonHttpHeaders() { headers.put(HttpCodec.CF_CONNECTING_IP_KEY, "8.8.8.8"); headers.put(HttpCodec.CF_CONNECTING_IP_V6_KEY, "9.9.9.9"); - TagContext context = extractor().extract(headers, stringValuesMap()); + TagContext context = this.extractor.extract(headers, stringValuesMap()); assertEquals("some-user-agent", context.getUserAgent()); assertEquals("1.1.1.1", context.getXClusterClientIp()); diff --git a/dd-trace-core/src/test/java/datadog/trace/core/propagation/DatadogHttpInjectorTest.java b/dd-trace-core/src/test/java/datadog/trace/core/propagation/DatadogHttpInjectorTest.java index ec1e049ab54..cc7e385ed10 100644 --- a/dd-trace-core/src/test/java/datadog/trace/core/propagation/DatadogHttpInjectorTest.java +++ b/dd-trace-core/src/test/java/datadog/trace/core/propagation/DatadogHttpInjectorTest.java @@ -9,12 +9,12 @@ import static datadog.trace.core.propagation.DatadogHttpCodec.SAMPLING_PRIORITY_KEY; import static datadog.trace.core.propagation.DatadogHttpCodec.SPAN_ID_KEY; import static datadog.trace.core.propagation.DatadogHttpCodec.TRACE_ID_KEY; +import static datadog.trace.core.propagation.PropagationTags.HeaderType.DATADOG; import static java.util.Collections.singletonMap; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; -import datadog.context.propagation.CarrierSetter; import datadog.trace.api.DD128bTraceId; import datadog.trace.api.DDSpanId; import datadog.trace.api.DDTraceId; @@ -25,63 +25,53 @@ import datadog.trace.core.DDCoreJavaSpecification; import datadog.trace.core.DDSpanContext; import datadog.trace.junit.utils.tabletest.PrioritySamplingConverter; -import java.util.LinkedHashMap; +import java.util.HashMap; import java.util.Map; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.converter.ConvertWith; import org.tabletest.junit.TableTest; class DatadogHttpInjectorTest extends DDCoreJavaSpecification { + private HttpCodec.Injector injector; + private CoreTracer tracer; - private static final CarrierSetter> MAP_SETTER = Map::put; + @BeforeEach + void setup() { + this.injector = DatadogHttpCodec.newInjector(singletonMap("some-baggage-key", "SOME_CUSTOM_HEADER")); - private final HttpCodec.Injector injector = - DatadogHttpCodec.newInjector(singletonMap("some-baggage-key", "SOME_CUSTOM_HEADER")); + ListWriter writer = new ListWriter(); + this.tracer = tracerBuilder().writer(writer).build(); + } + + @AfterEach + void tearDown() { + this.tracer.close(); + } @TableTest({ - "scenario | traceId | spanId | samplingPriority | origin ", - "unset no origin | '1' | '2' | PrioritySampling.UNSET | ", - "keep with origin | '1' | '2' | PrioritySampling.SAMPLER_KEEP | 'saipan'", - "uint64 max unset | '18446744073709551615' | '18446744073709551614' | PrioritySampling.UNSET | 'saipan'", - "uint64 max-1 keep | '18446744073709551614' | '18446744073709551615' | PrioritySampling.SAMPLER_KEEP | " + "scenario | traceId | spanId | samplingPriority | origin ", + "unset no origin | '1' | '2' | PrioritySampling.UNSET | ", + "keep with origin | '1' | '2' | PrioritySampling.SAMPLER_KEEP | 'saipan'", + "uint64 max unset | '18446744073709551615' | '18446744073709551614' | PrioritySampling.UNSET | 'saipan'", + "uint64 max-1 keep | '18446744073709551614' | '18446744073709551615' | PrioritySampling.SAMPLER_KEEP | " }) @SuppressWarnings("unchecked") void injectHttpHeaders( String traceId, String spanId, - @ConvertWith(PrioritySamplingConverter.class) int samplingPriority, + @ConvertWith(PrioritySamplingConverter.class) byte samplingPriority, String origin) { - ListWriter writer = new ListWriter(); - CoreTracer tracer = tracerBuilder().writer(writer).build(); - Map baggage = new LinkedHashMap<>(); + Map baggage = new HashMap<>(); baggage.put("k1", "v1"); baggage.put("k2", "v2"); baggage.put("some-baggage-key", "some-value"); - DDSpanContext mockedContext = - new DDSpanContext( - DDTraceId.from(traceId), - DDSpanId.from(spanId), - DDSpanId.ZERO, - null, - "fakeService", - "fakeOperation", - "fakeResource", - samplingPriority, - origin, - baggage, - false, - "fakeType", - 0, - tracer.createTraceCollector(DDTraceId.ONE), - null, - null, - NoopPathwayContext.INSTANCE, - false, - PropagationTags.factory() - .fromHeaderValue(PropagationTags.HeaderType.DATADOG, "_dd.p.usr=123")); + + DDSpanContext spanContext = mockSpanContext(traceId, spanId, samplingPriority, origin, baggage, "_dd.p.usr=123"); Map carrier = mock(Map.class); - injector.inject(mockedContext, carrier, MAP_SETTER); + this.injector.inject(spanContext, carrier, Map::put); verify(carrier).put(TRACE_ID_KEY, traceId); verify(carrier).put(SPAN_ID_KEY, spanId); @@ -101,40 +91,18 @@ void injectHttpHeaders( @Test @SuppressWarnings("unchecked") void injectHttpHeadersWithEndToEnd() { - ListWriter writer = new ListWriter(); - CoreTracer tracer = tracerBuilder().writer(writer).build(); - Map baggage = new LinkedHashMap<>(); + Map baggage = new HashMap<>(); baggage.put("k1", "v1"); baggage.put("k2", "v2"); - DDSpanContext mockedContext = - new DDSpanContext( - DDTraceId.from("1"), - DDSpanId.from("2"), - DDSpanId.ZERO, - null, - "fakeService", - "fakeOperation", - "fakeResource", - UNSET, - "fakeOrigin", - baggage, - false, - "fakeType", - 0, - tracer.createTraceCollector(DDTraceId.ONE), - null, - null, - NoopPathwayContext.INSTANCE, - false, - PropagationTags.factory() - .fromHeaderValue( - PropagationTags.HeaderType.DATADOG, "_dd.p.dm=-4,_dd.p.anytag=value")); - mockedContext.beginEndToEnd(); - String expectedT0 = String.valueOf(mockedContext.getEndToEndStartTime() / 1_000_000L); + + DDSpanContext spanContext = mockSpanContext("1", "2", UNSET, "fakeOrigin", baggage, "_dd.p.dm=-4,_dd.p.anytag=value"); + spanContext.beginEndToEnd(); + Map carrier = mock(Map.class); - injector.inject(mockedContext, carrier, MAP_SETTER); + this.injector.inject(spanContext, carrier, Map::put); + String expectedT0 = String.valueOf(spanContext.getEndToEndStartTime() / 1_000_000L); verify(carrier).put(TRACE_ID_KEY, "1"); verify(carrier).put(SPAN_ID_KEY, "2"); verify(carrier).put(ORIGIN_KEY, "fakeOrigin"); @@ -148,36 +116,15 @@ void injectHttpHeadersWithEndToEnd() { @Test @SuppressWarnings("unchecked") void injectTheDecisionMakerTag() { - ListWriter writer = new ListWriter(); - CoreTracer tracer = tracerBuilder().writer(writer).build(); - Map baggage = new LinkedHashMap<>(); + Map baggage = new HashMap<>(); baggage.put("k1", "v1"); baggage.put("k2", "v2"); - DDSpanContext mockedContext = - new DDSpanContext( - DDTraceId.from("1"), - DDSpanId.from("2"), - DDSpanId.ZERO, - null, - "fakeService", - "fakeOperation", - "fakeResource", - UNSET, - "fakeOrigin", - baggage, - false, - "fakeType", - 0, - tracer.createTraceCollector(DDTraceId.ONE), - null, - null, - NoopPathwayContext.INSTANCE, - false, - PropagationTags.factory().empty()); - mockedContext.setSamplingPriority(USER_KEEP, MANUAL); + + DDSpanContext spanContext = mockSpanContext("1", "2", UNSET, "fakeOrigin", baggage, null); + spanContext.setSamplingPriority(USER_KEEP, MANUAL); Map carrier = mock(Map.class); - injector.inject(mockedContext, carrier, MAP_SETTER); + this.injector.inject(spanContext, carrier, Map::put); verify(carrier).put(TRACE_ID_KEY, "1"); verify(carrier).put(SPAN_ID_KEY, "2"); @@ -190,50 +137,27 @@ void injectTheDecisionMakerTag() { } @TableTest({ - "scenario | hexId ", - "64-bit short | '1' ", - "64-bit max chars | '123456789abcdef0' ", - "128-bit | '123456789abcdef0123456789abcdef0'", - "128-bit zero middle | '64184f2400000000123456789abcdef0'", - "128-bit all f | 'ffffffffffffffffffffffffffffffff'" + "scenario | hexId ", + "64-bit short | '1' ", + "64-bit max chars | '123456789abcdef0' ", + "128-bit | '123456789abcdef0123456789abcdef0'", + "128-bit zero middle | '64184f2400000000123456789abcdef0'", + "128-bit all f | 'ffffffffffffffffffffffffffffffff'" }) @SuppressWarnings("unchecked") void injectHttpHeadersWith128BitTraceId(String hexId) { - ListWriter writer = new ListWriter(); - CoreTracer tracer = tracerBuilder().writer(writer).build(); DD128bTraceId traceId = DD128bTraceId.fromHex(hexId); - Map baggage = new LinkedHashMap<>(); + Map baggage = new HashMap<>(); baggage.put("k1", "v1"); baggage.put("k2", "v2"); - DDSpanContext mockedContext = - new DDSpanContext( - traceId, - DDSpanId.from("2"), - DDSpanId.ZERO, - null, - "fakeService", - "fakeOperation", - "fakeResource", - UNSET, - null, - baggage, - false, - "fakeType", - 0, - tracer.createTraceCollector(DDTraceId.ONE), - null, - null, - NoopPathwayContext.INSTANCE, - false, - PropagationTags.factory() - .fromHeaderValue( - PropagationTags.HeaderType.DATADOG, "_dd.p.dm=-4,_dd.p.anytag=value")); - mockedContext.beginEndToEnd(); - String expectedT0 = String.valueOf(mockedContext.getEndToEndStartTime() / 1_000_000L); + + DDSpanContext spanContext = mockSpanContext(traceId, "2", UNSET, null, baggage, "_dd.p.dm=-4,_dd.p.anytag=value"); + spanContext.beginEndToEnd(); Map carrier = mock(Map.class); - injector.inject(mockedContext, carrier, MAP_SETTER); + this.injector.inject(spanContext, carrier, Map::put); + String expectedT0 = String.valueOf(spanContext.getEndToEndStartTime() / 1_000_000L); verify(carrier).put(TRACE_ID_KEY, traceId.toString()); verify(carrier).put(SPAN_ID_KEY, "2"); verify(carrier).put(OT_BAGGAGE_PREFIX + "t0", expectedT0); @@ -248,4 +172,44 @@ void injectHttpHeadersWith128BitTraceId(String hexId) { } verifyNoMoreInteractions(carrier); } + + private DDSpanContext mockSpanContext( + String traceId, + String spanId, + byte samplingPriority, + String origin, + Map baggage, + String ddPTags) { + return mockSpanContext(DDTraceId.from(traceId), spanId, samplingPriority, origin, baggage, ddPTags); + } + + private DDSpanContext mockSpanContext( + DDTraceId traceId, + String spanId, + byte samplingPriority, + String origin, + Map baggage, + String ddPTags) { + PropagationTags propagationTags = ddPTags == null ? PropagationTags.factory().empty() : PropagationTags.factory().fromHeaderValue(DATADOG, ddPTags); + return new DDSpanContext( + traceId, + DDSpanId.from(spanId), + DDSpanId.ZERO, + null, + "fakeService", + "fakeOperation", + "fakeResource", + samplingPriority, + origin, + baggage, + false, + "fakeType", + 0, + this.tracer.createTraceCollector(DDTraceId.ONE), + null, + null, + NoopPathwayContext.INSTANCE, + false, + propagationTags); + } } diff --git a/dd-trace-core/src/test/java/datadog/trace/core/propagation/DatadogPropagationTagsTest.java b/dd-trace-core/src/test/java/datadog/trace/core/propagation/DatadogPropagationTagsTest.java index d4a0872347f..30a9e19f8ba 100644 --- a/dd-trace-core/src/test/java/datadog/trace/core/propagation/DatadogPropagationTagsTest.java +++ b/dd-trace-core/src/test/java/datadog/trace/core/propagation/DatadogPropagationTagsTest.java @@ -130,8 +130,8 @@ void datadogPropagationTagsShouldTranslateToW3cTags( }) void updatePropagationTagsSamplingMechanism( String originalTagSet, - @ConvertWith(PrioritySamplingConverter.class) int priority, - @ConvertWith(SamplingMechanismConverter.class) int mechanism, + @ConvertWith(PrioritySamplingConverter.class) byte priority, + @ConvertWith(SamplingMechanismConverter.class) byte mechanism, String expectedHeaderValue, Map tags) { PropagationTags propagationTags = factory().fromHeaderValue(DATADOG, originalTagSet); diff --git a/dd-trace-core/src/test/java/datadog/trace/core/propagation/HttpInjectorTest.java b/dd-trace-core/src/test/java/datadog/trace/core/propagation/HttpInjectorTest.java index ed9d1ce43ed..2bed3a09032 100644 --- a/dd-trace-core/src/test/java/datadog/trace/core/propagation/HttpInjectorTest.java +++ b/dd-trace-core/src/test/java/datadog/trace/core/propagation/HttpInjectorTest.java @@ -73,7 +73,7 @@ private String idOrPadded(String id, int size) { @SuppressWarnings("unchecked") void injectHttpHeadersUsingStyles( List styles, - @ConvertWith(PrioritySamplingConverter.class) int samplingPriority, + @ConvertWith(PrioritySamplingConverter.class) byte samplingPriority, String origin) { Set styleSet = new LinkedHashSet<>(styles); Config config = mock(Config.class); @@ -143,7 +143,7 @@ void injectHttpHeadersUsingStyles( @SuppressWarnings("unchecked") void injectHttpHeadersUsingStyle( TracePropagationStyle style, - @ConvertWith(PrioritySamplingConverter.class) int samplingPriority, + @ConvertWith(PrioritySamplingConverter.class) byte samplingPriority, String origin) { Config config = mock(Config.class); when(config.isTracePropagationStyleB3PaddingEnabled()).thenReturn(tracePropagationB3Padding()); diff --git a/dd-trace-core/src/test/java/datadog/trace/core/propagation/NoneHttpExtractorTest.java b/dd-trace-core/src/test/java/datadog/trace/core/propagation/NoneHttpExtractorTest.java index 196e26691e2..6481c2ff456 100644 --- a/dd-trace-core/src/test/java/datadog/trace/core/propagation/NoneHttpExtractorTest.java +++ b/dd-trace-core/src/test/java/datadog/trace/core/propagation/NoneHttpExtractorTest.java @@ -94,7 +94,7 @@ private HttpCodec.Extractor createExtractor() { void extractHttpHeaders( String traceId, String spanId, - @ConvertWith(PrioritySamplingConverter.class) int samplingPriority, + @ConvertWith(PrioritySamplingConverter.class) byte samplingPriority, String origin, boolean allowComma) { injectEnvConfig( diff --git a/dd-trace-core/src/test/java/datadog/trace/core/propagation/W3CHttpExtractorTest.java b/dd-trace-core/src/test/java/datadog/trace/core/propagation/W3CHttpExtractorTest.java index 633bbf591b7..f72e1068b5e 100644 --- a/dd-trace-core/src/test/java/datadog/trace/core/propagation/W3CHttpExtractorTest.java +++ b/dd-trace-core/src/test/java/datadog/trace/core/propagation/W3CHttpExtractorTest.java @@ -109,7 +109,7 @@ void extractTraceparent( boolean tpValid, String traceIdHex, long spanId, - @ConvertWith(PrioritySamplingConverter.class) int priority) { + @ConvertWith(PrioritySamplingConverter.class) byte priority) { Map headers = new LinkedHashMap<>(); if (traceparent != null) { headers.put(W3CHttpCodec.TRACE_PARENT_KEY, traceparent); @@ -151,7 +151,7 @@ void checkMaxFromW3CTraceIds(String traceIdHex) { void extractTraceparentTracestateAndHttpHeaders( String traceparent, String tracestate, - @ConvertWith(PrioritySamplingConverter.class) int priority, + @ConvertWith(PrioritySamplingConverter.class) byte priority, @ConvertWith(SamplingMechanismConverter.class) Byte decisionMaker, String origin) { Map headers = new LinkedHashMap<>(); diff --git a/dd-trace-core/src/test/java/datadog/trace/core/propagation/W3CHttpInjectorTest.java b/dd-trace-core/src/test/java/datadog/trace/core/propagation/W3CHttpInjectorTest.java index c7c13da4a52..0ffdf1e6e6c 100644 --- a/dd-trace-core/src/test/java/datadog/trace/core/propagation/W3CHttpInjectorTest.java +++ b/dd-trace-core/src/test/java/datadog/trace/core/propagation/W3CHttpInjectorTest.java @@ -47,7 +47,7 @@ void setup() { void injectHttpHeaders( String traceId, String spanId, - @ConvertWith(PrioritySamplingConverter.class) int samplingPriority, + @ConvertWith(PrioritySamplingConverter.class) byte samplingPriority, String origin, String tracestate) { ListWriter writer = new ListWriter(); diff --git a/dd-trace-core/src/test/java/datadog/trace/core/propagation/W3CPropagationTagsTest.java b/dd-trace-core/src/test/java/datadog/trace/core/propagation/W3CPropagationTagsTest.java index d9e16bd86cd..bbe1eb49427 100644 --- a/dd-trace-core/src/test/java/datadog/trace/core/propagation/W3CPropagationTagsTest.java +++ b/dd-trace-core/src/test/java/datadog/trace/core/propagation/W3CPropagationTagsTest.java @@ -302,8 +302,8 @@ void w3cPropagationTagsShouldTranslateToDatadogTags( }) void propagationTagsShouldBeUpdatedBySamplingAndOrigin( String headerValue, - @ConvertWith(PrioritySamplingConverter.class) int priority, - @ConvertWith(SamplingMechanismConverter.class) int mechanism, + @ConvertWith(PrioritySamplingConverter.class) byte priority, + @ConvertWith(SamplingMechanismConverter.class) byte mechanism, String origin, String expectedHeaderValue, Map tags) { diff --git a/dd-trace-core/src/test/java/datadog/trace/core/propagation/XRayHttpExtractorTest.java b/dd-trace-core/src/test/java/datadog/trace/core/propagation/XRayHttpExtractorTest.java index 2cb32113e3b..06c63192cab 100644 --- a/dd-trace-core/src/test/java/datadog/trace/core/propagation/XRayHttpExtractorTest.java +++ b/dd-trace-core/src/test/java/datadog/trace/core/propagation/XRayHttpExtractorTest.java @@ -69,7 +69,7 @@ void extractHttpHeaders( String traceId, String spanId, String samplingPriority, - @ConvertWith(PrioritySamplingConverter.class) int expectedSamplingPriority) { + @ConvertWith(PrioritySamplingConverter.class) byte expectedSamplingPriority) { Map headers = new LinkedHashMap<>(); headers.put( "X-Amzn-Trace-Id", diff --git a/dd-trace-core/src/test/java/datadog/trace/core/propagation/XRayHttpInjectorTest.java b/dd-trace-core/src/test/java/datadog/trace/core/propagation/XRayHttpInjectorTest.java index 68c28278321..dc7a123f262 100644 --- a/dd-trace-core/src/test/java/datadog/trace/core/propagation/XRayHttpInjectorTest.java +++ b/dd-trace-core/src/test/java/datadog/trace/core/propagation/XRayHttpInjectorTest.java @@ -54,7 +54,7 @@ void setup() { void injectHttpHeaders( String traceId, String spanId, - @ConvertWith(PrioritySamplingConverter.class) int samplingPriority, + @ConvertWith(PrioritySamplingConverter.class) byte samplingPriority, String expectedTraceHeader) { ListWriter writer = new ListWriter(); TimeSource timeSource = mock(TimeSource.class); diff --git a/dd-trace-core/src/test/java/datadog/trace/core/propagation/ptags/TagKeyTest.java b/dd-trace-core/src/test/java/datadog/trace/core/propagation/ptags/TagKeyTest.java index 568c638f83f..aaa08648799 100644 --- a/dd-trace-core/src/test/java/datadog/trace/core/propagation/ptags/TagKeyTest.java +++ b/dd-trace-core/src/test/java/datadog/trace/core/propagation/ptags/TagKeyTest.java @@ -1,6 +1,7 @@ package datadog.trace.core.propagation.ptags; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotSame; import static org.junit.jupiter.api.Assertions.assertSame; @@ -8,7 +9,6 @@ import org.tabletest.junit.TableTest; class TagKeyTest { - @TableTest({ "scenario | seq1 | enc1 | seq2 | enc2 | same ", "DD/DD same | '_dd.p.foo1' | DATADOG | '_dd.p.foo1' | DATADOG | true ", @@ -25,11 +25,13 @@ void tagKeysShouldUseCachedValuesWhenAppropriate( TagKey tk1 = TagKey.from(enc1, seq1); TagKey tk2 = TagKey.from(enc2, seq2); - assertEquals(seq1, tk1.forType(enc1).toString()); - assertEquals(seq2, tk2.forType(enc2).toString()); + assertNotNull(tk1); + assertNotNull(tk2); + assertEquals(seq1, tk1.forType(enc1)); + assertEquals(seq2, tk2.forType(enc2)); if (same) { assertSame(tk1, tk2); - assertEquals(seq2, tk1.forType(enc2).toString()); + assertEquals(seq2, tk1.forType(enc2)); } else { assertNotSame(tk1, tk2); } @@ -58,11 +60,13 @@ void tagKeysShouldUseCachedValuesFromSubSequences( TagKey tk2 = TagKey.from(enc2, seq2, s2, e2); String sub2 = seq2.substring(s2, e2); - assertEquals(sub1, tk1.forType(enc1).toString()); - assertEquals(sub2, tk2.forType(enc2).toString()); + assertNotNull(tk1); + assertNotNull(tk2); + assertEquals(sub1, tk1.forType(enc1)); + assertEquals(sub2, tk2.forType(enc2)); if (same) { assertSame(tk1, tk2); - assertEquals(sub2, tk1.forType(enc2).toString()); + assertEquals(sub2, tk1.forType(enc2)); } else { assertNotSame(tk1, tk2); } diff --git a/dd-trace-core/src/test/java/datadog/trace/core/propagation/ptags/TagValueTest.java b/dd-trace-core/src/test/java/datadog/trace/core/propagation/ptags/TagValueTest.java index 5b3de5e8b4a..e1640ab332c 100644 --- a/dd-trace-core/src/test/java/datadog/trace/core/propagation/ptags/TagValueTest.java +++ b/dd-trace-core/src/test/java/datadog/trace/core/propagation/ptags/TagValueTest.java @@ -1,6 +1,7 @@ package datadog.trace.core.propagation.ptags; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotSame; import static org.junit.jupiter.api.Assertions.assertSame; @@ -8,7 +9,6 @@ import org.tabletest.junit.TableTest; class TagValueTest { - @TableTest({ "scenario | seq1 | enc1 | seq2 | enc2 | same ", "DD/DD same | 'foo1' | DATADOG | 'foo1' | DATADOG | true ", @@ -26,11 +26,13 @@ void tagValuesShouldUseCachedValuesWhenAppropriate( TagValue tv1 = TagValue.from(enc1, seq1); TagValue tv2 = TagValue.from(enc2, seq2); - assertEquals(seq1, tv1.forType(enc1).toString()); - assertEquals(seq2, tv2.forType(enc2).toString()); + assertNotNull(tv1); + assertNotNull(tv2); + assertEquals(seq1, tv1.forType(enc1)); + assertEquals(seq2, tv2.forType(enc2)); if (same) { assertSame(tv1, tv2); - assertEquals(seq2, tv1.forType(enc2).toString()); + assertEquals(seq2, tv1.forType(enc2)); } else { assertNotSame(tv1, tv2); } @@ -61,11 +63,13 @@ void tagValuesShouldUseCachedValuesFromSubSequences( TagValue tv2 = TagValue.from(enc2, seq2, s2, e2); String sub2 = seq2.substring(s2, e2); - assertEquals(sub1, tv1.forType(enc1).toString()); - assertEquals(sub2, tv2.forType(enc2).toString()); + assertNotNull(tv1); + assertNotNull(tv2); + assertEquals(sub1, tv1.forType(enc1)); + assertEquals(sub2, tv2.forType(enc2)); if (same) { assertSame(tv1, tv2); - assertEquals(sub2, tv1.forType(enc2).toString()); + assertEquals(sub2, tv1.forType(enc2)); } else { assertNotSame(tv1, tv2); } diff --git a/dd-trace-ot/src/ot31CompatibilityTest/java/datadog/opentracing/OT31ApiTest.java b/dd-trace-ot/src/ot31CompatibilityTest/java/datadog/opentracing/OT31ApiTest.java index 4f85922674b..deb7cdbcc94 100644 --- a/dd-trace-ot/src/ot31CompatibilityTest/java/datadog/opentracing/OT31ApiTest.java +++ b/dd-trace-ot/src/ot31CompatibilityTest/java/datadog/opentracing/OT31ApiTest.java @@ -96,9 +96,9 @@ void testScopeManager(String scenario, boolean finishSpan) { }) void testInjectExtract( String scenario, - @ConvertWith(PrioritySamplingConverter.class) int contextPriority, - @ConvertWith(SamplingMechanismConverter.class) int samplingMechanism, - @ConvertWith(PrioritySamplingConverter.class) int propagatedPriority) + @ConvertWith(PrioritySamplingConverter.class) byte contextPriority, + @ConvertWith(SamplingMechanismConverter.class) byte samplingMechanism, + @ConvertWith(PrioritySamplingConverter.class) byte propagatedPriority) throws Exception { io.opentracing.Span span = tracer.buildSpan("some name").start(); io.opentracing.SpanContext context = span.context(); diff --git a/dd-trace-ot/src/ot33CompatibilityTest/java/datadog/opentracing/OT33ApiTest.java b/dd-trace-ot/src/ot33CompatibilityTest/java/datadog/opentracing/OT33ApiTest.java index 20f9600540f..5e9b46cef77 100644 --- a/dd-trace-ot/src/ot33CompatibilityTest/java/datadog/opentracing/OT33ApiTest.java +++ b/dd-trace-ot/src/ot33CompatibilityTest/java/datadog/opentracing/OT33ApiTest.java @@ -82,9 +82,9 @@ void testScopeManager() { }) void testInjectExtract( String scenario, - @ConvertWith(PrioritySamplingConverter.class) int contextPriority, - @ConvertWith(SamplingMechanismConverter.class) int samplingMechanism, - @ConvertWith(PrioritySamplingConverter.class) int propagatedPriority) + @ConvertWith(PrioritySamplingConverter.class) byte contextPriority, + @ConvertWith(SamplingMechanismConverter.class) byte samplingMechanism, + @ConvertWith(PrioritySamplingConverter.class) byte propagatedPriority) throws Exception { io.opentracing.Span span = tracer.buildSpan("some name").start(); io.opentracing.SpanContext context = span.context(); diff --git a/utils/junit-utils/src/main/java/datadog/trace/junit/utils/config/WithConfigExtension.java b/utils/junit-utils/src/main/java/datadog/trace/junit/utils/config/WithConfigExtension.java index 416ba4e97ad..4c1108f5f58 100644 --- a/utils/junit-utils/src/main/java/datadog/trace/junit/utils/config/WithConfigExtension.java +++ b/utils/junit-utils/src/main/java/datadog/trace/junit/utils/config/WithConfigExtension.java @@ -71,6 +71,7 @@ public class WithConfigExtension @Override public void beforeAll(ExtensionContext context) { + // Back up config and apply class-level config values. if (originalSystemProperties == null) { saveProperties(); } From 9082a36f00f9206d5ffd7f1e895c0c75864ae1bc Mon Sep 17 00:00:00 2001 From: Bruce Bujon Date: Fri, 5 Jun 2026 10:43:42 +0200 Subject: [PATCH 2/8] fix(core): Manually cleaning up AI code --- .../propagation/DatadogHttpInjectorTest.java | 137 +++++++++--------- 1 file changed, 69 insertions(+), 68 deletions(-) diff --git a/dd-trace-core/src/test/java/datadog/trace/core/propagation/DatadogHttpInjectorTest.java b/dd-trace-core/src/test/java/datadog/trace/core/propagation/DatadogHttpInjectorTest.java index cc7e385ed10..73e8da32701 100644 --- a/dd-trace-core/src/test/java/datadog/trace/core/propagation/DatadogHttpInjectorTest.java +++ b/dd-trace-core/src/test/java/datadog/trace/core/propagation/DatadogHttpInjectorTest.java @@ -1,5 +1,6 @@ package datadog.trace.core.propagation; +import static datadog.trace.api.internal.util.LongStringUtils.toHexStringPadded; import static datadog.trace.api.sampling.PrioritySampling.UNSET; import static datadog.trace.api.sampling.PrioritySampling.USER_KEEP; import static datadog.trace.api.sampling.SamplingMechanism.MANUAL; @@ -11,15 +12,12 @@ import static datadog.trace.core.propagation.DatadogHttpCodec.TRACE_ID_KEY; import static datadog.trace.core.propagation.PropagationTags.HeaderType.DATADOG; import static java.util.Collections.singletonMap; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.junit.jupiter.api.Assertions.assertEquals; import datadog.trace.api.DD128bTraceId; import datadog.trace.api.DDSpanId; import datadog.trace.api.DDTraceId; import datadog.trace.api.datastreams.NoopPathwayContext; -import datadog.trace.api.internal.util.LongStringUtils; import datadog.trace.common.writer.ListWriter; import datadog.trace.core.CoreTracer; import datadog.trace.core.DDCoreJavaSpecification; @@ -39,7 +37,8 @@ class DatadogHttpInjectorTest extends DDCoreJavaSpecification { @BeforeEach void setup() { - this.injector = DatadogHttpCodec.newInjector(singletonMap("some-baggage-key", "SOME_CUSTOM_HEADER")); + this.injector = + DatadogHttpCodec.newInjector(singletonMap("some-baggage-key", "SOME_CUSTOM_HEADER")); ListWriter writer = new ListWriter(); this.tracer = tracerBuilder().writer(writer).build(); @@ -51,13 +50,12 @@ void tearDown() { } @TableTest({ - "scenario | traceId | spanId | samplingPriority | origin ", - "unset no origin | '1' | '2' | PrioritySampling.UNSET | ", - "keep with origin | '1' | '2' | PrioritySampling.SAMPLER_KEEP | 'saipan'", - "uint64 max unset | '18446744073709551615' | '18446744073709551614' | PrioritySampling.UNSET | 'saipan'", - "uint64 max-1 keep | '18446744073709551614' | '18446744073709551615' | PrioritySampling.SAMPLER_KEEP | " + "scenario | traceId | spanId | samplingPriority | origin ", + "unset no origin | '1' | '2' | PrioritySampling.UNSET | ", + "keep with origin | '1' | '2' | PrioritySampling.SAMPLER_KEEP | 'saipan'", + "uint64 max unset | '18446744073709551615' | '18446744073709551614' | PrioritySampling.UNSET | 'saipan'", + "uint64 max-1 keep | '18446744073709551614' | '18446744073709551615' | PrioritySampling.SAMPLER_KEEP | " }) - @SuppressWarnings("unchecked") void injectHttpHeaders( String traceId, String spanId, @@ -68,53 +66,55 @@ void injectHttpHeaders( baggage.put("k2", "v2"); baggage.put("some-baggage-key", "some-value"); - DDSpanContext spanContext = mockSpanContext(traceId, spanId, samplingPriority, origin, baggage, "_dd.p.usr=123"); - Map carrier = mock(Map.class); + DDSpanContext spanContext = + mockSpanContext(traceId, spanId, samplingPriority, origin, baggage, "_dd.p.usr=123"); + Map carrier = new HashMap<>(); this.injector.inject(spanContext, carrier, Map::put); - verify(carrier).put(TRACE_ID_KEY, traceId); - verify(carrier).put(SPAN_ID_KEY, spanId); + int expectedSize = 6; // trace_id, span_id, k1, k2, custom_header, datadog_tags + assertEquals(traceId, carrier.get(TRACE_ID_KEY)); + assertEquals(spanId, carrier.get(SPAN_ID_KEY)); if (samplingPriority != UNSET) { - verify(carrier).put(SAMPLING_PRIORITY_KEY, String.valueOf(samplingPriority)); + assertEquals(String.valueOf(samplingPriority), carrier.get(SAMPLING_PRIORITY_KEY)); + expectedSize++; } if (origin != null) { - verify(carrier).put(ORIGIN_KEY, origin); + assertEquals(origin, carrier.get(ORIGIN_KEY)); + expectedSize++; } - verify(carrier).put(OT_BAGGAGE_PREFIX + "k1", "v1"); - verify(carrier).put(OT_BAGGAGE_PREFIX + "k2", "v2"); - verify(carrier).put("SOME_CUSTOM_HEADER", "some-value"); - verify(carrier).put(DATADOG_TAGS_KEY, "_dd.p.usr=123"); - verifyNoMoreInteractions(carrier); + assertEquals("v1", carrier.get(OT_BAGGAGE_PREFIX + "k1")); + assertEquals("v2", carrier.get(OT_BAGGAGE_PREFIX + "k2")); + assertEquals("some-value", carrier.get("SOME_CUSTOM_HEADER")); + assertEquals("_dd.p.usr=123", carrier.get(DATADOG_TAGS_KEY)); + assertEquals(expectedSize, carrier.size()); } @Test - @SuppressWarnings("unchecked") void injectHttpHeadersWithEndToEnd() { Map baggage = new HashMap<>(); baggage.put("k1", "v1"); baggage.put("k2", "v2"); - DDSpanContext spanContext = mockSpanContext("1", "2", UNSET, "fakeOrigin", baggage, "_dd.p.dm=-4,_dd.p.anytag=value"); + DDSpanContext spanContext = + mockSpanContext("1", "2", UNSET, "fakeOrigin", baggage, "_dd.p.dm=-4,_dd.p.anytag=value"); spanContext.beginEndToEnd(); - - Map carrier = mock(Map.class); + Map carrier = new HashMap<>(); this.injector.inject(spanContext, carrier, Map::put); String expectedT0 = String.valueOf(spanContext.getEndToEndStartTime() / 1_000_000L); - verify(carrier).put(TRACE_ID_KEY, "1"); - verify(carrier).put(SPAN_ID_KEY, "2"); - verify(carrier).put(ORIGIN_KEY, "fakeOrigin"); - verify(carrier).put(OT_BAGGAGE_PREFIX + "t0", expectedT0); - verify(carrier).put(OT_BAGGAGE_PREFIX + "k1", "v1"); - verify(carrier).put(OT_BAGGAGE_PREFIX + "k2", "v2"); - verify(carrier).put(DATADOG_TAGS_KEY, "_dd.p.dm=-4,_dd.p.anytag=value"); - verifyNoMoreInteractions(carrier); + assertEquals("1", carrier.get(TRACE_ID_KEY)); + assertEquals("2", carrier.get(SPAN_ID_KEY)); + assertEquals("fakeOrigin", carrier.get(ORIGIN_KEY)); + assertEquals(expectedT0, carrier.get(OT_BAGGAGE_PREFIX + "t0")); + assertEquals("v1", carrier.get(OT_BAGGAGE_PREFIX + "k1")); + assertEquals("v2", carrier.get(OT_BAGGAGE_PREFIX + "k2")); + assertEquals("_dd.p.dm=-4,_dd.p.anytag=value", carrier.get(DATADOG_TAGS_KEY)); + assertEquals(7, carrier.size()); } @Test - @SuppressWarnings("unchecked") void injectTheDecisionMakerTag() { Map baggage = new HashMap<>(); baggage.put("k1", "v1"); @@ -122,55 +122,52 @@ void injectTheDecisionMakerTag() { DDSpanContext spanContext = mockSpanContext("1", "2", UNSET, "fakeOrigin", baggage, null); spanContext.setSamplingPriority(USER_KEEP, MANUAL); - Map carrier = mock(Map.class); + Map carrier = new HashMap<>(); this.injector.inject(spanContext, carrier, Map::put); - verify(carrier).put(TRACE_ID_KEY, "1"); - verify(carrier).put(SPAN_ID_KEY, "2"); - verify(carrier).put(ORIGIN_KEY, "fakeOrigin"); - verify(carrier).put(OT_BAGGAGE_PREFIX + "k1", "v1"); - verify(carrier).put(OT_BAGGAGE_PREFIX + "k2", "v2"); - verify(carrier).put("x-datadog-sampling-priority", "2"); - verify(carrier).put(DATADOG_TAGS_KEY, "_dd.p.dm=-4"); - verifyNoMoreInteractions(carrier); + assertEquals("1", carrier.get(TRACE_ID_KEY)); + assertEquals("2", carrier.get(SPAN_ID_KEY)); + assertEquals("fakeOrigin", carrier.get(ORIGIN_KEY)); + assertEquals("v1", carrier.get(OT_BAGGAGE_PREFIX + "k1")); + assertEquals("v2", carrier.get(OT_BAGGAGE_PREFIX + "k2")); + assertEquals("2", carrier.get("x-datadog-sampling-priority")); + assertEquals("_dd.p.dm=-4", carrier.get(DATADOG_TAGS_KEY)); + assertEquals(7, carrier.size()); } @TableTest({ - "scenario | hexId ", - "64-bit short | '1' ", - "64-bit max chars | '123456789abcdef0' ", - "128-bit | '123456789abcdef0123456789abcdef0'", - "128-bit zero middle | '64184f2400000000123456789abcdef0'", - "128-bit all f | 'ffffffffffffffffffffffffffffffff'" + "scenario | hexId ", + "64-bit short | '1' ", + "64-bit max chars | '123456789abcdef0' ", + "128-bit | '123456789abcdef0123456789abcdef0'", + "128-bit zero middle | '64184f2400000000123456789abcdef0'", + "128-bit all f | 'ffffffffffffffffffffffffffffffff'" }) - @SuppressWarnings("unchecked") void injectHttpHeadersWith128BitTraceId(String hexId) { DD128bTraceId traceId = DD128bTraceId.fromHex(hexId); Map baggage = new HashMap<>(); baggage.put("k1", "v1"); baggage.put("k2", "v2"); - DDSpanContext spanContext = mockSpanContext(traceId, "2", UNSET, null, baggage, "_dd.p.dm=-4,_dd.p.anytag=value"); + DDSpanContext spanContext = + mockSpanContext(traceId, "2", UNSET, null, baggage, "_dd.p.dm=-4,_dd.p.anytag=value"); spanContext.beginEndToEnd(); - Map carrier = mock(Map.class); + Map carrier = new HashMap<>(); this.injector.inject(spanContext, carrier, Map::put); String expectedT0 = String.valueOf(spanContext.getEndToEndStartTime() / 1_000_000L); - verify(carrier).put(TRACE_ID_KEY, traceId.toString()); - verify(carrier).put(SPAN_ID_KEY, "2"); - verify(carrier).put(OT_BAGGAGE_PREFIX + "t0", expectedT0); - verify(carrier).put(OT_BAGGAGE_PREFIX + "k1", "v1"); - verify(carrier).put(OT_BAGGAGE_PREFIX + "k2", "v2"); - if (traceId.toHighOrderLong() == 0) { - verify(carrier).put(DATADOG_TAGS_KEY, "_dd.p.dm=-4,_dd.p.anytag=value"); - } else { - String tIdHex = LongStringUtils.toHexStringPadded(traceId.toHighOrderLong(), 16); - verify(carrier) - .put(DATADOG_TAGS_KEY, "_dd.p.dm=-4,_dd.p.tid=" + tIdHex + ",_dd.p.anytag=value"); - } - verifyNoMoreInteractions(carrier); + String expectDdPTags = traceId.toHighOrderLong() == 0 ? + "_dd.p.dm=-4,_dd.p.anytag=value" : + "_dd.p.dm=-4,_dd.p.tid=" + toHexStringPadded(traceId.toHighOrderLong(), 16) + ",_dd.p.anytag=value"; + assertEquals(traceId.toString(), carrier.get(TRACE_ID_KEY)); + assertEquals("2", carrier.get(SPAN_ID_KEY)); + assertEquals(expectedT0, carrier.get(OT_BAGGAGE_PREFIX + "t0")); + assertEquals("v1", carrier.get(OT_BAGGAGE_PREFIX + "k1")); + assertEquals("v2", carrier.get(OT_BAGGAGE_PREFIX + "k2")); + assertEquals(expectDdPTags, carrier.get(DATADOG_TAGS_KEY)); + assertEquals(6, carrier.size()); } private DDSpanContext mockSpanContext( @@ -180,7 +177,8 @@ private DDSpanContext mockSpanContext( String origin, Map baggage, String ddPTags) { - return mockSpanContext(DDTraceId.from(traceId), spanId, samplingPriority, origin, baggage, ddPTags); + return mockSpanContext( + DDTraceId.from(traceId), spanId, samplingPriority, origin, baggage, ddPTags); } private DDSpanContext mockSpanContext( @@ -190,7 +188,10 @@ private DDSpanContext mockSpanContext( String origin, Map baggage, String ddPTags) { - PropagationTags propagationTags = ddPTags == null ? PropagationTags.factory().empty() : PropagationTags.factory().fromHeaderValue(DATADOG, ddPTags); + PropagationTags propagationTags = + ddPTags == null + ? PropagationTags.factory().empty() + : PropagationTags.factory().fromHeaderValue(DATADOG, ddPTags); return new DDSpanContext( traceId, DDSpanId.from(spanId), From aa15a8a65cb62a58bed33be2bfa4fd0c7d9ebc13 Mon Sep 17 00:00:00 2001 From: Bruce Bujon Date: Fri, 5 Jun 2026 10:51:21 +0200 Subject: [PATCH 3/8] fix(core): Manually cleaning up AI code --- .../DatadogPropagationTagsTest.java | 22 ++++--------------- 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/dd-trace-core/src/test/java/datadog/trace/core/propagation/DatadogPropagationTagsTest.java b/dd-trace-core/src/test/java/datadog/trace/core/propagation/DatadogPropagationTagsTest.java index 30a9e19f8ba..e7b823a9164 100644 --- a/dd-trace-core/src/test/java/datadog/trace/core/propagation/DatadogPropagationTagsTest.java +++ b/dd-trace-core/src/test/java/datadog/trace/core/propagation/DatadogPropagationTagsTest.java @@ -4,12 +4,10 @@ import static datadog.trace.api.sampling.SamplingMechanism.MANUAL; import static datadog.trace.core.propagation.PropagationTags.HeaderType.DATADOG; import static datadog.trace.core.propagation.PropagationTags.HeaderType.W3C; +import static datadog.trace.core.propagation.PropagationTags.factory; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import datadog.trace.api.Config; import datadog.trace.junit.utils.tabletest.PrioritySamplingConverter; import datadog.trace.junit.utils.tabletest.ProductTraceSourceConverter; import datadog.trace.junit.utils.tabletest.SamplingMechanismConverter; @@ -21,18 +19,6 @@ import org.tabletest.junit.TableTest; class DatadogPropagationTagsTest extends DDJavaSpecification { - - private PropagationTags.Factory factory; - - private PropagationTags.Factory factory() { - if (factory == null) { - Config config = mock(Config.class); - when(config.getxDatadogTagsMaxLength()).thenReturn(512); - factory = PropagationTags.factory(config); - } - return factory; - } - @TableTest({ "scenario | headerValue | expectedHeaderValue | tags ", "null input | | | [:] ", @@ -172,7 +158,7 @@ void updatePropagationTagsTraceSourcePropagation( void extractionLimitExceeded() { String tags = "_dd.p.anytag=value"; int limit = tags.length() - 1; - PropagationTags propagationTags = PropagationTags.factory(limit).fromHeaderValue(DATADOG, tags); + PropagationTags propagationTags = factory(limit).fromHeaderValue(DATADOG, tags); propagationTags.updateTraceSamplingPriority(USER_KEEP, MANUAL); @@ -187,7 +173,7 @@ void extractionLimitExceeded() { void injectionLimitExceeded() { String tags = "_dd.p.anytag=value"; int limit = tags.length(); - PropagationTags propagationTags = PropagationTags.factory(limit).fromHeaderValue(DATADOG, tags); + PropagationTags propagationTags = factory(limit).fromHeaderValue(DATADOG, tags); propagationTags.updateTraceSamplingPriority(USER_KEEP, MANUAL); @@ -199,7 +185,7 @@ void injectionLimitExceeded() { @Test void injectionLimitExceededLimit0() { - PropagationTags propagationTags = PropagationTags.factory(0).fromHeaderValue(DATADOG, ""); + PropagationTags propagationTags = factory(0).fromHeaderValue(DATADOG, ""); propagationTags.updateTraceSamplingPriority(USER_KEEP, MANUAL); From 38e271f479707717a22f1258be6b9d8a03d4272a Mon Sep 17 00:00:00 2001 From: Bruce Bujon Date: Fri, 5 Jun 2026 11:00:21 +0200 Subject: [PATCH 4/8] fix(core): Manually cleaning up AI code --- .../propagation/DatadogHttpExtractorTest.java | 6 +- .../propagation/DatadogHttpInjectorTest.java | 9 +- .../HaystackHttpExtractorTest.java | 82 ++++++++++--------- 3 files changed, 53 insertions(+), 44 deletions(-) diff --git a/dd-trace-core/src/test/java/datadog/trace/core/propagation/DatadogHttpExtractorTest.java b/dd-trace-core/src/test/java/datadog/trace/core/propagation/DatadogHttpExtractorTest.java index d25747f41a1..5262bebd1b3 100644 --- a/dd-trace-core/src/test/java/datadog/trace/core/propagation/DatadogHttpExtractorTest.java +++ b/dd-trace-core/src/test/java/datadog/trace/core/propagation/DatadogHttpExtractorTest.java @@ -53,8 +53,8 @@ class DatadogHttpExtractorTest extends DDJavaSpecification { private static final String SOME_BAGGAGE = "some-baggage"; private static final String SOME_CASE_SENSITIVE_BAGGAGE = "some-CaseSensitive-baggage"; - private boolean origAppSecActive; private HttpCodec.Extractor extractor; + private boolean origAppSecActive; @BeforeEach void setup() { @@ -216,8 +216,8 @@ void extractHeadersWithXForwarding() { @Test void extractEmptyHeadersReturnsNull() { - Map carrier = singletonMap("ignored-header", "ignored-value"); - assertNull(this.extractor.extract(carrier, stringValuesMap())); + Map headers = singletonMap("ignored-header", "ignored-value"); + assertNull(this.extractor.extract(headers, stringValuesMap())); } @Test diff --git a/dd-trace-core/src/test/java/datadog/trace/core/propagation/DatadogHttpInjectorTest.java b/dd-trace-core/src/test/java/datadog/trace/core/propagation/DatadogHttpInjectorTest.java index 73e8da32701..1369bc5fd82 100644 --- a/dd-trace-core/src/test/java/datadog/trace/core/propagation/DatadogHttpInjectorTest.java +++ b/dd-trace-core/src/test/java/datadog/trace/core/propagation/DatadogHttpInjectorTest.java @@ -158,9 +158,12 @@ void injectHttpHeadersWith128BitTraceId(String hexId) { this.injector.inject(spanContext, carrier, Map::put); String expectedT0 = String.valueOf(spanContext.getEndToEndStartTime() / 1_000_000L); - String expectDdPTags = traceId.toHighOrderLong() == 0 ? - "_dd.p.dm=-4,_dd.p.anytag=value" : - "_dd.p.dm=-4,_dd.p.tid=" + toHexStringPadded(traceId.toHighOrderLong(), 16) + ",_dd.p.anytag=value"; + String expectDdPTags = + traceId.toHighOrderLong() == 0 + ? "_dd.p.dm=-4,_dd.p.anytag=value" + : "_dd.p.dm=-4,_dd.p.tid=" + + toHexStringPadded(traceId.toHighOrderLong(), 16) + + ",_dd.p.anytag=value"; assertEquals(traceId.toString(), carrier.get(TRACE_ID_KEY)); assertEquals("2", carrier.get(SPAN_ID_KEY)); assertEquals(expectedT0, carrier.get(OT_BAGGAGE_PREFIX + "t0")); diff --git a/dd-trace-core/src/test/java/datadog/trace/core/propagation/HaystackHttpExtractorTest.java b/dd-trace-core/src/test/java/datadog/trace/core/propagation/HaystackHttpExtractorTest.java index 7f8c81dac37..4121b7ebff7 100644 --- a/dd-trace-core/src/test/java/datadog/trace/core/propagation/HaystackHttpExtractorTest.java +++ b/dd-trace-core/src/test/java/datadog/trace/core/propagation/HaystackHttpExtractorTest.java @@ -1,11 +1,16 @@ package datadog.trace.core.propagation; +import static datadog.trace.api.config.TracerConfig.PROPAGATION_EXTRACT_LOG_HEADER_NAMES_ENABLED; +import static datadog.trace.api.sampling.PrioritySampling.SAMPLER_KEEP; +import static datadog.trace.bootstrap.ActiveSubsystems.APPSEC_ACTIVE; import static datadog.trace.bootstrap.instrumentation.api.ContextVisitors.stringValuesMap; +import static datadog.trace.core.CoreTracer.TRACE_ID_MAX; import static datadog.trace.core.propagation.HaystackHttpCodec.HAYSTACK_SPAN_ID_BAGGAGE_KEY; import static datadog.trace.core.propagation.HaystackHttpCodec.HAYSTACK_TRACE_ID_BAGGAGE_KEY; import static datadog.trace.core.propagation.HaystackHttpCodec.OT_BAGGAGE_PREFIX; import static datadog.trace.core.propagation.HaystackHttpCodec.SPAN_ID_KEY; import static datadog.trace.core.propagation.HaystackHttpCodec.TRACE_ID_KEY; +import static java.math.BigInteger.ONE; import static java.util.Collections.singletonMap; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -17,19 +22,17 @@ import datadog.trace.api.DDSpanId; import datadog.trace.api.DDTraceId; import datadog.trace.api.DynamicConfig; -import datadog.trace.api.sampling.PrioritySampling; -import datadog.trace.bootstrap.ActiveSubsystems; import datadog.trace.bootstrap.instrumentation.api.TagContext; import datadog.trace.junit.utils.config.WithConfig; import datadog.trace.test.util.DDJavaSpecification; -import java.util.LinkedHashMap; +import java.util.HashMap; import java.util.Map; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.tabletest.junit.TableTest; -@WithConfig(key = "propagation.extract.log_header_names.enabled", value = "true") +@WithConfig(key = PROPAGATION_EXTRACT_LOG_HEADER_NAMES_ENABLED, value = "true") class HaystackHttpExtractorTest extends DDJavaSpecification { private static final String SOME_HEADER = "SOME_HEADER"; @@ -45,7 +48,7 @@ class HaystackHttpExtractorTest extends DDJavaSpecification { @BeforeEach void setup() { - Map baggageMap = new LinkedHashMap<>(); + Map baggageMap = new HashMap<>(); baggageMap.put(SOME_CUSTOM_BAGGAGE_HEADER, SOME_BAGGAGE); baggageMap.put(SOME_CUSTOM_BAGGAGE_HEADER_2, SOME_CASE_SENSITIVE_BAGGAGE); DynamicConfig dynamicConfig = @@ -53,15 +56,16 @@ void setup() { .setHeaderTags(singletonMap(SOME_HEADER, SOME_TAG)) .setBaggageMapping(baggageMap) .apply(); - extractor = - HaystackHttpCodec.newExtractor(Config.get(), () -> dynamicConfig.captureTraceConfig()); - origAppSecActive = ActiveSubsystems.APPSEC_ACTIVE; - ActiveSubsystems.APPSEC_ACTIVE = true; + this.extractor = + HaystackHttpCodec.newExtractor(Config.get(), dynamicConfig::captureTraceConfig); + + this.origAppSecActive = APPSEC_ACTIVE; + APPSEC_ACTIVE = true; } @AfterEach void teardown() { - ActiveSubsystems.APPSEC_ACTIVE = origAppSecActive; + APPSEC_ACTIVE = origAppSecActive; } @TableTest({ @@ -72,7 +76,7 @@ void teardown() { "uint64 max-1 | '18446744073709551614' | '18446744073709551608' | '44617461-646f-6721-ffff-fffffffffffe' | '44617461-646f-6721-ffff-fffffffffff8'" }) void extractHttpHeaders(String traceId, String spanId, String traceUuid, String spanUuid) { - Map headers = new LinkedHashMap<>(); + Map headers = new HashMap<>(); headers.put("", "empty key"); headers.put(TRACE_ID_KEY.toUpperCase(), traceUuid); headers.put(SPAN_ID_KEY.toUpperCase(), spanUuid); @@ -83,11 +87,12 @@ void extractHttpHeaders(String traceId, String spanId, String traceUuid, String headers.put(SOME_CUSTOM_BAGGAGE_HEADER, "my-interesting-baggage-info"); headers.put(SOME_CUSTOM_BAGGAGE_HEADER_2, "my-interesting-baggage-info-2"); - ExtractedContext context = (ExtractedContext) extractor.extract(headers, stringValuesMap()); + ExtractedContext context = + (ExtractedContext) this.extractor.extract(headers, stringValuesMap()); assertEquals(DDTraceId.from(traceId), context.getTraceId()); assertEquals(DDSpanId.from(spanId), context.getSpanId()); - Map expectedBaggage = new LinkedHashMap<>(); + Map expectedBaggage = new HashMap<>(); expectedBaggage.put("k1", "v1"); expectedBaggage.put("k2", "v2"); expectedBaggage.put("k3", "%76%33"); // expect value decoded only once @@ -97,7 +102,7 @@ void extractHttpHeaders(String traceId, String spanId, String traceUuid, String expectedBaggage.put(SOME_CASE_SENSITIVE_BAGGAGE, "my-interesting-baggage-info-2"); assertEquals(expectedBaggage, context.getBaggage()); assertEquals(singletonMap(SOME_TAG, "my-interesting-info"), context.getTags()); - assertEquals(PrioritySampling.SAMPLER_KEEP, context.getSamplingPriority()); + assertEquals(SAMPLER_KEEP, context.getSamplingPriority()); assertNull(context.getOrigin()); } @@ -105,7 +110,7 @@ void extractHttpHeaders(String traceId, String spanId, String traceUuid, String void extractHeaderTagsWithNoPropagation() { Map headers = singletonMap(SOME_HEADER, "my-interesting-info"); - TagContext context = extractor.extract(headers, stringValuesMap()); + TagContext context = this.extractor.extract(headers, stringValuesMap()); assertFalse(context instanceof ExtractedContext); assertEquals(singletonMap(SOME_TAG, "my-interesting-info"), context.getTags()); @@ -117,18 +122,18 @@ void extractHeadersWithForwarding() { String forwardedPort = "123"; String forwarded = "for=" + forwardedIp + ":" + forwardedPort; Map tagOnlyCtx = singletonMap("Forwarded", forwarded); - Map fullCtx = new LinkedHashMap<>(); + Map fullCtx = new HashMap<>(); fullCtx.put(TRACE_ID_KEY.toUpperCase(), "1"); fullCtx.put(SPAN_ID_KEY.toUpperCase(), "2"); fullCtx.put("Forwarded", forwarded); - TagContext context = extractor.extract(tagOnlyCtx, stringValuesMap()); + TagContext context = this.extractor.extract(tagOnlyCtx, stringValuesMap()); assertNotNull(context); assertFalse(context instanceof ExtractedContext); assertEquals(forwarded, context.getForwarded()); - context = extractor.extract(fullCtx, stringValuesMap()); + context = this.extractor.extract(fullCtx, stringValuesMap()); assertInstanceOf(ExtractedContext.class, context); assertEquals(1L, context.getTraceId().toLong()); @@ -140,22 +145,22 @@ void extractHeadersWithForwarding() { void extractHeadersWithXForwarding() { String forwardedIp = "1.2.3.4"; String forwardedPort = "123"; - Map tagOnlyCtx = new LinkedHashMap<>(); + Map tagOnlyCtx = new HashMap<>(); tagOnlyCtx.put("X-Forwarded-For", forwardedIp); tagOnlyCtx.put("X-Forwarded-Port", forwardedPort); - Map fullCtx = new LinkedHashMap<>(); + Map fullCtx = new HashMap<>(); fullCtx.put(TRACE_ID_KEY.toUpperCase(), "1"); fullCtx.put(SPAN_ID_KEY.toUpperCase(), "2"); fullCtx.put("x-forwarded-for", forwardedIp); fullCtx.put("x-forwarded-port", forwardedPort); - TagContext context = extractor.extract(tagOnlyCtx, stringValuesMap()); + TagContext context = this.extractor.extract(tagOnlyCtx, stringValuesMap()); assertNotNull(context); assertEquals(forwardedIp, context.getXForwardedFor()); assertEquals(forwardedPort, context.getXForwardedPort()); - context = extractor.extract(fullCtx, stringValuesMap()); + context = this.extractor.extract(fullCtx, stringValuesMap()); assertInstanceOf(ExtractedContext.class, context); assertEquals(1L, context.getTraceId().toLong()); @@ -166,48 +171,49 @@ void extractHeadersWithXForwarding() { @Test void extractEmptyHeadersReturnsNull() { - assertNull( - extractor.extract(singletonMap("ignored-header", "ignored-value"), stringValuesMap())); + Map headers = singletonMap("ignored-header", "ignored-value"); + assertNull(this.extractor.extract(headers, stringValuesMap())); } @Test void extractHttpHeadersWithInvalidNonNumericId() { - Map headers = new LinkedHashMap<>(); + Map headers = new HashMap<>(); headers.put(TRACE_ID_KEY.toUpperCase(), "traceId"); headers.put(SPAN_ID_KEY.toUpperCase(), "spanId"); headers.put((OT_BAGGAGE_PREFIX + "k1").toUpperCase(), "v1"); headers.put((OT_BAGGAGE_PREFIX + "k2").toUpperCase(), "v2"); headers.put(SOME_HEADER, "my-interesting-info"); - TagContext context = extractor.extract(headers, stringValuesMap()); + TagContext context = this.extractor.extract(headers, stringValuesMap()); assertNull(context); } @Test void extractHttpHeadersWithOutOfRangeTraceId() { - Map headers = new LinkedHashMap<>(); - headers.put(TRACE_ID_KEY.toUpperCase(), "18446744073709551616"); // TRACE_ID_MAX + 1 + String outOfRangeTraceId = TRACE_ID_MAX.add(ONE).toString(); + Map headers = new HashMap<>(); + headers.put(TRACE_ID_KEY.toUpperCase(), outOfRangeTraceId); headers.put(SPAN_ID_KEY.toUpperCase(), "0"); headers.put((OT_BAGGAGE_PREFIX + "k1").toUpperCase(), "v1"); headers.put((OT_BAGGAGE_PREFIX + "k2").toUpperCase(), "v2"); headers.put(SOME_HEADER, "my-interesting-info"); - TagContext context = extractor.extract(headers, stringValuesMap()); + TagContext context = this.extractor.extract(headers, stringValuesMap()); assertNull(context); } @Test void extractHttpHeadersWithOutOfRangeSpanId() { - Map headers = new LinkedHashMap<>(); + Map headers = new HashMap<>(); headers.put(TRACE_ID_KEY.toUpperCase(), "0"); headers.put(SPAN_ID_KEY.toUpperCase(), "-1"); headers.put((OT_BAGGAGE_PREFIX + "k1").toUpperCase(), "v1"); headers.put((OT_BAGGAGE_PREFIX + "k2").toUpperCase(), "v2"); headers.put(SOME_HEADER, "my-interesting-info"); - TagContext context = extractor.extract(headers, stringValuesMap()); + TagContext context = this.extractor.extract(headers, stringValuesMap()); assertNull(context); } @@ -220,7 +226,7 @@ void extractHttpHeadersWithOutOfRangeSpanId() { "uuid format | '44617461-646f-6721-463a-c35c9f6413ad' | '44617461-646f-6721-463a-c35c9f6413ad' | true " }) void baggageIsMappedOnContextCreation(String traceId, String spanId, boolean ctxCreated) { - Map headers = new LinkedHashMap<>(); + Map headers = new HashMap<>(); headers.put(TRACE_ID_KEY.toUpperCase(), traceId); headers.put(SPAN_ID_KEY.toUpperCase(), spanId); headers.put(SOME_CUSTOM_BAGGAGE_HEADER, "mappedBaggageValue"); @@ -228,11 +234,11 @@ void baggageIsMappedOnContextCreation(String traceId, String spanId, boolean ctx headers.put((OT_BAGGAGE_PREFIX + "k2").toUpperCase(), "v2"); headers.put(SOME_ARBITRARY_HEADER, "my-interesting-info"); - TagContext context = extractor.extract(headers, stringValuesMap()); + TagContext context = this.extractor.extract(headers, stringValuesMap()); if (ctxCreated) { assertNotNull(context); - Map expectedBaggage = new LinkedHashMap<>(); + Map expectedBaggage = new HashMap<>(); expectedBaggage.put(HAYSTACK_TRACE_ID_BAGGAGE_KEY, traceId); expectedBaggage.put(HAYSTACK_SPAN_ID_BAGGAGE_KEY, spanId); expectedBaggage.put(SOME_BAGGAGE, "mappedBaggageValue"); @@ -267,11 +273,11 @@ void extract128BitIdTruncatesIdTo64Bit( Long expectedTraceIdLong, long expectedSpanId, boolean ctxCreated) { - Map headers = new LinkedHashMap<>(); + Map headers = new HashMap<>(); headers.put(TRACE_ID_KEY.toUpperCase(), traceId); headers.put(SPAN_ID_KEY.toUpperCase(), spanId); - TagContext context = extractor.extract(headers, stringValuesMap()); + TagContext context = this.extractor.extract(headers, stringValuesMap()); if (expectedTraceIdLong != null) { assertEquals(DDTraceId.from(expectedTraceIdLong), context.getTraceId()); @@ -286,7 +292,7 @@ void extract128BitIdTruncatesIdTo64Bit( @Test void extractCommonHttpHeaders() { - Map headers = new LinkedHashMap<>(); + Map headers = new HashMap<>(); headers.put(HttpCodec.USER_AGENT_KEY, "some-user-agent"); headers.put(HttpCodec.X_CLUSTER_CLIENT_IP_KEY, "1.1.1.1"); headers.put(HttpCodec.X_REAL_IP_KEY, "2.2.2.2"); @@ -298,7 +304,7 @@ void extractCommonHttpHeaders() { headers.put(HttpCodec.CF_CONNECTING_IP_KEY, "8.8.8.8"); headers.put(HttpCodec.CF_CONNECTING_IP_V6_KEY, "9.9.9.9"); - TagContext context = extractor.extract(headers, stringValuesMap()); + TagContext context = this.extractor.extract(headers, stringValuesMap()); assertEquals("some-user-agent", context.getUserAgent()); assertEquals("1.1.1.1", context.getXClusterClientIp()); From 368fb9e613ac693f0d3038579e6e1b1bb7037fa8 Mon Sep 17 00:00:00 2001 From: Bruce Bujon Date: Fri, 5 Jun 2026 11:17:14 +0200 Subject: [PATCH 5/8] fix(core): Manually cleaning up AI code --- .../core/propagation/HaystackHttpCodec.java | 2 +- .../propagation/HaystackHttpInjectorTest.java | 153 +++++++++--------- 2 files changed, 75 insertions(+), 80 deletions(-) diff --git a/dd-trace-core/src/main/java/datadog/trace/core/propagation/HaystackHttpCodec.java b/dd-trace-core/src/main/java/datadog/trace/core/propagation/HaystackHttpCodec.java index 7913025de31..90573ea763b 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/propagation/HaystackHttpCodec.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/propagation/HaystackHttpCodec.java @@ -32,7 +32,7 @@ class HaystackHttpCodec { static final String OT_BAGGAGE_PREFIX = "Baggage-"; static final String TRACE_ID_KEY = "Trace-ID"; static final String SPAN_ID_KEY = "Span-ID"; - private static final String PARENT_ID_KEY = "Parent-ID"; + static final String PARENT_ID_KEY = "Parent-ID"; static final String DD_TRACE_ID_BAGGAGE_KEY = OT_BAGGAGE_PREFIX + "Datadog-Trace-Id"; static final String DD_SPAN_ID_BAGGAGE_KEY = OT_BAGGAGE_PREFIX + "Datadog-Span-Id"; diff --git a/dd-trace-core/src/test/java/datadog/trace/core/propagation/HaystackHttpInjectorTest.java b/dd-trace-core/src/test/java/datadog/trace/core/propagation/HaystackHttpInjectorTest.java index 84a39dcb218..7e5b02e76f5 100644 --- a/dd-trace-core/src/test/java/datadog/trace/core/propagation/HaystackHttpInjectorTest.java +++ b/dd-trace-core/src/test/java/datadog/trace/core/propagation/HaystackHttpInjectorTest.java @@ -6,14 +6,12 @@ import static datadog.trace.core.propagation.HaystackHttpCodec.DD_TRACE_ID_BAGGAGE_KEY; import static datadog.trace.core.propagation.HaystackHttpCodec.HAYSTACK_TRACE_ID_BAGGAGE_KEY; import static datadog.trace.core.propagation.HaystackHttpCodec.OT_BAGGAGE_PREFIX; +import static datadog.trace.core.propagation.HaystackHttpCodec.PARENT_ID_KEY; import static datadog.trace.core.propagation.HaystackHttpCodec.SPAN_ID_KEY; import static datadog.trace.core.propagation.HaystackHttpCodec.TRACE_ID_KEY; import static java.util.Collections.singletonMap; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import datadog.context.propagation.CarrierSetter; import datadog.trace.api.DDSpanId; import datadog.trace.api.DDTraceId; import datadog.trace.api.datastreams.NoopPathwayContext; @@ -21,16 +19,32 @@ import datadog.trace.core.CoreTracer; import datadog.trace.core.DDCoreJavaSpecification; import datadog.trace.core.DDSpanContext; -import java.util.LinkedHashMap; +import java.util.HashMap; import java.util.Map; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.tabletest.junit.TableTest; class HaystackHttpInjectorTest extends DDCoreJavaSpecification { + // UUID representation of DDSpanId.ZERO + private static final String ZERO_UUID = "44617461-646f-6721-0000-000000000000"; - private static final CarrierSetter> MAP_SETTER = Map::put; + private HttpCodec.Injector injector; + private CoreTracer tracer; - private final HttpCodec.Injector injector = - HaystackHttpCodec.newInjector(singletonMap("some-baggage-key", "SOME_CUSTOM_HEADER")); + @BeforeEach + void setup() { + Map baggageMap = singletonMap("some-baggage-key", "SOME_CUSTOM_HEADER"); + this.injector = HaystackHttpCodec.newInjector(baggageMap); + + ListWriter writer = new ListWriter(); + this.tracer = tracerBuilder().writer(writer).build(); + } + + @AfterEach + void tearDown() { + this.tracer.close(); + } @TableTest({ "scenario | traceId | spanId | traceUuid | spanUuid ", @@ -39,50 +53,27 @@ class HaystackHttpInjectorTest extends DDCoreJavaSpecification { "uint64 max trace | '18446744073709551615' | '18446744073709551614' | '44617461-646f-6721-ffff-ffffffffffff' | '44617461-646f-6721-ffff-fffffffffffe'", "uint64 max-1 trace | '18446744073709551614' | '18446744073709551615' | '44617461-646f-6721-ffff-fffffffffffe' | '44617461-646f-6721-ffff-ffffffffffff'" }) - @SuppressWarnings("unchecked") void injectHttpHeaders(String traceId, String spanId, String traceUuid, String spanUuid) { - ListWriter writer = new ListWriter(); - CoreTracer tracer = tracerBuilder().writer(writer).build(); - Map baggage = new LinkedHashMap<>(); + Map baggage = new HashMap<>(); baggage.put("k1", "v1"); baggage.put("k2", "v2"); baggage.put("some-baggage-key", "some-value"); - DDSpanContext mockedContext = - new DDSpanContext( - DDTraceId.from(traceId), - DDSpanId.from(spanId), - DDSpanId.ZERO, - null, - "fakeService", - "fakeOperation", - "fakeResource", - SAMPLER_KEEP, - null, - baggage, - false, - "fakeType", - 0, - tracer.createTraceCollector(DDTraceId.ONE), - null, - null, - NoopPathwayContext.INSTANCE, - false, - null); - Map carrier = mock(Map.class); - - injector.inject(mockedContext, carrier, MAP_SETTER); + DDSpanContext spanContext = mockSpanContext(traceId, spanId, baggage); + Map carrier = new HashMap<>(); - verify(carrier).put(TRACE_ID_KEY, traceUuid); - assertEquals(traceUuid, mockedContext.getTags().get(HAYSTACK_TRACE_ID_BAGGAGE_KEY)); - verify(carrier).put(DD_TRACE_ID_BAGGAGE_KEY, traceId); - verify(carrier).put(SPAN_ID_KEY, spanUuid); - verify(carrier).put(DD_SPAN_ID_BAGGAGE_KEY, spanId); - verify(carrier).put(OT_BAGGAGE_PREFIX + "k1", "v1"); - verify(carrier).put(OT_BAGGAGE_PREFIX + "k2", "v2"); - verify(carrier).put("SOME_CUSTOM_HEADER", "some-value"); - verify(carrier).put(DD_PARENT_ID_BAGGAGE_KEY, "0"); + this.injector.inject(spanContext, carrier, Map::put); - tracer.close(); + assertEquals(traceUuid, carrier.get(TRACE_ID_KEY)); + assertEquals(traceUuid, spanContext.unsafeGetTag(HAYSTACK_TRACE_ID_BAGGAGE_KEY)); + assertEquals(traceId, carrier.get(DD_TRACE_ID_BAGGAGE_KEY)); + assertEquals(spanUuid, carrier.get(SPAN_ID_KEY)); + assertEquals(spanId, carrier.get(DD_SPAN_ID_BAGGAGE_KEY)); + assertEquals(ZERO_UUID, carrier.get(PARENT_ID_KEY)); + assertEquals("0", carrier.get(DD_PARENT_ID_BAGGAGE_KEY)); + assertEquals("v1", carrier.get(OT_BAGGAGE_PREFIX + "k1")); + assertEquals("v2", carrier.get(OT_BAGGAGE_PREFIX + "k2")); + assertEquals("some-value", carrier.get("SOME_CUSTOM_HEADER")); + assertEquals(9, carrier.size()); } @TableTest({ @@ -92,47 +83,51 @@ void injectHttpHeaders(String traceId, String spanId, String traceUuid, String s "uint64 max trace | '18446744073709551615' | '18446744073709551614' | '54617461-646f-6721-ffff-ffffffffffff' | '44617461-646f-6721-ffff-fffffffffffe'", "uint64 max-1 trace | '18446744073709551614' | '18446744073709551615' | '54617461-646f-6721-ffff-fffffffffffe' | '44617461-646f-6721-ffff-ffffffffffff'" }) - @SuppressWarnings("unchecked") void injectHttpHeadersWithHaystackTraceIdInBaggage( String traceId, String spanId, String traceUuid, String spanUuid) { - ListWriter writer = new ListWriter(); - CoreTracer tracer = tracerBuilder().writer(writer).build(); - Map baggage = new LinkedHashMap<>(); + Map baggage = new HashMap<>(); baggage.put("k1", "v1"); baggage.put("k2", "v2"); baggage.put(HAYSTACK_TRACE_ID_BAGGAGE_KEY, traceUuid); - DDSpanContext mockedContext = - new DDSpanContext( - DDTraceId.from(traceId), - DDSpanId.from(spanId), - DDSpanId.ZERO, - null, - "fakeService", - "fakeOperation", - "fakeResource", - SAMPLER_KEEP, - null, - baggage, - false, - "fakeType", - 0, - tracer.createTraceCollector(DDTraceId.ONE), - null, - null, - NoopPathwayContext.INSTANCE, - false, - null); - Map carrier = mock(Map.class); + DDSpanContext spanContext = mockSpanContext(traceId, spanId, baggage); + Map carrier = new HashMap<>(); - injector.inject(mockedContext, carrier, MAP_SETTER); + injector.inject(spanContext, carrier, Map::put); - verify(carrier).put(TRACE_ID_KEY, traceUuid); - verify(carrier).put(DD_TRACE_ID_BAGGAGE_KEY, traceId); - verify(carrier).put(SPAN_ID_KEY, spanUuid); - verify(carrier).put(DD_SPAN_ID_BAGGAGE_KEY, spanId); - verify(carrier).put(OT_BAGGAGE_PREFIX + "k1", "v1"); - verify(carrier).put(OT_BAGGAGE_PREFIX + "k2", "v2"); + assertEquals(traceUuid, carrier.get(TRACE_ID_KEY)); + assertEquals(traceUuid, spanContext.unsafeGetTag(HAYSTACK_TRACE_ID_BAGGAGE_KEY)); + assertEquals(traceId, carrier.get(DD_TRACE_ID_BAGGAGE_KEY)); + assertEquals(spanUuid, carrier.get(SPAN_ID_KEY)); + assertEquals(spanId, carrier.get(DD_SPAN_ID_BAGGAGE_KEY)); + assertEquals(ZERO_UUID, carrier.get(PARENT_ID_KEY)); + assertEquals("0", carrier.get(DD_PARENT_ID_BAGGAGE_KEY)); + assertEquals("v1", carrier.get(OT_BAGGAGE_PREFIX + "k1")); + assertEquals("v2", carrier.get(OT_BAGGAGE_PREFIX + "k2")); + assertEquals(traceUuid, carrier.get(OT_BAGGAGE_PREFIX + "Haystack-Trace-ID")); + assertEquals(9, carrier.size()); + } - tracer.close(); + private DDSpanContext mockSpanContext( + String traceId, String spanId, Map baggage) { + return new DDSpanContext( + DDTraceId.from(traceId), + DDSpanId.from(spanId), + DDSpanId.ZERO, + null, + "fakeService", + "fakeOperation", + "fakeResource", + SAMPLER_KEEP, + null, + baggage, + false, + "fakeType", + 0, + this.tracer.createTraceCollector(DDTraceId.ONE), + null, + null, + NoopPathwayContext.INSTANCE, + false, + null); } } From 1056ccbbeeaeb326c04a03648905dc4c2b8e1186 Mon Sep 17 00:00:00 2001 From: Bruce Bujon Date: Fri, 5 Jun 2026 11:18:57 +0200 Subject: [PATCH 6/8] fix(core): Manually cleaning up AI code --- .../trace/core/propagation/HaystackHttpExtractorTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/dd-trace-core/src/test/java/datadog/trace/core/propagation/HaystackHttpExtractorTest.java b/dd-trace-core/src/test/java/datadog/trace/core/propagation/HaystackHttpExtractorTest.java index 4121b7ebff7..524ca59fa61 100644 --- a/dd-trace-core/src/test/java/datadog/trace/core/propagation/HaystackHttpExtractorTest.java +++ b/dd-trace-core/src/test/java/datadog/trace/core/propagation/HaystackHttpExtractorTest.java @@ -65,6 +65,7 @@ void setup() { @AfterEach void teardown() { + this.extractor.cleanup(); APPSEC_ACTIVE = origAppSecActive; } From 02a86a1fa4ef7ed878cc7c19617b5cb8c3a27061 Mon Sep 17 00:00:00 2001 From: Bruce Bujon Date: Fri, 5 Jun 2026 12:50:33 +0200 Subject: [PATCH 7/8] fix(core): Manually cleaning up AI code --- .../datadog/trace/core/propagation/B3HttpExtractorTest.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dd-trace-core/src/test/java/datadog/trace/core/propagation/B3HttpExtractorTest.java b/dd-trace-core/src/test/java/datadog/trace/core/propagation/B3HttpExtractorTest.java index 57cafd002a1..d171f282323 100644 --- a/dd-trace-core/src/test/java/datadog/trace/core/propagation/B3HttpExtractorTest.java +++ b/dd-trace-core/src/test/java/datadog/trace/core/propagation/B3HttpExtractorTest.java @@ -25,6 +25,7 @@ import datadog.trace.junit.utils.tabletest.PrioritySamplingConverter; import datadog.trace.test.util.DDJavaSpecification; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -106,7 +107,7 @@ void extractHttpHeadersWithB3HeaderAtTheBeginning( @ConvertWith(PrioritySamplingConverter.class) byte expectedSamplingPriority) { String traceIdHex = "1"; String spanIdHex = "2"; - Map headers = new HashMap<>(); + Map headers = new LinkedHashMap<>(); headers.put("", "empty key"); headers.put(B3_KEY, b3); headers.put(TRACE_ID_KEY.toUpperCase(), traceIdHex); @@ -135,7 +136,7 @@ void extractHttpHeadersWithB3HeaderAtTheEnd( @ConvertWith(PrioritySamplingConverter.class) byte expectedSamplingPriority) { String traceIdHex = "1"; String spanIdHex = "2"; - Map headers = new HashMap<>(); + Map headers = new LinkedHashMap<>(); headers.put("", "empty key"); headers.put(TRACE_ID_KEY.toUpperCase(), traceIdHex); headers.put(SPAN_ID_KEY.toUpperCase(), spanIdHex); From adf8e114412a67b385e7d1cc511017da26f67b9e Mon Sep 17 00:00:00 2001 From: Bruce Bujon Date: Fri, 5 Jun 2026 13:07:18 +0200 Subject: [PATCH 8/8] fix(core): Manually cleaning up AI code --- .../core/propagation/HttpExtractorTest.java | 117 +++++++++--------- 1 file changed, 61 insertions(+), 56 deletions(-) diff --git a/dd-trace-core/src/test/java/datadog/trace/core/propagation/HttpExtractorTest.java b/dd-trace-core/src/test/java/datadog/trace/core/propagation/HttpExtractorTest.java index fec64c12662..28126cb724b 100644 --- a/dd-trace-core/src/test/java/datadog/trace/core/propagation/HttpExtractorTest.java +++ b/dd-trace-core/src/test/java/datadog/trace/core/propagation/HttpExtractorTest.java @@ -3,10 +3,13 @@ import static datadog.trace.api.DDTags.PARENT_ID; import static datadog.trace.api.TracePropagationStyle.TRACECONTEXT; import static datadog.trace.bootstrap.instrumentation.api.ContextVisitors.stringValuesMap; +import static datadog.trace.core.propagation.B3HttpCodec.B3_SPAN_ID; +import static datadog.trace.core.propagation.B3HttpCodec.B3_TRACE_ID; import static java.util.Collections.emptyMap; import static java.util.Collections.singletonMap; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -19,6 +22,7 @@ import datadog.trace.bootstrap.instrumentation.api.AgentSpanLink; import datadog.trace.bootstrap.instrumentation.api.TagContext; import datadog.trace.test.util.DDJavaSpecification; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; @@ -87,7 +91,7 @@ void extractHttpHeadersUsingStyles( boolean tagContext, boolean extractFirst) { Config config = mock(Config.class); - when(config.getTracePropagationStylesToExtract()).thenReturn(linkedHashSetOf(styles)); + when(config.getTracePropagationStylesToExtract()).thenReturn(orderedSetOf(styles)); when(config.isTracePropagationExtractFirst()).thenReturn(extractFirst); DynamicConfig dynamicConfig = DynamicConfig.create() @@ -95,29 +99,20 @@ void extractHttpHeadersUsingStyles( .setBaggageMapping(emptyMap()) .apply(); HttpCodec.Extractor extractor = - HttpCodec.createExtractor(config, () -> dynamicConfig.captureTraceConfig()); + HttpCodec.createExtractor(config, dynamicConfig::captureTraceConfig); - Map actual = new LinkedHashMap<>(); - if (datadogTraceId != null) { - actual.put(DatadogHttpCodec.TRACE_ID_KEY.toUpperCase(), datadogTraceId); - } - if (datadogSpanId != null) { - actual.put(DatadogHttpCodec.SPAN_ID_KEY.toUpperCase(), datadogSpanId); - } - if (b3TraceId != null) { - actual.put(B3HttpCodec.TRACE_ID_KEY.toUpperCase(), b3TraceId); - } - if (b3SpanId != null) { - actual.put(B3HttpCodec.SPAN_ID_KEY.toUpperCase(), b3SpanId); - } - if (w3cTraceParent != null) { - actual.put(W3CHttpCodec.TRACE_PARENT_KEY.toUpperCase(), w3cTraceParent); - } - if (putDatadogFields) { - actual.put("SOME_HEADER", "my-interesting-info"); - } + // spotless:off + Map headers = headers( + DatadogHttpCodec.TRACE_ID_KEY, datadogTraceId, + DatadogHttpCodec.SPAN_ID_KEY, datadogSpanId, + B3HttpCodec.TRACE_ID_KEY, b3TraceId, + B3HttpCodec.SPAN_ID_KEY, b3SpanId, + W3CHttpCodec.TRACE_PARENT_KEY, w3cTraceParent, + "SOME_HEADER", putDatadogFields ? "my-interesting-info" : null + ); + // spotless:on - TagContext context = extractor.extract(actual, stringValuesMap()); + TagContext context = extractor.extract(headers, stringValuesMap()); if (tagContext) { assertInstanceOf(TagContext.class, context); @@ -132,10 +127,11 @@ void extractHttpHeadersUsingStyles( if (expectDatadogFields) { Map expectedTags = new LinkedHashMap<>(); if (tagContext && b3TraceId != null) { - expectedTags.put("b3.traceid", b3TraceId); - expectedTags.put("b3.spanid", b3SpanId); + expectedTags.put(B3_TRACE_ID, b3TraceId); + expectedTags.put(B3_SPAN_ID, b3SpanId); } expectedTags.put("some-tag", "my-interesting-info"); + assertNotNull(context); assertEquals(expectedTags, context.getTags()); } } @@ -165,34 +161,27 @@ void checkW3CTraceContextOverride( String expectedSpanId, String expectedParentId) { Config config = mock(Config.class); - when(config.getTracePropagationStylesToExtract()).thenReturn(linkedHashSetOf(styles)); + when(config.getTracePropagationStylesToExtract()).thenReturn(orderedSetOf(styles)); DynamicConfig dynamicConfig = DynamicConfig.create().apply(); HttpCodec.Extractor extractor = - HttpCodec.createExtractor(config, () -> dynamicConfig.captureTraceConfig()); + HttpCodec.createExtractor(config, dynamicConfig::captureTraceConfig); - Map actual = new LinkedHashMap<>(); - actual.put(W3CHttpCodec.TRACE_PARENT_KEY.toUpperCase(), W3C_TRACE_PARENT); - if (datadogTraceId != null) { - actual.put(DatadogHttpCodec.TRACE_ID_KEY.toUpperCase(), datadogTraceId); - } - if (datadogSpanId != null) { - actual.put(DatadogHttpCodec.SPAN_ID_KEY.toUpperCase(), datadogSpanId); - } - if (b3TraceId != null) { - actual.put(B3HttpCodec.TRACE_ID_KEY.toUpperCase(), b3TraceId); - } - if (b3SpanId != null) { - actual.put(B3HttpCodec.SPAN_ID_KEY.toUpperCase(), b3SpanId); - } - if (traceState != null) { - actual.put(W3CHttpCodec.TRACE_STATE_KEY.toUpperCase(), traceState); - } + // spotless:off + Map headers = headers( + W3CHttpCodec.TRACE_PARENT_KEY, W3C_TRACE_PARENT, + DatadogHttpCodec.TRACE_ID_KEY, datadogTraceId, + DatadogHttpCodec.SPAN_ID_KEY, datadogSpanId, + B3HttpCodec.TRACE_ID_KEY, b3TraceId, + B3HttpCodec.SPAN_ID_KEY, b3SpanId, + W3CHttpCodec.TRACE_STATE_KEY, traceState + ); + // spotless:on - TagContext context = extractor.extract(actual, stringValuesMap()); + TagContext context = extractor.extract(headers, stringValuesMap()); assertEquals(DDTraceId.from(expectedTraceId).toLong(), context.getTraceId().toLong()); assertEquals(DDSpanId.from(expectedSpanId), context.getSpanId()); - assertEquals(expectedParentId, context.getTags().get(PARENT_ID)); + assertEquals(expectedParentId, context.getTags().getString(PARENT_ID)); // TODO Add some more W3C override checks } @@ -213,20 +202,23 @@ void verifyExistenceOfSpanLinks( String traceState, List expectedSpanLinks) { Config config = mock(Config.class); - when(config.getTracePropagationStylesToExtract()).thenReturn(linkedHashSetOf(styles)); + when(config.getTracePropagationStylesToExtract()).thenReturn(orderedSetOf(styles)); DynamicConfig dynamicConfig = DynamicConfig.create().apply(); HttpCodec.Extractor extractor = - HttpCodec.createExtractor(config, () -> dynamicConfig.captureTraceConfig()); + HttpCodec.createExtractor(config, dynamicConfig::captureTraceConfig); - Map actual = new LinkedHashMap<>(); - actual.put(DatadogHttpCodec.TRACE_ID_KEY.toUpperCase(), datadogTraceId); - actual.put(DatadogHttpCodec.SPAN_ID_KEY.toUpperCase(), datadogSpanId); - actual.put(B3HttpCodec.TRACE_ID_KEY.toUpperCase(), b3TraceId); - actual.put(B3HttpCodec.SPAN_ID_KEY.toUpperCase(), b3SpanId); - actual.put(W3CHttpCodec.TRACE_PARENT_KEY.toUpperCase(), w3cTraceParent); - actual.put(W3CHttpCodec.TRACE_STATE_KEY.toUpperCase(), traceState); + // spotless:off + Map headers = headers( + DatadogHttpCodec.TRACE_ID_KEY, datadogTraceId, + DatadogHttpCodec.SPAN_ID_KEY, datadogSpanId, + B3HttpCodec.TRACE_ID_KEY, b3TraceId, + B3HttpCodec.SPAN_ID_KEY, b3SpanId, + W3CHttpCodec.TRACE_PARENT_KEY, w3cTraceParent, + W3CHttpCodec.TRACE_STATE_KEY, traceState + ); + // spotless:on - TagContext context = extractor.extract(actual, stringValuesMap()); + TagContext context = extractor.extract(headers, stringValuesMap()); List links = context.getTerminatedContextLinks(); assertEquals(expectedSpanLinks.size(), links.size()); @@ -239,7 +231,20 @@ void verifyExistenceOfSpanLinks( } } - private static Set linkedHashSetOf(List styles) { + private static Set orderedSetOf(List styles) { return new LinkedHashSet<>(styles); } + + private static Map headers(String... headerKeysAndValues) { + HashMap headers = new HashMap<>(); + for (int i = 0; i < headerKeysAndValues.length / 2; i++) { + String headerValue = headerKeysAndValues[i * 2 + 1]; + if (headerValue == null) { + continue; + } + String headerName = headerKeysAndValues[i * 2].toUpperCase(); + headers.put(headerName, headerValue); + } + return headers; + } }