diff --git a/dd-trace-core/src/main/java/datadog/trace/core/propagation/opg/OrgGuardEnforcer.java b/dd-trace-core/src/main/java/datadog/trace/core/propagation/opg/OrgGuardEnforcer.java index 2d91c872c83..2bf37d87324 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/propagation/opg/OrgGuardEnforcer.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/propagation/opg/OrgGuardEnforcer.java @@ -113,11 +113,11 @@ private ExtractedContext strip( ctx.getTraceId(), ctx.getSpanId(), PrioritySampling.UNSET, - /* origin */ null, + null, ctx.getEndToEndStartTime(), ctx.getBaggage(), ctx.getTags(), - /* httpHeaders */ null, + null, stripped, ctx.getTraceConfig(), ctx.getPropagationStyle()); diff --git a/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/W3CPTagsCodec.java b/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/W3CPTagsCodec.java index d7f0d0e02a3..b0a9959a131 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/W3CPTagsCodec.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/propagation/ptags/W3CPTagsCodec.java @@ -4,6 +4,7 @@ import datadog.logging.RatelimitedLogger; import datadog.trace.api.ProductTraceSource; +import datadog.trace.api.internal.VisibleForTesting; import datadog.trace.api.sampling.PrioritySampling; import datadog.trace.core.propagation.PropagationTags; import datadog.trace.core.propagation.ptags.PTagsFactory.PTags; @@ -26,7 +27,7 @@ public class W3CPTagsCodec extends PTagsCodec { private static final char KEY_VALUE_SEPARATOR = ':'; private static final int MIN_ALLOWED_CHAR = 32; private static final int MAX_ALLOWED_CHAR = 126; - private static final int MAX_MEMBER_COUNT = 32; + @VisibleForTesting public static final int MAX_MEMBER_COUNT = 32; @Override PropagationTags fromHeaderValue(PTagsFactory tagsFactory, String value) { diff --git a/dd-trace-core/src/test/java/datadog/trace/civisibility/interceptor/CiVisibilityTraceInterceptorTest.java b/dd-trace-core/src/test/java/datadog/trace/civisibility/interceptor/CiVisibilityTraceInterceptorTest.java index 64d58898179..42cb3a52843 100644 --- a/dd-trace-core/src/test/java/datadog/trace/civisibility/interceptor/CiVisibilityTraceInterceptorTest.java +++ b/dd-trace-core/src/test/java/datadog/trace/civisibility/interceptor/CiVisibilityTraceInterceptorTest.java @@ -9,7 +9,7 @@ import datadog.trace.core.CoreTracer; import datadog.trace.core.DDCoreJavaSpecification; import datadog.trace.core.DDSpan; -import datadog.trace.junit.utils.tabletest.DDSpanTypesConverter; +import datadog.trace.junit.utils.converter.DDSpanTypesConverter; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; 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 9ec455ff233..2baf8ac06fe 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 @@ -24,7 +24,7 @@ import datadog.trace.api.DynamicConfig; import datadog.trace.bootstrap.instrumentation.api.TagContext; import datadog.trace.junit.utils.config.WithConfig; -import datadog.trace.junit.utils.tabletest.PrioritySamplingConverter; +import datadog.trace.junit.utils.converter.PrioritySamplingConverter; import datadog.trace.test.util.DDJavaSpecification; import java.util.HashMap; import java.util.Map; @@ -63,12 +63,12 @@ void teardown() { } @TableTest({ - "scenario | traceIdHex | spanIdHex | samplingPriority | expectedSamplingPriority ", - "no priority | '1' | '2' | | PrioritySampling.UNSET ", - "sampler keep | '2' | '3' | 1 | PrioritySampling.SAMPLER_KEEP", - "sampler drop | '3' | '4' | 0 | PrioritySampling.SAMPLER_DROP", - "uint64 max drop | 'ffffffffffffffff' | 'fffffffffffffffe' | 0 | PrioritySampling.SAMPLER_DROP", - "uint64 max-1 keep | 'fffffffffffffffe' | 'ffffffffffffffff' | 1 | PrioritySampling.SAMPLER_KEEP" + "scenario | traceIdHex | spanIdHex | samplingPriority | expectedSamplingPriority", + "no priority | '1' | '2' | | UNSET ", + "sampler keep | '2' | '3' | 1 | SAMPLER_KEEP ", + "sampler drop | '3' | '4' | 0 | SAMPLER_DROP ", + "uint64 max drop | 'ffffffffffffffff' | 'fffffffffffffffe' | 0 | SAMPLER_DROP ", + "uint64 max-1 keep | 'fffffffffffffffe' | 'ffffffffffffffff' | 1 | SAMPLER_KEEP " }) void extractHttpHeaders( String traceIdHex, @@ -95,11 +95,11 @@ void extractHttpHeaders( } @TableTest({ - "scenario | b3 | expectedTraceIdHex | expectedSpanId | expectedSamplingPriority ", - "b3 takes precedence | '2-3-0' | '2' | 3 | PrioritySampling.SAMPLER_DROP", - "b3 without priority | '2-3' | '2' | 3 | PrioritySampling.UNSET ", - "invalid b3 falls back | '0' | '1' | 2 | PrioritySampling.SAMPLER_KEEP", - "absent b3 falls back | | '1' | 2 | PrioritySampling.SAMPLER_KEEP" + "scenario | b3 | expectedTraceIdHex | expectedSpanId | expectedSamplingPriority", + "b3 takes precedence | '2-3-0' | '2' | 3 | SAMPLER_DROP ", + "b3 without priority | '2-3' | '2' | 3 | UNSET ", + "invalid b3 falls back | '0' | '1' | 2 | SAMPLER_KEEP ", + "absent b3 falls back | | '1' | 2 | SAMPLER_KEEP " }) void extractHttpHeadersWithB3HeaderAtTheBeginning( String b3, @@ -127,11 +127,11 @@ void extractHttpHeadersWithB3HeaderAtTheBeginning( } @TableTest({ - "scenario | b3 | expectedTraceIdHex | expectedSpanId | expectedSamplingPriority ", - "b3 takes precedence | '2-3-0' | '2' | 3 | PrioritySampling.SAMPLER_DROP", - "b3 without priority | '2-3' | '2' | 3 | PrioritySampling.UNSET ", - "invalid b3 falls back | '0' | '1' | 2 | PrioritySampling.SAMPLER_KEEP", - "absent b3 falls back | | '1' | 2 | PrioritySampling.SAMPLER_KEEP" + "scenario | b3 | expectedTraceIdHex | expectedSpanId | expectedSamplingPriority", + "b3 takes precedence | '2-3-0' | '2' | 3 | SAMPLER_DROP ", + "b3 without priority | '2-3' | '2' | 3 | UNSET ", + "invalid b3 falls back | '0' | '1' | 2 | SAMPLER_KEEP ", + "absent b3 falls back | | '1' | 2 | SAMPLER_KEEP " }) void extractHttpHeadersWithB3HeaderAtTheEnd( String b3, 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 c3d653498ef..b1a606c1106 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 @@ -24,7 +24,7 @@ import datadog.trace.core.CoreTracer; import datadog.trace.core.DDCoreJavaSpecification; import datadog.trace.core.DDSpanContext; -import datadog.trace.junit.utils.tabletest.PrioritySamplingConverter; +import datadog.trace.junit.utils.converter.PrioritySamplingConverter; import java.util.HashMap; import java.util.Map; import org.junit.jupiter.api.AfterEach; @@ -62,14 +62,14 @@ void tearDown() { } @TableTest({ - "scenario | traceId | spanId | samplingPriority | expectedSamplingPriority ", - "unset | 1 | 2 | PrioritySampling.UNSET | ", - "sampler keep | 2 | 3 | PrioritySampling.SAMPLER_KEEP | PrioritySampling.SAMPLER_KEEP", - "sampler drop | 4 | 5 | PrioritySampling.SAMPLER_DROP | PrioritySampling.SAMPLER_DROP", - "user keep | 5 | 6 | PrioritySampling.USER_KEEP | PrioritySampling.SAMPLER_KEEP", - "user drop | 6 | 7 | PrioritySampling.USER_DROP | PrioritySampling.SAMPLER_DROP", - "uint64 max unset | -1 | -2 | PrioritySampling.UNSET | ", - "uint64 max-1 keep | -2 | -1 | PrioritySampling.SAMPLER_KEEP | PrioritySampling.SAMPLER_KEEP" + "scenario | traceId | spanId | samplingPriority | expectedSamplingPriority", + "unset | 1 | 2 | UNSET | ", + "sampler keep | 2 | 3 | SAMPLER_KEEP | SAMPLER_KEEP ", + "sampler drop | 4 | 5 | SAMPLER_DROP | SAMPLER_DROP ", + "user keep | 5 | 6 | USER_KEEP | SAMPLER_KEEP ", + "user drop | 6 | 7 | USER_DROP | SAMPLER_DROP ", + "uint64 max unset | -1 | -2 | UNSET | ", + "uint64 max-1 keep | -2 | -1 | SAMPLER_KEEP | SAMPLER_KEEP " }) void injectHttpHeaders( long traceId, diff --git a/dd-trace-core/src/test/java/datadog/trace/core/propagation/ControllableSampler.java b/dd-trace-core/src/test/java/datadog/trace/core/propagation/ControllableSampler.java index 504de399851..e649844069f 100644 --- a/dd-trace-core/src/test/java/datadog/trace/core/propagation/ControllableSampler.java +++ b/dd-trace-core/src/test/java/datadog/trace/core/propagation/ControllableSampler.java @@ -1,17 +1,18 @@ package datadog.trace.core.propagation; -import datadog.trace.api.sampling.PrioritySampling; -import datadog.trace.api.sampling.SamplingMechanism; +import static datadog.trace.api.sampling.PrioritySampling.SAMPLER_KEEP; +import static datadog.trace.api.sampling.SamplingMechanism.DEFAULT; + import datadog.trace.common.sampling.PrioritySampler; import datadog.trace.common.sampling.Sampler; import datadog.trace.core.CoreSpan; public class ControllableSampler implements Sampler, PrioritySampler { - protected int nextSamplingPriority = PrioritySampling.SAMPLER_KEEP; + protected int nextSamplingPriority = SAMPLER_KEEP; @Override public > void setSamplingPriority(T span) { - span.setSamplingPriority(nextSamplingPriority, SamplingMechanism.DEFAULT); + span.setSamplingPriority(nextSamplingPriority, DEFAULT); } @Override 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 fcd680711ff..ae27363f07d 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 @@ -14,7 +14,7 @@ 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.HttpCodecTestHelper.headers; -import static datadog.trace.junit.utils.tabletest.TraceIdConverter.TRACE_ID_MAX_PLUS_1; +import static datadog.trace.junit.utils.converter.TraceIdConverter.TRACE_ID_MAX_PLUS_1; import static java.util.Collections.singletonMap; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -31,8 +31,8 @@ import datadog.trace.api.internal.util.LongStringUtils; import datadog.trace.bootstrap.instrumentation.api.TagContext; import datadog.trace.junit.utils.config.WithConfig; -import datadog.trace.junit.utils.tabletest.PrioritySamplingConverter; -import datadog.trace.junit.utils.tabletest.TraceIdConverter; +import datadog.trace.junit.utils.converter.PrioritySamplingConverter; +import datadog.trace.junit.utils.converter.TraceIdConverter; import datadog.trace.test.util.DDJavaSpecification; import java.util.HashMap; import java.util.Map; @@ -80,11 +80,11 @@ void teardown() { } @TableTest({ - "scenario | traceId | spanId | samplingPriority | origin ", - "unset no origin | '1' | '2' | PrioritySampling.UNSET | ", - "keep with origin | '2' | '3' | PrioritySampling.SAMPLER_KEEP | 'saipan'", - "uint64 max unset | 'TRACE_ID_MAX' | 'TRACE_ID_MAX-1' | PrioritySampling.UNSET | 'saipan'", - "uint64 max-1 keep | 'TRACE_ID_MAX-1' | 'TRACE_ID_MAX' | PrioritySampling.SAMPLER_KEEP | 'saipan'" + "scenario | traceId | spanId | samplingPriority | origin ", + "unset no origin | '1' | '2' | UNSET | ", + "keep with origin | '2' | '3' | SAMPLER_KEEP | 'saipan'", + "uint64 max unset | 'MAX' | 'MAX-1' | UNSET | 'saipan'", + "uint64 max-1 keep | 'MAX-1' | 'MAX' | SAMPLER_KEEP | 'saipan'" }) void extractHttpHeaders( @ConvertWith(TraceIdConverter.class) String traceId, @@ -362,15 +362,15 @@ void extractHttpHeadersWithOutOfRangeSpanId() { } @TableTest({ - "scenario | traceId | spanId | expectExtraction", - "negative traceId | '-1' | '1' | false ", - "negative spanId | '1' | '-1' | false ", - "zero traceId | '0' | '1' | false ", - "zero spanId | '1' | '0' | true ", - "uint64 max traceId | 'TRACE_ID_MAX' | '1' | true ", - "out-of-range traceId | 'TRACE_ID_MAX+1' | '1' | false ", - "uint64 max spanId | '1' | 'TRACE_ID_MAX' | true ", - "out-of-range spanId | '1' | 'TRACE_ID_MAX+1' | false " + "scenario | traceId | spanId | expectExtraction", + "negative traceId | '-1' | '1' | false ", + "negative spanId | '1' | '-1' | false ", + "zero traceId | '0' | '1' | false ", + "zero spanId | '1' | '0' | true ", + "uint64 max traceId | 'MAX' | '1' | true ", + "out-of-range traceId | 'MAX+1' | '1' | false ", + "uint64 max spanId | '1' | 'MAX' | true ", + "out-of-range spanId | '1' | 'MAX+1' | false " }) void moreIdRangeValidation( @ConvertWith(TraceIdConverter.class) String traceId, @@ -430,11 +430,11 @@ void extractHttpHeadersWithEndToEnd(String traceId, String spanId, long endToEnd } @TableTest({ - "scenario | traceId | spanId | ctxCreated", - "negative traceId | '-1' | '1' | false ", - "negative spanId | '1' | '-1' | false ", - "zero traceId | '0' | '1' | true ", - "uint64 max-1 ids | 'TRACE_ID_MAX-1' | 'TRACE_ID_MAX-1' | true " + "scenario | traceId | spanId | ctxCreated", + "negative traceId | '-1' | '1' | false ", + "negative spanId | '1' | '-1' | false ", + "zero traceId | '0' | '1' | true ", + "uint64 max-1 ids | 'MAX-1' | 'MAX-1' | true " }) void baggageIsMappedOnContextCreation( @ConvertWith(TraceIdConverter.class) String traceId, 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 b76f8f810d1..5ad95b53a5f 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 @@ -22,8 +22,8 @@ import datadog.trace.core.CoreTracer; import datadog.trace.core.DDCoreJavaSpecification; import datadog.trace.core.DDSpanContext; -import datadog.trace.junit.utils.tabletest.PrioritySamplingConverter; -import datadog.trace.junit.utils.tabletest.TraceIdConverter; +import datadog.trace.junit.utils.converter.PrioritySamplingConverter; +import datadog.trace.junit.utils.converter.TraceIdConverter; import java.util.HashMap; import java.util.Map; import org.junit.jupiter.api.AfterEach; @@ -51,11 +51,11 @@ 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 | 'TRACE_ID_MAX' | 'TRACE_ID_MAX-1' | PrioritySampling.UNSET | 'saipan'", - "uint64 max-1 keep | 'TRACE_ID_MAX-1' | 'TRACE_ID_MAX' | PrioritySampling.SAMPLER_KEEP | " + "scenario | traceId | spanId | samplingPriority | origin ", + "unset no origin | '1' | '2' | UNSET | ", + "keep with origin | '1' | '2' | SAMPLER_KEEP | 'saipan'", + "uint64 max unset | 'MAX' | 'MAX-1' | UNSET | 'saipan'", + "uint64 max-1 keep | 'MAX-1' | 'MAX' | SAMPLER_KEEP | " }) void injectHttpHeaders( @ConvertWith(TraceIdConverter.class) String traceId, 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 e7b823a9164..0d34c2fbe4b 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 @@ -8,9 +8,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; -import datadog.trace.junit.utils.tabletest.PrioritySamplingConverter; -import datadog.trace.junit.utils.tabletest.ProductTraceSourceConverter; -import datadog.trace.junit.utils.tabletest.SamplingMechanismConverter; +import datadog.trace.junit.utils.converter.PrioritySamplingConverter; +import datadog.trace.junit.utils.converter.ProductTraceSourceConverter; +import datadog.trace.junit.utils.converter.SamplingMechanismConverter; import datadog.trace.test.util.DDJavaSpecification; import java.util.HashMap; import java.util.Map; @@ -93,26 +93,26 @@ void datadogPropagationTagsShouldTranslateToW3cTags( } @TableTest({ - "scenario | originalTagSet | priority | mechanism | expectedHeaderValue | tags ", - "keep dm unchanged unset | '_dd.p.dm=934086a686-4' | PrioritySampling.UNSET | SamplingMechanism.UNKNOWN | '_dd.p.dm=934086a686-4' | [_dd.p.dm: '934086a686-4'] ", - "keep dm unchanged sampler keep | '_dd.p.dm=934086a686-3' | PrioritySampling.SAMPLER_KEEP | SamplingMechanism.AGENT_RATE | '_dd.p.dm=934086a686-3' | [_dd.p.dm: '934086a686-3'] ", - "keep dm unchanged appsec | '_dd.p.dm=93485302ab-1' | PrioritySampling.SAMPLER_KEEP | SamplingMechanism.APPSEC | '_dd.p.dm=93485302ab-1' | [_dd.p.dm: '93485302ab-1'] ", - "keep dm with anytag | '_dd.p.dm=934086a686-4,_dd.p.anytag=value' | PrioritySampling.SAMPLER_KEEP | SamplingMechanism.AGENT_RATE | '_dd.p.dm=934086a686-4,_dd.p.anytag=value' | [_dd.p.dm: '934086a686-4', _dd.p.anytag: 'value'] ", - "keep dm with anytag appsec | '_dd.p.dm=93485302ab-2,_dd.p.anytag=value' | PrioritySampling.SAMPLER_KEEP | SamplingMechanism.APPSEC | '_dd.p.dm=93485302ab-2,_dd.p.anytag=value' | [_dd.p.dm: '93485302ab-2', _dd.p.anytag: 'value'] ", - "dm moves to front | '_dd.p.anytag=value,_dd.p.dm=934086a686-4' | PrioritySampling.SAMPLER_KEEP | SamplingMechanism.AGENT_RATE | '_dd.p.dm=934086a686-4,_dd.p.anytag=value' | [_dd.p.anytag: 'value', _dd.p.dm: '934086a686-4'] ", - "dm moves to front appsec | '_dd.p.anytag=value,_dd.p.dm=93485302ab-2' | PrioritySampling.SAMPLER_KEEP | SamplingMechanism.APPSEC | '_dd.p.dm=93485302ab-2,_dd.p.anytag=value' | [_dd.p.anytag: 'value', _dd.p.dm: '93485302ab-2'] ", - "dm reordered with multiple tags | '_dd.p.anytag=value,_dd.p.dm=934086a686-4,_dd.p.atag=value' | PrioritySampling.SAMPLER_KEEP | SamplingMechanism.AGENT_RATE | '_dd.p.dm=934086a686-4,_dd.p.anytag=value,_dd.p.atag=value' | [_dd.p.anytag: 'value', _dd.p.dm: '934086a686-4', _dd.p.atag: 'value']", - "dm reordered multiple tags appsec | '_dd.p.anytag=value,_dd.p.dm=93485302ab-2,_dd.p.atag=value' | PrioritySampling.SAMPLER_KEEP | SamplingMechanism.APPSEC | '_dd.p.dm=93485302ab-2,_dd.p.anytag=value,_dd.p.atag=value' | [_dd.p.anytag: 'value', _dd.p.dm: '93485302ab-2', _dd.p.atag: 'value']", - "user drop manual single dm | '_dd.p.dm=93485302ab-2' | PrioritySampling.USER_DROP | SamplingMechanism.MANUAL | '_dd.p.dm=93485302ab-2' | [_dd.p.dm: '93485302ab-2'] ", - "sampler drop manual reorder | '_dd.p.anytag=value,_dd.p.dm=93485302ab-2' | PrioritySampling.SAMPLER_DROP | SamplingMechanism.MANUAL | '_dd.p.dm=93485302ab-2,_dd.p.anytag=value' | [_dd.p.anytag: 'value', _dd.p.dm: '93485302ab-2'] ", - "user drop manual | '_dd.p.dm=93485302ab-2,_dd.p.anytag=value' | PrioritySampling.USER_DROP | SamplingMechanism.MANUAL | '_dd.p.dm=93485302ab-2,_dd.p.anytag=value' | [_dd.p.dm: '93485302ab-2', _dd.p.anytag: 'value'] ", - "user drop manual triple | '_dd.p.atag=value,_dd.p.dm=93485302ab-2,_dd.p.anytag=value' | PrioritySampling.USER_DROP | SamplingMechanism.MANUAL | '_dd.p.dm=93485302ab-2,_dd.p.atag=value,_dd.p.anytag=value' | [_dd.p.atag: 'value', _dd.p.dm: '93485302ab-2', _dd.p.anytag: 'value']", - "empty sampler keep default | '' | PrioritySampling.SAMPLER_KEEP | SamplingMechanism.DEFAULT | '_dd.p.dm=-0' | [_dd.p.dm: '-0'] ", - "empty sampler keep agent rate | '' | PrioritySampling.SAMPLER_KEEP | SamplingMechanism.AGENT_RATE | '_dd.p.dm=-1' | [_dd.p.dm: '-1'] ", - "anytag user keep manual | '_dd.p.anytag=value' | PrioritySampling.USER_KEEP | SamplingMechanism.MANUAL | '_dd.p.dm=-4,_dd.p.anytag=value' | [_dd.p.anytag: 'value', _dd.p.dm: '-4'] ", - "no dm change sampler drop manual | '_dd.p.anytag=value,_dd.p.atag=value' | PrioritySampling.SAMPLER_DROP | SamplingMechanism.MANUAL | '_dd.p.anytag=value,_dd.p.atag=value' | [_dd.p.anytag: 'value', _dd.p.atag: 'value'] ", - "no dm when mechanism unknown | '_dd.p.anytag=123' | PrioritySampling.SAMPLER_KEEP | SamplingMechanism.UNKNOWN | '_dd.p.anytag=123' | [_dd.p.anytag: '123'] ", - "invalid input still updates dm | ',_dd.p.dm=Value' | PrioritySampling.SAMPLER_KEEP | SamplingMechanism.AGENT_RATE | '_dd.p.dm=-1' | [_dd.propagation_error: 'decoding_error', _dd.p.dm: '-1'] " + "scenario | originalTagSet | priority | mechanism | expectedHeaderValue | tags ", + "keep dm unchanged unset | '_dd.p.dm=934086a686-4' | UNSET | SamplingMechanism.UNKNOWN | '_dd.p.dm=934086a686-4' | [_dd.p.dm: '934086a686-4'] ", + "keep dm unchanged sampler keep | '_dd.p.dm=934086a686-3' | SAMPLER_KEEP | SamplingMechanism.AGENT_RATE | '_dd.p.dm=934086a686-3' | [_dd.p.dm: '934086a686-3'] ", + "keep dm unchanged appsec | '_dd.p.dm=93485302ab-1' | SAMPLER_KEEP | SamplingMechanism.APPSEC | '_dd.p.dm=93485302ab-1' | [_dd.p.dm: '93485302ab-1'] ", + "keep dm with anytag | '_dd.p.dm=934086a686-4,_dd.p.anytag=value' | SAMPLER_KEEP | SamplingMechanism.AGENT_RATE | '_dd.p.dm=934086a686-4,_dd.p.anytag=value' | [_dd.p.dm: '934086a686-4', _dd.p.anytag: 'value'] ", + "keep dm with anytag appsec | '_dd.p.dm=93485302ab-2,_dd.p.anytag=value' | SAMPLER_KEEP | SamplingMechanism.APPSEC | '_dd.p.dm=93485302ab-2,_dd.p.anytag=value' | [_dd.p.dm: '93485302ab-2', _dd.p.anytag: 'value'] ", + "dm moves to front | '_dd.p.anytag=value,_dd.p.dm=934086a686-4' | SAMPLER_KEEP | SamplingMechanism.AGENT_RATE | '_dd.p.dm=934086a686-4,_dd.p.anytag=value' | [_dd.p.anytag: 'value', _dd.p.dm: '934086a686-4'] ", + "dm moves to front appsec | '_dd.p.anytag=value,_dd.p.dm=93485302ab-2' | SAMPLER_KEEP | SamplingMechanism.APPSEC | '_dd.p.dm=93485302ab-2,_dd.p.anytag=value' | [_dd.p.anytag: 'value', _dd.p.dm: '93485302ab-2'] ", + "dm reordered with multiple tags | '_dd.p.anytag=value,_dd.p.dm=934086a686-4,_dd.p.atag=value' | SAMPLER_KEEP | SamplingMechanism.AGENT_RATE | '_dd.p.dm=934086a686-4,_dd.p.anytag=value,_dd.p.atag=value' | [_dd.p.anytag: 'value', _dd.p.dm: '934086a686-4', _dd.p.atag: 'value']", + "dm reordered multiple tags appsec | '_dd.p.anytag=value,_dd.p.dm=93485302ab-2,_dd.p.atag=value' | SAMPLER_KEEP | SamplingMechanism.APPSEC | '_dd.p.dm=93485302ab-2,_dd.p.anytag=value,_dd.p.atag=value' | [_dd.p.anytag: 'value', _dd.p.dm: '93485302ab-2', _dd.p.atag: 'value']", + "user drop manual single dm | '_dd.p.dm=93485302ab-2' | USER_DROP | SamplingMechanism.MANUAL | '_dd.p.dm=93485302ab-2' | [_dd.p.dm: '93485302ab-2'] ", + "sampler drop manual reorder | '_dd.p.anytag=value,_dd.p.dm=93485302ab-2' | SAMPLER_DROP | SamplingMechanism.MANUAL | '_dd.p.dm=93485302ab-2,_dd.p.anytag=value' | [_dd.p.anytag: 'value', _dd.p.dm: '93485302ab-2'] ", + "user drop manual | '_dd.p.dm=93485302ab-2,_dd.p.anytag=value' | USER_DROP | SamplingMechanism.MANUAL | '_dd.p.dm=93485302ab-2,_dd.p.anytag=value' | [_dd.p.dm: '93485302ab-2', _dd.p.anytag: 'value'] ", + "user drop manual triple | '_dd.p.atag=value,_dd.p.dm=93485302ab-2,_dd.p.anytag=value' | USER_DROP | SamplingMechanism.MANUAL | '_dd.p.dm=93485302ab-2,_dd.p.atag=value,_dd.p.anytag=value' | [_dd.p.atag: 'value', _dd.p.dm: '93485302ab-2', _dd.p.anytag: 'value']", + "empty sampler keep default | '' | SAMPLER_KEEP | SamplingMechanism.DEFAULT | '_dd.p.dm=-0' | [_dd.p.dm: '-0'] ", + "empty sampler keep agent rate | '' | SAMPLER_KEEP | SamplingMechanism.AGENT_RATE | '_dd.p.dm=-1' | [_dd.p.dm: '-1'] ", + "anytag user keep manual | '_dd.p.anytag=value' | USER_KEEP | SamplingMechanism.MANUAL | '_dd.p.dm=-4,_dd.p.anytag=value' | [_dd.p.anytag: 'value', _dd.p.dm: '-4'] ", + "no dm change sampler drop manual | '_dd.p.anytag=value,_dd.p.atag=value' | SAMPLER_DROP | SamplingMechanism.MANUAL | '_dd.p.anytag=value,_dd.p.atag=value' | [_dd.p.anytag: 'value', _dd.p.atag: 'value'] ", + "no dm when mechanism unknown | '_dd.p.anytag=123' | SAMPLER_KEEP | SamplingMechanism.UNKNOWN | '_dd.p.anytag=123' | [_dd.p.anytag: '123'] ", + "invalid input still updates dm | ',_dd.p.dm=Value' | SAMPLER_KEEP | SamplingMechanism.AGENT_RATE | '_dd.p.dm=-1' | [_dd.propagation_error: 'decoding_error', _dd.p.dm: '-1'] " }) void updatePropagationTagsSamplingMechanism( String originalTagSet, 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 f56c31fac62..f87a600e23f 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 @@ -10,7 +10,7 @@ import static datadog.trace.core.propagation.HaystackHttpCodec.SPAN_ID_KEY; import static datadog.trace.core.propagation.HaystackHttpCodec.TRACE_ID_KEY; import static datadog.trace.core.propagation.HttpCodecTestHelper.headers; -import static datadog.trace.junit.utils.tabletest.TraceIdConverter.TRACE_ID_MAX_PLUS_1; +import static datadog.trace.junit.utils.converter.TraceIdConverter.TRACE_ID_MAX_PLUS_1; import static java.util.Collections.singletonMap; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -24,7 +24,7 @@ import datadog.trace.api.DynamicConfig; import datadog.trace.bootstrap.instrumentation.api.TagContext; import datadog.trace.junit.utils.config.WithConfig; -import datadog.trace.junit.utils.tabletest.TraceIdConverter; +import datadog.trace.junit.utils.converter.TraceIdConverter; import datadog.trace.test.util.DDJavaSpecification; import java.util.HashMap; import java.util.Map; @@ -72,11 +72,11 @@ void teardown() { } @TableTest({ - "scenario | traceId | spanId | traceUuid | spanUuid ", - "small ids | '1' | '2' | '44617461-646f-6721-0000-000000000001' | '44617461-646f-6721-0000-000000000002'", - "incrementing ids | '2' | '3' | '44617461-646f-6721-0000-000000000002' | '44617461-646f-6721-0000-000000000003'", - "uint64 max | 'TRACE_ID_MAX' | '18446744073709551609' | '44617461-646f-6721-ffff-ffffffffffff' | '44617461-646f-6721-ffff-fffffffffff9'", - "uint64 max-1 | 'TRACE_ID_MAX-1' | '18446744073709551608' | '44617461-646f-6721-ffff-fffffffffffe' | '44617461-646f-6721-ffff-fffffffffff8'" + "scenario | traceId | spanId | traceUuid | spanUuid ", + "small ids | '1' | '2' | '44617461-646f-6721-0000-000000000001' | '44617461-646f-6721-0000-000000000002'", + "incrementing ids | '2' | '3' | '44617461-646f-6721-0000-000000000002' | '44617461-646f-6721-0000-000000000003'", + "uint64 max | 'MAX' | '18446744073709551609' | '44617461-646f-6721-ffff-ffffffffffff' | '44617461-646f-6721-ffff-fffffffffff9'", + "uint64 max-1 | 'MAX-1' | '18446744073709551608' | '44617461-646f-6721-ffff-fffffffffffe' | '44617461-646f-6721-ffff-fffffffffff8'" }) void extractHttpHeaders( @ConvertWith(TraceIdConverter.class) String traceId, 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 e8b5f1151fe..4e1ba647c85 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 @@ -19,7 +19,7 @@ import datadog.trace.core.CoreTracer; import datadog.trace.core.DDCoreJavaSpecification; import datadog.trace.core.DDSpanContext; -import datadog.trace.junit.utils.tabletest.TraceIdConverter; +import datadog.trace.junit.utils.converter.TraceIdConverter; import java.util.HashMap; import java.util.Map; import org.junit.jupiter.api.AfterEach; @@ -49,11 +49,11 @@ void tearDown() { } @TableTest({ - "scenario | traceId | spanId | traceUuid | spanUuid ", - "small ids | '1' | '2' | '44617461-646f-6721-0000-000000000001' | '44617461-646f-6721-0000-000000000002'", - "small ids duplicate | '1' | '2' | '44617461-646f-6721-0000-000000000001' | '44617461-646f-6721-0000-000000000002'", - "uint64 max trace | 'TRACE_ID_MAX' | 'TRACE_ID_MAX-1' | '44617461-646f-6721-ffff-ffffffffffff' | '44617461-646f-6721-ffff-fffffffffffe'", - "uint64 max-1 trace | 'TRACE_ID_MAX-1' | 'TRACE_ID_MAX' | '44617461-646f-6721-ffff-fffffffffffe' | '44617461-646f-6721-ffff-ffffffffffff'" + "scenario | traceId | spanId | traceUuid | spanUuid ", + "small ids | '1' | '2' | '44617461-646f-6721-0000-000000000001' | '44617461-646f-6721-0000-000000000002'", + "small ids duplicate | '1' | '2' | '44617461-646f-6721-0000-000000000001' | '44617461-646f-6721-0000-000000000002'", + "uint64 max trace | 'MAX' | 'MAX-1' | '44617461-646f-6721-ffff-ffffffffffff' | '44617461-646f-6721-ffff-fffffffffffe'", + "uint64 max-1 trace | 'MAX-1' | 'MAX' | '44617461-646f-6721-ffff-fffffffffffe' | '44617461-646f-6721-ffff-ffffffffffff'" }) void injectHttpHeaders( @ConvertWith(TraceIdConverter.class) String traceId, @@ -83,11 +83,11 @@ void injectHttpHeaders( } @TableTest({ - "scenario | traceId | spanId | traceUuid | spanUuid ", - "small ids | '1' | '2' | '54617461-646f-6721-0000-000000000001' | '44617461-646f-6721-0000-000000000002'", - "small ids duplicate | '1' | '2' | '54617461-646f-6721-0000-000000000001' | '44617461-646f-6721-0000-000000000002'", - "uint64 max trace | 'TRACE_ID_MAX' | 'TRACE_ID_MAX-1' | '54617461-646f-6721-ffff-ffffffffffff' | '44617461-646f-6721-ffff-fffffffffffe'", - "uint64 max-1 trace | 'TRACE_ID_MAX-1' | 'TRACE_ID_MAX' | '54617461-646f-6721-ffff-fffffffffffe' | '44617461-646f-6721-ffff-ffffffffffff'" + "scenario | traceId | spanId | traceUuid | spanUuid ", + "small ids | '1' | '2' | '54617461-646f-6721-0000-000000000001' | '44617461-646f-6721-0000-000000000002'", + "small ids duplicate | '1' | '2' | '54617461-646f-6721-0000-000000000001' | '44617461-646f-6721-0000-000000000002'", + "uint64 max trace | 'MAX' | 'MAX-1' | '54617461-646f-6721-ffff-ffffffffffff' | '44617461-646f-6721-ffff-fffffffffffe'", + "uint64 max-1 trace | 'MAX-1' | 'MAX' | '54617461-646f-6721-ffff-fffffffffffe' | '44617461-646f-6721-ffff-ffffffffffff'" }) void injectHttpHeadersWithHaystackTraceIdInBaggage( @ConvertWith(TraceIdConverter.class) String traceId, diff --git a/dd-trace-core/src/test/java/datadog/trace/core/propagation/HttpInjectorB3PaddingTest.java b/dd-trace-core/src/test/java/datadog/trace/core/propagation/HttpInjectorB3PaddingTest.java deleted file mode 100644 index c65fc25cfa6..00000000000 --- a/dd-trace-core/src/test/java/datadog/trace/core/propagation/HttpInjectorB3PaddingTest.java +++ /dev/null @@ -1,8 +0,0 @@ -package datadog.trace.core.propagation; - -class HttpInjectorB3PaddingTest extends HttpInjectorTest { - @Override - protected boolean tracePropagationB3Padding() { - return true; - } -} 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 abd959426e3..24812059903 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 @@ -23,7 +23,7 @@ import datadog.trace.core.CoreTracer; import datadog.trace.core.DDCoreJavaSpecification; import datadog.trace.core.DDSpanContext; -import datadog.trace.junit.utils.tabletest.PrioritySamplingConverter; +import datadog.trace.junit.utils.converter.PrioritySamplingConverter; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; @@ -40,12 +40,12 @@ class HttpInjectorTest extends DDCoreJavaSpecification { @BeforeEach void setup() { ListWriter writer = new ListWriter(); - tracer = tracerBuilder().writer(writer).build(); + this.tracer = tracerBuilder().writer(writer).build(); } @AfterEach void tearDown() { - tracer.close(); + this.tracer.close(); } protected boolean tracePropagationB3Padding() { @@ -53,21 +53,21 @@ protected boolean tracePropagationB3Padding() { } @TableTest({ - "scenario | styles | samplingPriority | origin ", - "DATADOG,B3SINGLE unset | [DATADOG, B3SINGLE] | PrioritySampling.UNSET | ", - "DATADOG,B3SINGLE keep saipan | [DATADOG, B3SINGLE] | PrioritySampling.SAMPLER_KEEP | 'saipan'", - "DATADOG only unset | [DATADOG] | PrioritySampling.UNSET | ", - "DATADOG only keep saipan | [DATADOG] | PrioritySampling.SAMPLER_KEEP | 'saipan'", - "B3SINGLE only unset | [B3SINGLE] | PrioritySampling.UNSET | ", - "B3SINGLE only keep saipan | [B3SINGLE] | PrioritySampling.SAMPLER_KEEP | 'saipan'", - "B3SINGLE,DATADOG keep saipan | [B3SINGLE, DATADOG] | PrioritySampling.SAMPLER_KEEP | 'saipan'", - "DATADOG,B3MULTI,B3SINGLE unset | [DATADOG, B3MULTI, B3SINGLE] | PrioritySampling.UNSET | ", - "DATADOG,B3MULTI,B3SINGLE keep | [DATADOG, B3MULTI, B3SINGLE] | PrioritySampling.SAMPLER_KEEP | 'saipan'", - "DATADOG,B3MULTI unset | [DATADOG, B3MULTI] | PrioritySampling.UNSET | ", - "DATADOG,B3MULTI keep saipan | [DATADOG, B3MULTI] | PrioritySampling.SAMPLER_KEEP | 'saipan'", - "B3MULTI only unset | [B3MULTI] | PrioritySampling.UNSET | ", - "B3MULTI only keep saipan | [B3MULTI] | PrioritySampling.SAMPLER_KEEP | 'saipan'", - "B3MULTI,DATADOG keep saipan | [B3MULTI, DATADOG] | PrioritySampling.SAMPLER_KEEP | 'saipan'" + "scenario | styles | samplingPriority | origin ", + "DATADOG,B3SINGLE unset | [DATADOG, B3SINGLE] | UNSET | ", + "DATADOG,B3SINGLE keep saipan | [DATADOG, B3SINGLE] | SAMPLER_KEEP | 'saipan'", + "DATADOG only unset | [DATADOG] | UNSET | ", + "DATADOG only keep saipan | [DATADOG] | SAMPLER_KEEP | 'saipan'", + "B3SINGLE only unset | [B3SINGLE] | UNSET | ", + "B3SINGLE only keep saipan | [B3SINGLE] | SAMPLER_KEEP | 'saipan'", + "B3SINGLE,DATADOG keep saipan | [B3SINGLE, DATADOG] | SAMPLER_KEEP | 'saipan'", + "DATADOG,B3MULTI,B3SINGLE unset | [DATADOG, B3MULTI, B3SINGLE] | UNSET | ", + "DATADOG,B3MULTI,B3SINGLE keep | [DATADOG, B3MULTI, B3SINGLE] | SAMPLER_KEEP | 'saipan'", + "DATADOG,B3MULTI unset | [DATADOG, B3MULTI] | UNSET | ", + "DATADOG,B3MULTI keep saipan | [DATADOG, B3MULTI] | SAMPLER_KEEP | 'saipan'", + "B3MULTI only unset | [B3MULTI] | UNSET | ", + "B3MULTI only keep saipan | [B3MULTI] | SAMPLER_KEEP | 'saipan'", + "B3MULTI,DATADOG keep saipan | [B3MULTI, DATADOG] | SAMPLER_KEEP | 'saipan'" }) void injectHttpHeadersUsingStyles( List styles, @@ -127,16 +127,16 @@ void injectHttpHeadersUsingStyles( } @TableTest({ - "scenario | style | samplingPriority | origin ", - "DATADOG unset | DATADOG | PrioritySampling.UNSET | ", - "DATADOG keep no origin | DATADOG | PrioritySampling.SAMPLER_KEEP | ", - "DATADOG keep saipan | DATADOG | PrioritySampling.SAMPLER_KEEP | 'saipan'", - "B3SINGLE unset | B3SINGLE | PrioritySampling.UNSET | ", - "B3SINGLE keep no orig | B3SINGLE | PrioritySampling.SAMPLER_KEEP | ", - "B3SINGLE keep saipan | B3SINGLE | PrioritySampling.SAMPLER_KEEP | 'saipan'", - "B3MULTI unset | B3MULTI | PrioritySampling.UNSET | ", - "B3MULTI keep no origin | B3MULTI | PrioritySampling.SAMPLER_KEEP | ", - "B3MULTI keep saipan | B3MULTI | PrioritySampling.SAMPLER_KEEP | 'saipan'" + "scenario | style | samplingPriority | origin ", + "DATADOG unset | DATADOG | UNSET | ", + "DATADOG keep no origin | DATADOG | SAMPLER_KEEP | ", + "DATADOG keep saipan | DATADOG | SAMPLER_KEEP | 'saipan'", + "B3SINGLE unset | B3SINGLE | UNSET | ", + "B3SINGLE keep no orig | B3SINGLE | SAMPLER_KEEP | ", + "B3SINGLE keep saipan | B3SINGLE | SAMPLER_KEEP | 'saipan'", + "B3MULTI unset | B3MULTI | UNSET | ", + "B3MULTI keep no origin | B3MULTI | SAMPLER_KEEP | ", + "B3MULTI keep saipan | B3MULTI | SAMPLER_KEEP | 'saipan'" }) void injectHttpHeadersUsingStyle( TracePropagationStyle style, 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 81d885b0b2f..8bcc8ca9e6c 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 @@ -28,7 +28,7 @@ import datadog.trace.api.internal.util.LongStringUtils; import datadog.trace.bootstrap.instrumentation.api.TagContext; import datadog.trace.junit.utils.config.WithConfig; -import datadog.trace.junit.utils.tabletest.TraceIdConverter; +import datadog.trace.junit.utils.converter.TraceIdConverter; import datadog.trace.test.util.DDJavaSpecification; import java.util.HashMap; import java.util.Map; @@ -75,10 +75,10 @@ void teardown() { } @TableTest({ - "scenario | traceId | spanId ", - "no origin | '1' | '2' ", - "uint64 max | 'TRACE_ID_MAX' | 'TRACE_ID_MAX-1'", - "uint64 max-1 | 'TRACE_ID_MAX-1' | 'TRACE_ID_MAX' " + "scenario | traceId | spanId ", + "no origin | '1' | '2' ", + "uint64 max | 'MAX' | 'MAX-1'", + "uint64 max-1 | 'MAX-1' | 'MAX' " }) void extractHttpHeaders( @ConvertWith(TraceIdConverter.class) String traceId, diff --git a/dd-trace-core/src/test/java/datadog/trace/core/propagation/OrgGuardEndToEndTest.java b/dd-trace-core/src/test/java/datadog/trace/core/propagation/OrgGuardEndToEndTest.java index 7252ebc01f7..447310d897e 100644 --- a/dd-trace-core/src/test/java/datadog/trace/core/propagation/OrgGuardEndToEndTest.java +++ b/dd-trace-core/src/test/java/datadog/trace/core/propagation/OrgGuardEndToEndTest.java @@ -1,5 +1,8 @@ package datadog.trace.core.propagation; +import static datadog.trace.api.sampling.PrioritySampling.UNSET; +import static datadog.trace.bootstrap.instrumentation.api.ContextVisitors.stringValuesMap; +import static datadog.trace.core.propagation.PropagationTags.HeaderType.W3C; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -10,12 +13,10 @@ import static org.mockito.Mockito.when; import datadog.context.Context; -import datadog.context.propagation.CarrierVisitor; import datadog.trace.api.Config; import datadog.trace.api.DDTraceId; import datadog.trace.api.TraceConfig; import datadog.trace.api.TracePropagationStyle; -import datadog.trace.api.sampling.PrioritySampling; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.core.DDSpanContext; import datadog.trace.core.TraceCollector; @@ -28,16 +29,12 @@ import java.util.Map; import java.util.Set; import java.util.function.Supplier; -import javax.annotation.ParametersAreNonnullByDefault; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @DisplayName("Org Propagation Guard end-to-end propagator wiring") class OrgGuardEndToEndTest { - - private static final MapVisitor VISITOR = new MapVisitor(); - private PropagationTags.Factory factory; private HealthMetrics healthMetrics; private Supplier traceConfigSupplier; @@ -56,7 +53,7 @@ void injectStampsLocalOpm() { TracingPropagator propagator = buildPropagator(true, false, Collections.emptySet(), () -> "L1"); Map carrier = new HashMap<>(); - Context ctx = Context.root().with(buildSpanForInjection(/*opmInTags*/ null)); + Context ctx = Context.root().with(buildSpanForInjection(null)); propagator.inject(ctx, carrier, Map::put); String datadogTags = carrier.get(DatadogHttpCodec.DATADOG_TAGS_KEY); @@ -94,13 +91,13 @@ void extractStripsOnMismatch() { headers.put(DatadogHttpCodec.SAMPLING_PRIORITY_KEY, "2"); headers.put(DatadogHttpCodec.DATADOG_TAGS_KEY, "_dd.p.opm=X1,_dd.p.dm=-4"); - Context extracted = propagator.extract(Context.root(), headers, VISITOR); + Context extracted = propagator.extract(Context.root(), headers, stringValuesMap()); AgentSpan span = AgentSpan.fromContext(extracted); assertNotNull(span, "extracted span missing"); ExtractedContext ec = (ExtractedContext) span.context(); assertEquals(DDTraceId.from(123L), ec.getTraceId()); assertEquals(456L, ec.getSpanId()); - assertEquals(PrioritySampling.UNSET, ec.getSamplingPriority()); + assertEquals(UNSET, ec.getSamplingPriority()); assertNull(ec.getOrigin()); assertNull(ec.getPropagationTags().getOrgPropagationMarker()); } @@ -118,7 +115,7 @@ void extractTrustedOpm() { headers.put(DatadogHttpCodec.SAMPLING_PRIORITY_KEY, "2"); headers.put(DatadogHttpCodec.DATADOG_TAGS_KEY, "_dd.p.opm=TRUSTED1,_dd.p.dm=-4"); - Context extracted = propagator.extract(Context.root(), headers, VISITOR); + Context extracted = propagator.extract(Context.root(), headers, stringValuesMap()); ExtractedContext ec = (ExtractedContext) AgentSpan.fromContext(extracted).context(); assertEquals(2, ec.getSamplingPriority()); assertEquals("TRUSTED1", ec.getPropagationTags().getOrgPropagationMarker().toString()); @@ -135,11 +132,11 @@ void roundTripPreservesForeignVendors() { "00-0000000000000000000000000000007b-00000000000001c8-01"); // 0x7b=123, 0x1c8=456 headers.put("tracestate", "dd=s:2;o:foo;t.opm:upstream-X;t.dm:-4,vendor1=abc,vendor2=def"); - Context extracted = propagator.extract(Context.root(), headers, VISITOR); + Context extracted = propagator.extract(Context.root(), headers, stringValuesMap()); ExtractedContext ec = (ExtractedContext) AgentSpan.fromContext(extracted).context(); - assertEquals(PrioritySampling.UNSET, ec.getSamplingPriority(), "should be stripped"); + assertEquals(UNSET, ec.getSamplingPriority(), "should be stripped"); - String reEncoded = ec.getPropagationTags().headerValue(PropagationTags.HeaderType.W3C); + String reEncoded = ec.getPropagationTags().headerValue(W3C); assertNotNull(reEncoded, "re-encoded tracestate is null"); assertTrue(reEncoded.contains("vendor1=abc"), "vendor1 missing: " + reEncoded); assertTrue(reEncoded.contains("vendor2=def"), "vendor2 missing: " + reEncoded); @@ -195,15 +192,4 @@ private AgentSpan buildSpanForInjection(String preExistingOpm) { when(ddCtx.getTraceCollector()).thenReturn(collector); return AgentSpan.fromSpanContext(ddCtx); } - - @ParametersAreNonnullByDefault - private static final class MapVisitor implements CarrierVisitor> { - @Override - public void forEachKeyValue( - Map carrier, java.util.function.BiConsumer classifier) { - for (Map.Entry e : carrier.entrySet()) { - classifier.accept(e.getKey(), e.getValue()); - } - } - } } diff --git a/dd-trace-core/src/test/java/datadog/trace/core/propagation/TracingPropagatorTest.java b/dd-trace-core/src/test/java/datadog/trace/core/propagation/TracingPropagatorTest.java index 51149e768ba..6805c853912 100644 --- a/dd-trace-core/src/test/java/datadog/trace/core/propagation/TracingPropagatorTest.java +++ b/dd-trace-core/src/test/java/datadog/trace/core/propagation/TracingPropagatorTest.java @@ -5,6 +5,7 @@ import static datadog.trace.api.sampling.PrioritySampling.SAMPLER_KEEP; import static datadog.trace.api.sampling.PrioritySampling.USER_DROP; import static datadog.trace.bootstrap.instrumentation.api.AgentPropagation.XRAY_TRACING_CONCERN; +import static datadog.trace.bootstrap.instrumentation.api.ContextVisitors.stringValuesMap; import static datadog.trace.bootstrap.instrumentation.api.Tags.PROPAGATED_TRACE_SOURCE; import static datadog.trace.core.propagation.DatadogHttpCodec.SAMPLING_PRIORITY_KEY; import static datadog.trace.core.propagation.XRayHttpCodec.X_AMZN_TRACE_ID; @@ -18,14 +19,13 @@ import static org.mockito.Mockito.verify; import datadog.context.Context; -import datadog.context.propagation.CarrierVisitor; import datadog.context.propagation.Propagator; import datadog.context.propagation.Propagators; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.core.CoreTracer; import datadog.trace.core.DDCoreJavaSpecification; import datadog.trace.core.DDSpanContext; -import datadog.trace.junit.utils.tabletest.ProductTraceSourceConverter; +import datadog.trace.junit.utils.converter.ProductTraceSourceConverter; import java.util.HashMap; import java.util.Map; import org.junit.jupiter.api.BeforeEach; @@ -66,9 +66,8 @@ void testTracingPropagatorContextInjection() { void testTracingPropagatorContextExtractor() { Context context = Context.root(); Map carrier = new HashMap<>(); - CarrierVisitor> visitor = (c, v) -> {}; - this.propagator.extract(context, carrier, visitor); + this.propagator.extract(context, carrier, stringValuesMap()); verify(this.extractor).extract(same(carrier), any()); } 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 8ee8c4ecf33..510a0e9a5f0 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 @@ -1,7 +1,14 @@ 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.TRACE_CLIENT_IP_HEADER; +import static datadog.trace.api.config.TracerConfig.TRACE_CLIENT_IP_RESOLVER_ENABLED; +import static datadog.trace.bootstrap.ActiveSubsystems.APPSEC_ACTIVE; import static datadog.trace.bootstrap.instrumentation.api.ContextVisitors.stringValuesMap; import static datadog.trace.core.propagation.HttpCodecTestHelper.headers; +import static datadog.trace.core.propagation.W3CHttpCodec.OT_BAGGAGE_PREFIX; +import static datadog.trace.core.propagation.W3CHttpCodec.TRACE_PARENT_KEY; +import static datadog.trace.core.propagation.W3CHttpCodec.TRACE_STATE_KEY; import static java.util.Collections.emptyMap; import static java.util.Collections.singletonMap; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -12,113 +19,112 @@ import datadog.trace.api.Config; import datadog.trace.api.DD64bTraceId; +import datadog.trace.api.DDSpanId; import datadog.trace.api.DDTraceId; import datadog.trace.api.DynamicConfig; -import datadog.trace.api.config.TracerConfig; -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.junit.utils.tabletest.SamplingMechanismConverter; +import datadog.trace.junit.utils.converter.PrioritySamplingConverter; +import datadog.trace.junit.utils.converter.SamplingMechanismConverter; 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; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ParameterContext; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.converter.ArgumentConversionException; +import org.junit.jupiter.params.converter.ArgumentConverter; import org.junit.jupiter.params.converter.ConvertWith; +import org.junit.jupiter.params.provider.ValueSource; import org.tabletest.junit.TableTest; -@WithConfig(key = TracerConfig.PROPAGATION_EXTRACT_LOG_HEADER_NAMES_ENABLED, value = "true") +@WithConfig(key = PROPAGATION_EXTRACT_LOG_HEADER_NAMES_ENABLED, value = "true") class W3CHttpExtractorTest extends DDJavaSpecification { private static final long TEST_SPAN_ID = 1311768467463790320L; private static final DDTraceId TRACE_ID_ONE = DDTraceId.fromHex("00000000000000000000000000000001"); + private static final DDTraceId TRACE_ID_NO_HIGH_LOW_MAX = + DDTraceId.fromHex("0000000000000000ffffffffffffffff"); + private static final DDTraceId TRACE_ID_LOW_MAX = + DDTraceId.fromHex("123456789abcdef0ffffffffffffffff"); 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"; private static final String SOME_ARBITRARY_HEADER = "SOME_ARBITRARY_HEADER"; - private DynamicConfig dynamicConfig; - private HttpCodec.Extractor lazyExtractor; + private HttpCodec.Extractor extractor; private boolean origAppSecActive; @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-CaseSensitive-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 = W3CHttpCodec.newExtractor(Config.get(), dynamicConfig::captureTraceConfig); + this.origAppSecActive = APPSEC_ACTIVE; + APPSEC_ACTIVE = true; } @AfterEach void teardown() { - ActiveSubsystems.APPSEC_ACTIVE = origAppSecActive; - if (lazyExtractor != null) { - lazyExtractor.cleanup(); - } - } - - private HttpCodec.Extractor extractor() { - if (lazyExtractor == null) { - lazyExtractor = - W3CHttpCodec.newExtractor(Config.get(), () -> dynamicConfig.captureTraceConfig()); - } - return lazyExtractor; + this.extractor.cleanup(); + APPSEC_ACTIVE = origAppSecActive; } @TableTest({ - "scenario | traceparent | tpValid | traceIdHex | spanId | priority ", - "null traceparent | | false | | 0 | PrioritySampling.UNSET ", - "all zeros trace id | '00-00000000000000000000000000000000-123456789abcdef0-01' | false | | 0 | PrioritySampling.UNSET ", - "too long trace id | '00-123456789abcdef00000000000000000-123456789abcdef0-01' | false | | 0 | PrioritySampling.UNSET ", - "all zeros span id | '00-00000000000000000000000000000001-0000000000000000-01' | false | | 0 | PrioritySampling.UNSET ", - "valid keep | '00-00000000000000000000000000000001-123456789abcdef0-01' | true | '00000000000000000000000000000001' | 1311768467463790320 | PrioritySampling.SAMPLER_KEEP", - "leading tab | '\t00-00000000000000000000000000000001-123456789abcdef0-01' | true | '00000000000000000000000000000001' | 1311768467463790320 | PrioritySampling.SAMPLER_KEEP", - "trailing tab | '00-00000000000000000000000000000001-123456789abcdef0-01\t' | true | '00000000000000000000000000000001' | 1311768467463790320 | PrioritySampling.SAMPLER_KEEP", - "surrounding spaces | ' 00-00000000000000000000000000000001-123456789abcdef0-01 ' | true | '00000000000000000000000000000001' | 1311768467463790320 | PrioritySampling.SAMPLER_KEEP", - "max span id keep | '00-0000000000000000ffffffffffffffff-ffffffffffffffff-01' | true | '0000000000000000ffffffffffffffff' | -1 | PrioritySampling.SAMPLER_KEEP", - "max span id drop | '00-0000000000000000ffffffffffffffff-ffffffffffffffff-00' | true | '0000000000000000ffffffffffffffff' | -1 | PrioritySampling.SAMPLER_DROP", - "low max trace id drop | '00-123456789abcdef0ffffffffffffffff-123456789abcdef0-00' | true | '123456789abcdef0ffffffffffffffff' | 1311768467463790320 | PrioritySampling.SAMPLER_DROP", - "uppercase F in trace id low part | '00-123456789abcdef0ffffffffffffffFf-123456789abcdef0-00' | false | | 0 | PrioritySampling.UNSET ", - "uppercase F in trace id high part | '00-123456789abcdeF0ffffffffffffffff-123456789abcdef0-00' | false | | 0 | PrioritySampling.UNSET ", - "uppercase F in trace id mid | '00-123456789abcdef0fffffffffFffffff-123456789abcdef0-00' | false | | 0 | PrioritySampling.UNSET ", - "uppercase A in span id | '00-123456789abcdef0ffffffffffffffff-123456789Abcdef0-00' | false | | 0 | PrioritySampling.UNSET ", - "unicode a-umlaut in trace id start | '00-123456789äbcdef0ffffffffffffffff-123456789abcdef0-00' | false | | 0 | PrioritySampling.UNSET ", - "unicode a-umlaut in trace id mid | '00-123456789abcdef0ffffffffäfffffff-123456789abcdef0-00' | false | | 0 | PrioritySampling.UNSET ", - "unicode a-umlaut in span id | '00-123456789abcdef0ffffffffffffffff-123456789äbcdef0-00' | false | | 0 | PrioritySampling.UNSET ", - "version 01 flags 02 | '01-00000000000000000000000000000001-0000000000000001-02' | true | '00000000000000000000000000000001' | 1 | PrioritySampling.SAMPLER_DROP", - "too long version | '000-0000000000000000000000000000001-0000000000000001-01' | false | | 0 | PrioritySampling.UNSET ", - "space inside trace id | '00-0000000000000000000000000000001 -0000000000000001-01' | false | | 0 | PrioritySampling.UNSET ", - "trace id too short | '00-0000000000000000000000000000001-0000000000000001-01' | false | | 0 | PrioritySampling.UNSET ", - "span id too short | '00-00000000000000000000000000000001-000000000000001-01' | false | | 0 | PrioritySampling.UNSET ", - "flags too short | '00-00000000000000000000000000000001-0000000000000001-0' | false | | 0 | PrioritySampling.UNSET ", - "version ff invalid | 'ff-00000000000000000000000000000001-0000000000000001-00' | false | | 0 | PrioritySampling.UNSET ", - "version fe flags 02 | 'fe-00000000000000000000000000000001-0000000000000001-02' | true | '00000000000000000000000000000001' | 1 | PrioritySampling.SAMPLER_DROP", - "extra data with version 00 | '00-00000000000000000000000000000001-0000000000000001-03-0' | false | | 0 | PrioritySampling.UNSET ", - "invalid separator after flags with fe | 'fe-00000000000000000000000000000001-0000000000000001-02.0' | false | | 0 | PrioritySampling.UNSET " + "scenario | traceparent | tpValid | traceId | spanId | priority ", + "null traceparent | | false | | 0 | UNSET ", + "all zeros trace id | '00-00000000000000000000000000000000-123456789abcdef0-01' | false | | 0 | UNSET ", + "too long trace id | '00-123456789abcdef00000000000000000-123456789abcdef0-01' | false | | 0 | UNSET ", + "all zeros span id | '00-00000000000000000000000000000001-0000000000000000-01' | false | | 0 | UNSET ", + "valid keep | '00-00000000000000000000000000000001-123456789abcdef0-01' | true | TRACE_ID_ONE | SPAN_ID_TEST | SAMPLER_KEEP", + "leading tab | '\t00-00000000000000000000000000000001-123456789abcdef0-01' | true | TRACE_ID_ONE | SPAN_ID_TEST | SAMPLER_KEEP", + "trailing tab | '00-00000000000000000000000000000001-123456789abcdef0-01\t' | true | TRACE_ID_ONE | SPAN_ID_TEST | SAMPLER_KEEP", + "surrounding spaces | ' 00-00000000000000000000000000000001-123456789abcdef0-01 ' | true | TRACE_ID_ONE | SPAN_ID_TEST | SAMPLER_KEEP", + "max span id keep | '00-0000000000000000ffffffffffffffff-ffffffffffffffff-01' | true | TRACE_ID_NO_HIGH_LOW_MAX | SPAN_ID_MAX | SAMPLER_KEEP", + "max span id drop | '00-0000000000000000ffffffffffffffff-ffffffffffffffff-00' | true | TRACE_ID_NO_HIGH_LOW_MAX | SPAN_ID_MAX | SAMPLER_DROP", + "low max trace id drop | '00-123456789abcdef0ffffffffffffffff-123456789abcdef0-00' | true | TRACE_ID_LOW_MAX | SPAN_ID_TEST | SAMPLER_DROP", + "uppercase F in trace id low part | '00-123456789abcdef0ffffffffffffffFf-123456789abcdef0-00' | false | | 0 | UNSET ", + "uppercase F in trace id high part | '00-123456789abcdeF0ffffffffffffffff-123456789abcdef0-00' | false | | 0 | UNSET ", + "uppercase F in trace id mid | '00-123456789abcdef0fffffffffFffffff-123456789abcdef0-00' | false | | 0 | UNSET ", + "uppercase A in span id | '00-123456789abcdef0ffffffffffffffff-123456789Abcdef0-00' | false | | 0 | UNSET ", + "unicode a-umlaut in trace id start | '00-123456789äbcdef0ffffffffffffffff-123456789abcdef0-00' | false | | 0 | UNSET ", + "unicode a-umlaut in trace id mid | '00-123456789abcdef0ffffffffäfffffff-123456789abcdef0-00' | false | | 0 | UNSET ", + "unicode a-umlaut in span id | '00-123456789abcdef0ffffffffffffffff-123456789äbcdef0-00' | false | | 0 | UNSET ", + "version 01 flags 02 | '01-00000000000000000000000000000001-0000000000000001-02' | true | TRACE_ID_ONE | SPAN_ID_ONE | SAMPLER_DROP", + "too long version | '000-0000000000000000000000000000001-0000000000000001-01' | false | | 0 | UNSET ", + "space inside trace id | '00-0000000000000000000000000000001 -0000000000000001-01' | false | | 0 | UNSET ", + "trace id too short | '00-0000000000000000000000000000001-0000000000000001-01' | false | | 0 | UNSET ", + "span id too short | '00-00000000000000000000000000000001-000000000000001-01' | false | | 0 | UNSET ", + "flags too short | '00-00000000000000000000000000000001-0000000000000001-0' | false | | 0 | UNSET ", + "version ff invalid | 'ff-00000000000000000000000000000001-0000000000000001-00' | false | | 0 | UNSET ", + "version fe flags 02 | 'fe-00000000000000000000000000000001-0000000000000001-02' | true | TRACE_ID_ONE | SPAN_ID_ONE | SAMPLER_DROP", + "extra data with version 00 | '00-00000000000000000000000000000001-0000000000000001-03-0' | false | | 0 | UNSET ", + "invalid separator after flags with fe | 'fe-00000000000000000000000000000001-0000000000000001-02.0' | false | | 0 | UNSET " }) void extractTraceparent( String traceparent, boolean tpValid, - String traceIdHex, - long spanId, + @ConvertWith(TraceIdTestConverter.class) DDTraceId traceId, + @ConvertWith(SpanIdTestConverter.class) long spanId, @ConvertWith(PrioritySamplingConverter.class) byte priority) { - Map headers = headers(W3CHttpCodec.TRACE_PARENT_KEY, traceparent); + Map headers = headers(TRACE_PARENT_KEY, traceparent); - TagContext result = extractor().extract(headers, stringValuesMap()); + TagContext result = this.extractor.extract(headers, stringValuesMap()); if (tpValid) { assertInstanceOf(ExtractedContext.class, result); ExtractedContext context = (ExtractedContext) result; - assertEquals(DDTraceId.fromHex(traceIdHex), context.getTraceId()); + assertEquals(traceId, context.getTraceId()); assertEquals(spanId, context.getSpanId()); assertEquals(priority, context.getSamplingPriority()); } else { @@ -126,25 +132,22 @@ void extractTraceparent( } } - @TableTest({ - "scenario | traceIdHex ", - "low max | '123456789abcdef0ffffffffffffffff'", - "no high low max | '0000000000000000ffffffffffffffff'" - }) - void checkMaxFromW3CTraceIds(String traceIdHex) { - assertEquals(DD64bTraceId.MAX.toLong(), DDTraceId.fromHex(traceIdHex).toLong()); + @ParameterizedTest + @ValueSource(strings = {"TRACE_ID_LOW_MAX", "TRACE_ID_NO_HIGH_LOW_MAX"}) + void checkMaxFromW3CTraceIds(@ConvertWith(TraceIdTestConverter.class) DDTraceId traceId) { + assertEquals(DD64bTraceId.MAX.toLong(), traceId.toLong()); } @TableTest({ - "scenario | traceparent | tracestate | priority | decisionMaker | origin", - "keep empty state | '00-00000000000000000000000000000001-123456789abcdef0-01' | '' | PrioritySampling.SAMPLER_KEEP | SamplingMechanism.DEFAULT | ", - "drop empty state | '00-00000000000000000000000000000001-123456789abcdef0-00' | '' | PrioritySampling.SAMPLER_DROP | | ", - "keep with user keep state | '00-00000000000000000000000000000001-123456789abcdef0-01' | 'dd=s:2;o:some' | PrioritySampling.USER_KEEP | | some ", - "keep with user keep state and manual dm | '00-00000000000000000000000000000001-123456789abcdef0-01' | 'dd=s:2;o:some;t.dm:-4' | PrioritySampling.USER_KEEP | SamplingMechanism.MANUAL | some ", - "drop with user keep state and manual dm | '00-00000000000000000000000000000001-123456789abcdef0-00' | 'dd=s:2;o:some;t.dm:-4' | PrioritySampling.SAMPLER_DROP | | some ", - "drop with user drop state | '00-00000000000000000000000000000001-123456789abcdef0-00' | 'dd=s:-1;o:some' | PrioritySampling.USER_DROP | | some ", - "drop with user drop state and manual dm | '00-00000000000000000000000000000001-123456789abcdef0-00' | 'dd=s:-1;o:some;t.dm:-4' | PrioritySampling.USER_DROP | SamplingMechanism.MANUAL | some ", - "keep overrides user drop state with manual dm | '00-00000000000000000000000000000001-123456789abcdef0-01' | 'dd=s:-1;o:some;t.dm:-4' | PrioritySampling.SAMPLER_KEEP | SamplingMechanism.DEFAULT | some " + "scenario | traceparent | tracestate | priority | decisionMaker | origin", + "keep empty state | '00-00000000000000000000000000000001-123456789abcdef0-01' | '' | SAMPLER_KEEP | SamplingMechanism.DEFAULT | ", + "drop empty state | '00-00000000000000000000000000000001-123456789abcdef0-00' | '' | SAMPLER_DROP | | ", + "keep with user keep state | '00-00000000000000000000000000000001-123456789abcdef0-01' | 'dd=s:2;o:some' | USER_KEEP | | some ", + "keep with user keep state and manual dm | '00-00000000000000000000000000000001-123456789abcdef0-01' | 'dd=s:2;o:some;t.dm:-4' | USER_KEEP | SamplingMechanism.MANUAL | some ", + "drop with user keep state and manual dm | '00-00000000000000000000000000000001-123456789abcdef0-00' | 'dd=s:2;o:some;t.dm:-4' | SAMPLER_DROP | | some ", + "drop with user drop state | '00-00000000000000000000000000000001-123456789abcdef0-00' | 'dd=s:-1;o:some' | USER_DROP | | some ", + "drop with user drop state and manual dm | '00-00000000000000000000000000000001-123456789abcdef0-00' | 'dd=s:-1;o:some;t.dm:-4' | USER_DROP | SamplingMechanism.MANUAL | some ", + "keep overrides user drop state with manual dm | '00-00000000000000000000000000000001-123456789abcdef0-01' | 'dd=s:-1;o:some;t.dm:-4' | SAMPLER_KEEP | SamplingMechanism.DEFAULT | some " }) void extractTraceparentTracestateAndHttpHeaders( String traceparent, @@ -155,21 +158,22 @@ void extractTraceparentTracestateAndHttpHeaders( // spotless:off Map headers = headers( "", "empty key", - W3CHttpCodec.TRACE_PARENT_KEY, traceparent, - W3CHttpCodec.TRACE_STATE_KEY, tracestate, - W3CHttpCodec.OT_BAGGAGE_PREFIX + "k1", "v1", - W3CHttpCodec.OT_BAGGAGE_PREFIX + "k2", "v2", + TRACE_PARENT_KEY, traceparent, + TRACE_STATE_KEY, tracestate, + OT_BAGGAGE_PREFIX + "k1", "v1", + OT_BAGGAGE_PREFIX + "k2", "v2", SOME_HEADER, "my-interesting-info", SOME_CUSTOM_BAGGAGE_HEADER, "my-interesting-baggage-info", SOME_CUSTOM_BAGGAGE_HEADER_2, "my-interesting-baggage-info-2" ); // spotless:on - ExtractedContext context = (ExtractedContext) extractor().extract(headers, stringValuesMap()); + ExtractedContext context = + (ExtractedContext) this.extractor.extract(headers, stringValuesMap()); assertEquals(TRACE_ID_ONE, context.getTraceId()); assertEquals(TEST_SPAN_ID, 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"); @@ -177,13 +181,9 @@ void extractTraceparentTracestateAndHttpHeaders( assertEquals(expectedBaggage, context.getBaggage()); assertEquals(singletonMap("some-tag", "my-interesting-info"), context.getTags()); assertEquals(priority, context.getSamplingPriority()); - if (decisionMaker != null) { - assertEquals( - singletonMap("_dd.p.dm", "-" + decisionMaker), - context.getPropagationTags().createTagMap()); - } else { - assertEquals(emptyMap(), context.getPropagationTags().createTagMap()); - } + Map expectedPTags = + decisionMaker != null ? singletonMap("_dd.p.dm", "-" + decisionMaker) : emptyMap(); + assertEquals(expectedPTags, context.getPropagationTags().createTagMap()); if (origin != null) { assertEquals(origin, context.getOrigin().toString()); } @@ -193,7 +193,7 @@ void extractTraceparentTracestateAndHttpHeaders( void extractHeaderTagsWithNoPropagation() { Map headers = headers(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()); @@ -207,18 +207,18 @@ void extractHeadersWithForwarding() { Map tagOnlyCtx = headers("Forwarded", forwarded); // spotless:off Map fullCtx = headers( - W3CHttpCodec.TRACE_PARENT_KEY, "00-00000000000000000000000000000001-0000000000000002-01", + TRACE_PARENT_KEY, "00-00000000000000000000000000000001-0000000000000002-01", "Forwarded", forwarded ); // spotless:on - 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()); @@ -236,20 +236,20 @@ void extractHeadersWithXForwarding() { "X-Forwarded-Port", forwardedPort ); Map fullCtx = headers( - W3CHttpCodec.TRACE_PARENT_KEY, "00-00000000000000000000000000000001-0000000000000002-01", + TRACE_PARENT_KEY, "00-00000000000000000000000000000001-0000000000000002-01", "x-forwarded-for", forwardedIp, "x-forwarded-port", forwardedPort ); // spotless:on - TagContext context = extractor().extract(tagOnlyCtx, stringValuesMap()); + TagContext context = this.extractor.extract(tagOnlyCtx, stringValuesMap()); assertNotNull(context); assertFalse(context instanceof ExtractedContext); 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()); @@ -260,17 +260,21 @@ void extractHeadersWithXForwarding() { @Test void extractEmptyHeadersReturnsNull() { - assertNull(extractor().extract(headers("ignored-header", "ignored-value"), stringValuesMap())); + assertNull( + this.extractor.extract(headers("ignored-header", "ignored-value"), 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<>(); - tagOnlyCtx.put("X-Forwarded-For", "::1"); - tagOnlyCtx.put("User-agent", "foo/bar"); + // spotless:off + Map tagOnlyCtx = headers( + "X-Forwarded-For", "::1", + "User-agent", "foo/bar" + ); + // spotless:on - TagContext ctx = extractor().extract(tagOnlyCtx, stringValuesMap()); + TagContext ctx = this.extractor.extract(tagOnlyCtx, stringValuesMap()); assertNotNull(ctx); assertNull(ctx.getXForwardedFor()); @@ -279,25 +283,31 @@ void extractHeadersWithIpResolutionDisabled() { @Test void extractHeadersWithIpResolutionDisabledAppsecDisabled() { - ActiveSubsystems.APPSEC_ACTIVE = false; - Map tagOnlyCtx = new LinkedHashMap<>(); - tagOnlyCtx.put("X-Forwarded-For", "::1"); - tagOnlyCtx.put("User-agent", "foo/bar"); + APPSEC_ACTIVE = false; + // spotless:off + Map tagOnlyCtx = headers( + "X-Forwarded-For", "::1", + "User-agent", "foo/bar" + ); + // spotless:on - TagContext ctx = extractor().extract(tagOnlyCtx, stringValuesMap()); + TagContext ctx = this.extractor.extract(tagOnlyCtx, stringValuesMap()); assertNotNull(ctx); assertNull(ctx.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<>(); - tagOnlyCtx.put("X-Forwarded-For", "::1"); - tagOnlyCtx.put("My-Header", "8.8.8.8"); + // spotless:off + Map tagOnlyCtx = headers( + "X-Forwarded-For", "::1", + "My-Header", "8.8.8.8" + ); + // spotless:on - TagContext ctx = extractor().extract(tagOnlyCtx, stringValuesMap()); + TagContext ctx = extractor.extract(tagOnlyCtx, stringValuesMap()); assertNotNull(ctx); assertEquals("::1", ctx.getXForwardedFor()); @@ -313,17 +323,17 @@ void extractHttpHeadersWithEndToEnd(long endToEndStartTime) { // spotless:off Map headers = headers( "", "empty key", - W3CHttpCodec.TRACE_PARENT_KEY, "00-00000000000000000000000000000001-123456789abcdef0-01", - W3CHttpCodec.OT_BAGGAGE_PREFIX + "k1", "v1", - W3CHttpCodec.OT_BAGGAGE_PREFIX + "t0", String.valueOf(endToEndStartTime), - W3CHttpCodec.OT_BAGGAGE_PREFIX + "k2", "v2", + TRACE_PARENT_KEY, "00-00000000000000000000000000000001-123456789abcdef0-01", + OT_BAGGAGE_PREFIX + "k1", "v1", + OT_BAGGAGE_PREFIX + "t0", String.valueOf(endToEndStartTime), + OT_BAGGAGE_PREFIX + "k2", "v2", SOME_HEADER, "my-interesting-info", SOME_CUSTOM_BAGGAGE_HEADER, "my-interesting-baggage-info", SOME_CUSTOM_BAGGAGE_HEADER_2, "my-interesting-baggage-info-2" ); // spotless:on - ExtractedContext context = (ExtractedContext) extractor().extract(headers, stringValuesMap()); + ExtractedContext context = (ExtractedContext) extractor.extract(headers, stringValuesMap()); assertEquals(TRACE_ID_ONE, context.getTraceId()); assertEquals(TEST_SPAN_ID, context.getSpanId()); @@ -346,15 +356,15 @@ void extractHttpHeadersWithEndToEnd(long endToEndStartTime) { void baggageIsMappedOnContextCreation(boolean tpValid, String traceparent) { // spotless:off Map headers = headers( - W3CHttpCodec.TRACE_PARENT_KEY, traceparent, + TRACE_PARENT_KEY, traceparent, SOME_CUSTOM_BAGGAGE_HEADER, "mappedBaggageValue", - W3CHttpCodec.OT_BAGGAGE_PREFIX + "k1", "v1", - W3CHttpCodec.OT_BAGGAGE_PREFIX + "k2", "v2", + OT_BAGGAGE_PREFIX + "k1", "v1", + OT_BAGGAGE_PREFIX + "k2", "v2", SOME_ARBITRARY_HEADER, "my-interesting-info" ); // spotless:on - TagContext context = extractor().extract(headers, stringValuesMap()); + TagContext context = extractor.extract(headers, stringValuesMap()); assertNotNull(context); if (tpValid) { @@ -385,7 +395,7 @@ void extractCommonHttpHeaders() { ); // spotless:on - TagContext context = extractor().extract(headers, stringValuesMap()); + TagContext context = extractor.extract(headers, stringValuesMap()); assertEquals("some-user-agent", context.getUserAgent()); assertEquals("1.1.1.1", context.getXClusterClientIp()); @@ -409,11 +419,11 @@ void markInconsistentTidAsPropagationError( String traceparent, String tracestate, boolean consistent) { // spotless:off Map headers = headers( - W3CHttpCodec.TRACE_PARENT_KEY, traceparent, - W3CHttpCodec.TRACE_STATE_KEY, tracestate); + TRACE_PARENT_KEY, traceparent, + TRACE_STATE_KEY, tracestate); // spotless:on - ExtractedContext context = (ExtractedContext) extractor().extract(headers, stringValuesMap()); + ExtractedContext context = (ExtractedContext) extractor.extract(headers, stringValuesMap()); String tid = tracestate.isEmpty() ? "" : tracestate.substring(9); Map defaultTags = new LinkedHashMap<>(); @@ -425,4 +435,45 @@ void markInconsistentTidAsPropagationError( } assertEquals(expectedTags, context.getPropagationTags().createTagMap()); } + + static final class TraceIdTestConverter implements ArgumentConverter { + @Override + public Object convert(Object source, ParameterContext context) + throws ArgumentConversionException { + if (source == null) { + return null; + } + switch (source.toString()) { + case "TRACE_ID_ONE": + return TRACE_ID_ONE; + case "TRACE_ID_NO_HIGH_LOW_MAX": + return TRACE_ID_NO_HIGH_LOW_MAX; + case "TRACE_ID_LOW_MAX": + return TRACE_ID_LOW_MAX; + default: + return source; + } + } + } + + static final class SpanIdTestConverter implements ArgumentConverter { + @Override + public Object convert(Object source, ParameterContext context) + throws ArgumentConversionException { + if (source == null) { + return null; + } + String s = source.toString(); + switch (s) { + case "SPAN_ID_MAX": + return DDSpanId.MAX; + case "SPAN_ID_TEST": + return TEST_SPAN_ID; + case "SPAN_ID_ONE": + return 1; + default: + return Long.parseLong(s); + } + } + } } 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 c580db9aa17..459c035b42d 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 @@ -1,26 +1,30 @@ package datadog.trace.core.propagation; +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; +import static datadog.trace.core.propagation.PropagationTags.HeaderType.DATADOG; import static datadog.trace.core.propagation.W3CHttpCodec.OT_BAGGAGE_PREFIX; import static datadog.trace.core.propagation.W3CHttpCodec.TRACE_PARENT_KEY; import static datadog.trace.core.propagation.W3CHttpCodec.TRACE_STATE_KEY; import static datadog.trace.core.propagation.W3CHttpCodec.newInjector; +import static java.util.Collections.singletonMap; import static org.junit.jupiter.api.Assertions.assertEquals; import datadog.trace.api.DDSpanId; import datadog.trace.api.DDTraceId; import datadog.trace.api.datastreams.NoopPathwayContext; -import datadog.trace.api.sampling.PrioritySampling; import datadog.trace.bootstrap.instrumentation.api.AgentScope; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; import datadog.trace.common.writer.ListWriter; import datadog.trace.core.CoreTracer; import datadog.trace.core.DDCoreJavaSpecification; import datadog.trace.core.DDSpanContext; -import datadog.trace.junit.utils.tabletest.PrioritySamplingConverter; -import datadog.trace.junit.utils.tabletest.TraceIdConverter; -import java.util.LinkedHashMap; +import datadog.trace.junit.utils.converter.PrioritySamplingConverter; +import datadog.trace.junit.utils.converter.TraceIdConverter; +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; @@ -29,21 +33,28 @@ class W3CHttpInjectorTest extends DDCoreJavaSpecification { private HttpCodec.Injector injector; + private CoreTracer tracer; @BeforeEach void setup() { - Map mapping = new LinkedHashMap<>(); - mapping.put("some-baggage-key", "SOME_CUSTOM_HEADER"); - injector = newInjector(mapping); + this.injector = 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 | tracestate ", - "unset 1->2 | 1 | 2 | PrioritySampling.UNSET | | 'dd=p:0000000000000002;t.usr:123' ", - "keep 1->4 saipan | 1 | 4 | PrioritySampling.SAMPLER_KEEP | saipan | 'dd=s:1;o:saipan;p:0000000000000004;t.usr:123'", - "unset max->max-1 saipan | TRACE_ID_MAX | TRACE_ID_MAX-1 | PrioritySampling.UNSET | saipan | 'dd=o:saipan;p:fffffffffffffffe;t.usr:123' ", - "keep max-1->max | TRACE_ID_MAX-1 | TRACE_ID_MAX | PrioritySampling.SAMPLER_KEEP | | 'dd=s:1;p:ffffffffffffffff;t.usr:123' ", - "drop max-1->max | TRACE_ID_MAX-1 | TRACE_ID_MAX | PrioritySampling.SAMPLER_DROP | | 'dd=s:0;p:ffffffffffffffff;t.usr:123' " + "scenario | traceId | spanId | samplingPriority | origin | tracestate ", + "unset 1->2 | 1 | 2 | UNSET | | 'dd=p:0000000000000002;t.usr:123' ", + "keep 1->4 saipan | 1 | 4 | SAMPLER_KEEP | saipan | 'dd=s:1;o:saipan;p:0000000000000004;t.usr:123'", + "unset max->max-1 saipan | MAX | MAX-1 | UNSET | saipan | 'dd=o:saipan;p:fffffffffffffffe;t.usr:123' ", + "keep max-1->max | MAX-1 | MAX | SAMPLER_KEEP | | 'dd=s:1;p:ffffffffffffffff;t.usr:123' ", + "drop max-1->max | MAX-1 | MAX | SAMPLER_DROP | | 'dd=s:0;p:ffffffffffffffff;t.usr:123' " }) void injectHttpHeaders( @ConvertWith(TraceIdConverter.class) String traceId, @@ -51,138 +62,115 @@ void injectHttpHeaders( @ConvertWith(PrioritySamplingConverter.class) byte samplingPriority, String origin, String tracestate) { - 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 = - createContext( - tracer, + DDSpanContext spanContext = + mockSpanContext( DDTraceId.from(traceId), DDSpanId.from(spanId), samplingPriority, origin, baggage, - PropagationTags.factory() - .fromHeaderValue(PropagationTags.HeaderType.DATADOG, "_dd.p.usr=123")); - Map carrier = new LinkedHashMap<>(); - Map expected = new LinkedHashMap<>(); + PropagationTags.factory().fromHeaderValue(DATADOG, "_dd.p.usr=123")); + Map carrier = new HashMap<>(); + + this.injector.inject(spanContext, carrier, Map::put); + + Map expected = new HashMap<>(); expected.put(TRACE_PARENT_KEY, buildTraceParent(traceId, spanId, samplingPriority)); expected.put(TRACE_STATE_KEY, tracestate); expected.put(OT_BAGGAGE_PREFIX + "k1", "v1"); expected.put(OT_BAGGAGE_PREFIX + "k2", "v2"); expected.put("SOME_CUSTOM_HEADER", "some-value"); - - injector.inject(mockedContext, carrier, Map::put); - assertEquals(expected, carrier); - - tracer.close(); } @Test 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 = - createContext( - tracer, + mockSpanContext( DDTraceId.from("1"), DDSpanId.from("2"), - PrioritySampling.UNSET, + UNSET, "fakeOrigin", baggage, - PropagationTags.factory() - .fromHeaderValue( - PropagationTags.HeaderType.DATADOG, "_dd.p.dm=-4,_dd.p.anytag=value")); + PropagationTags.factory().fromHeaderValue(DATADOG, "_dd.p.dm=-4,_dd.p.anytag=value")); mockedContext.beginEndToEnd(); - Map carrier = new LinkedHashMap<>(); + Map carrier = new HashMap<>(); - injector.inject(mockedContext, carrier, Map::put); + this.injector.inject(mockedContext, carrier, Map::put); - Map expected = new LinkedHashMap<>(); - expected.put(TRACE_PARENT_KEY, buildTraceParent("1", "2", PrioritySampling.UNSET)); + Map expected = new HashMap<>(); + expected.put(TRACE_PARENT_KEY, buildTraceParent("1", "2", UNSET)); expected.put(TRACE_STATE_KEY, "dd=o:fakeOrigin;p:0000000000000002;t.dm:-4;t.anytag:value"); expected.put( OT_BAGGAGE_PREFIX + "t0", String.valueOf(mockedContext.getEndToEndStartTime() / 1000000L)); expected.put(OT_BAGGAGE_PREFIX + "k1", "v1"); expected.put(OT_BAGGAGE_PREFIX + "k2", "v2"); assertEquals(expected, carrier); - - tracer.close(); } @Test 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 = - createContext( - tracer, + mockSpanContext( DDTraceId.from("1"), DDSpanId.from("2"), - PrioritySampling.UNSET, + UNSET, "fakeOrigin", baggage, PropagationTags.factory().empty()); - mockedContext.setSamplingPriority(PrioritySampling.USER_KEEP, MANUAL); - Map carrier = new LinkedHashMap<>(); + mockedContext.setSamplingPriority(USER_KEEP, MANUAL); + Map carrier = new HashMap<>(); - injector.inject(mockedContext, carrier, Map::put); + this.injector.inject(mockedContext, carrier, Map::put); - Map expected = new LinkedHashMap<>(); - expected.put(TRACE_PARENT_KEY, buildTraceParent("1", "2", PrioritySampling.USER_KEEP)); + Map expected = new HashMap<>(); + expected.put(TRACE_PARENT_KEY, buildTraceParent("1", "2", USER_KEEP)); expected.put(TRACE_STATE_KEY, "dd=s:2;o:fakeOrigin;p:0000000000000002;t.dm:-4"); expected.put(OT_BAGGAGE_PREFIX + "k1", "v1"); expected.put(OT_BAGGAGE_PREFIX + "k2", "v2"); assertEquals(expected, carrier); - - tracer.close(); } @Test void updateLastParentIdOnChildSpan() { - ListWriter writer = new ListWriter(); - CoreTracer tracer = tracerBuilder().writer(writer).build(); - Map carrier = new LinkedHashMap<>(); + Map carrier = new HashMap<>(); // injecting root span context - AgentSpan rootSpan = tracer.startSpan("test", "root"); + AgentSpan rootSpan = this.tracer.startSpan("test", "root"); long rootSpanId = rootSpan.getSpanId(); - AgentScope rootScope = tracer.activateSpan(rootSpan); + AgentScope rootScope = this.tracer.activateSpan(rootSpan); - injector.inject((DDSpanContext) rootSpan.context(), carrier, Map::put); - long lastParentId = extractLastParentId(carrier); + this.injector.inject((DDSpanContext) rootSpan.context(), carrier, Map::put); // trace state has root span id as last parent - assertEquals(rootSpanId, lastParentId); + assertEquals(rootSpanId, extractLastParentId(carrier)); // injecting child span context - AgentSpan childSpan = tracer.startSpan("test", "child"); + AgentSpan childSpan = this.tracer.startSpan("test", "child"); long childSpanId = childSpan.getSpanId(); carrier.clear(); - injector.inject((DDSpanContext) childSpan.context(), carrier, Map::put); - lastParentId = extractLastParentId(carrier); + this.injector.inject((DDSpanContext) childSpan.context(), carrier, Map::put); // trace state has child span id as last parent - assertEquals(childSpanId, lastParentId); + assertEquals(childSpanId, extractLastParentId(carrier)); // injecting root span again childSpan.finish(); carrier.clear(); - injector.inject((DDSpanContext) rootSpan.context(), carrier, Map::put); - lastParentId = extractLastParentId(carrier); + this.injector.inject((DDSpanContext) rootSpan.context(), carrier, Map::put); // trace state has root span is as last parent again - assertEquals(rootSpanId, lastParentId); + assertEquals(rootSpanId, extractLastParentId(carrier)); rootScope.close(); rootSpan.finish(); @@ -211,8 +199,7 @@ static long extractLastParentId(Map carrier) { throw new AssertionError("No 'p:' in dd tracestate: " + traceState); } - private static DDSpanContext createContext( - CoreTracer tracer, + private DDSpanContext mockSpanContext( DDTraceId traceId, long spanId, int samplingPriority, @@ -233,7 +220,7 @@ private static DDSpanContext createContext( false, "fakeType", 0, - tracer.createTraceCollector(DDTraceId.ONE), + this.tracer.createTraceCollector(DDTraceId.ONE), null, null, NoopPathwayContext.INSTANCE, 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 bbe1eb49427..eb5145f7caa 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 @@ -1,19 +1,25 @@ package datadog.trace.core.propagation; import static datadog.trace.core.propagation.PropagationTags.HeaderType; +import static datadog.trace.core.propagation.PropagationTags.HeaderType.W3C; +import static datadog.trace.core.propagation.PropagationTags.factory; +import static datadog.trace.core.propagation.ptags.W3CPTagsCodec.MAX_MEMBER_COUNT; +import static java.lang.Math.min; import static java.util.Collections.emptyMap; +import static java.util.Collections.singletonMap; +import static java.util.stream.IntStream.concat; +import static java.util.stream.IntStream.rangeClosed; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.params.provider.Arguments.arguments; import datadog.trace.core.DDCoreJavaSpecification; -import datadog.trace.junit.utils.tabletest.PrioritySamplingConverter; -import datadog.trace.junit.utils.tabletest.ProductTraceSourceConverter; -import datadog.trace.junit.utils.tabletest.SamplingMechanismConverter; -import java.util.HashSet; +import datadog.trace.junit.utils.converter.PrioritySamplingConverter; +import datadog.trace.junit.utils.converter.ProductTraceSourceConverter; +import datadog.trace.junit.utils.converter.SamplingMechanismConverter; import java.util.Map; -import java.util.Set; import java.util.stream.IntStream; import java.util.stream.Stream; import org.junit.jupiter.params.ParameterizedTest; @@ -24,24 +30,18 @@ class W3CPropagationTagsTest extends DDCoreJavaSpecification { - private static final int DD_TAGS_MAX_LEN = 512; - - private static PropagationTags.Factory factory() { - return PropagationTags.factory(DD_TAGS_MAX_LEN); - } - @ParameterizedTest @MethodSource("validateTracestateHeaderLimitsArguments") void validateTracestateHeaderLimits(String headerValue, boolean valid) { - PropagationTags propagationTags = factory().fromHeaderValue(HeaderType.W3C, headerValue); + PropagationTags propagationTags = factory().fromHeaderValue(W3C, headerValue); if (valid) { - assertEquals(headerValue.trim(), propagationTags.headerValue(HeaderType.W3C)); + assertEquals(headerValue.trim(), propagationTags.headerValue(W3C)); } else { - assertNull(propagationTags.headerValue(HeaderType.W3C)); + assertNull(propagationTags.headerValue(W3C)); } // we're not using any dd members in the tests - assertEquals(emptyMap(), propagationTags.createTagMap()); + assertTrue(propagationTags.createTagMap().isEmpty()); } static Stream validateTracestateHeaderLimitsArguments() { @@ -66,115 +66,112 @@ static Stream validateTracestateHeaderLimitsArguments() { @ParameterizedTest @MethodSource("validateTracestateHeaderValidKeyContentsArguments") void validateTracestateHeaderValidKeyContents(String headerChar) { - String lcAlpha = toLcAlpha(headerChar); + String lcAlpha = toLowerCaseAlpha(headerChar); String simpleKeyHeader = lcAlpha + headerChar + "_-*/=1"; String multiKeyHeader = headerChar + "@" + lcAlpha + headerChar + "_-*/=1"; - PropagationTags simpleKeyPT = factory().fromHeaderValue(HeaderType.W3C, simpleKeyHeader); - PropagationTags multiKeyPT = factory().fromHeaderValue(HeaderType.W3C, multiKeyHeader); + PropagationTags simpleKeyPT = factory().fromHeaderValue(W3C, simpleKeyHeader); + PropagationTags multiKeyPT = factory().fromHeaderValue(W3C, multiKeyHeader); - assertEquals(simpleKeyHeader, simpleKeyPT.headerValue(HeaderType.W3C)); - assertEquals(multiKeyHeader, multiKeyPT.headerValue(HeaderType.W3C)); + assertEquals(simpleKeyHeader, simpleKeyPT.headerValue(W3C)); + assertEquals(multiKeyHeader, multiKeyPT.headerValue(W3C)); // we're not using any dd members in the tests - assertEquals(emptyMap(), simpleKeyPT.createTagMap()); - assertEquals(emptyMap(), multiKeyPT.createTagMap()); + assertTrue(simpleKeyPT.createTagMap().isEmpty()); + assertTrue(multiKeyPT.createTagMap().isEmpty()); } static Stream validateTracestateHeaderValidKeyContentsArguments() { - return IntStream.concat(IntStream.rangeClosed('a', 'z'), IntStream.rangeClosed('0', '9')) + return concat(rangeClosed('a', 'z'), rangeClosed('0', '9')) .mapToObj(c -> arguments(String.valueOf((char) c))); } @ParameterizedTest @MethodSource("validateTracestateHeaderInvalidKeyContentsArguments") void validateTracestateHeaderInvalidKeyContents(String headerChar) { - String lcAlpha = toLcAlpha(headerChar); + String lcAlpha = toLowerCaseAlpha(headerChar); String simpleKeyHeader = lcAlpha + headerChar + "_-*/=1"; String multiKeyHeader = lcAlpha + headerChar + "@" + lcAlpha + headerChar + "_-*/=1"; - PropagationTags simpleKeyPT = factory().fromHeaderValue(HeaderType.W3C, simpleKeyHeader); - PropagationTags multiKeyPT = factory().fromHeaderValue(HeaderType.W3C, multiKeyHeader); + PropagationTags simpleKeyPT = factory().fromHeaderValue(W3C, simpleKeyHeader); + PropagationTags multiKeyPT = factory().fromHeaderValue(W3C, multiKeyHeader); - assertNull(simpleKeyPT.headerValue(HeaderType.W3C)); - assertNull(multiKeyPT.headerValue(HeaderType.W3C)); + assertNull(simpleKeyPT.headerValue(W3C)); + assertNull(multiKeyPT.headerValue(W3C)); // we're not using any dd members in the tests assertEquals(emptyMap(), simpleKeyPT.createTagMap()); assertEquals(emptyMap(), multiKeyPT.createTagMap()); } static Stream validateTracestateHeaderInvalidKeyContentsArguments() { - Set validKeyChars = new HashSet<>(); - for (char c = 'a'; c <= 'z'; c++) validKeyChars.add(c); - for (char c = '0'; c <= '9'; c++) validKeyChars.add(c); - validKeyChars.add('_'); - validKeyChars.add('-'); - validKeyChars.add('*'); - validKeyChars.add('/'); - Stream.Builder builder = Stream.builder(); - for (char c = ' '; c <= 'ÿ'; c++) { - if (!validKeyChars.contains(c)) { - builder.add(arguments(String.valueOf(c))); - } + return rangeClosed(' ', 'ÿ') + .filter(W3CPropagationTagsTest::invalidKeyChar) + .mapToObj(value -> String.valueOf((char) value)) + .map(Arguments::of); + } + + static boolean invalidKeyChar(int i) { + if (i >= 'a' && i <= 'z') { + return false; + } + if (i >= '0' && i <= '9') { + return false; } - return builder.build(); + return i != '_' && i != '-' && i != '*' && i != '/'; } @ParameterizedTest @MethodSource("validateTracestateHeaderValidValueContentsArguments") void validateTracestateHeaderValidValueContents(String valueChar) { - String lcAlpha = toLcAlpha(valueChar); + String lcAlpha = toLowerCaseAlpha(valueChar); String mostlyOkHeader = lcAlpha + "=" + valueChar; String alwaysOkHeader = lcAlpha + "=" + lcAlpha + valueChar + lcAlpha; - PropagationTags mostlyOkPT = factory().fromHeaderValue(HeaderType.W3C, mostlyOkHeader); - PropagationTags alwaysOkPT = factory().fromHeaderValue(HeaderType.W3C, alwaysOkHeader); + PropagationTags mostlyOkPT = factory().fromHeaderValue(W3C, mostlyOkHeader); + PropagationTags alwaysOkPT = factory().fromHeaderValue(W3C, alwaysOkHeader); if (" ".equals(valueChar)) { - assertNull(mostlyOkPT.headerValue(HeaderType.W3C)); + assertNull(mostlyOkPT.headerValue(W3C)); } else { - assertEquals(mostlyOkHeader, mostlyOkPT.headerValue(HeaderType.W3C)); + assertEquals(mostlyOkHeader, mostlyOkPT.headerValue(W3C)); } - assertEquals(alwaysOkHeader, alwaysOkPT.headerValue(HeaderType.W3C)); + assertEquals(alwaysOkHeader, alwaysOkPT.headerValue(W3C)); // we're not using any dd members in the tests assertEquals(emptyMap(), mostlyOkPT.createTagMap()); assertEquals(emptyMap(), alwaysOkPT.createTagMap()); } static Stream validateTracestateHeaderValidValueContentsArguments() { - Stream.Builder builder = Stream.builder(); - for (char c = ' '; c <= '~'; c++) { - if (c != ',' && c != '=') { - builder.add(arguments(String.valueOf(c))); - } - } - return builder.build(); + return rangeClosed(' ', '~') + .filter(c -> c != ',' && c != '=') + .mapToObj(String::valueOf) + .map(Arguments::of); } @ParameterizedTest @MethodSource("validateTracestateHeaderInvalidValueContentsArguments") void validateTracestateHeaderInvalidValueContents(String valueChar) { - String lcAlpha = toLcAlpha(valueChar); + String lcAlpha = toLowerCaseAlpha(valueChar); String alwaysBadHeader = lcAlpha + "=" + lcAlpha + valueChar + lcAlpha; - PropagationTags alwaysBadPT = factory().fromHeaderValue(HeaderType.W3C, alwaysBadHeader); + PropagationTags alwaysBadPT = factory().fromHeaderValue(W3C, alwaysBadHeader); - assertNull(alwaysBadPT.headerValue(HeaderType.W3C)); + assertNull(alwaysBadPT.headerValue(W3C)); // we're not using any dd members in the tests assertEquals(emptyMap(), alwaysBadPT.createTagMap()); } static Stream validateTracestateHeaderInvalidValueContentsArguments() { - Set validValueChars = new HashSet<>(); - for (char c = ' '; c <= '~'; c++) { - if (c != ',' && c != '=') validValueChars.add(c); - } - Stream.Builder builder = Stream.builder(); - for (char c = ' '; c <= 'ÿ'; c++) { - if (!validValueChars.contains(c)) { - builder.add(arguments(String.valueOf(c))); - } + return rangeClosed(' ', 'ÿ') + .filter(W3CPropagationTagsTest::invalidValueChar) + .mapToObj(value -> String.valueOf((char) value)) + .map(Arguments::of); + } + + static boolean invalidValueChar(int i) { + if (i >= ' ' && i <= '~') { + return i == ',' || i == '='; } - return builder.build(); + return true; } @ParameterizedTest(name = "{0} members") @@ -182,12 +179,12 @@ static Stream validateTracestateHeaderInvalidValueContentsArguments() void validateTracestateHeaderNumberOfMembersWithoutDatadogMember(int memberCount) { String header = buildHeader(memberCount); - PropagationTags headerPT = factory().fromHeaderValue(HeaderType.W3C, header); + PropagationTags headerPT = factory().fromHeaderValue(W3C, header); if (memberCount <= 32) { - assertEquals(header, headerPT.headerValue(HeaderType.W3C)); + assertEquals(header, headerPT.headerValue(W3C)); } else { - assertNull(headerPT.headerValue(HeaderType.W3C)); + assertNull(headerPT.headerValue(W3C)); } // we're not using any dd members in the tests assertEquals(emptyMap(), headerPT.createTagMap()); @@ -198,12 +195,12 @@ void validateTracestateHeaderNumberOfMembersWithoutDatadogMember(int memberCount void validateTracestateHeaderNumberOfMembersWithDatadogMember(int memberCount) { String header = "dd=s:1," + buildHeader(memberCount); - PropagationTags headerPT = factory().fromHeaderValue(HeaderType.W3C, header); + PropagationTags headerPT = factory().fromHeaderValue(W3C, header); if (memberCount + 1 <= 32) { - assertEquals(header, headerPT.headerValue(HeaderType.W3C)); + assertEquals(header, headerPT.headerValue(W3C)); } else { - assertNull(headerPT.headerValue(HeaderType.W3C)); + assertNull(headerPT.headerValue(W3C)); } // we're not using any dd members in the tests assertEquals(emptyMap(), headerPT.createTagMap()); @@ -214,24 +211,22 @@ void validateTracestateHeaderNumberOfMembersWithDatadogMember(int memberCount) { void validateTracestateHeaderNumberOfMembersWhenPropagatingOriginalTracestate(int memberCount) { String header = buildHeader(memberCount); String expectedHeader = - "dd=t.dm:-4," + (memberCount > 32 ? "" : buildHeader(Math.min(memberCount, 31))); + "dd=t.dm:-4," + (memberCount > MAX_MEMBER_COUNT ? "" : buildHeader(min(memberCount, 31))); PropagationTags datadogHeaderPT = factory().fromHeaderValue(HeaderType.DATADOG, "_dd.p.dm=-4"); - PropagationTags headerPT = factory().fromHeaderValue(HeaderType.W3C, header); + PropagationTags headerPT = factory().fromHeaderValue(W3C, header); datadogHeaderPT.updateW3CTracestate(headerPT.getW3CTracestate()); if (memberCount <= 32) { - assertEquals(expectedHeader, datadogHeaderPT.headerValue(HeaderType.W3C)); + assertEquals(expectedHeader, datadogHeaderPT.headerValue(W3C)); } else { - assertEquals("dd=t.dm:-4", datadogHeaderPT.headerValue(HeaderType.W3C)); + assertEquals("dd=t.dm:-4", datadogHeaderPT.headerValue(W3C)); } - Map expectedTags = new java.util.LinkedHashMap<>(); - expectedTags.put("_dd.p.dm", "-4"); - assertEquals(expectedTags, datadogHeaderPT.createTagMap()); + assertEquals(singletonMap("_dd.p.dm", "-4"), datadogHeaderPT.createTagMap()); } static IntStream memberCountArguments() { - return IntStream.rangeClosed(1, 37); + return rangeClosed(1, 37); } @TableTest({ @@ -267,9 +262,9 @@ static IntStream memberCountArguments() { }) void createPropagationTagsFromHeaderValue( String headerValue, String expectedHeaderValue, Map tags) { - PropagationTags propagationTags = factory().fromHeaderValue(HeaderType.W3C, headerValue); + PropagationTags propagationTags = factory().fromHeaderValue(W3C, headerValue); - assertEquals(expectedHeaderValue, propagationTags.headerValue(HeaderType.W3C)); + assertEquals(expectedHeaderValue, propagationTags.headerValue(W3C)); assertEquals(tags, propagationTags.createTagMap()); } @@ -286,19 +281,19 @@ void createPropagationTagsFromHeaderValue( }) void w3cPropagationTagsShouldTranslateToDatadogTags( String headerValue, String expectedHeaderValue, Map tags) { - PropagationTags propagationTags = factory().fromHeaderValue(HeaderType.W3C, headerValue); + PropagationTags propagationTags = factory().fromHeaderValue(W3C, headerValue); assertEquals(expectedHeaderValue, propagationTags.headerValue(HeaderType.DATADOG)); assertEquals(tags, propagationTags.createTagMap()); } @TableTest({ - "scenario | headerValue | priority | mechanism | origin | expectedHeaderValue | tags ", - "sampler keep default | 'dd=s:0;o:some;t.dm:934086a686-4' | PrioritySampling.SAMPLER_KEEP | SamplingMechanism.DEFAULT | other | 'dd=s:0;o:other;t.dm:934086a686-4' | [_dd.p.dm: 934086a686-4]", - "user keep local rule | 'dd=s:0;o:some;x:unknown' | PrioritySampling.USER_KEEP | SamplingMechanism.LOCAL_USER_RULE | same | 'dd=s:2;o:same;t.dm:-3;x:unknown' | [_dd.p.dm: '-3'] ", - "user drop manual | 'dd=s:0;o:some;x:unknown' | PrioritySampling.USER_DROP | SamplingMechanism.MANUAL | | 'dd=s:-1;x:unknown' | [:] ", - "keep external override | 'dd=s:0;o:some;t.dm:934086a686-4' | PrioritySampling.SAMPLER_KEEP | SamplingMechanism.EXTERNAL_OVERRIDE | other | 'dd=s:1;o:other;t.dm:-0' | [_dd.p.dm: '-0'] ", - "drop external override | 'dd=s:1;o:some;t.dm:934086a686-4' | PrioritySampling.SAMPLER_DROP | SamplingMechanism.EXTERNAL_OVERRIDE | other | 'dd=s:0;o:other' | [:] " + "scenario | headerValue | priority | mechanism | origin | expectedHeaderValue | tags ", + "sampler keep default | 'dd=s:0;o:some;t.dm:934086a686-4' | SAMPLER_KEEP | SamplingMechanism.DEFAULT | other | 'dd=s:0;o:other;t.dm:934086a686-4' | [_dd.p.dm: 934086a686-4]", + "user keep local rule | 'dd=s:0;o:some;x:unknown' | USER_KEEP | SamplingMechanism.LOCAL_USER_RULE | same | 'dd=s:2;o:same;t.dm:-3;x:unknown' | [_dd.p.dm: '-3'] ", + "user drop manual | 'dd=s:0;o:some;x:unknown' | USER_DROP | SamplingMechanism.MANUAL | | 'dd=s:-1;x:unknown' | [:] ", + "keep external override | 'dd=s:0;o:some;t.dm:934086a686-4' | SAMPLER_KEEP | SamplingMechanism.EXTERNAL_OVERRIDE | other | 'dd=s:1;o:other;t.dm:-0' | [_dd.p.dm: '-0'] ", + "drop external override | 'dd=s:1;o:some;t.dm:934086a686-4' | SAMPLER_DROP | SamplingMechanism.EXTERNAL_OVERRIDE | other | 'dd=s:0;o:other' | [:] " }) void propagationTagsShouldBeUpdatedBySamplingAndOrigin( String headerValue, @@ -307,14 +302,14 @@ void propagationTagsShouldBeUpdatedBySamplingAndOrigin( String origin, String expectedHeaderValue, Map tags) { - PropagationTags propagationTags = factory().fromHeaderValue(HeaderType.W3C, headerValue); + PropagationTags propagationTags = factory().fromHeaderValue(W3C, headerValue); - assertNotEquals(expectedHeaderValue, propagationTags.headerValue(HeaderType.W3C)); + assertNotEquals(expectedHeaderValue, propagationTags.headerValue(W3C)); propagationTags.updateTraceSamplingPriority(priority, mechanism); propagationTags.updateTraceOrigin(origin); - assertEquals(expectedHeaderValue, propagationTags.headerValue(HeaderType.W3C)); + assertEquals(expectedHeaderValue, propagationTags.headerValue(W3C)); assertEquals(tags, propagationTags.createTagMap()); } @@ -330,13 +325,13 @@ void propagationTagsShouldBeUpdatedByProductTraceSourcePropagation( @ConvertWith(ProductTraceSourceConverter.class) int product, String expectedHeaderValue, Map tags) { - PropagationTags propagationTags = factory().fromHeaderValue(HeaderType.W3C, headerValue); + PropagationTags propagationTags = factory().fromHeaderValue(W3C, headerValue); - assertNotEquals(expectedHeaderValue, propagationTags.headerValue(HeaderType.W3C)); + assertNotEquals(expectedHeaderValue, propagationTags.headerValue(W3C)); propagationTags.addTraceSource(product); - assertEquals(expectedHeaderValue, propagationTags.headerValue(HeaderType.W3C)); + assertEquals(expectedHeaderValue, propagationTags.headerValue(W3C)); assertEquals(tags, propagationTags.createTagMap()); } @@ -355,8 +350,7 @@ private static String repeat(String s, int n) { return sb.toString(); } - private static String toLcAlpha(String cs) { - // Argh groovy and characters + private static String toLowerCaseAlpha(String cs) { char c = cs.charAt(0); char a = 'a'; char z = 'z'; 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 ca9dac478ff..fa2673c7031 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 @@ -1,7 +1,9 @@ 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.HttpCodecTestHelper.headers; +import static datadog.trace.core.propagation.XRayHttpCodec.X_AMZN_TRACE_ID; import static java.util.Collections.singletonMap; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -14,12 +16,11 @@ import datadog.trace.api.DDTraceId; import datadog.trace.api.DynamicConfig; import datadog.trace.api.config.TracerConfig; -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.junit.utils.converter.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; @@ -34,37 +35,37 @@ class XRayHttpExtractorTest extends DDJavaSpecification { 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"; - private DynamicConfig dynamicConfig; private HttpCodec.Extractor extractor; private boolean origAppSecActive; @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-CaseSensitive-baggage"); - dynamicConfig = + DynamicConfig dynamicConfig = DynamicConfig.create() .setHeaderTags(singletonMap(SOME_HEADER, "some-tag")) .setBaggageMapping(baggageMap) .apply(); - extractor = XRayHttpCodec.newExtractor(Config.get(), () -> dynamicConfig.captureTraceConfig()); - origAppSecActive = ActiveSubsystems.APPSEC_ACTIVE; - ActiveSubsystems.APPSEC_ACTIVE = true; + this.extractor = XRayHttpCodec.newExtractor(Config.get(), dynamicConfig::captureTraceConfig); + + this.origAppSecActive = APPSEC_ACTIVE; + APPSEC_ACTIVE = true; } @AfterEach void teardown() { - ActiveSubsystems.APPSEC_ACTIVE = origAppSecActive; + APPSEC_ACTIVE = this.origAppSecActive; } @TableTest({ - "scenario | traceId | spanId | samplingPriority | expectedSamplingPriority ", - "no sampling | 1 | 2 | '' | PrioritySampling.UNSET ", - "sampled 1 | 2 | 3 | ';Sampled=1' | PrioritySampling.SAMPLER_KEEP", - "sampled 0 | 3 | 4 | ';Sampled=0' | PrioritySampling.SAMPLER_DROP", - "max trace | ffffffffffffffff | fffffffffffffffe | ';Sampled=0' | PrioritySampling.SAMPLER_DROP", - "max span | fffffffffffffffe | ffffffffffffffff | ';Sampled=1' | PrioritySampling.SAMPLER_KEEP" + "scenario | traceId | spanId | samplingPriority | expectedSamplingPriority", + "no sampling | 1 | 2 | '' | UNSET ", + "sampled 1 | 2 | 3 | ';Sampled=1' | SAMPLER_KEEP ", + "sampled 0 | 3 | 4 | ';Sampled=0' | SAMPLER_DROP ", + "max trace | ffffffffffffffff | fffffffffffffffe | ';Sampled=0' | SAMPLER_DROP ", + "max span | fffffffffffffffe | ffffffffffffffff | ';Sampled=1' | SAMPLER_KEEP " }) void extractHttpHeaders( String traceId, @@ -73,10 +74,10 @@ void extractHttpHeaders( @ConvertWith(PrioritySamplingConverter.class) byte expectedSamplingPriority) { // spotless:off Map headers = headers( - "X-Amzn-Trace-Id", "Root=1-00000000-00000000" - + padLeft(traceId, 16, '0') + X_AMZN_TRACE_ID, "Root=1-00000000-00000000" + + XRayTestHelper.zeroPadId(traceId) + ";Parent=" - + padLeft(spanId, 16, '0') + + XRayTestHelper.zeroPadId(spanId) + samplingPriority + ";=empty key;empty value=;=;;", SOME_HEADER, "my-interesting-info", @@ -85,11 +86,12 @@ void extractHttpHeaders( ); // spotless:on - ExtractedContext context = (ExtractedContext) extractor.extract(headers, stringValuesMap()); + ExtractedContext context = + (ExtractedContext) this.extractor.extract(headers, stringValuesMap()); assertEquals(DDTraceId.fromHex(traceId), context.getTraceId()); assertEquals(DDSpanId.fromHex(spanId), context.getSpanId()); - Map expectedBaggage = new LinkedHashMap<>(); + Map expectedBaggage = new HashMap<>(); expectedBaggage.put("empty value", ""); expectedBaggage.put("some-baggage", "my-interesting-baggage-info"); expectedBaggage.put("some-CaseSensitive-baggage", "my-interesting-baggage-info-2"); @@ -103,7 +105,7 @@ void extractHttpHeaders( void extractHeaderTagsWithNoPropagation() { Map headers = headers(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 +119,18 @@ void extractHeadersWithForwarding() { Map tagOnlyCtx = headers("Forwarded", forwarded); // spotless:off Map fullCtx = headers( - "x-amzn-trace-id", "Root=1-00000000-000000000000000000000001;Parent=0000000000000002", + X_AMZN_TRACE_ID, "Root=1-00000000-000000000000000000000001;Parent=0000000000000002", "Forwarded", forwarded ); // spotless:on - 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()); @@ -152,14 +154,14 @@ void extractHeadersWithXForwarding() { ); // spotless:on - TagContext context = extractor.extract(tagOnlyCtx, stringValuesMap()); + TagContext context = this.extractor.extract(tagOnlyCtx, stringValuesMap()); assertNotNull(context); assertFalse(context instanceof ExtractedContext); 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()); @@ -170,7 +172,8 @@ void extractHeadersWithXForwarding() { @Test void noContextWithEmptyHeaders() { - assertNull(extractor.extract(headers("ignored-header", "ignored-value"), stringValuesMap())); + assertNull( + this.extractor.extract(headers("ignored-header", "ignored-value"), stringValuesMap())); } @Test @@ -182,7 +185,7 @@ void noContextWithInvalidNonNumericId() { ); // spotless:on - TagContext context = extractor.extract(headers, stringValuesMap()); + TagContext context = this.extractor.extract(headers, stringValuesMap()); assertNull(context); } @@ -191,7 +194,7 @@ void noContextWithInvalidNonNumericId() { void noContextWithTooLargeTraceId() { Map headers = headers( - "X-Amzn-Trace-Id", "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8"); + X_AMZN_TRACE_ID, "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8"); TagContext context = extractor.extract(headers, stringValuesMap()); @@ -202,7 +205,7 @@ void noContextWithTooLargeTraceId() { void extractHttpHeadersWithNonZeroEpoch() { Map headers = headers( - "X-Amzn-Trace-Id", "Root=1-5759e988-00000000e1be46a994272793;Parent=53995c3f42cd8ad8"); + X_AMZN_TRACE_ID, "Root=1-5759e988-00000000e1be46a994272793;Parent=53995c3f42cd8ad8"); TagContext context = extractor.extract(headers, stringValuesMap()); @@ -223,18 +226,18 @@ void extractIdsWhileRetainingTheOriginalString( String traceId, String spanId, String expectedTraceIdHex, long expectedSpanId) { Map headers = headers( - "X-Amzn-Trace-Id", + X_AMZN_TRACE_ID, "Root=1-00000000-00000000" - + padLeft(traceId, 16, '0') + + XRayTestHelper.zeroPadId(traceId) + ";Parent=" - + padLeft(spanId, 16, '0')); + + XRayTestHelper.zeroPadId(spanId)); ExtractedContext context = (ExtractedContext) extractor.extract(headers, stringValuesMap()); assertEquals(DDTraceId.fromHex(expectedTraceIdHex), context.getTraceId()); - assertEquals(padLeft(traceId, 16, '0'), context.getTraceId().toHexStringPadded(16)); + assertEquals(XRayTestHelper.zeroPadId(traceId), context.getTraceId().toHexStringPadded(16)); assertEquals(expectedSpanId, context.getSpanId()); - assertEquals(padLeft(spanId, 16, '0'), DDSpanId.toHexStringPadded(context.getSpanId())); + assertEquals(XRayTestHelper.zeroPadId(spanId), DDSpanId.toHexStringPadded(context.getSpanId())); } @TableTest({ @@ -245,20 +248,21 @@ void extractIdsWhileRetainingTheOriginalString( void extractHeadersWithEndToEnd(String traceId, String spanId, long endToEndStartTime) { Map headers = headers( - "X-Amzn-Trace-Id", + X_AMZN_TRACE_ID, "Root=1-00000000-00000000" - + padLeft(traceId, 16, '0') + + XRayTestHelper.zeroPadId(traceId) + ";Parent=" - + padLeft(spanId, 16, '0') + + XRayTestHelper.zeroPadId(spanId) + ";k1=v1;t0=" + endToEndStartTime + ";k2=v2"); - 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"); assertEquals(expectedBaggage, context.getBaggage()); @@ -282,7 +286,7 @@ void extractCommonHttpHeaders() { ); // spotless:on - 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()); @@ -295,12 +299,4 @@ void extractCommonHttpHeaders() { assertEquals("8.8.8.8", context.getCfConnectingIp()); assertEquals("9.9.9.9", context.getCfConnectingIpv6()); } - - private static String padLeft(String s, int size, char pad) { - if (s.length() >= size) return s; - StringBuilder sb = new StringBuilder(size); - for (int i = 0; i < size - s.length(); i++) sb.append(pad); - sb.append(s); - return sb.toString(); - } } 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 886d686c9e3..db681314524 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 @@ -1,14 +1,14 @@ package datadog.trace.core.propagation; +import static datadog.trace.api.sampling.PrioritySampling.UNSET; import static datadog.trace.bootstrap.instrumentation.api.ContextVisitors.stringValuesMap; import static datadog.trace.core.propagation.HttpCodecTestHelper.headers; +import static datadog.trace.core.propagation.XRayHttpCodec.X_AMZN_TRACE_ID; +import static datadog.trace.core.propagation.XRayTestHelper.zeroPadId; import static java.util.Collections.emptyMap; import static java.util.Collections.singletonMap; -import static org.mockito.Mockito.clearInvocations; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import datadog.trace.api.Config; @@ -16,7 +16,6 @@ import datadog.trace.api.DDTraceId; import datadog.trace.api.DynamicConfig; import datadog.trace.api.datastreams.NoopPathwayContext; -import datadog.trace.api.sampling.PrioritySampling; import datadog.trace.api.time.TimeSource; import datadog.trace.bootstrap.instrumentation.api.TagContext; import datadog.trace.common.writer.ListWriter; @@ -24,65 +23,67 @@ import datadog.trace.core.DDCoreJavaSpecification; import datadog.trace.core.DDSpanContext; import datadog.trace.core.datastreams.DataStreamsMonitoring; -import datadog.trace.junit.utils.tabletest.PrioritySamplingConverter; -import datadog.trace.junit.utils.tabletest.TraceIdConverter; -import java.util.LinkedHashMap; +import datadog.trace.junit.utils.converter.PrioritySamplingConverter; +import datadog.trace.junit.utils.converter.TraceIdConverter; +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 XRayHttpInjectorTest extends DDCoreJavaSpecification { - private HttpCodec.Injector injector; + private CoreTracer tracer; @BeforeEach void setup() { - injector = XRayHttpCodec.newInjector(singletonMap("some-baggage-key", "SOME_CUSTOM_HEADER")); + this.injector = + XRayHttpCodec.newInjector(singletonMap("some-baggage-key", "SOME_CUSTOM_HEADER")); + TimeSource timeSource = mock(TimeSource.class); + when(timeSource.getCurrentTimeMillis()).thenReturn(1_664_906_869_196L); + when(timeSource.getCurrentTimeNanos()).thenReturn(1_664_906_869_196_787_813L); + when(timeSource.getNanoTicks()).thenReturn(1_664_906_869_196L); + this.tracer = + tracerBuilder() + .dataStreamsMonitoring(mock(DataStreamsMonitoring.class)) + .writer(new ListWriter()) + .timeSource(timeSource) + .build(); + } + + @AfterEach + void tearDown() { + this.tracer.close(); } @TableTest({ - "scenario | traceId | spanId | samplingPriority | expectedTraceHeader ", - "unset 1->2 | 1 | 2 | PrioritySampling.UNSET | 'Root=1-633c7675-000000000000000000000001;Parent=0000000000000002;_dd.origin=fakeOrigin;SOME_CUSTOM_HEADER=some-value;k=v' ", - "keep 2->3 | 2 | 3 | PrioritySampling.SAMPLER_KEEP | 'Root=1-633c7675-000000000000000000000002;Parent=0000000000000003;Sampled=1;_dd.origin=fakeOrigin;SOME_CUSTOM_HEADER=some-value;k=v'", - "drop 4->5 | 4 | 5 | PrioritySampling.SAMPLER_DROP | 'Root=1-633c7675-000000000000000000000004;Parent=0000000000000005;Sampled=0;_dd.origin=fakeOrigin;SOME_CUSTOM_HEADER=some-value;k=v'", - "user keep 5->6 | 5 | 6 | PrioritySampling.USER_KEEP | 'Root=1-633c7675-000000000000000000000005;Parent=0000000000000006;Sampled=1;_dd.origin=fakeOrigin;SOME_CUSTOM_HEADER=some-value;k=v'", - "user drop 6->7 | 6 | 7 | PrioritySampling.USER_DROP | 'Root=1-633c7675-000000000000000000000006;Parent=0000000000000007;Sampled=0;_dd.origin=fakeOrigin;SOME_CUSTOM_HEADER=some-value;k=v'", - "unset max->max-1 | TRACE_ID_MAX | TRACE_ID_MAX-1 | PrioritySampling.UNSET | 'Root=1-633c7675-00000000ffffffffffffffff;Parent=fffffffffffffffe;_dd.origin=fakeOrigin;SOME_CUSTOM_HEADER=some-value;k=v' ", - "keep max-1->max | TRACE_ID_MAX-1 | TRACE_ID_MAX | PrioritySampling.SAMPLER_KEEP | 'Root=1-633c7675-00000000fffffffffffffffe;Parent=ffffffffffffffff;Sampled=1;_dd.origin=fakeOrigin;SOME_CUSTOM_HEADER=some-value;k=v'" + "scenario | traceId | spanId | samplingPriority | expectedTraceHeader ", + "unset 1->2 | 1 | 2 | UNSET | 'Root=1-633c7675-000000000000000000000001;Parent=0000000000000002;_dd.origin=fakeOrigin;SOME_CUSTOM_HEADER=some-value;k=v' ", + "keep 2->3 | 2 | 3 | SAMPLER_KEEP | 'Root=1-633c7675-000000000000000000000002;Parent=0000000000000003;Sampled=1;_dd.origin=fakeOrigin;SOME_CUSTOM_HEADER=some-value;k=v'", + "drop 4->5 | 4 | 5 | SAMPLER_DROP | 'Root=1-633c7675-000000000000000000000004;Parent=0000000000000005;Sampled=0;_dd.origin=fakeOrigin;SOME_CUSTOM_HEADER=some-value;k=v'", + "user keep 5->6 | 5 | 6 | USER_KEEP | 'Root=1-633c7675-000000000000000000000005;Parent=0000000000000006;Sampled=1;_dd.origin=fakeOrigin;SOME_CUSTOM_HEADER=some-value;k=v'", + "user drop 6->7 | 6 | 7 | USER_DROP | 'Root=1-633c7675-000000000000000000000006;Parent=0000000000000007;Sampled=0;_dd.origin=fakeOrigin;SOME_CUSTOM_HEADER=some-value;k=v'", + "unset max->max-1 | MAX | MAX-1 | UNSET | 'Root=1-633c7675-00000000ffffffffffffffff;Parent=fffffffffffffffe;_dd.origin=fakeOrigin;SOME_CUSTOM_HEADER=some-value;k=v' ", + "keep max-1->max | MAX-1 | MAX | SAMPLER_KEEP | 'Root=1-633c7675-00000000fffffffffffffffe;Parent=ffffffffffffffff;Sampled=1;_dd.origin=fakeOrigin;SOME_CUSTOM_HEADER=some-value;k=v'" }) - @SuppressWarnings("unchecked") void injectHttpHeaders( @ConvertWith(TraceIdConverter.class) String traceId, @ConvertWith(TraceIdConverter.class) String spanId, @ConvertWith(PrioritySamplingConverter.class) byte samplingPriority, String expectedTraceHeader) { - ListWriter writer = new ListWriter(); - TimeSource timeSource = mock(TimeSource.class); - when(timeSource.getCurrentTimeMillis()).thenReturn(1_664_906_869_196L); - CoreTracer tracer = - tracerBuilder() - .dataStreamsMonitoring(mock(DataStreamsMonitoring.class)) - .writer(writer) - .timeSource(timeSource) - .build(); - Map baggage = new LinkedHashMap<>(); + Map baggage = new HashMap<>(); baggage.put("k", "v"); baggage.put("some-baggage-key", "some-value"); - DDSpanContext mockedContext = - createContext( - tracer, DDTraceId.from(traceId), DDSpanId.from(spanId), samplingPriority, baggage); - Map carrier = mock(Map.class); - clearInvocations(timeSource); - - injector.inject(mockedContext, carrier, Map::put); + DDSpanContext spanContext = + createContext(DDTraceId.from(traceId), DDSpanId.from(spanId), samplingPriority, baggage); + Map carrier = new HashMap<>(); - verify(timeSource).getCurrentTimeMillis(); - verify(carrier).put("X-Amzn-Trace-Id", expectedTraceHeader); - verifyNoMoreInteractions(timeSource, carrier); + this.injector.inject(spanContext, carrier, Map::put); - tracer.close(); + assertEquals(1, carrier.size()); + assertEquals(expectedTraceHeader, carrier.get(X_AMZN_TRACE_ID)); } @TableTest({ @@ -94,93 +95,48 @@ void injectHttpHeaders( "mixed trace id | aaaaaaaaffffffff | 1 | 'Root=1-633c7675-00000000aaaaaaaaffffffff;Parent=0000000000000001;_dd.origin=fakeOrigin;SOME_CUSTOM_HEADER=some-value;k=v'", "max span id | 1 | ffffffffffffffff | 'Root=1-633c7675-000000000000000000000001;Parent=ffffffffffffffff;_dd.origin=fakeOrigin;SOME_CUSTOM_HEADER=some-value;k=v'" }) - @SuppressWarnings("unchecked") void injectHttpHeadersWithExtractedOriginal( String traceId, String spanId, String expectedTraceHeader) { - ListWriter writer = new ListWriter(); - TimeSource timeSource = mock(TimeSource.class); - when(timeSource.getCurrentTimeMillis()).thenReturn(1_664_906_869_196L); - CoreTracer tracer = - tracerBuilder() - .dataStreamsMonitoring(mock(DataStreamsMonitoring.class)) - .writer(writer) - .timeSource(timeSource) - .build(); - Map headers = - headers( - "X-Amzn-Trace-Id", - "Root=1-00000000-00000000" - + padLeft(traceId, 16, '0') - + ";Parent=" - + padLeft(spanId, 16, '0')); + // spotless:off + Map headers = headers( + X_AMZN_TRACE_ID, "Root=1-00000000-00000000" + zeroPadId(traceId) + ";Parent=" + zeroPadId(spanId) + ); + // spotless:on DynamicConfig dynamicConfig = DynamicConfig.create().setHeaderTags(emptyMap()).setBaggageMapping(emptyMap()).apply(); HttpCodec.Extractor extractor = - XRayHttpCodec.newExtractor(Config.get(), () -> dynamicConfig.captureTraceConfig()); + XRayHttpCodec.newExtractor(Config.get(), dynamicConfig::captureTraceConfig); TagContext context = extractor.extract(headers, stringValuesMap()); - Map baggage = new LinkedHashMap<>(); + Map baggage = new HashMap<>(); baggage.put("k", "v"); baggage.put("some-baggage-key", "some-value"); - DDSpanContext mockedContext = - createContext( - tracer, context.getTraceId(), context.getSpanId(), PrioritySampling.UNSET, baggage); - Map carrier = mock(Map.class); - clearInvocations(timeSource); - - injector.inject(mockedContext, carrier, Map::put); + DDSpanContext spanContext = + createContext(context.getTraceId(), context.getSpanId(), UNSET, baggage); + Map carrier = new HashMap<>(); - verify(timeSource).getCurrentTimeMillis(); - verify(carrier).put("X-Amzn-Trace-Id", expectedTraceHeader); - verifyNoMoreInteractions(timeSource, carrier); + this.injector.inject(spanContext, carrier, Map::put); - tracer.close(); + assertEquals(1, carrier.size()); + assertEquals(expectedTraceHeader, carrier.get(X_AMZN_TRACE_ID)); } @Test - @SuppressWarnings("unchecked") void injectHttpHeadersWithEndToEnd() { - ListWriter writer = new ListWriter(); - TimeSource timeSource = mock(TimeSource.class); - CoreTracer tracer = - tracerBuilder() - .dataStreamsMonitoring(mock(DataStreamsMonitoring.class)) - .writer(writer) - .timeSource(timeSource) - .build(); - // Stub time source AFTER tracer build so init reads default (0) values, matching Spock's - // semantics where stubs declared in then: blocks are not active during setup. - when(timeSource.getCurrentTimeNanos()).thenReturn(1_664_906_869_196_787_813L); - when(timeSource.getNanoTicks()).thenReturn(1_664_906_869_196L); - DDSpanContext mockedContext = - createContext( - tracer, - DDTraceId.from("1"), - DDSpanId.from("2"), - PrioritySampling.UNSET, - singletonMap("k", "v")); - Map carrier = mock(Map.class); - - mockedContext.beginEndToEnd(); - injector.inject(mockedContext, carrier, Map::put); + DDSpanContext spanContext = + createContext(DDTraceId.from("1"), DDSpanId.from("2"), UNSET, singletonMap("k", "v")); + spanContext.beginEndToEnd(); + Map carrier = new HashMap<>(); - // 2 calls: CoreTracer constructor + beginEndToEnd() - verify(timeSource, times(2)).getCurrentTimeNanos(); - verify(timeSource, times(2)).getNanoTicks(); - verify(carrier) - .put( - "X-Amzn-Trace-Id", - "Root=1-633c7675-000000000000000000000001;Parent=0000000000000002;_dd.origin=fakeOrigin;t0=1664906869195;k=v"); - verifyNoMoreInteractions(timeSource, carrier); + this.injector.inject(spanContext, carrier, Map::put); - tracer.close(); + String expectedTraceHeader = + "Root=1-633c7675-000000000000000000000001;Parent=0000000000000002;_dd.origin=fakeOrigin;t0=1664906869196;k=v"; + assertEquals(1, carrier.size()); + assertEquals(expectedTraceHeader, carrier.get(X_AMZN_TRACE_ID)); } - private static DDSpanContext createContext( - CoreTracer tracer, - DDTraceId traceId, - long spanId, - int samplingPriority, - Map baggage) { + private DDSpanContext createContext( + DDTraceId traceId, long spanId, int samplingPriority, Map baggage) { return new DDSpanContext( traceId, spanId, @@ -195,19 +151,11 @@ private static DDSpanContext createContext( false, "fakeType", 0, - tracer.createTraceCollector(DDTraceId.ONE), + this.tracer.createTraceCollector(DDTraceId.ONE), null, null, NoopPathwayContext.INSTANCE, false, null); } - - private static String padLeft(String s, int size, char pad) { - if (s.length() >= size) return s; - StringBuilder sb = new StringBuilder(size); - for (int i = 0; i < size - s.length(); i++) sb.append(pad); - sb.append(s); - return sb.toString(); - } } diff --git a/dd-trace-core/src/test/java/datadog/trace/core/propagation/XRayTestHelper.java b/dd-trace-core/src/test/java/datadog/trace/core/propagation/XRayTestHelper.java new file mode 100644 index 00000000000..d8325552f43 --- /dev/null +++ b/dd-trace-core/src/test/java/datadog/trace/core/propagation/XRayTestHelper.java @@ -0,0 +1,15 @@ +package datadog.trace.core.propagation; + +public class XRayTestHelper { + static String zeroPadId(String s) { + if (s.length() >= 16) { + return s; + } + StringBuilder sb = new StringBuilder(16); + for (int i = 0; i < 16 - s.length(); i++) { + sb.append('0'); + } + sb.append(s); + return sb.toString(); + } +} diff --git a/dd-trace-core/src/test/java/datadog/trace/core/propagation/opg/OpmStampingInjectorTest.java b/dd-trace-core/src/test/java/datadog/trace/core/propagation/opg/OpmStampingInjectorTest.java index 95241e36e7f..a614cc43783 100644 --- a/dd-trace-core/src/test/java/datadog/trace/core/propagation/opg/OpmStampingInjectorTest.java +++ b/dd-trace-core/src/test/java/datadog/trace/core/propagation/opg/OpmStampingInjectorTest.java @@ -1,5 +1,7 @@ package datadog.trace.core.propagation.opg; +import static datadog.trace.core.propagation.PropagationTags.HeaderType.DATADOG; +import static datadog.trace.core.propagation.PropagationTags.HeaderType.W3C; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; @@ -13,20 +15,16 @@ import java.util.HashMap; import java.util.Map; import java.util.function.Supplier; -import javax.annotation.ParametersAreNonnullByDefault; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @DisplayName("OpmStampingInjector") class OpmStampingInjectorTest { - - private static final MapSetter MAP_SETTER = new MapSetter(); - @Test @DisplayName("stamps the local OPM into PropagationTags before delegating") void stampsLocalOpm() { PropagationTags.Factory factory = PropagationTags.factory(); - PropagationTags tags = factory.fromHeaderValue(PropagationTags.HeaderType.W3C, ""); + PropagationTags tags = factory.fromHeaderValue(W3C, ""); DDSpanContext ctx = mock(DDSpanContext.class); when(ctx.getPropagationTags()).thenReturn(tags); @@ -36,7 +34,7 @@ void stampsLocalOpm() { OpmStampingInjector wrapped = new OpmStampingInjector(delegate, supplier); Map carrier = new HashMap<>(); - wrapped.inject(ctx, carrier, MAP_SETTER); + wrapped.inject(ctx, carrier, Map::put); assertNotNull(tags.getOrgPropagationMarker()); assertEquals("local-opm-1", tags.getOrgPropagationMarker().toString()); @@ -46,8 +44,7 @@ void stampsLocalOpm() { @DisplayName("with null supplier value, leaves PropagationTags untouched") void supplierNullLeavesTagsUntouched() { PropagationTags.Factory factory = PropagationTags.factory(); - PropagationTags tags = - factory.fromHeaderValue(PropagationTags.HeaderType.DATADOG, "_dd.p.opm=upstream-abc"); + PropagationTags tags = factory.fromHeaderValue(DATADOG, "_dd.p.opm=upstream-abc"); DDSpanContext ctx = mock(DDSpanContext.class); when(ctx.getPropagationTags()).thenReturn(tags); @@ -56,7 +53,7 @@ void supplierNullLeavesTagsUntouched() { OpmStampingInjector wrapped = new OpmStampingInjector(delegate, () -> null); Map carrier = new HashMap<>(); - wrapped.inject(ctx, carrier, MAP_SETTER); + wrapped.inject(ctx, carrier, Map::put); assertNotNull(tags.getOrgPropagationMarker()); assertEquals("upstream-abc", tags.getOrgPropagationMarker().toString()); @@ -66,8 +63,7 @@ void supplierNullLeavesTagsUntouched() { @DisplayName("local supplier value overrides any inherited OPM") void localOpmOverridesInherited() { PropagationTags.Factory factory = PropagationTags.factory(); - PropagationTags tags = - factory.fromHeaderValue(PropagationTags.HeaderType.DATADOG, "_dd.p.opm=upstream-abc"); + PropagationTags tags = factory.fromHeaderValue(DATADOG, "_dd.p.opm=upstream-abc"); DDSpanContext ctx = mock(DDSpanContext.class); when(ctx.getPropagationTags()).thenReturn(tags); @@ -76,7 +72,7 @@ void localOpmOverridesInherited() { OpmStampingInjector wrapped = new OpmStampingInjector(delegate, () -> "local-xyz"); Map carrier = new HashMap<>(); - wrapped.inject(ctx, carrier, MAP_SETTER); + wrapped.inject(ctx, carrier, Map::put); assertEquals("local-xyz", tags.getOrgPropagationMarker().toString()); } @@ -93,7 +89,7 @@ void delegateInvoked() { CountingInjector delegate = new CountingInjector(); OpmStampingInjector wrapped = new OpmStampingInjector(delegate, () -> null); - wrapped.inject(ctx, new HashMap<>(), MAP_SETTER); + wrapped.inject(ctx, new HashMap<>(), Map::put); assertEquals(1, delegate.calls); assertNull(tags.getOrgPropagationMarker()); } @@ -111,12 +107,4 @@ public void inject(DDSpanContext context, C carrier, CarrierSetter setter calls++; } } - - @ParametersAreNonnullByDefault - private static final class MapSetter implements CarrierSetter> { - @Override - public void set(Map carrier, String key, String value) { - carrier.put(key, value); - } - } } diff --git a/dd-trace-core/src/test/java/datadog/trace/core/propagation/opg/OrgGuardEnforcerTest.java b/dd-trace-core/src/test/java/datadog/trace/core/propagation/opg/OrgGuardEnforcerTest.java index f0abed549b3..65d7ee271d4 100644 --- a/dd-trace-core/src/test/java/datadog/trace/core/propagation/opg/OrgGuardEnforcerTest.java +++ b/dd-trace-core/src/test/java/datadog/trace/core/propagation/opg/OrgGuardEnforcerTest.java @@ -1,5 +1,11 @@ package datadog.trace.core.propagation.opg; +import static datadog.trace.api.TracePropagationStyle.DATADOG; +import static datadog.trace.api.sampling.PrioritySampling.SAMPLER_KEEP; +import static datadog.trace.api.sampling.PrioritySampling.UNSET; +import static datadog.trace.api.sampling.SamplingMechanism.MANUAL; +import static datadog.trace.core.propagation.PropagationTags.HeaderType.W3C; +import static java.util.Collections.emptySet; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -15,12 +21,10 @@ import datadog.trace.api.DDTraceId; import datadog.trace.api.TracePropagationStyle; -import datadog.trace.api.sampling.PrioritySampling; import datadog.trace.bootstrap.instrumentation.api.TagContext; import datadog.trace.core.monitor.HealthMetrics; import datadog.trace.core.propagation.ExtractedContext; import datadog.trace.core.propagation.PropagationTags; -import java.util.Collections; import java.util.HashSet; import java.util.Set; import java.util.function.Supplier; @@ -43,7 +47,7 @@ void setUp() { @Test @DisplayName("local OPM unknown -> no enforcement") void localUnknown() { - OrgGuardEnforcer enforcer = enforcer(false, Collections.emptySet(), () -> null); + OrgGuardEnforcer enforcer = enforcer(false, emptySet(), () -> null); ExtractedContext ctx = ctxWithOpm("X"); assertSame(ctx, enforcer.enforce(ctx)); verify(healthMetrics, never()).onOrgGuardEnforce(any(OrgGuard.Reason.class)); @@ -52,7 +56,7 @@ void localUnknown() { @Test @DisplayName("lax: inbound OPM missing -> no enforcement") void laxInboundMissing() { - OrgGuardEnforcer enforcer = enforcer(false, Collections.emptySet(), () -> "L"); + OrgGuardEnforcer enforcer = enforcer(false, emptySet(), () -> "L"); ExtractedContext ctx = ctxWithOpm(null); assertSame(ctx, enforcer.enforce(ctx)); verify(healthMetrics, never()).onOrgGuardEnforce(any(OrgGuard.Reason.class)); @@ -61,7 +65,7 @@ void laxInboundMissing() { @Test @DisplayName("strict: inbound OPM missing -> strip with strict_missing") void strictInboundMissing() { - OrgGuardEnforcer enforcer = enforcer(true, Collections.emptySet(), () -> "L"); + OrgGuardEnforcer enforcer = enforcer(true, emptySet(), () -> "L"); ExtractedContext ctx = ctxWithOpm(null, /*samplingPriority*/ 2, "synthetics"); TagContext result = enforcer.enforce(ctx); assertNotSame(ctx, result); @@ -72,7 +76,7 @@ void strictInboundMissing() { @Test @DisplayName("inbound OPM matches local -> no enforcement") void match() { - OrgGuardEnforcer enforcer = enforcer(false, Collections.emptySet(), () -> "L"); + OrgGuardEnforcer enforcer = enforcer(false, emptySet(), () -> "L"); ExtractedContext ctx = ctxWithOpm("L"); assertSame(ctx, enforcer.enforce(ctx)); verify(healthMetrics, never()).onOrgGuardEnforce(any(OrgGuard.Reason.class)); @@ -93,8 +97,8 @@ void trusted() { @Test @DisplayName("lax: inbound != local -> strip with mismatch") void mismatchLax() { - OrgGuardEnforcer enforcer = enforcer(false, Collections.emptySet(), () -> "L"); - ExtractedContext ctx = ctxWithOpm("X", /*samplingPriority*/ 2, "synthetics"); + OrgGuardEnforcer enforcer = enforcer(false, emptySet(), () -> "L"); + ExtractedContext ctx = ctxWithOpm("X", 2, "synthetics"); TagContext result = enforcer.enforce(ctx); assertNotSame(ctx, result); assertStripped((ExtractedContext) result, ctx); @@ -104,8 +108,8 @@ void mismatchLax() { @Test @DisplayName("strict: inbound != local -> strip with mismatch") void mismatchStrict() { - OrgGuardEnforcer enforcer = enforcer(true, Collections.emptySet(), () -> "L"); - ExtractedContext ctx = ctxWithOpm("X", /*samplingPriority*/ 2, "synthetics"); + OrgGuardEnforcer enforcer = enforcer(true, emptySet(), () -> "L"); + ExtractedContext ctx = ctxWithOpm("X", 2, "synthetics"); TagContext result = enforcer.enforce(ctx); assertNotSame(ctx, result); assertStripped((ExtractedContext) result, ctx); @@ -115,7 +119,7 @@ void mismatchStrict() { @Test @DisplayName("partial TagContext (not ExtractedContext) -> always pass through") void partialContext() { - OrgGuardEnforcer enforcer = enforcer(true, Collections.emptySet(), () -> "L"); + OrgGuardEnforcer enforcer = enforcer(true, emptySet(), () -> "L"); TagContext partial = new TagContext("upstream", null); assertSame(partial, enforcer.enforce(partial)); verify(healthMetrics, never()).onOrgGuardEnforce(any(OrgGuard.Reason.class)); @@ -124,7 +128,7 @@ void partialContext() { @Test @DisplayName("null input is passed through") void nullInput() { - OrgGuardEnforcer enforcer = enforcer(true, Collections.emptySet(), () -> "L"); + OrgGuardEnforcer enforcer = enforcer(true, emptySet(), () -> "L"); assertNull(enforcer.enforce(null)); verify(healthMetrics, never()).onOrgGuardEnforce(any(OrgGuard.Reason.class)); } @@ -132,18 +136,16 @@ void nullInput() { @Test @DisplayName("strip preserves W3C non-dd vendor tracestate sections") void stripPreservesNonDdVendors() { - OrgGuardEnforcer enforcer = enforcer(false, Collections.emptySet(), () -> "L"); + OrgGuardEnforcer enforcer = enforcer(false, emptySet(), () -> "L"); PropagationTags tags = - factory.fromHeaderValue( - PropagationTags.HeaderType.W3C, - "dd=s:1;o:foo;t.opm:upstream-X,vendor1=abc,vendor2=def"); + factory.fromHeaderValue(W3C, "dd=s:1;o:foo;t.opm:upstream-X,vendor1=abc,vendor2=def"); ExtractedContext ctx = new ExtractedContext( DDTraceId.from(123L), 456L, 2, "origin", tags, TracePropagationStyle.TRACECONTEXT); TagContext result = enforcer.enforce(ctx); assertNotSame(ctx, result); ExtractedContext stripped = (ExtractedContext) result; - String reEncoded = stripped.getPropagationTags().headerValue(PropagationTags.HeaderType.W3C); + String reEncoded = stripped.getPropagationTags().headerValue(W3C); assertNotNull(reEncoded); assertFalse(reEncoded.contains("dd="), "dd= should be dropped: " + reEncoded); assertTrue(reEncoded.contains("vendor1=abc"), "vendor1 missing: " + reEncoded); @@ -158,7 +160,7 @@ private OrgGuardEnforcer enforcer( } private ExtractedContext ctxWithOpm(String opm) { - return ctxWithOpm(opm, PrioritySampling.SAMPLER_KEEP, "origin"); + return ctxWithOpm(opm, SAMPLER_KEEP, "origin"); } private ExtractedContext ctxWithOpm(String opm, int samplingPriority, String origin) { @@ -166,19 +168,19 @@ private ExtractedContext ctxWithOpm(String opm, int samplingPriority, String ori if (opm != null) { tags.updateOrgPropagationMarker(opm); } - tags.updateTraceSamplingPriority(samplingPriority, /* mechanism = MANUAL */ 4); + tags.updateTraceSamplingPriority(samplingPriority, MANUAL); tags.updateTraceOrigin(origin); return new ExtractedContext( - DDTraceId.from(123L), 456L, samplingPriority, origin, tags, TracePropagationStyle.DATADOG); + DDTraceId.from(123L), 456L, samplingPriority, origin, tags, DATADOG); } private static void assertStripped(ExtractedContext stripped, ExtractedContext original) { assertEquals(original.getTraceId(), stripped.getTraceId()); assertEquals(original.getSpanId(), stripped.getSpanId()); - assertEquals(PrioritySampling.UNSET, stripped.getSamplingPriority()); + assertEquals(UNSET, stripped.getSamplingPriority()); assertNull(stripped.getOrigin()); assertNull(stripped.getPropagationTags().getOrgPropagationMarker()); assertNull(stripped.getPropagationTags().getOrigin()); - assertEquals(PrioritySampling.UNSET, stripped.getPropagationTags().getSamplingPriority()); + assertEquals(UNSET, stripped.getPropagationTags().getSamplingPriority()); } } diff --git a/dd-trace-core/src/test/java/datadog/trace/core/taginterceptor/TagInterceptorTest.java b/dd-trace-core/src/test/java/datadog/trace/core/taginterceptor/TagInterceptorTest.java index ab926b317ff..296c6d11997 100644 --- a/dd-trace-core/src/test/java/datadog/trace/core/taginterceptor/TagInterceptorTest.java +++ b/dd-trace-core/src/test/java/datadog/trace/core/taginterceptor/TagInterceptorTest.java @@ -1,9 +1,16 @@ package datadog.trace.core.taginterceptor; +import static datadog.trace.api.ConfigDefaults.DEFAULT_SERVICE_NAME; import static datadog.trace.api.DDTags.ANALYTICS_SAMPLE_RATE; import static datadog.trace.api.TracePropagationStyle.DATADOG; +import static datadog.trace.api.config.GeneralConfig.SERVICE_NAME; import static datadog.trace.api.config.TracerConfig.SPLIT_BY_TAGS; +import static datadog.trace.bootstrap.instrumentation.api.Tags.HTTP_METHOD; +import static datadog.trace.bootstrap.instrumentation.api.Tags.HTTP_STATUS; +import static datadog.trace.bootstrap.instrumentation.api.Tags.HTTP_URL; import static datadog.trace.junit.utils.config.WithConfigExtension.injectSysConfig; +import static java.util.Collections.emptySet; +import static java.util.Collections.singletonMap; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; @@ -19,6 +26,7 @@ import datadog.trace.api.DDTags; import datadog.trace.api.DDTraceId; import datadog.trace.api.ProductTraceSource; +import datadog.trace.api.env.CapturedEnvironment; import datadog.trace.api.remoteconfig.ServiceNameCollector; import datadog.trace.api.remoteconfig.ServiceNameCollectorTestBridge; import datadog.trace.api.sampling.PrioritySampling; @@ -38,8 +46,8 @@ import datadog.trace.core.propagation.ExtractedContext; import datadog.trace.core.propagation.PropagationTags; import datadog.trace.junit.utils.config.WithConfig; -import datadog.trace.junit.utils.tabletest.ConfigDefaultsConverter; -import datadog.trace.junit.utils.tabletest.DDTagsConverter; +import datadog.trace.junit.utils.converter.ConfigDefaultsConverter; +import datadog.trace.junit.utils.converter.TagsConverter; import java.util.Collections; import java.util.Map; import java.util.function.Function; @@ -69,9 +77,8 @@ class TagInterceptorTest extends DDCoreJavaSpecification { "sn.tag2 other | 'sn.tag2' | 'other-service' | 'other-service'" }) @WithConfig(key = "dd.trace.PeerServiceTagInterceptor.enabled", value = "true", addPrefix = false) - void setServiceName( - @ConvertWith(DDTagsConverter.class) String tag, String name, String expected) { - Map mapping = Collections.singletonMap("some-service", "new-service"); + void setServiceName(@ConvertWith(TagsConverter.class) String tag, String name, String expected) { + Map mapping = singletonMap("some-service", "new-service"); CoreTracer tracer = tracerBuilder() .serviceName("wrong-service") @@ -86,16 +93,10 @@ void setServiceName( assertEquals(expected, span.getServiceName()); } - @TableTest({ - "scenario | serviceName | expected | mapping ", - "default service / no match | 'DEFAULT_SERVICE_NAME' | 'DEFAULT_SERVICE_NAME' | [other-service-name: other-service] ", - "default service / match | 'DEFAULT_SERVICE_NAME' | 'new-service' | ['DEFAULT_SERVICE_NAME': new-service]", - "custom service / match | 'other-service-name' | 'other-service' | [other-service-name: other-service] " - }) + @ParameterizedTest + @MethodSource("defaultOrConfiguredServiceNameCanBeRemappedWithoutSettingTagArguments") void defaultOrConfiguredServiceNameCanBeRemappedWithoutSettingTag( - @ConvertWith(ConfigDefaultsConverter.class) String serviceName, - @ConvertWith(ConfigDefaultsConverter.class) String expected, - @ConvertWith(ConfigDefaultsConverter.class) Map mapping) { + String serviceName, String expected, Map mapping) { CoreTracer tracer = tracerBuilder() .serviceName(serviceName) @@ -109,6 +110,16 @@ void defaultOrConfiguredServiceNameCanBeRemappedWithoutSettingTag( assertEquals(expected, span.getServiceName()); } + static Stream defaultOrConfiguredServiceNameCanBeRemappedWithoutSettingTagArguments() { + return Stream.of( + // spotless:off + arguments(DEFAULT_SERVICE_NAME, DEFAULT_SERVICE_NAME, singletonMap("other-service-name", "other-service")), + arguments(DEFAULT_SERVICE_NAME, "new-service", singletonMap(DEFAULT_SERVICE_NAME, "new-service")), + arguments("other-service-name", "other-service", singletonMap("other-service-name", "other-service")) + // spotless:on + ); + } + @TableTest({ "scenario | context | serviceName | expected ", "root context with default service | '/' | 'DEFAULT_SERVLET_ROOT_CONTEXT_SERVICE_NAME' | 'DEFAULT_SERVLET_ROOT_CONTEXT_SERVICE_NAME'", @@ -149,6 +160,9 @@ void setServiceNameFromServletContext( }) void settingServiceNameAsPropertyDisablesServletContext( String context, @ConvertWith(ConfigDefaultsConverter.class) String serviceName) { + if ("ENV_SERVICE_NAME".equals(serviceName)) { + serviceName = CapturedEnvironment.get().getProperties().get(SERVICE_NAME); + } injectSysConfig("service", serviceName); CoreTracer tracer = tracerBuilder().writer(new ListWriter()).build(); AgentSpan span = tracer.buildSpan("datadog", "test").start(); @@ -157,15 +171,10 @@ void settingServiceNameAsPropertyDisablesServletContext( assertEquals(serviceName, span.getServiceName()); } - @TableTest({ - "scenario | context | serviceName | mapping ", - "default service | '/some-context' | 'DEFAULT_SERVICE_NAME' | [DEFAULT_SERVICE_NAME: new-service]", - "my-service | '/some-context' | 'my-service' | [my-service: new-service] " - }) - void mappingCausesServletContextToNotChangeServiceName( - String context, - @ConvertWith(ConfigDefaultsConverter.class) String serviceName, - @ConvertWith(ConfigDefaultsConverter.class) Map mapping) { + @ParameterizedTest + @ValueSource(strings = {DEFAULT_SERVICE_NAME, "my-service"}) + void mappingCausesServletContextToNotChangeServiceName(String serviceName) { + Map mapping = singletonMap(serviceName, "new-service"); CoreTracer tracer = tracerBuilder() .serviceName(serviceName) @@ -175,7 +184,7 @@ void mappingCausesServletContextToNotChangeServiceName( .build(); AgentSpan span = tracer.buildSpan("datadog", "some span").start(); - span.setTag("servlet.context", context); + span.setTag("servlet.context", "/some-context"); span.finish(); assertEquals("new-service", span.getServiceName()); @@ -206,8 +215,7 @@ void splitByTagsForServletContextAndExperimentalJeeSplitByDeployment( .writer(new LoggingWriter()) .sampler(new AllSampler()) .tagInterceptor( - new TagInterceptor( - false, "my-service", Collections.emptySet(), new RuleFlags(), jeeActive)) + new TagInterceptor(false, "my-service", emptySet(), new RuleFlags(), jeeActive)) .build(); AgentSpan span = tracer.buildSpan("datadog", "some span").start(); @@ -585,7 +593,7 @@ void disableDecoratorViaConfig(String decorator, boolean enabled) { "sn.tag1 | 'sn.tag1' | 'new-service' | 'new-service' " }) void disablingServiceDecoratorDoesNotDisableSplitByTags( - @ConvertWith(DDTagsConverter.class) String tag, String name, String expected) { + @ConvertWith(TagsConverter.class) String tag, String name, String expected) { injectSysConfig("dd.trace.ServiceNameTagInterceptor.enabled", "false", false); CoreTracer tracer = @@ -657,35 +665,41 @@ void treat1ValueAsTrueForBooleanTagValues( } @TableTest({ - "scenario | value | resourceName | meta ", - "null url | | 'fakeOperation' | [:] ", - "space url | ' ' | '/' | [:] ", - "tab url | '\t' | '/' | [:] ", - "simple path | '/path' | '/path' | [:] ", - "complex path | '/ABC/a-1/b_2/c.3/d4d/5f/6' | '/ABC/?/?/?/?/?/?' | [:] ", - "not found | '/not-found' | '404' | [Tags.HTTP_STATUS: 404] ", - "with method | '/with-method' | 'POST /with-method' | [Tags.HTTP_METHOD: Post]" + "scenario | URL | tags | expectedResourceName", + "null url | | | 'fakeOperation' ", + "space url | ' ' | | '/' ", + "tab url | '\t' | | '/' ", + "simple path | '/path' | | '/path' ", + "complex path | '/ABC/a-1/b_2/c.3/d4d/5f/6' | | '/ABC/?/?/?/?/?/?' " }) + @ParameterizedTest + @MethodSource("urlAsResourceNameRuleSetsTheResourceNameArguments") void urlAsResourceNameRuleSetsTheResourceName( - String value, - String resourceName, - @ConvertWith(DDTagsConverter.class) Map meta) { + String url, Map tags, String expectedResourceName) { CoreTracer tracer = tracerBuilder().writer(new ListWriter()).build(); AgentSpan span = tracer.buildSpan("datadog", "fakeOperation").start(); - for (Map.Entry entry : meta.entrySet()) { - span.setTag(entry.getKey(), entry.getValue()); + span.setTag(HTTP_URL, url); + if (tags != null) { + tags.forEach(span::setTag); } - span.setTag(Tags.HTTP_URL, value); - try { - assertEquals(resourceName, span.getResourceName().toString()); + assertEquals(expectedResourceName, span.getResourceName().toString()); } finally { span.finish(); } } + static Stream urlAsResourceNameRuleSetsTheResourceNameArguments() { + return Stream.of( + // spotless:off + arguments("/not-found", singletonMap(HTTP_STATUS, "404"), "404"), + arguments("/with-method", singletonMap(HTTP_METHOD, "Post"), "POST /with-method") + // spotless:on + ); + } + @Test void whenUserSetsPeerServiceTheSourceShouldBePeerService() { CoreTracer tracer = tracerBuilder().writer(new ListWriter()).build(); diff --git a/dd-trace-core/src/test/java/datadog/trace/core/traceinterceptor/LatencyTraceInterceptorTest.java b/dd-trace-core/src/test/java/datadog/trace/core/traceinterceptor/LatencyTraceInterceptorTest.java index 87facab95fe..2397ca2fe6b 100644 --- a/dd-trace-core/src/test/java/datadog/trace/core/traceinterceptor/LatencyTraceInterceptorTest.java +++ b/dd-trace-core/src/test/java/datadog/trace/core/traceinterceptor/LatencyTraceInterceptorTest.java @@ -8,7 +8,7 @@ import datadog.trace.core.CoreTracer; import datadog.trace.core.DDCoreJavaSpecification; import datadog.trace.core.DDSpan; -import datadog.trace.junit.utils.tabletest.DDTagsConverter; +import datadog.trace.junit.utils.converter.TagsConverter; import java.util.List; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.Timeout; @@ -32,7 +32,7 @@ class LatencyTraceInterceptorTest extends DDCoreJavaSpecification { void testSetSamplingPriorityAccordingToLatency( String partialFlushEnabled, String latencyThreshold, - @ConvertWith(DDTagsConverter.class) String priorityTag, + @ConvertWith(TagsConverter.class) String priorityTag, long minDuration, int expected) throws InterruptedException { 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 deb7cdbcc94..01693ddcdb2 100644 --- a/dd-trace-ot/src/ot31CompatibilityTest/java/datadog/opentracing/OT31ApiTest.java +++ b/dd-trace-ot/src/ot31CompatibilityTest/java/datadog/opentracing/OT31ApiTest.java @@ -12,8 +12,8 @@ import datadog.trace.common.writer.ListWriter; import datadog.trace.core.DDSpan; import datadog.trace.core.DDSpanContext; -import datadog.trace.junit.utils.tabletest.PrioritySamplingConverter; -import datadog.trace.junit.utils.tabletest.SamplingMechanismConverter; +import datadog.trace.junit.utils.converter.PrioritySamplingConverter; +import datadog.trace.junit.utils.converter.SamplingMechanismConverter; import datadog.trace.test.util.DDJavaSpecification; import io.opentracing.Scope; import io.opentracing.Tracer; 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 5e9b46cef77..cfbfa9a7568 100644 --- a/dd-trace-ot/src/ot33CompatibilityTest/java/datadog/opentracing/OT33ApiTest.java +++ b/dd-trace-ot/src/ot33CompatibilityTest/java/datadog/opentracing/OT33ApiTest.java @@ -10,8 +10,8 @@ import datadog.trace.api.internal.util.LongStringUtils; import datadog.trace.common.writer.ListWriter; import datadog.trace.core.DDSpanContext; -import datadog.trace.junit.utils.tabletest.PrioritySamplingConverter; -import datadog.trace.junit.utils.tabletest.SamplingMechanismConverter; +import datadog.trace.junit.utils.converter.PrioritySamplingConverter; +import datadog.trace.junit.utils.converter.SamplingMechanismConverter; import datadog.trace.test.util.DDJavaSpecification; import io.opentracing.Scope; import io.opentracing.Tracer; diff --git a/utils/config-utils/src/test/java/datadog/trace/api/ConfigSettingTest.java b/utils/config-utils/src/test/java/datadog/trace/api/ConfigSettingTest.java index ad086241a6d..873688d8a61 100644 --- a/utils/config-utils/src/test/java/datadog/trace/api/ConfigSettingTest.java +++ b/utils/config-utils/src/test/java/datadog/trace/api/ConfigSettingTest.java @@ -3,8 +3,10 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; -import datadog.trace.junit.utils.tabletest.BoxedValueConverter; import datadog.trace.junit.utils.tabletest.ConfigValueConverter; +import org.junit.jupiter.api.extension.ParameterContext; +import org.junit.jupiter.params.converter.ArgumentConversionException; +import org.junit.jupiter.params.converter.ArgumentConverter; import org.junit.jupiter.params.converter.ConvertWith; import org.tabletest.junit.TableTest; @@ -80,4 +82,58 @@ void convertIterableMapAndBitSetToString( @ConvertWith(ConfigValueConverter.class) Object value, String rendered) { assertEquals(rendered, ConfigSetting.of("key", value, ConfigOrigin.DEFAULT).stringValue()); } + + /** + * Converts a String cell value to the most specific boxed Java primitive type. Use with + * {@code @ConvertWith(BoxedValueConverter.class)} on {@code Object}-typed parameters when the + * test needs actual typed values (e.g. {@code Float} not {@code String "2.33f"}). + * + *

Conversion rules: + * + *

    + *
  • blank/null -> null + *
  • {@code "true"}/{@code "false"} -> {@link Boolean} + *
  • ends with {@code "f"} -> {@link Float} + *
  • contains {@code "."} -> {@link Double} + *
  • parseable as integer -> {@link Integer} + *
  • otherwise -> {@link String} + *
+ */ + static class BoxedValueConverter implements ArgumentConverter { + @Override + public Object convert(Object source, ParameterContext context) + throws ArgumentConversionException { + if (source == null) { + return null; + } + + String s = source.toString(); + switch (s) { + case "": + return null; + case "true": + return Boolean.TRUE; + case "false": + return Boolean.FALSE; + } + if (s.endsWith("f")) { + try { + return Float.parseFloat(s.substring(0, s.length() - 1)); + } catch (NumberFormatException ignored) { + } + } + + if (s.contains(".")) { + try { + return Double.parseDouble(s); + } catch (NumberFormatException ignored) { + } + } + try { + return Integer.parseInt(s); + } catch (NumberFormatException ignored) { + } + return s; + } + } } diff --git a/utils/junit-utils/src/main/java/datadog/trace/junit/utils/converter/AbstractClassConstantConvertor.java b/utils/junit-utils/src/main/java/datadog/trace/junit/utils/converter/AbstractClassConstantConvertor.java new file mode 100644 index 00000000000..99605ced5c8 --- /dev/null +++ b/utils/junit-utils/src/main/java/datadog/trace/junit/utils/converter/AbstractClassConstantConvertor.java @@ -0,0 +1,59 @@ +package datadog.trace.junit.utils.converter; + +import java.util.Map; +import org.junit.jupiter.api.extension.ParameterContext; +import org.junit.jupiter.params.converter.ArgumentConversionException; +import org.junit.jupiter.params.converter.ArgumentConverter; + +public abstract class AbstractClassConstantConvertor implements ArgumentConverter { + /** + * Returns the class name (simple class name, not fully qualified) of the constants to convert. + * + * @return The simple class name. + */ + protected abstract String className(); + + /** + * Returns the constant mapping between their string representations to their values. + * + * @return The constant mapping between their string representations to their values. + */ + protected abstract Map mapping(); + + @Override + public T convert(Object source, ParameterContext context) { + if (source == null) { + return null; + } + String className = className(); + int length = className.length(); + String s = source.toString(); + if (s.startsWith(className) && s.charAt(length) == '.') { + s = s.substring(length + 1); + } + T mappedValue = mapping().get(s); + if (mappedValue == null && throwsOnUnsupportedValue()) { + throw new ArgumentConversionException( + "Unsupported constant " + source + " from " + className); + } + return mappedValue; + } + + protected boolean throwsOnUnsupportedValue() { + return true; + } + + public abstract static class AbstractStringFallThruConverter + extends AbstractClassConstantConvertor { + @Override + public String convert(Object source, ParameterContext context) { + String convert = super.convert(source, context); + return convert == null ? source.toString() : convert; + } + + @Override + protected boolean throwsOnUnsupportedValue() { + return false; + } + } +} diff --git a/utils/junit-utils/src/main/java/datadog/trace/junit/utils/converter/ConfigDefaultsConverter.java b/utils/junit-utils/src/main/java/datadog/trace/junit/utils/converter/ConfigDefaultsConverter.java new file mode 100644 index 00000000000..8c58f0b0ce6 --- /dev/null +++ b/utils/junit-utils/src/main/java/datadog/trace/junit/utils/converter/ConfigDefaultsConverter.java @@ -0,0 +1,29 @@ +package datadog.trace.junit.utils.converter; + +import static datadog.trace.api.ConfigDefaults.DEFAULT_SERVICE_NAME; +import static datadog.trace.api.ConfigDefaults.DEFAULT_SERVLET_ROOT_CONTEXT_SERVICE_NAME; + +import datadog.trace.junit.utils.converter.AbstractClassConstantConvertor.AbstractStringFallThruConverter; +import java.util.HashMap; +import java.util.Map; + +public class ConfigDefaultsConverter extends AbstractStringFallThruConverter { + private static final Map MAPPING; + + static { + MAPPING = new HashMap<>(); + MAPPING.put("DEFAULT_SERVICE_NAME", DEFAULT_SERVICE_NAME); + MAPPING.put( + "DEFAULT_SERVLET_ROOT_CONTEXT_SERVICE_NAME", DEFAULT_SERVLET_ROOT_CONTEXT_SERVICE_NAME); + } + + @Override + protected String className() { + return "ConfigDefaults"; + } + + @Override + protected Map mapping() { + return MAPPING; + } +} diff --git a/utils/junit-utils/src/main/java/datadog/trace/junit/utils/converter/DDSpanTypesConverter.java b/utils/junit-utils/src/main/java/datadog/trace/junit/utils/converter/DDSpanTypesConverter.java new file mode 100644 index 00000000000..0e0a2c42893 --- /dev/null +++ b/utils/junit-utils/src/main/java/datadog/trace/junit/utils/converter/DDSpanTypesConverter.java @@ -0,0 +1,87 @@ +package datadog.trace.junit.utils.converter; + +import static datadog.trace.api.DDSpanTypes.AEROSPIKE; +import static datadog.trace.api.DDSpanTypes.CACHE; +import static datadog.trace.api.DDSpanTypes.CASSANDRA; +import static datadog.trace.api.DDSpanTypes.COUCHBASE; +import static datadog.trace.api.DDSpanTypes.DATANUCLEUS; +import static datadog.trace.api.DDSpanTypes.ELASTICSEARCH; +import static datadog.trace.api.DDSpanTypes.GRAPHQL; +import static datadog.trace.api.DDSpanTypes.HIBERNATE; +import static datadog.trace.api.DDSpanTypes.HTTP_CLIENT; +import static datadog.trace.api.DDSpanTypes.HTTP_SERVER; +import static datadog.trace.api.DDSpanTypes.LLMOBS; +import static datadog.trace.api.DDSpanTypes.MEMCACHED; +import static datadog.trace.api.DDSpanTypes.MESSAGE_BROKER; +import static datadog.trace.api.DDSpanTypes.MESSAGE_CLIENT; +import static datadog.trace.api.DDSpanTypes.MESSAGE_CONSUMER; +import static datadog.trace.api.DDSpanTypes.MESSAGE_PRODUCER; +import static datadog.trace.api.DDSpanTypes.MONGO; +import static datadog.trace.api.DDSpanTypes.MULE; +import static datadog.trace.api.DDSpanTypes.OPENSEARCH; +import static datadog.trace.api.DDSpanTypes.PROTOBUF; +import static datadog.trace.api.DDSpanTypes.REDIS; +import static datadog.trace.api.DDSpanTypes.RPC; +import static datadog.trace.api.DDSpanTypes.SERVERLESS; +import static datadog.trace.api.DDSpanTypes.SOAP; +import static datadog.trace.api.DDSpanTypes.SQL; +import static datadog.trace.api.DDSpanTypes.TEST; +import static datadog.trace.api.DDSpanTypes.TEST_MODULE_END; +import static datadog.trace.api.DDSpanTypes.TEST_SESSION_END; +import static datadog.trace.api.DDSpanTypes.TEST_SUITE_END; +import static datadog.trace.api.DDSpanTypes.VALKEY; +import static datadog.trace.api.DDSpanTypes.VULNERABILITY; +import static datadog.trace.api.DDSpanTypes.WEBSOCKET; + +import java.util.HashMap; +import java.util.Map; + +public class DDSpanTypesConverter extends AbstractClassConstantConvertor { + private static final Map MAPPING; + + static { + MAPPING = new HashMap<>(); + MAPPING.put("HTTP_CLIENT", HTTP_CLIENT); + MAPPING.put("HTTP_SERVER", HTTP_SERVER); + MAPPING.put("RPC", RPC); + MAPPING.put("CACHE", CACHE); + MAPPING.put("SOAP", SOAP); + MAPPING.put("SQL", SQL); + MAPPING.put("MONGO", MONGO); + MAPPING.put("CASSANDRA", CASSANDRA); + MAPPING.put("COUCHBASE", COUCHBASE); + MAPPING.put("REDIS", REDIS); + MAPPING.put("MEMCACHED", MEMCACHED); + MAPPING.put("ELASTICSEARCH", ELASTICSEARCH); + MAPPING.put("OPENSEARCH", OPENSEARCH); + MAPPING.put("HIBERNATE", HIBERNATE); + MAPPING.put("AEROSPIKE", AEROSPIKE); + MAPPING.put("DATANUCLEUS", DATANUCLEUS); + MAPPING.put("MESSAGE_CLIENT", MESSAGE_CLIENT); + MAPPING.put("MESSAGE_CONSUMER", MESSAGE_CONSUMER); + MAPPING.put("MESSAGE_PRODUCER", MESSAGE_PRODUCER); + MAPPING.put("MESSAGE_BROKER", MESSAGE_BROKER); + MAPPING.put("GRAPHQL", GRAPHQL); + MAPPING.put("TEST", TEST); + MAPPING.put("TEST_SUITE_END", TEST_SUITE_END); + MAPPING.put("TEST_MODULE_END", TEST_MODULE_END); + MAPPING.put("TEST_SESSION_END", TEST_SESSION_END); + MAPPING.put("VULNERABILITY", VULNERABILITY); + MAPPING.put("PROTOBUF", PROTOBUF); + MAPPING.put("MULE", MULE); + MAPPING.put("VALKEY", VALKEY); + MAPPING.put("WEBSOCKET", WEBSOCKET); + MAPPING.put("SERVERLESS", SERVERLESS); + MAPPING.put("LLMOBS", LLMOBS); + } + + @Override + protected String className() { + return "DDSpanTypes"; + } + + @Override + protected Map mapping() { + return MAPPING; + } +} diff --git a/utils/junit-utils/src/main/java/datadog/trace/junit/utils/converter/PrioritySamplingConverter.java b/utils/junit-utils/src/main/java/datadog/trace/junit/utils/converter/PrioritySamplingConverter.java new file mode 100644 index 00000000000..2d9bb6b547e --- /dev/null +++ b/utils/junit-utils/src/main/java/datadog/trace/junit/utils/converter/PrioritySamplingConverter.java @@ -0,0 +1,33 @@ +package datadog.trace.junit.utils.converter; + +import static datadog.trace.api.sampling.PrioritySampling.SAMPLER_DROP; +import static datadog.trace.api.sampling.PrioritySampling.SAMPLER_KEEP; +import static datadog.trace.api.sampling.PrioritySampling.UNSET; +import static datadog.trace.api.sampling.PrioritySampling.USER_DROP; +import static datadog.trace.api.sampling.PrioritySampling.USER_KEEP; + +import java.util.HashMap; +import java.util.Map; + +public class PrioritySamplingConverter extends AbstractClassConstantConvertor { + private static final Map MAPPING; + + static { + MAPPING = new HashMap<>(); + MAPPING.put("UNSET", UNSET); + MAPPING.put("SAMPLER_KEEP", SAMPLER_KEEP); + MAPPING.put("SAMPLER_DROP", SAMPLER_DROP); + MAPPING.put("USER_DROP", USER_DROP); + MAPPING.put("USER_KEEP", USER_KEEP); + } + + @Override + protected String className() { + return "PrioritySampling"; + } + + @Override + protected Map mapping() { + return MAPPING; + } +} diff --git a/utils/junit-utils/src/main/java/datadog/trace/junit/utils/converter/ProductTraceSourceConverter.java b/utils/junit-utils/src/main/java/datadog/trace/junit/utils/converter/ProductTraceSourceConverter.java new file mode 100644 index 00000000000..102d62bedee --- /dev/null +++ b/utils/junit-utils/src/main/java/datadog/trace/junit/utils/converter/ProductTraceSourceConverter.java @@ -0,0 +1,33 @@ +package datadog.trace.junit.utils.converter; + +import static datadog.trace.api.ProductTraceSource.APM; +import static datadog.trace.api.ProductTraceSource.ASM; +import static datadog.trace.api.ProductTraceSource.DBM; +import static datadog.trace.api.ProductTraceSource.DSM; +import static datadog.trace.api.ProductTraceSource.UNSET; + +import java.util.HashMap; +import java.util.Map; + +public class ProductTraceSourceConverter extends AbstractClassConstantConvertor { + private static final Map MAPPING; + + static { + MAPPING = new HashMap<>(); + MAPPING.put("UNSET", UNSET); + MAPPING.put("APM", APM); + MAPPING.put("ASM", ASM); + MAPPING.put("DSM", DSM); + MAPPING.put("DBM", DBM); + } + + @Override + protected String className() { + return "ProductTraceSource"; + } + + @Override + protected Map mapping() { + return MAPPING; + } +} diff --git a/utils/junit-utils/src/main/java/datadog/trace/junit/utils/converter/SamplingMechanismConverter.java b/utils/junit-utils/src/main/java/datadog/trace/junit/utils/converter/SamplingMechanismConverter.java new file mode 100644 index 00000000000..4a6166ec6f2 --- /dev/null +++ b/utils/junit-utils/src/main/java/datadog/trace/junit/utils/converter/SamplingMechanismConverter.java @@ -0,0 +1,51 @@ +package datadog.trace.junit.utils.converter; + +import static datadog.trace.api.sampling.SamplingMechanism.AGENT_RATE; +import static datadog.trace.api.sampling.SamplingMechanism.AI_GUARD; +import static datadog.trace.api.sampling.SamplingMechanism.APPSEC; +import static datadog.trace.api.sampling.SamplingMechanism.DATA_JOBS; +import static datadog.trace.api.sampling.SamplingMechanism.DEFAULT; +import static datadog.trace.api.sampling.SamplingMechanism.EXTERNAL_OVERRIDE; +import static datadog.trace.api.sampling.SamplingMechanism.LOCAL_USER_RULE; +import static datadog.trace.api.sampling.SamplingMechanism.MANUAL; +import static datadog.trace.api.sampling.SamplingMechanism.REMOTE_ADAPTIVE_RULE; +import static datadog.trace.api.sampling.SamplingMechanism.REMOTE_AUTO_RATE; +import static datadog.trace.api.sampling.SamplingMechanism.REMOTE_USER_RATE; +import static datadog.trace.api.sampling.SamplingMechanism.REMOTE_USER_RULE; +import static datadog.trace.api.sampling.SamplingMechanism.SPAN_SAMPLING_RATE; +import static datadog.trace.api.sampling.SamplingMechanism.UNKNOWN; + +import java.util.HashMap; +import java.util.Map; + +public class SamplingMechanismConverter extends AbstractClassConstantConvertor { + private static final Map MAPPING; + + static { + MAPPING = new HashMap<>(); + MAPPING.put("UNKNOWN", UNKNOWN); + MAPPING.put("DEFAULT", DEFAULT); + MAPPING.put("AGENT_RATE", AGENT_RATE); + MAPPING.put("REMOTE_AUTO_RATE", REMOTE_AUTO_RATE); + MAPPING.put("LOCAL_USER_RULE", LOCAL_USER_RULE); + MAPPING.put("MANUAL", MANUAL); + MAPPING.put("APPSEC", APPSEC); + MAPPING.put("REMOTE_USER_RATE", REMOTE_USER_RATE); + MAPPING.put("SPAN_SAMPLING_RATE", SPAN_SAMPLING_RATE); + MAPPING.put("DATA_JOBS", DATA_JOBS); + MAPPING.put("REMOTE_USER_RULE", REMOTE_USER_RULE); + MAPPING.put("REMOTE_ADAPTIVE_RULE", REMOTE_ADAPTIVE_RULE); + MAPPING.put("AI_GUARD", AI_GUARD); + MAPPING.put("EXTERNAL_OVERRIDE", EXTERNAL_OVERRIDE); + } + + @Override + protected String className() { + return "SamplingMechanism"; + } + + @Override + protected Map mapping() { + return MAPPING; + } +} diff --git a/utils/junit-utils/src/main/java/datadog/trace/junit/utils/converter/TagsConverter.java b/utils/junit-utils/src/main/java/datadog/trace/junit/utils/converter/TagsConverter.java new file mode 100644 index 00000000000..1078a48523e --- /dev/null +++ b/utils/junit-utils/src/main/java/datadog/trace/junit/utils/converter/TagsConverter.java @@ -0,0 +1,66 @@ +package datadog.trace.junit.utils.converter; + +import static datadog.trace.api.DDTags.MANUAL_DROP; +import static datadog.trace.api.DDTags.MANUAL_KEEP; +import static datadog.trace.api.DDTags.RESOURCE_NAME; +import static datadog.trace.api.DDTags.SERVICE_NAME; +import static datadog.trace.api.DDTags.SPAN_TYPE; +import static datadog.trace.api.DDTags.THREAD_ID; +import static datadog.trace.api.DDTags.THREAD_NAME; +import static datadog.trace.bootstrap.instrumentation.api.Tags.HTTP_METHOD; +import static datadog.trace.bootstrap.instrumentation.api.Tags.HTTP_STATUS; +import static datadog.trace.bootstrap.instrumentation.api.Tags.HTTP_URL; +import static datadog.trace.bootstrap.instrumentation.api.Tags.PEER_SERVICE; +import static datadog.trace.bootstrap.instrumentation.api.Tags.SPAN_KIND_BROKER; +import static datadog.trace.bootstrap.instrumentation.api.Tags.SPAN_KIND_CLIENT; +import static datadog.trace.bootstrap.instrumentation.api.Tags.SPAN_KIND_CONSUMER; +import static datadog.trace.bootstrap.instrumentation.api.Tags.SPAN_KIND_PRODUCER; +import static datadog.trace.bootstrap.instrumentation.api.Tags.SPAN_KIND_SERVER; + +import datadog.trace.junit.utils.converter.AbstractClassConstantConvertor.AbstractStringFallThruConverter; +import java.util.HashMap; +import java.util.Map; + +public class TagsConverter extends AbstractStringFallThruConverter { + private static final Map MAPPING; + + static { + MAPPING = new HashMap<>(); + // Tags mapping (class name will be trimmed) + MAPPING.put("SPAN_KIND_SERVER", SPAN_KIND_SERVER); + MAPPING.put("SPAN_KIND_CLIENT", SPAN_KIND_CLIENT); + MAPPING.put("SPAN_KIND_PRODUCER", SPAN_KIND_PRODUCER); + MAPPING.put("SPAN_KIND_CONSUMER", SPAN_KIND_CONSUMER); + MAPPING.put("SPAN_KIND_BROKER", SPAN_KIND_BROKER); + MAPPING.put("PEER_SERVICE", PEER_SERVICE); + MAPPING.put("HTTP_URL", HTTP_URL); + MAPPING.put("HTTP_STATUS", HTTP_STATUS); + MAPPING.put("HTTP_METHOD", HTTP_METHOD); + // DDTags mapping with class name + MAPPING.put("DDTags.SPAN_TYPE", SPAN_TYPE); + MAPPING.put("DDTags.SERVICE_NAME", SERVICE_NAME); + MAPPING.put("DDTags.RESOURCE_NAME", RESOURCE_NAME); + MAPPING.put("DDTags.THREAD_NAME", THREAD_NAME); + MAPPING.put("DDTags.THREAD_ID", THREAD_ID); + MAPPING.put("DDTags.MANUAL_KEEP", MANUAL_KEEP); + MAPPING.put("DDTags.MANUAL_DROP", MANUAL_DROP); + // DDTags mapping with direct field name + MAPPING.put("SPAN_TYPE", SPAN_TYPE); + MAPPING.put("SERVICE_NAME", SERVICE_NAME); + MAPPING.put("RESOURCE_NAME", RESOURCE_NAME); + MAPPING.put("THREAD_NAME", THREAD_NAME); + MAPPING.put("THREAD_ID", THREAD_ID); + MAPPING.put("MANUAL_KEEP", MANUAL_KEEP); + MAPPING.put("MANUAL_DROP", MANUAL_DROP); + } + + @Override + protected String className() { + return "Tags"; + } + + @Override + protected Map mapping() { + return MAPPING; + } +} diff --git a/utils/junit-utils/src/main/java/datadog/trace/junit/utils/converter/TraceIdConverter.java b/utils/junit-utils/src/main/java/datadog/trace/junit/utils/converter/TraceIdConverter.java new file mode 100644 index 00000000000..b6bf33671b3 --- /dev/null +++ b/utils/junit-utils/src/main/java/datadog/trace/junit/utils/converter/TraceIdConverter.java @@ -0,0 +1,63 @@ +package datadog.trace.junit.utils.converter; + +import static java.math.BigInteger.ONE; + +import datadog.trace.api.DDTraceId; +import java.math.BigInteger; +import org.junit.jupiter.api.extension.ParameterContext; +import org.junit.jupiter.params.converter.ArgumentConversionException; +import org.junit.jupiter.params.converter.ArgumentConverter; + +/** + * Converts symbolic trace/span ID names to their decimal string representation. + * + *

Supported names: + * + *

    + *
  • {@code MAX} — max unsigned 64-bit value (18446744073709551615 = 2⁶⁴ − 1) + *
  • {@code MAX-1} — max minus one (18446744073709551614 = 2⁶⁴ − 2) + *
  • {@code MAX+1} — first out-of-range value (18446744073709551616 = 2⁶⁴) + *
+ * + *

All other values are passed through unchanged. + */ +public class TraceIdConverter implements ArgumentConverter { + // 2^64 - 1 + public static final String TRACE_ID_MAX = Long.toUnsignedString(-1L); + // 2^64 - 2 + public static final String TRACE_ID_MAX_MINUS_1 = Long.toUnsignedString(-2L); + // 2^64 (first out-of-range value) + public static final String TRACE_ID_MAX_PLUS_1 = new BigInteger(TRACE_ID_MAX).add(ONE).toString(); + + @Override + public Object convert(Object source, ParameterContext context) + throws ArgumentConversionException { + if (source == null) { + return null; + } + String s = source.toString(); + String traceId; + switch (s) { + case "MAX": + traceId = TRACE_ID_MAX; + break; + case "MAX-1": + traceId = TRACE_ID_MAX_MINUS_1; + break; + case "MAX+1": + traceId = TRACE_ID_MAX_PLUS_1; + break; + default: + traceId = s; + } + + Class parameterType = context.getParameter().getType(); + if (parameterType.isAssignableFrom(DDTraceId.class)) { + return DDTraceId.from(s); + } else if (parameterType.isAssignableFrom(Long.class)) { + return DDTraceId.from(s).toLong(); + } else { + return traceId; + } + } +} diff --git a/utils/junit-utils/src/main/java/datadog/trace/junit/utils/tabletest/BoxedValueConverter.java b/utils/junit-utils/src/main/java/datadog/trace/junit/utils/tabletest/BoxedValueConverter.java deleted file mode 100644 index 77cb72bfc67..00000000000 --- a/utils/junit-utils/src/main/java/datadog/trace/junit/utils/tabletest/BoxedValueConverter.java +++ /dev/null @@ -1,55 +0,0 @@ -package datadog.trace.junit.utils.tabletest; - -import org.junit.jupiter.api.extension.ParameterContext; -import org.junit.jupiter.params.converter.ArgumentConversionException; -import org.junit.jupiter.params.converter.ArgumentConverter; - -/** - * Converts a String cell value to the most specific boxed Java primitive type. Use with - * {@code @ConvertWith(BoxedValueConverter.class)} on {@code Object}-typed parameters when the test - * needs actual typed values (e.g. {@code Float} not {@code String "2.33f"}). - * - *

Conversion rules: - * - *

    - *
  • blank/null -> null - *
  • {@code "true"}/{@code "false"} -> {@link Boolean} - *
  • ends with {@code "f"} -> {@link Float} - *
  • contains {@code "."} -> {@link Double} - *
  • parseable as integer -> {@link Integer} - *
  • otherwise -> {@link String} - *
- */ -public class BoxedValueConverter implements ArgumentConverter { - - @Override - public Object convert(Object source, ParameterContext context) - throws ArgumentConversionException { - if (source == null) return null; - - String s = source.toString(); - if (s.isEmpty()) return null; - - if ("true".equals(s)) return Boolean.TRUE; - if ("false".equals(s)) return Boolean.FALSE; - - if (s.endsWith("f")) { - try { - return Float.parseFloat(s.substring(0, s.length() - 1)); - } catch (NumberFormatException ignored) { - } - } - - if (s.contains(".")) { - try { - return Double.parseDouble(s); - } catch (NumberFormatException ignored) { - } - } - try { - return Integer.parseInt(s); - } catch (NumberFormatException ignored) { - } - return s; - } -} diff --git a/utils/junit-utils/src/main/java/datadog/trace/junit/utils/tabletest/ConfigDefaultsConverter.java b/utils/junit-utils/src/main/java/datadog/trace/junit/utils/tabletest/ConfigDefaultsConverter.java deleted file mode 100644 index be412469330..00000000000 --- a/utils/junit-utils/src/main/java/datadog/trace/junit/utils/tabletest/ConfigDefaultsConverter.java +++ /dev/null @@ -1,40 +0,0 @@ -package datadog.trace.junit.utils.tabletest; - -import datadog.trace.api.ConfigDefaults; -import datadog.trace.api.config.GeneralConfig; -import datadog.trace.api.env.CapturedEnvironment; -import java.util.HashMap; -import java.util.Map; -import org.junit.jupiter.api.extension.ParameterContext; -import org.junit.jupiter.params.converter.ArgumentConversionException; -import org.junit.jupiter.params.converter.ArgumentConverter; - -public class ConfigDefaultsConverter implements ArgumentConverter { - @Override - public Object convert(Object source, ParameterContext context) - throws ArgumentConversionException { - if (source instanceof Map) { - // convert keys and values from the map - Map map = new HashMap<>(); - for (Map.Entry e : - ((Map) source).entrySet()) { - map.put(convert(e.getKey(), context), convert(e.getValue(), context)); - } - return map; - } - if (source.toString().startsWith("DEFAULT_")) { - switch (source.toString()) { - case "DEFAULT_SERVICE_NAME": - return ConfigDefaults.DEFAULT_SERVICE_NAME; - case "DEFAULT_SERVLET_ROOT_CONTEXT_SERVICE_NAME": - return ConfigDefaults.DEFAULT_SERVLET_ROOT_CONTEXT_SERVICE_NAME; - default: - throw new ArgumentConversionException("Cannot convert " + source); - } - } - if ("ENV_SERVICE_NAME".equals(source.toString())) { - return CapturedEnvironment.get().getProperties().get(GeneralConfig.SERVICE_NAME); - } - return source.toString(); - } -} diff --git a/utils/junit-utils/src/main/java/datadog/trace/junit/utils/tabletest/DDSpanTypesConverter.java b/utils/junit-utils/src/main/java/datadog/trace/junit/utils/tabletest/DDSpanTypesConverter.java deleted file mode 100644 index 7a7032fe185..00000000000 --- a/utils/junit-utils/src/main/java/datadog/trace/junit/utils/tabletest/DDSpanTypesConverter.java +++ /dev/null @@ -1,88 +0,0 @@ -package datadog.trace.junit.utils.tabletest; - -import datadog.trace.api.DDSpanTypes; -import org.junit.jupiter.api.extension.ParameterContext; -import org.junit.jupiter.params.converter.ArgumentConversionException; -import org.junit.jupiter.params.converter.ArgumentConverter; - -public class DDSpanTypesConverter implements ArgumentConverter { - - @Override - public Object convert(Object source, ParameterContext context) - throws ArgumentConversionException { - if (source == null) { - return null; - } - if (source.toString().startsWith("DDSpanTypes.")) { - switch (source.toString()) { - case "DDSpanTypes.HTTP_CLIENT": - return DDSpanTypes.HTTP_CLIENT; - case "DDSpanTypes.HTTP_SERVER": - return DDSpanTypes.HTTP_SERVER; - case "DDSpanTypes.RPC": - return DDSpanTypes.RPC; - case "DDSpanTypes.CACHE": - return DDSpanTypes.CACHE; - case "DDSpanTypes.SOAP": - return DDSpanTypes.SOAP; - case "DDSpanTypes.SQL": - return DDSpanTypes.SQL; - case "DDSpanTypes.MONGO": - return DDSpanTypes.MONGO; - case "DDSpanTypes.CASSANDRA": - return DDSpanTypes.CASSANDRA; - case "DDSpanTypes.COUCHBASE": - return DDSpanTypes.COUCHBASE; - case "DDSpanTypes.REDIS": - return DDSpanTypes.REDIS; - case "DDSpanTypes.MEMCACHED": - return DDSpanTypes.MEMCACHED; - case "DDSpanTypes.ELASTICSEARCH": - return DDSpanTypes.ELASTICSEARCH; - case "DDSpanTypes.OPENSEARCH": - return DDSpanTypes.OPENSEARCH; - case "DDSpanTypes.HIBERNATE": - return DDSpanTypes.HIBERNATE; - case "DDSpanTypes.AEROSPIKE": - return DDSpanTypes.AEROSPIKE; - case "DDSpanTypes.DATANUCLEUS": - return DDSpanTypes.DATANUCLEUS; - case "DDSpanTypes.MESSAGE_CLIENT": - return DDSpanTypes.MESSAGE_CLIENT; - case "DDSpanTypes.MESSAGE_CONSUMER": - return DDSpanTypes.MESSAGE_CONSUMER; - case "DDSpanTypes.MESSAGE_PRODUCER": - return DDSpanTypes.MESSAGE_PRODUCER; - case "DDSpanTypes.MESSAGE_BROKER": - return DDSpanTypes.MESSAGE_BROKER; - case "DDSpanTypes.GRAPHQL": - return DDSpanTypes.GRAPHQL; - case "DDSpanTypes.TEST": - return DDSpanTypes.TEST; - case "DDSpanTypes.TEST_SUITE_END": - return DDSpanTypes.TEST_SUITE_END; - case "DDSpanTypes.TEST_MODULE_END": - return DDSpanTypes.TEST_MODULE_END; - case "DDSpanTypes.TEST_SESSION_END": - return DDSpanTypes.TEST_SESSION_END; - case "DDSpanTypes.VULNERABILITY": - return DDSpanTypes.VULNERABILITY; - case "DDSpanTypes.PROTOBUF": - return DDSpanTypes.PROTOBUF; - case "DDSpanTypes.MULE": - return DDSpanTypes.MULE; - case "DDSpanTypes.VALKEY": - return DDSpanTypes.VALKEY; - case "DDSpanTypes.WEBSOCKET": - return DDSpanTypes.WEBSOCKET; - case "DDSpanTypes.SERVERLESS": - return DDSpanTypes.SERVERLESS; - case "DDSpanTypes.LLMOBS": - return DDSpanTypes.LLMOBS; - default: - throw new ArgumentConversionException("Cannot convert " + source); - } - } - return source; - } -} diff --git a/utils/junit-utils/src/main/java/datadog/trace/junit/utils/tabletest/DDTagsConverter.java b/utils/junit-utils/src/main/java/datadog/trace/junit/utils/tabletest/DDTagsConverter.java deleted file mode 100644 index ca8121b6b21..00000000000 --- a/utils/junit-utils/src/main/java/datadog/trace/junit/utils/tabletest/DDTagsConverter.java +++ /dev/null @@ -1,70 +0,0 @@ -package datadog.trace.junit.utils.tabletest; - -import datadog.trace.api.DDTags; -import datadog.trace.bootstrap.instrumentation.api.Tags; -import java.util.HashMap; -import java.util.Map; -import org.junit.jupiter.api.extension.ParameterContext; -import org.junit.jupiter.params.converter.ArgumentConversionException; -import org.junit.jupiter.params.converter.ArgumentConverter; - -public class DDTagsConverter implements ArgumentConverter { - @Override - public Object convert(Object source, ParameterContext context) - throws ArgumentConversionException { - if (source instanceof Map) { - // convert keys and values from the map - Map map = new HashMap<>(); - for (Map.Entry e : - ((Map) source).entrySet()) { - map.put(convert(e.getKey(), context), convert(e.getValue(), context)); - } - return map; - } - if (source.toString().startsWith("DDTags.")) { - switch (source.toString()) { - case "DDTags.SPAN_TYPE": - return DDTags.SPAN_TYPE; - case "DDTags.SERVICE_NAME": - return DDTags.SERVICE_NAME; - case "DDTags.RESOURCE_NAME": - return DDTags.RESOURCE_NAME; - case "DDTags.THREAD_NAME": - return DDTags.THREAD_NAME; - case "DDTags.THREAD_ID": - return DDTags.THREAD_ID; - case "DDTags.MANUAL_KEEP": - return DDTags.MANUAL_KEEP; - case "DDTags.MANUAL_DROP": - return DDTags.MANUAL_DROP; - default: - throw new ArgumentConversionException("Cannot convert " + source); - } - } - if (source.toString().startsWith("Tags.")) { - switch (source.toString()) { - case "Tags.SPAN_KIND_SERVER": - return Tags.SPAN_KIND_SERVER; - case "Tags.SPAN_KIND_CLIENT": - return Tags.SPAN_KIND_CLIENT; - case "Tags.SPAN_KIND_PRODUCER": - return Tags.SPAN_KIND_PRODUCER; - case "Tags.SPAN_KIND_CONSUMER": - return Tags.SPAN_KIND_CONSUMER; - case "Tags.SPAN_KIND_BROKER": - return Tags.SPAN_KIND_BROKER; - case "Tags.PEER_SERVICE": - return Tags.PEER_SERVICE; - case "Tags.HTTP_URL": - return Tags.HTTP_URL; - case "Tags.HTTP_STATUS": - return Tags.HTTP_STATUS; - case "Tags.HTTP_METHOD": - return Tags.HTTP_METHOD; - default: - throw new ArgumentConversionException("Cannot convert " + source); - } - } - return source; - } -} diff --git a/utils/junit-utils/src/main/java/datadog/trace/junit/utils/tabletest/PrioritySamplingConverter.java b/utils/junit-utils/src/main/java/datadog/trace/junit/utils/tabletest/PrioritySamplingConverter.java deleted file mode 100644 index f4a4c3d8144..00000000000 --- a/utils/junit-utils/src/main/java/datadog/trace/junit/utils/tabletest/PrioritySamplingConverter.java +++ /dev/null @@ -1,34 +0,0 @@ -package datadog.trace.junit.utils.tabletest; - -import datadog.trace.api.sampling.PrioritySampling; -import org.junit.jupiter.api.extension.ParameterContext; -import org.junit.jupiter.params.converter.ArgumentConversionException; -import org.junit.jupiter.params.converter.ArgumentConverter; - -public class PrioritySamplingConverter implements ArgumentConverter { - - @Override - public Object convert(Object source, ParameterContext context) - throws ArgumentConversionException { - if (source == null) { - return null; - } - if (source.toString().startsWith("PrioritySampling.")) { - switch (source.toString()) { - case "PrioritySampling.UNSET": - return PrioritySampling.UNSET; - case "PrioritySampling.SAMPLER_KEEP": - return PrioritySampling.SAMPLER_KEEP; - case "PrioritySampling.SAMPLER_DROP": - return PrioritySampling.SAMPLER_DROP; - case "PrioritySampling.USER_DROP": - return PrioritySampling.USER_DROP; - case "PrioritySampling.USER_KEEP": - return PrioritySampling.USER_KEEP; - default: - throw new ArgumentConversionException("Cannot convert " + source); - } - } - return source; - } -} diff --git a/utils/junit-utils/src/main/java/datadog/trace/junit/utils/tabletest/ProductTraceSourceConverter.java b/utils/junit-utils/src/main/java/datadog/trace/junit/utils/tabletest/ProductTraceSourceConverter.java deleted file mode 100644 index 0a46dd7da70..00000000000 --- a/utils/junit-utils/src/main/java/datadog/trace/junit/utils/tabletest/ProductTraceSourceConverter.java +++ /dev/null @@ -1,34 +0,0 @@ -package datadog.trace.junit.utils.tabletest; - -import datadog.trace.api.ProductTraceSource; -import org.junit.jupiter.api.extension.ParameterContext; -import org.junit.jupiter.params.converter.ArgumentConversionException; -import org.junit.jupiter.params.converter.ArgumentConverter; - -public class ProductTraceSourceConverter implements ArgumentConverter { - - @Override - public Object convert(Object source, ParameterContext context) - throws ArgumentConversionException { - if (source == null) { - return null; - } - if (source.toString().startsWith("ProductTraceSource.")) { - switch (source.toString()) { - case "ProductTraceSource.UNSET": - return ProductTraceSource.UNSET; - case "ProductTraceSource.APM": - return ProductTraceSource.APM; - case "ProductTraceSource.ASM": - return ProductTraceSource.ASM; - case "ProductTraceSource.DSM": - return ProductTraceSource.DSM; - case "ProductTraceSource.DBM": - return ProductTraceSource.DBM; - default: - throw new ArgumentConversionException("Cannot convert " + source); - } - } - return source; - } -} diff --git a/utils/junit-utils/src/main/java/datadog/trace/junit/utils/tabletest/SamplingMechanismConverter.java b/utils/junit-utils/src/main/java/datadog/trace/junit/utils/tabletest/SamplingMechanismConverter.java deleted file mode 100644 index 74e0e63b4e0..00000000000 --- a/utils/junit-utils/src/main/java/datadog/trace/junit/utils/tabletest/SamplingMechanismConverter.java +++ /dev/null @@ -1,52 +0,0 @@ -package datadog.trace.junit.utils.tabletest; - -import datadog.trace.api.sampling.SamplingMechanism; -import org.junit.jupiter.api.extension.ParameterContext; -import org.junit.jupiter.params.converter.ArgumentConversionException; -import org.junit.jupiter.params.converter.ArgumentConverter; - -public class SamplingMechanismConverter implements ArgumentConverter { - - @Override - public Object convert(Object source, ParameterContext context) - throws ArgumentConversionException { - if (source == null) { - return null; - } - if (source.toString().startsWith("SamplingMechanism.")) { - switch (source.toString()) { - case "SamplingMechanism.UNKNOWN": - return SamplingMechanism.UNKNOWN; - case "SamplingMechanism.DEFAULT": - return SamplingMechanism.DEFAULT; - case "SamplingMechanism.AGENT_RATE": - return SamplingMechanism.AGENT_RATE; - case "SamplingMechanism.REMOTE_AUTO_RATE": - return SamplingMechanism.REMOTE_AUTO_RATE; - case "SamplingMechanism.LOCAL_USER_RULE": - return SamplingMechanism.LOCAL_USER_RULE; - case "SamplingMechanism.MANUAL": - return SamplingMechanism.MANUAL; - case "SamplingMechanism.APPSEC": - return SamplingMechanism.APPSEC; - case "SamplingMechanism.REMOTE_USER_RATE": - return SamplingMechanism.REMOTE_USER_RATE; - case "SamplingMechanism.SPAN_SAMPLING_RATE": - return SamplingMechanism.SPAN_SAMPLING_RATE; - case "SamplingMechanism.DATA_JOBS": - return SamplingMechanism.DATA_JOBS; - case "SamplingMechanism.REMOTE_USER_RULE": - return SamplingMechanism.REMOTE_USER_RULE; - case "SamplingMechanism.REMOTE_ADAPTIVE_RULE": - return SamplingMechanism.REMOTE_ADAPTIVE_RULE; - case "SamplingMechanism.AI_GUARD": - return SamplingMechanism.AI_GUARD; - case "SamplingMechanism.EXTERNAL_OVERRIDE": - return SamplingMechanism.EXTERNAL_OVERRIDE; - default: - throw new ArgumentConversionException("Cannot convert " + source); - } - } - return source; - } -} diff --git a/utils/junit-utils/src/main/java/datadog/trace/junit/utils/tabletest/TraceIdConverter.java b/utils/junit-utils/src/main/java/datadog/trace/junit/utils/tabletest/TraceIdConverter.java deleted file mode 100644 index 00dce0b20ea..00000000000 --- a/utils/junit-utils/src/main/java/datadog/trace/junit/utils/tabletest/TraceIdConverter.java +++ /dev/null @@ -1,46 +0,0 @@ -package datadog.trace.junit.utils.tabletest; - -import static java.math.BigInteger.ONE; - -import java.math.BigInteger; -import org.junit.jupiter.api.extension.ParameterContext; -import org.junit.jupiter.params.converter.ArgumentConversionException; -import org.junit.jupiter.params.converter.ArgumentConverter; - -/** - * Converts symbolic trace/span ID names to their decimal string representation. - * - *

Supported names: - * - *

    - *
  • {@code TRACE_ID_MAX} — max unsigned 64-bit value (18446744073709551615 = 2⁶⁴ − 1) - *
  • {@code TRACE_ID_MAX-1} — max minus one (18446744073709551614 = 2⁶⁴ − 2) - *
  • {@code TRACE_ID_MAX+1} — first out-of-range value (18446744073709551616 = 2⁶⁴) - *
- * - *

All other values are passed through unchanged. - */ -public class TraceIdConverter implements ArgumentConverter { - // 2^64 - 1 - public static final String TRACE_ID_MAX = Long.toUnsignedString(-1L); - // 2^64 - 2 - public static final String TRACE_ID_MAX_MINUS_1 = Long.toUnsignedString(-2L); - // 2^64 (first out-of-range value) - public static final String TRACE_ID_MAX_PLUS_1 = new BigInteger(TRACE_ID_MAX).add(ONE).toString(); - - @Override - public Object convert(Object source, ParameterContext context) - throws ArgumentConversionException { - if (source == null) return null; - switch (source.toString()) { - case "TRACE_ID_MAX": - return TRACE_ID_MAX; - case "TRACE_ID_MAX-1": - return TRACE_ID_MAX_MINUS_1; - case "TRACE_ID_MAX+1": - return TRACE_ID_MAX_PLUS_1; - default: - return source.toString(); - } - } -}