diff --git a/dd-java-agent/instrumentation/akka-http-10.0/src/test/groovy/AkkaHttpServerInstrumentationTest.groovy b/dd-java-agent/instrumentation/akka-http-10.0/src/test/groovy/AkkaHttpServerInstrumentationTest.groovy index 254bfdecf5..a2083d69a9 100644 --- a/dd-java-agent/instrumentation/akka-http-10.0/src/test/groovy/AkkaHttpServerInstrumentationTest.groovy +++ b/dd-java-agent/instrumentation/akka-http-10.0/src/test/groovy/AkkaHttpServerInstrumentationTest.groovy @@ -47,8 +47,8 @@ class AkkaHttpServerInstrumentationTest extends AgentTestRunner { assertTraces(TEST_WRITER, 1) { trace(0, 2) { span(0) { - traceId 123 - parentId 456 + traceId "123" + parentId "456" serviceName "unnamed-java-app" operationName "akka-http.request" resourceName "GET /test" diff --git a/dd-java-agent/instrumentation/aws-java-sdk-1.11.0/src/test/groovy/AWSClientTest.groovy b/dd-java-agent/instrumentation/aws-java-sdk-1.11.0/src/test/groovy/AWSClientTest.groovy index eea79aa12c..c40cebf86e 100644 --- a/dd-java-agent/instrumentation/aws-java-sdk-1.11.0/src/test/groovy/AWSClientTest.groovy +++ b/dd-java-agent/instrumentation/aws-java-sdk-1.11.0/src/test/groovy/AWSClientTest.groovy @@ -87,7 +87,7 @@ class AWSClientTest extends AgentTestRunner { span1.resourceName == "apache.http" span1.type == null !span1.context().getErrorFlag() - span1.context().parentId == 0 + span1.context().parentId == "0" def tags1 = span1.context().tags @@ -130,7 +130,7 @@ class AWSClientTest extends AgentTestRunner { span.resourceName == "$service.$operation" span.type == "web" !span.context().getErrorFlag() - span.context().parentId == 0 + span.context().parentId == "0" def tags = span.context().tags tags[Tags.COMPONENT.key] == "java-aws-sdk" diff --git a/dd-java-agent/instrumentation/aws-java-sdk-1.11.106/src/test/groovy/AWSClientTest.groovy b/dd-java-agent/instrumentation/aws-java-sdk-1.11.106/src/test/groovy/AWSClientTest.groovy index 81db986447..4058674980 100644 --- a/dd-java-agent/instrumentation/aws-java-sdk-1.11.106/src/test/groovy/AWSClientTest.groovy +++ b/dd-java-agent/instrumentation/aws-java-sdk-1.11.106/src/test/groovy/AWSClientTest.groovy @@ -116,7 +116,7 @@ class AWSClientTest extends AgentTestRunner { span1.resourceName == "apache.http" span1.type == null !span1.context().getErrorFlag() - span1.context().parentId == 0 + span1.context().parentId == "0" def tags1 = span1.context().tags @@ -159,7 +159,7 @@ class AWSClientTest extends AgentTestRunner { span.resourceName == "$service.$operation" span.type == "web" !span.context().getErrorFlag() - span.context().parentId == 0 + span.context().parentId == "0" def tags = span.context().tags tags[Tags.COMPONENT.key] == "java-aws-sdk" diff --git a/dd-java-agent/instrumentation/jax-rs-client/src/test/groovy/JaxRsClientTest.groovy b/dd-java-agent/instrumentation/jax-rs-client/src/test/groovy/JaxRsClientTest.groovy index f20b0e5384..348067f7e3 100644 --- a/dd-java-agent/instrumentation/jax-rs-client/src/test/groovy/JaxRsClientTest.groovy +++ b/dd-java-agent/instrumentation/jax-rs-client/src/test/groovy/JaxRsClientTest.groovy @@ -57,7 +57,7 @@ class JaxRsClientTest extends AgentTestRunner { span.resourceName == "GET /ping" span.type == "http" !span.context().getErrorFlag() - span.context().parentId == 0 + span.context().parentId == "0" def tags = span.context().tags diff --git a/dd-java-agent/instrumentation/jetty-8/src/test/groovy/JettyHandlerTest.groovy b/dd-java-agent/instrumentation/jetty-8/src/test/groovy/JettyHandlerTest.groovy index c77debcedb..03e8c3d429 100644 --- a/dd-java-agent/instrumentation/jetty-8/src/test/groovy/JettyHandlerTest.groovy +++ b/dd-java-agent/instrumentation/jetty-8/src/test/groovy/JettyHandlerTest.groovy @@ -66,7 +66,7 @@ class JettyHandlerTest extends AgentTestRunner { context.resourceName == "GET ${handler.class.name}" context.spanType == DDSpanTypes.WEB_SERVLET !context.getErrorFlag() - context.parentId == 0 + context.parentId == "0" def tags = context.tags tags["http.url"] == "http://localhost:$port/" tags["http.method"] == "GET" @@ -154,7 +154,7 @@ class JettyHandlerTest extends AgentTestRunner { context.resourceName == "GET ${handler.class.name}" context.spanType == DDSpanTypes.WEB_SERVLET context.getErrorFlag() - context.parentId == 0 + context.parentId == "0" def tags = context.tags tags["http.url"] == "http://localhost:$port/" tags["http.method"] == "GET" diff --git a/dd-java-agent/instrumentation/kafka-clients-0.11/src/test/groovy/KafkaClientTest.groovy b/dd-java-agent/instrumentation/kafka-clients-0.11/src/test/groovy/KafkaClientTest.groovy index da2680dd7e..c1889142fe 100644 --- a/dd-java-agent/instrumentation/kafka-clients-0.11/src/test/groovy/KafkaClientTest.groovy +++ b/dd-java-agent/instrumentation/kafka-clients-0.11/src/test/groovy/KafkaClientTest.groovy @@ -85,7 +85,7 @@ class KafkaClientTest extends AgentTestRunner { t1span1.resourceName == "Produce Topic $SHARED_TOPIC" t1span1.type == "queue" !t1span1.context().getErrorFlag() - t1span1.context().parentId == 0 + t1span1.context().parentId == "0" def t1tags1 = t1span1.context().tags t1tags1["component"] == "java-kafka" diff --git a/dd-java-agent/instrumentation/kafka-streams-0.11/src/test/groovy/KafkaStreamsTest.groovy b/dd-java-agent/instrumentation/kafka-streams-0.11/src/test/groovy/KafkaStreamsTest.groovy index 93059b0222..f10e596b72 100644 --- a/dd-java-agent/instrumentation/kafka-streams-0.11/src/test/groovy/KafkaStreamsTest.groovy +++ b/dd-java-agent/instrumentation/kafka-streams-0.11/src/test/groovy/KafkaStreamsTest.groovy @@ -111,7 +111,7 @@ class KafkaStreamsTest extends AgentTestRunner { t1span1.resourceName == "Produce Topic $STREAM_PENDING" t1span1.type == "queue" !t1span1.context().getErrorFlag() - t1span1.context().parentId == 0 + t1span1.context().parentId == "0" def t1tags1 = t1span1.context().tags t1tags1["component"] == "java-kafka" diff --git a/dd-java-agent/instrumentation/okhttp-3/src/test/groovy/OkHttp3Test.groovy b/dd-java-agent/instrumentation/okhttp-3/src/test/groovy/OkHttp3Test.groovy index 10866979e6..322642ee6d 100644 --- a/dd-java-agent/instrumentation/okhttp-3/src/test/groovy/OkHttp3Test.groovy +++ b/dd-java-agent/instrumentation/okhttp-3/src/test/groovy/OkHttp3Test.groovy @@ -45,7 +45,7 @@ class OkHttp3Test extends AgentTestRunner { span1.resourceName == "okhttp.http" span1.type == DDSpanTypes.WEB_SERVLET !span1.context().getErrorFlag() - span1.context().parentId == 0 + span1.context().parentId == "0" def tags1 = span1.context().tags diff --git a/dd-java-agent/instrumentation/play-2.4/src/latestDepTest/groovy/Play26Test.groovy b/dd-java-agent/instrumentation/play-2.4/src/latestDepTest/groovy/Play26Test.groovy index 929f7c1432..3247ea3be0 100644 --- a/dd-java-agent/instrumentation/play-2.4/src/latestDepTest/groovy/Play26Test.groovy +++ b/dd-java-agent/instrumentation/play-2.4/src/latestDepTest/groovy/Play26Test.groovy @@ -45,8 +45,8 @@ class Play26Test extends AgentTestRunner { assertTraces(TEST_WRITER, 1) { trace(0, 3) { span(0) { - traceId 123 - parentId 456 + traceId "123" + parentId "456" serviceName "unnamed-java-app" operationName "akka-http.request" resourceName "GET /helloplay/:from" diff --git a/dd-java-agent/instrumentation/play-2.4/src/test/groovy/Play24Test.groovy b/dd-java-agent/instrumentation/play-2.4/src/test/groovy/Play24Test.groovy index e3fa32ab40..4e2eb5c923 100644 --- a/dd-java-agent/instrumentation/play-2.4/src/test/groovy/Play24Test.groovy +++ b/dd-java-agent/instrumentation/play-2.4/src/test/groovy/Play24Test.groovy @@ -46,8 +46,8 @@ class Play24Test extends AgentTestRunner { playTrace.size() == 2 playTrace[1].operationName == 'TracedWork$.doWork' - root.traceId == 123 - root.parentId == 456 + root.traceId == "123" + root.parentId == "456" root.serviceName == "unnamed-java-app" root.operationName == "play.request" root.resourceName == "GET /helloplay/:from" diff --git a/dd-java-agent/instrumentation/sparkjava-2.4/src/test/groovy/SparkJavaBasedTest.groovy b/dd-java-agent/instrumentation/sparkjava-2.4/src/test/groovy/SparkJavaBasedTest.groovy index 7888cbb001..febe9084c3 100644 --- a/dd-java-agent/instrumentation/sparkjava-2.4/src/test/groovy/SparkJavaBasedTest.groovy +++ b/dd-java-agent/instrumentation/sparkjava-2.4/src/test/groovy/SparkJavaBasedTest.groovy @@ -81,7 +81,7 @@ class SparkJavaBasedTest extends AgentTestRunner { context.resourceName == "GET /param/:param" context.spanType == DDSpanTypes.WEB_SERVLET !context.getErrorFlag() - context.parentId == 0 + context.parentId == "0" def tags = context.tags tags["http.url"] == "http://localhost:$port/param/asdf1234" tags["http.method"] == "GET" diff --git a/dd-java-agent/instrumentation/spring-web/src/test/groovy/test/SpringBootBasedTest.groovy b/dd-java-agent/instrumentation/spring-web/src/test/groovy/test/SpringBootBasedTest.groovy index 1a3e424c88..97d82bae46 100644 --- a/dd-java-agent/instrumentation/spring-web/src/test/groovy/test/SpringBootBasedTest.groovy +++ b/dd-java-agent/instrumentation/spring-web/src/test/groovy/test/SpringBootBasedTest.groovy @@ -43,7 +43,7 @@ class SpringBootBasedTest extends AgentTestRunner { span.context().resourceName == "GET /param/{parameter}/" span.context().spanType == DDSpanTypes.WEB_SERVLET !span.context().getErrorFlag() - span.context().parentId == 0 + span.context().parentId == "0" span.context().tags["http.url"] == "http://localhost:$port/param/asdf1234/" span.context().tags["http.method"] == "GET" span.context().tags["span.kind"] == "server" @@ -72,7 +72,7 @@ class SpringBootBasedTest extends AgentTestRunner { span0.context().resourceName == "404" span0.context().spanType == DDSpanTypes.WEB_SERVLET !span0.context().getErrorFlag() - span0.context().parentId == 0 + span0.context().parentId == "0" span0.context().tags["http.url"] == "http://localhost:$port/invalid" span0.context().tags["http.method"] == "GET" span0.context().tags["span.kind"] == "server" @@ -92,7 +92,7 @@ class SpringBootBasedTest extends AgentTestRunner { span1.context().resourceName == "404" span1.context().spanType == DDSpanTypes.WEB_SERVLET !span1.context().getErrorFlag() - span1.context().parentId == 0 + span1.context().parentId == "0" span1.context().tags["http.url"] == "http://localhost:$port/error" span1.context().tags["http.method"] == "GET" span1.context().tags["span.kind"] == "server" @@ -123,7 +123,7 @@ class SpringBootBasedTest extends AgentTestRunner { span0.context().resourceName == "GET /error/{parameter}/" span0.context().spanType == DDSpanTypes.WEB_SERVLET span0.context().getErrorFlag() - span0.context().parentId == 0 + span0.context().parentId == "0" span0.context().tags["http.url"] == "http://localhost:$port/error/qwerty/" span0.context().tags["http.method"] == "GET" span0.context().tags["span.kind"] == "server" @@ -146,7 +146,7 @@ class SpringBootBasedTest extends AgentTestRunner { span1.context().operationName == "servlet.request" span1.context().resourceName == "GET /error" span1.context().spanType == DDSpanTypes.WEB_SERVLET - span1.context().parentId == 0 + span1.context().parentId == "0" span1.context().tags["http.url"] == "http://localhost:$port/error" span1.context().tags["http.method"] == "GET" span1.context().tags["span.kind"] == "server" @@ -173,7 +173,7 @@ class SpringBootBasedTest extends AgentTestRunner { span.context().resourceName == "POST /validated" span.context().spanType == DDSpanTypes.WEB_SERVLET !span.context().getErrorFlag() - span.context().parentId == 0 + span.context().parentId == "0" span.context().tags["http.url"] == "http://localhost:$port/validated" span.context().tags["http.method"] == "POST" span.context().tags["span.kind"] == "server" @@ -204,7 +204,7 @@ class SpringBootBasedTest extends AgentTestRunner { span0.context().resourceName == "POST /validated" span0.context().spanType == DDSpanTypes.WEB_SERVLET !span0.context().getErrorFlag() // This should be an error once we have the http status code decorator working. - span0.context().parentId == 0 + span0.context().parentId == "0" span0.context().tags["http.url"] == "http://localhost:$port/validated" span0.context().tags["http.method"] == "POST" span0.context().tags["span.kind"] == "server" @@ -228,7 +228,7 @@ class SpringBootBasedTest extends AgentTestRunner { span1.context().resourceName == "POST /error" span1.context().spanType == DDSpanTypes.WEB_SERVLET !span1.context().getErrorFlag() - span1.context().parentId == 0 + span1.context().parentId == "0" span1.context().tags["http.url"] == "http://localhost:$port/error" span1.context().tags["http.method"] == "POST" span1.context().tags["span.kind"] == "server" diff --git a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/SpanAssert.groovy b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/SpanAssert.groovy index 66d2473098..43238a36fc 100644 --- a/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/SpanAssert.groovy +++ b/dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/SpanAssert.groovy @@ -39,14 +39,14 @@ class SpanAssert { } def parent() { - assert span.parentId == 0 + assert span.parentId == "0" } - def parentId(long parentId) { + def parentId(String parentId) { assert span.parentId == parentId } - def traceId(long traceId) { + def traceId(String traceId) { assert span.traceId == traceId } diff --git a/dd-java-agent/testing/src/test/groovy/TraceCorrelationTest.groovy b/dd-java-agent/testing/src/test/groovy/TraceCorrelationTest.groovy index abcdc37eea..f47aa73f3b 100644 --- a/dd-java-agent/testing/src/test/groovy/TraceCorrelationTest.groovy +++ b/dd-java-agent/testing/src/test/groovy/TraceCorrelationTest.groovy @@ -19,7 +19,7 @@ class TraceCorrelationTest extends AgentTestRunner { scope.close() then: - CorrelationIdentifier.traceId == 0 - CorrelationIdentifier.spanId == 0 + CorrelationIdentifier.traceId == "0" + CorrelationIdentifier.spanId == "0" } } diff --git a/dd-trace-api/src/main/java/datadog/trace/api/CorrelationIdentifier.java b/dd-trace-api/src/main/java/datadog/trace/api/CorrelationIdentifier.java index d54e5ab679..dc7a51f61b 100644 --- a/dd-trace-api/src/main/java/datadog/trace/api/CorrelationIdentifier.java +++ b/dd-trace-api/src/main/java/datadog/trace/api/CorrelationIdentifier.java @@ -16,29 +16,29 @@ public class CorrelationIdentifier { } } - public static long getTraceId() { + public static String getTraceId() { return provider.get().getTraceId(); } - public static long getSpanId() { + public static String getSpanId() { return provider.get().getSpanId(); } public interface Provider { - long getTraceId(); + String getTraceId(); - long getSpanId(); + String getSpanId(); Provider NO_OP = new Provider() { @Override - public long getTraceId() { - return 0; + public String getTraceId() { + return "0"; } @Override - public long getSpanId() { - return 0; + public String getSpanId() { + return "0"; } }; } diff --git a/dd-trace-ot/dd-trace-ot.gradle b/dd-trace-ot/dd-trace-ot.gradle index b1fc6ec3b3..0a30dc7289 100644 --- a/dd-trace-ot/dd-trace-ot.gradle +++ b/dd-trace-ot/dd-trace-ot.gradle @@ -34,7 +34,9 @@ dependencies { compile deps.jackson compile deps.slf4j - compile group: 'org.msgpack', name: 'jackson-dataformat-msgpack', version: '0.8.2' + // any higher versions seems to break ES tests with this exception: + // java.lang.NoSuchMethodError: com.fasterxml.jackson.dataformat.smile.SmileGenerator.getOutputContext() + compile group: 'org.msgpack', name: 'jackson-dataformat-msgpack', version: '0.8.14' testCompile deps.autoservice testCompile group: 'org.objenesis', name: 'objenesis', version: '2.6' diff --git a/dd-trace-ot/src/main/java/datadog/opentracing/DDSpan.java b/dd-trace-ot/src/main/java/datadog/opentracing/DDSpan.java index b0bca952e0..68f66e9f87 100644 --- a/dd-trace-ot/src/main/java/datadog/opentracing/DDSpan.java +++ b/dd-trace-ot/src/main/java/datadog/opentracing/DDSpan.java @@ -4,11 +4,16 @@ import static io.opentracing.log.Fields.ERROR_OBJECT; import com.fasterxml.jackson.annotation.JsonGetter; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; import datadog.trace.api.DDTags; import datadog.trace.api.interceptor.MutableSpan; import datadog.trace.api.sampling.PrioritySampling; import datadog.trace.common.util.Clock; import io.opentracing.Span; +import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.lang.ref.WeakReference; @@ -110,7 +115,7 @@ public class DDSpan implements Span, MutableSpan { */ @JsonIgnore public final boolean isRootSpan() { - return context.getParentId() == 0; + return "0".equals(context.getParentId()); } @Override @@ -317,17 +322,20 @@ public class DDSpan implements Span, MutableSpan { } @JsonGetter("trace_id") - public long getTraceId() { + @JsonSerialize(using = UInt64IDStringSerializer.class) + public String getTraceId() { return context.getTraceId(); } @JsonGetter("span_id") - public long getSpanId() { + @JsonSerialize(using = UInt64IDStringSerializer.class) + public String getSpanId() { return context.getSpanId(); } @JsonGetter("parent_id") - public long getParentId() { + @JsonSerialize(using = UInt64IDStringSerializer.class) + public String getParentId() { return context.getParentId(); } @@ -390,4 +398,21 @@ public class DDSpan implements Span, MutableSpan { .append(durationNano) .toString(); } + + protected static class UInt64IDStringSerializer extends StdSerializer { + + public UInt64IDStringSerializer() { + this(null); + } + + public UInt64IDStringSerializer(Class stringClass) { + super(stringClass); + } + + @Override + public void serialize(String value, JsonGenerator gen, SerializerProvider provider) + throws IOException { + gen.writeNumber(value); + } + } } diff --git a/dd-trace-ot/src/main/java/datadog/opentracing/DDSpanContext.java b/dd-trace-ot/src/main/java/datadog/opentracing/DDSpanContext.java index a84acf27aa..45e5f4edbf 100644 --- a/dd-trace-ot/src/main/java/datadog/opentracing/DDSpanContext.java +++ b/dd-trace-ot/src/main/java/datadog/opentracing/DDSpanContext.java @@ -35,9 +35,9 @@ public class DDSpanContext implements io.opentracing.SpanContext { private final Map baggageItems; // Not Shared with other span contexts - private final long traceId; - private final long spanId; - private final long parentId; + private final String traceId; + private final String spanId; + private final String parentId; /** Tags are associated to the current span, they will not propagate to the children span */ private final Map tags = new ConcurrentHashMap<>(); @@ -67,9 +67,9 @@ public class DDSpanContext implements io.opentracing.SpanContext { private final long threadId = Thread.currentThread().getId(); public DDSpanContext( - final long traceId, - final long spanId, - final long parentId, + final String traceId, + final String spanId, + final String parentId, final String serviceName, final String operationName, final String resourceName, @@ -86,6 +86,9 @@ public class DDSpanContext implements io.opentracing.SpanContext { this.tracer = tracer; this.trace = trace; + assert traceId != null; + assert spanId != null; + assert parentId != null; this.traceId = traceId; this.spanId = spanId; this.parentId = parentId; @@ -111,15 +114,15 @@ public class DDSpanContext implements io.opentracing.SpanContext { } } - public long getTraceId() { + public String getTraceId() { return this.traceId; } - public long getParentId() { + public String getParentId() { return this.parentId; } - public long getSpanId() { + public String getSpanId() { return this.spanId; } diff --git a/dd-trace-ot/src/main/java/datadog/opentracing/DDTracer.java b/dd-trace-ot/src/main/java/datadog/opentracing/DDTracer.java index 0b4a74dd74..3b085c7d83 100644 --- a/dd-trace-ot/src/main/java/datadog/opentracing/DDTracer.java +++ b/dd-trace-ot/src/main/java/datadog/opentracing/DDTracer.java @@ -465,9 +465,10 @@ public class DDTracer implements io.opentracing.Tracer { return this; } - private long generateNewId() { + private String generateNewId() { + // TODO: expand the range of numbers generated to be from 1 to uint 64 MAX // Ensure the generated ID is in a valid range: - return ThreadLocalRandom.current().nextLong(1, Long.MAX_VALUE); + return String.valueOf(ThreadLocalRandom.current().nextLong(1, Long.MAX_VALUE)); } /** @@ -477,9 +478,9 @@ public class DDTracer implements io.opentracing.Tracer { * @return the context */ private DDSpanContext buildSpanContext() { - final long traceId; - final long spanId = generateNewId(); - final long parentSpanId; + final String traceId; + final String spanId = generateNewId(); + final String parentSpanId; final Map baggage; final PendingTrace parentTrace; final int samplingPriority; @@ -521,7 +522,7 @@ public class DDTracer implements io.opentracing.Tracer { // Start a new trace } else { traceId = generateNewId(); - parentSpanId = 0L; + parentSpanId = "0"; baggage = null; parentTrace = new PendingTrace(DDTracer.this, traceId, serviceNameMappings); samplingPriority = PrioritySampling.UNSET; diff --git a/dd-trace-ot/src/main/java/datadog/opentracing/OTTraceCorrelation.java b/dd-trace-ot/src/main/java/datadog/opentracing/OTTraceCorrelation.java index 96c763bb71..c7478d6334 100644 --- a/dd-trace-ot/src/main/java/datadog/opentracing/OTTraceCorrelation.java +++ b/dd-trace-ot/src/main/java/datadog/opentracing/OTTraceCorrelation.java @@ -22,20 +22,20 @@ public class OTTraceCorrelation implements CorrelationIdentifier.Provider { } @Override - public long getTraceId() { + public String getTraceId() { final Span activeSpan = tracer.activeSpan(); if (activeSpan instanceof DDSpan) { return ((DDSpan) activeSpan).getTraceId(); } - return 0; + return "0"; } @Override - public long getSpanId() { + public String getSpanId() { final Span activeSpan = tracer.activeSpan(); if (activeSpan instanceof DDSpan) { return ((DDSpan) activeSpan).getSpanId(); } - return 0; + return "0"; } } diff --git a/dd-trace-ot/src/main/java/datadog/opentracing/PendingTrace.java b/dd-trace-ot/src/main/java/datadog/opentracing/PendingTrace.java index 16bf8b5690..d56187f5bb 100644 --- a/dd-trace-ot/src/main/java/datadog/opentracing/PendingTrace.java +++ b/dd-trace-ot/src/main/java/datadog/opentracing/PendingTrace.java @@ -30,7 +30,7 @@ public class PendingTrace extends ConcurrentLinkedDeque { } private final DDTracer tracer; - private final long traceId; + private final String traceId; private final Map serviceNameMappings; // TODO: consider moving these time fields into DDTracer to ensure that traces have precise @@ -51,7 +51,7 @@ public class PendingTrace extends ConcurrentLinkedDeque { private final AtomicBoolean isWritten = new AtomicBoolean(false); PendingTrace( - final DDTracer tracer, final long traceId, final Map serviceNameMappings) { + final DDTracer tracer, final String traceId, final Map serviceNameMappings) { this.tracer = tracer; this.traceId = traceId; this.serviceNameMappings = serviceNameMappings; @@ -77,7 +77,13 @@ public class PendingTrace extends ConcurrentLinkedDeque { } public void registerSpan(final DDSpan span) { - if (span.context().getTraceId() != traceId) { + if (traceId == null || span.context() == null) { + log.error( + "Failed to register span ({}) due to null PendingTrace traceId or null span context", + span); + return; + } + if (!traceId.equals(span.context().getTraceId())) { log.debug("{} - span registered for wrong trace ({})", span, traceId); return; } @@ -95,7 +101,12 @@ public class PendingTrace extends ConcurrentLinkedDeque { } private void expireSpan(final DDSpan span) { - if (span.context().getTraceId() != traceId) { + if (traceId == null || span.context() == null) { + log.error( + "Failed to expire span ({}) due to null PendingTrace traceId or null span context", span); + return; + } + if (!traceId.equals(span.context().getTraceId())) { log.debug("{} - span expired for wrong trace ({})", span, traceId); return; } @@ -116,7 +127,12 @@ public class PendingTrace extends ConcurrentLinkedDeque { log.debug("{} - added to trace, but not complete.", span); return; } - if (traceId != span.getTraceId()) { + if (traceId == null || span.context() == null) { + log.error( + "Failed to add span ({}) due to null PendingTrace traceId or null span context", span); + return; + } + if (!traceId.equals(span.getTraceId())) { log.debug("{} - added to a mismatched trace.", span); return; } diff --git a/dd-trace-ot/src/main/java/datadog/opentracing/propagation/ExtractedContext.java b/dd-trace-ot/src/main/java/datadog/opentracing/propagation/ExtractedContext.java index b67e6c0523..e89d2f659f 100644 --- a/dd-trace-ot/src/main/java/datadog/opentracing/propagation/ExtractedContext.java +++ b/dd-trace-ot/src/main/java/datadog/opentracing/propagation/ExtractedContext.java @@ -5,16 +5,16 @@ import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; public class ExtractedContext implements SpanContext { - private final Long traceId; - private final Long spanId; + private final String traceId; + private final String spanId; private final int samplingPriority; private final Map baggage; private final Map tags; private final AtomicBoolean samplingPriorityLocked = new AtomicBoolean(false); public ExtractedContext( - final Long traceId, - final Long spanId, + final String traceId, + final String spanId, final int samplingPriority, final Map baggage, final Map tags) { @@ -34,11 +34,11 @@ public class ExtractedContext implements SpanContext { samplingPriorityLocked.set(true); } - public Long getTraceId() { + public String getTraceId() { return traceId; } - public Long getSpanId() { + public String getSpanId() { return spanId; } diff --git a/dd-trace-ot/src/main/java/datadog/opentracing/propagation/HTTPCodec.java b/dd-trace-ot/src/main/java/datadog/opentracing/propagation/HTTPCodec.java index 6e961d8f7b..c1dcf6767c 100644 --- a/dd-trace-ot/src/main/java/datadog/opentracing/propagation/HTTPCodec.java +++ b/dd-trace-ot/src/main/java/datadog/opentracing/propagation/HTTPCodec.java @@ -4,6 +4,7 @@ import datadog.opentracing.DDSpanContext; import datadog.trace.api.sampling.PrioritySampling; import io.opentracing.propagation.TextMap; import java.io.UnsupportedEncodingException; +import java.math.BigInteger; import java.net.URLDecoder; import java.net.URLEncoder; import java.util.Collections; @@ -15,6 +16,10 @@ import lombok.extern.slf4j.Slf4j; @Slf4j public class HTTPCodec implements Codec { + // uint 64 bits max value, 2^64 - 1 + static final BigInteger BIG_INTEGER_UINT64_MAX = + (new BigInteger("2")).pow(64).subtract(BigInteger.ONE); + private static final String OT_BAGGAGE_PREFIX = "ot-baggage-"; private static final String TRACE_ID_KEY = "x-datadog-trace-id"; private static final String SPAN_ID_KEY = "x-datadog-parent-id"; @@ -48,34 +53,36 @@ public class HTTPCodec implements Codec { Map baggage = Collections.emptyMap(); Map tags = Collections.emptyMap(); - Long traceId = 0L; - Long spanId = 0L; + String traceId = "0"; + String spanId = "0"; int samplingPriority = PrioritySampling.UNSET; for (final Map.Entry entry : carrier) { final String key = entry.getKey().toLowerCase(); - if (key.equalsIgnoreCase(TRACE_ID_KEY)) { - traceId = Long.parseLong(entry.getValue()); - } else if (key.equalsIgnoreCase(SPAN_ID_KEY)) { - spanId = Long.parseLong(entry.getValue()); + final String val = entry.getValue(); + + if (TRACE_ID_KEY.equalsIgnoreCase(key)) { + traceId = validateUInt64BitsID(val); + } else if (SPAN_ID_KEY.equalsIgnoreCase(key)) { + spanId = validateUInt64BitsID(val); } else if (key.startsWith(OT_BAGGAGE_PREFIX)) { if (baggage.isEmpty()) { baggage = new HashMap<>(); } - baggage.put(key.replace(OT_BAGGAGE_PREFIX, ""), decode(entry.getValue())); - } else if (key.equalsIgnoreCase(SAMPLING_PRIORITY_KEY)) { - samplingPriority = Integer.parseInt(entry.getValue()); + baggage.put(key.replace(OT_BAGGAGE_PREFIX, ""), decode(val)); + } else if (SAMPLING_PRIORITY_KEY.equalsIgnoreCase(key)) { + samplingPriority = Integer.parseInt(val); } if (taggedHeaders.containsKey(key)) { if (tags.isEmpty()) { tags = new HashMap<>(); } - tags.put(taggedHeaders.get(key), decode(entry.getValue())); + tags.put(taggedHeaders.get(key), decode(val)); } } ExtractedContext context = null; - if (traceId != 0L) { + if (!"0".equals(traceId)) { context = new ExtractedContext(traceId, spanId, samplingPriority, baggage, tags); context.lockSamplingPriority(); @@ -104,4 +111,27 @@ public class HTTPCodec implements Codec { } return decoded; } + + /** + * Helper method to validate an ID String to verify that it is an unsigned 64 bits number and is + * within range. + * + * @param val the String that contains the ID + * @return the ID in String format if it passes validations + * @throws IllegalArgumentException if val is not a number or if the number is out of range + */ + private String validateUInt64BitsID(String val) throws IllegalArgumentException { + try { + BigInteger validate = new BigInteger(val); + if (validate.compareTo(BigInteger.ZERO) == -1 + || validate.compareTo(BIG_INTEGER_UINT64_MAX) == 1) { + throw new IllegalArgumentException( + "ID out of range, must be between 0 and 2^64-1, got: " + val); + } + return val; + } catch (NumberFormatException nfe) { + throw new IllegalArgumentException( + "Expecting a number for trace ID or span ID, but got: " + val, nfe); + } + } } diff --git a/dd-trace-ot/src/main/java/datadog/trace/common/writer/DDApi.java b/dd-trace-ot/src/main/java/datadog/trace/common/writer/DDApi.java index c32e5961d1..69d8f7d152 100644 --- a/dd-trace-ot/src/main/java/datadog/trace/common/writer/DDApi.java +++ b/dd-trace-ot/src/main/java/datadog/trace/common/writer/DDApi.java @@ -118,7 +118,7 @@ public class DDApi { return false; } - log.debug("Succesfully sent {} of {} traces to the DD agent.", traces.size(), totalSize); + log.debug("Successfully sent {} of {} traces to the DD agent.", traces.size(), totalSize); try { if (null != responseString @@ -130,7 +130,7 @@ public class DDApi { } } } catch (final IOException e) { - log.debug("failed to parse DD agent response: " + responseString, e); + log.debug("Failed to parse DD agent response: " + responseString, e); } return true; diff --git a/dd-trace-ot/src/test/groovy/datadog/opentracing/DDSpanBuilderTest.groovy b/dd-trace-ot/src/test/groovy/datadog/opentracing/DDSpanBuilderTest.groovy index 9e41819b57..e4c7005ca3 100644 --- a/dd-trace-ot/src/test/groovy/datadog/opentracing/DDSpanBuilderTest.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/opentracing/DDSpanBuilderTest.groovy @@ -141,14 +141,14 @@ class DDSpanBuilderTest extends Specification { def "should link to parent span"() { setup: - final long spanId = 1L + final String spanId = "1" final long expectedParentId = spanId final DDSpanContext mockedContext = mock(DDSpanContext) - + when(mockedContext.getTraceId()).thenReturn(spanId) when(mockedContext.getSpanId()).thenReturn(spanId) when(mockedContext.getServiceName()).thenReturn("foo") - when(mockedContext.getTrace()).thenReturn(new PendingTrace(tracer, 1L, [:])) + when(mockedContext.getTrace()).thenReturn(new PendingTrace(tracer, "1", [:])) final String expectedName = "fakeName" @@ -163,6 +163,7 @@ class DDSpanBuilderTest extends Specification { expect: actualContext.getParentId() == expectedParentId + actualContext.getTraceId() == spanId } def "should inherit the DD parent attributes"() { @@ -265,8 +266,8 @@ class DDSpanBuilderTest extends Specification { where: extractedContext | _ - new ExtractedContext(1, 2, 0, [:], [:]) | _ - new ExtractedContext(3, 4, 1, ["asdf": "qwer"], ["zxcv": "1234"]) | _ + new ExtractedContext("1", "2", 0, [:], [:]) | _ + new ExtractedContext("3", "4", 1, ["asdf": "qwer"], ["zxcv": "1234"]) | _ } def "global span tags populated on each span"() { diff --git a/dd-trace-ot/src/test/groovy/datadog/opentracing/DDSpanSerializationTest.groovy b/dd-trace-ot/src/test/groovy/datadog/opentracing/DDSpanSerializationTest.groovy index 51b87a7260..2d94496fb6 100644 --- a/dd-trace-ot/src/test/groovy/datadog/opentracing/DDSpanSerializationTest.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/opentracing/DDSpanSerializationTest.groovy @@ -39,9 +39,9 @@ class DDSpanSerializationTest extends Specification { def tracer = new DDTracer(writer) final DDSpanContext context = new DDSpanContext( - 1L, - 2L, - 0L, + "1", + "2", + "0", "service", "operation", null, @@ -50,7 +50,7 @@ class DDSpanSerializationTest extends Specification { false, "type", tags, - new PendingTrace(tracer, 1L, [:]), + new PendingTrace(tracer, "1", [:]), tracer) baggage.put(DDTags.THREAD_NAME, Thread.currentThread().getName()) diff --git a/dd-trace-ot/src/test/groovy/datadog/opentracing/DDSpanTest.groovy b/dd-trace-ot/src/test/groovy/datadog/opentracing/DDSpanTest.groovy index 51e2800410..d228cfbee2 100644 --- a/dd-trace-ot/src/test/groovy/datadog/opentracing/DDSpanTest.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/opentracing/DDSpanTest.groovy @@ -15,9 +15,9 @@ class DDSpanTest extends Specification { setup: final DDSpanContext context = new DDSpanContext( - 1L, - 1L, - 0L, + "1", + "1", + "0", "fakeService", "fakeOperation", "fakeResource", @@ -26,7 +26,7 @@ class DDSpanTest extends Specification { false, "fakeType", null, - new PendingTrace(tracer, 1L, [:]), + new PendingTrace(tracer, "1", [:]), tracer) final DDSpan span = new DDSpan(1L, context) diff --git a/dd-trace-ot/src/test/groovy/datadog/opentracing/OTTraceCorrelationTest.groovy b/dd-trace-ot/src/test/groovy/datadog/opentracing/OTTraceCorrelationTest.groovy index 1c26bf75b1..5a4645a0fa 100644 --- a/dd-trace-ot/src/test/groovy/datadog/opentracing/OTTraceCorrelationTest.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/opentracing/OTTraceCorrelationTest.groovy @@ -24,7 +24,7 @@ class OTTraceCorrelationTest extends Specification { scope.close() expect: - 0 == traceCorrelation.getTraceId() + "0" == traceCorrelation.getTraceId() } def "get trace id with trace"() { @@ -37,7 +37,7 @@ class OTTraceCorrelationTest extends Specification { scope.close() expect: - 0 == traceCorrelation.getSpanId() + "0" == traceCorrelation.getSpanId() } def "get span id with trace"() { diff --git a/dd-trace-ot/src/test/groovy/datadog/opentracing/PendingTraceTest.groovy b/dd-trace-ot/src/test/groovy/datadog/opentracing/PendingTraceTest.groovy index dbb7ac863e..fd87e317dc 100644 --- a/dd-trace-ot/src/test/groovy/datadog/opentracing/PendingTraceTest.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/opentracing/PendingTraceTest.groovy @@ -13,9 +13,10 @@ class PendingTraceTest extends Specification { def traceCount = tracer.traceCount def traceId = System.identityHashCode(this) + String traceIdStr = String.valueOf(traceId) @Subject - PendingTrace trace = new PendingTrace(tracer, traceId, [:]) + PendingTrace trace = new PendingTrace(tracer, traceIdStr, [:]) DDSpan rootSpan = SpanFactory.newSpanOf(trace) @@ -130,7 +131,7 @@ class PendingTraceTest extends Specification { def "register span to wrong trace fails"() { setup: - def otherTrace = new PendingTrace(tracer, traceId - 10, [:]) + def otherTrace = new PendingTrace(tracer, String.valueOf(traceId - 10), [:]) otherTrace.registerSpan(new DDSpan(0, rootSpan.context())) expect: @@ -141,7 +142,7 @@ class PendingTraceTest extends Specification { def "add span to wrong trace fails"() { setup: - def otherTrace = new PendingTrace(tracer, traceId - 10, [:]) + def otherTrace = new PendingTrace(tracer, String.valueOf(traceId - 10), [:]) rootSpan.finish() otherTrace.addSpan(rootSpan) diff --git a/dd-trace-ot/src/test/groovy/datadog/opentracing/SpanFactory.groovy b/dd-trace-ot/src/test/groovy/datadog/opentracing/SpanFactory.groovy index 5e5b7132ae..fb54f74ff8 100644 --- a/dd-trace-ot/src/test/groovy/datadog/opentracing/SpanFactory.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/opentracing/SpanFactory.groovy @@ -8,9 +8,9 @@ class SpanFactory { def writer = new ListWriter() def tracer = new DDTracer(writer) def context = new DDSpanContext( - 1L, - 1L, - 0L, + "1", + "1", + "0", "fakeService", "fakeOperation", "fakeResource", @@ -19,16 +19,16 @@ class SpanFactory { false, "fakeType", Collections.emptyMap(), - new PendingTrace(tracer, 1L, [:]), + new PendingTrace(tracer, "1", [:]), tracer) return new DDSpan(timestampMicro, context) } static newSpanOf(DDTracer tracer) { def context = new DDSpanContext( - 1L, - 1L, - 0L, + "1", + "1", + "0", "fakeService", "fakeOperation", "fakeResource", @@ -37,7 +37,7 @@ class SpanFactory { false, "fakeType", Collections.emptyMap(), - new PendingTrace(tracer, 1L, [:]), + new PendingTrace(tracer, "1", [:]), tracer) return new DDSpan(1, context) } @@ -45,8 +45,8 @@ class SpanFactory { static newSpanOf(PendingTrace trace) { def context = new DDSpanContext( trace.traceId, - 1L, - 0L, + "1", + "0", "fakeService", "fakeOperation", "fakeResource", @@ -64,9 +64,9 @@ class SpanFactory { def writer = new ListWriter() def tracer = new DDTracer(writer) def context = new DDSpanContext( - 1L, - 1L, - 0L, + "1", + "1", + "0", serviceName, "fakeOperation", "fakeResource", @@ -75,7 +75,7 @@ class SpanFactory { false, "fakeType", Collections.emptyMap(), - new PendingTrace(tracer, 1L, [:]), + new PendingTrace(tracer, "1", [:]), tracer) context.setTag("env", envName) return new DDSpan(0l, context) diff --git a/dd-trace-ot/src/test/groovy/datadog/opentracing/decorators/URLAsResourceNameTest.groovy b/dd-trace-ot/src/test/groovy/datadog/opentracing/decorators/URLAsResourceNameTest.groovy index 24959820e5..1aa4402133 100644 --- a/dd-trace-ot/src/test/groovy/datadog/opentracing/decorators/URLAsResourceNameTest.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/opentracing/decorators/URLAsResourceNameTest.groovy @@ -87,9 +87,9 @@ class URLAsResourceNameTest extends Specification { when: final DDSpanContext context = new DDSpanContext( - 1L, - 1L, - 0L, + "1", + "1", + "0", "fakeService", "fakeOperation", "fakeResource", @@ -98,7 +98,7 @@ class URLAsResourceNameTest extends Specification { false, "fakeType", tags, - new PendingTrace(tracer, 1L, [:]), + new PendingTrace(tracer, "1", [:]), tracer) then: diff --git a/dd-trace-ot/src/test/groovy/datadog/opentracing/propagation/HTTPCodecTest.groovy b/dd-trace-ot/src/test/groovy/datadog/opentracing/propagation/HTTPCodecTest.groovy index 2d786126ff..8fdc478b2c 100644 --- a/dd-trace-ot/src/test/groovy/datadog/opentracing/propagation/HTTPCodecTest.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/opentracing/propagation/HTTPCodecTest.groovy @@ -10,6 +10,8 @@ import io.opentracing.propagation.TextMapInjectAdapter import spock.lang.Shared import spock.lang.Specification +import static datadog.opentracing.propagation.HTTPCodec.BIG_INTEGER_UINT64_MAX + class HTTPCodecTest extends Specification { @Shared private static final String OT_BAGGAGE_PREFIX = "ot-baggage-" @@ -28,9 +30,9 @@ class HTTPCodecTest extends Specification { def tracer = new DDTracer(writer) final DDSpanContext mockedContext = new DDSpanContext( - 1L, - 2L, - 0L, + "1", + "2", + "0", "fakeService", "fakeOperation", "fakeResource", @@ -44,7 +46,7 @@ class HTTPCodecTest extends Specification { false, "fakeType", null, - new PendingTrace(tracer, 1L, [:]), + new PendingTrace(tracer, "1", [:]), tracer) final Map carrier = new HashMap<>() @@ -64,6 +66,96 @@ class HTTPCodecTest extends Specification { PrioritySampling.SAMPLER_KEEP | _ } + def "inject http headers with larger than Java long IDs"() { + String largeTraceId = "9523372036854775807" + String largeSpanId = "15815582334751494918" + String largeParentId = "15815582334751494914" + setup: + def writer = new ListWriter() + def tracer = new DDTracer(writer) + final DDSpanContext mockedContext = + new DDSpanContext( + largeTraceId, + largeSpanId, + largeParentId, + "fakeService", + "fakeOperation", + "fakeResource", + samplingPriority, + new HashMap() { + { + put("k1", "v1") + put("k2", "v2") + } + }, + false, + "fakeType", + null, + new PendingTrace(tracer, largeTraceId, [:]), + tracer) + + final Map carrier = new HashMap<>() + + codec.inject(mockedContext, new TextMapInjectAdapter(carrier)) + + expect: + carrier.get(TRACE_ID_KEY) == largeTraceId + carrier.get(SPAN_ID_KEY) == largeSpanId + carrier.get(SAMPLING_PRIORITY_KEY) == (samplingPriority == PrioritySampling.UNSET ? null : String.valueOf(samplingPriority)) + carrier.get(OT_BAGGAGE_PREFIX + "k1") == "v1" + carrier.get(OT_BAGGAGE_PREFIX + "k2") == "v2" + + where: + samplingPriority | _ + PrioritySampling.UNSET | _ + PrioritySampling.SAMPLER_KEEP | _ + } + + def "inject http headers with uint 64 max IDs"() { + String largeTraceId = "18446744073709551615" + String largeSpanId = "18446744073709551614" + String largeParentId = "18446744073709551613" + setup: + def writer = new ListWriter() + def tracer = new DDTracer(writer) + final DDSpanContext mockedContext = + new DDSpanContext( + largeTraceId, + largeSpanId, + largeParentId, + "fakeService", + "fakeOperation", + "fakeResource", + samplingPriority, + new HashMap() { + { + put("k1", "v1") + put("k2", "v2") + } + }, + false, + "fakeType", + null, + new PendingTrace(tracer, largeTraceId, [:]), + tracer) + + final Map carrier = new HashMap<>() + + codec.inject(mockedContext, new TextMapInjectAdapter(carrier)) + + expect: + carrier.get(TRACE_ID_KEY) == largeTraceId + carrier.get(SPAN_ID_KEY) == largeSpanId + carrier.get(SAMPLING_PRIORITY_KEY) == (samplingPriority == PrioritySampling.UNSET ? null : String.valueOf(samplingPriority)) + carrier.get(OT_BAGGAGE_PREFIX + "k1") == "v1" + carrier.get(OT_BAGGAGE_PREFIX + "k2") == "v2" + + where: + samplingPriority | _ + PrioritySampling.UNSET | _ + PrioritySampling.SAMPLER_KEEP | _ + } + def "extract http headers"() { setup: final Map actual = [ @@ -81,8 +173,8 @@ class HTTPCodecTest extends Specification { final ExtractedContext context = codec.extract(new TextMapExtractAdapter(actual)) expect: - context.getTraceId() == 1l - context.getSpanId() == 2l + context.getTraceId() == "1" + context.getSpanId() == "2" context.getBaggage().get("k1") == "v1" context.getBaggage().get("k2") == "v2" context.getTags() == ["some-tag": "my-interesting-info"] @@ -93,4 +185,147 @@ class HTTPCodecTest extends Specification { PrioritySampling.UNSET | _ PrioritySampling.SAMPLER_KEEP | _ } + + def "extract http headers with larger than Java long IDs"() { + setup: + String largeTraceId = "9523372036854775807" + String largeSpanId = "15815582334751494918" + final Map actual = [ + (TRACE_ID_KEY.toUpperCase()) : largeTraceId, + (SPAN_ID_KEY.toUpperCase()) : largeSpanId, + (OT_BAGGAGE_PREFIX.toUpperCase() + "k1"): "v1", + (OT_BAGGAGE_PREFIX.toUpperCase() + "k2"): "v2", + SOME_HEADER : "my-interesting-info", + ] + + if (samplingPriority != PrioritySampling.UNSET) { + actual.put(SAMPLING_PRIORITY_KEY, String.valueOf(samplingPriority)) + } + + final ExtractedContext context = codec.extract(new TextMapExtractAdapter(actual)) + + expect: + context.getTraceId() == largeTraceId + context.getSpanId() == largeSpanId + context.getBaggage().get("k1") == "v1" + context.getBaggage().get("k2") == "v2" + context.getTags() == ["some-tag": "my-interesting-info"] + context.getSamplingPriority() == samplingPriority + + where: + samplingPriority | _ + PrioritySampling.UNSET | _ + PrioritySampling.SAMPLER_KEEP | _ + } + + def "extract http headers with uint 64 max IDs"() { + setup: + String largeSpanId = BIG_INTEGER_UINT64_MAX.subtract(BigInteger.ONE).toString() + final Map actual = [ + (TRACE_ID_KEY.toUpperCase()) : BIG_INTEGER_UINT64_MAX.toString(), + (SPAN_ID_KEY.toUpperCase()) : BIG_INTEGER_UINT64_MAX.minus(1).toString(), + (OT_BAGGAGE_PREFIX.toUpperCase() + "k1"): "v1", + (OT_BAGGAGE_PREFIX.toUpperCase() + "k2"): "v2", + SOME_HEADER : "my-interesting-info", + ] + + if (samplingPriority != PrioritySampling.UNSET) { + actual.put(SAMPLING_PRIORITY_KEY, String.valueOf(samplingPriority)) + } + + final ExtractedContext context = codec.extract(new TextMapExtractAdapter(actual)) + + expect: + context.getTraceId() == BIG_INTEGER_UINT64_MAX.toString() + context.getSpanId() == largeSpanId + context.getBaggage().get("k1") == "v1" + context.getBaggage().get("k2") == "v2" + context.getTags() == ["some-tag": "my-interesting-info"] + context.getSamplingPriority() == samplingPriority + + where: + samplingPriority | _ + PrioritySampling.UNSET | _ + PrioritySampling.SAMPLER_KEEP | _ + } + + def "extract http headers with invalid non-numeric ID"() { + setup: + final Map actual = [ + (TRACE_ID_KEY.toUpperCase()) : "traceID", + (SPAN_ID_KEY.toUpperCase()) : "spanID", + (OT_BAGGAGE_PREFIX.toUpperCase() + "k1"): "v1", + (OT_BAGGAGE_PREFIX.toUpperCase() + "k2"): "v2", + SOME_HEADER : "my-interesting-info", + ] + + if (samplingPriority != PrioritySampling.UNSET) { + actual.put(SAMPLING_PRIORITY_KEY, String.valueOf(samplingPriority)) + } + + when: + codec.extract(new TextMapExtractAdapter(actual)) + + then: + def iae = thrown(IllegalArgumentException) + assert iae.cause instanceof NumberFormatException + + where: + samplingPriority | _ + PrioritySampling.UNSET | _ + PrioritySampling.SAMPLER_KEEP | _ + } + + def "extract http headers with out of range trace ID"() { + setup: + String outOfRangeTraceId = BIG_INTEGER_UINT64_MAX.add(BigInteger.ONE).toString() + final Map actual = [ + (TRACE_ID_KEY.toUpperCase()) : outOfRangeTraceId, + (SPAN_ID_KEY.toUpperCase()) : "0", + (OT_BAGGAGE_PREFIX.toUpperCase() + "k1"): "v1", + (OT_BAGGAGE_PREFIX.toUpperCase() + "k2"): "v2", + SOME_HEADER : "my-interesting-info", + ] + + if (samplingPriority != PrioritySampling.UNSET) { + actual.put(SAMPLING_PRIORITY_KEY, String.valueOf(samplingPriority)) + } + + when: + codec.extract(new TextMapExtractAdapter(actual)) + + then: + thrown(IllegalArgumentException) + + where: + samplingPriority | _ + PrioritySampling.UNSET | _ + PrioritySampling.SAMPLER_KEEP | _ + } + + def "extract http headers with out of range span ID"() { + setup: + final Map actual = [ + (TRACE_ID_KEY.toUpperCase()) : "0", + (SPAN_ID_KEY.toUpperCase()) : "-1", + (OT_BAGGAGE_PREFIX.toUpperCase() + "k1"): "v1", + (OT_BAGGAGE_PREFIX.toUpperCase() + "k2"): "v2", + SOME_HEADER : "my-interesting-info", + ] + + if (samplingPriority != PrioritySampling.UNSET) { + actual.put(SAMPLING_PRIORITY_KEY, String.valueOf(samplingPriority)) + } + + when: + codec.extract(new TextMapExtractAdapter(actual)) + + then: + thrown(IllegalArgumentException) + + where: + samplingPriority | _ + PrioritySampling.UNSET | _ + PrioritySampling.SAMPLER_KEEP | _ + } } diff --git a/dd-trace-ot/src/traceAgentTest/groovy/DDApiIntegrationTest.groovy b/dd-trace-ot/src/traceAgentTest/groovy/DDApiIntegrationTest.groovy index 93a35fcb2e..27d8e776a4 100644 --- a/dd-trace-ot/src/traceAgentTest/groovy/DDApiIntegrationTest.groovy +++ b/dd-trace-ot/src/traceAgentTest/groovy/DDApiIntegrationTest.groovy @@ -17,9 +17,9 @@ class DDApiIntegrationTest { static final WRITER = new ListWriter() static final TRACER = new DDTracer(WRITER) static final CONTEXT = new DDSpanContext( - 1L, - 1L, - 0L, + "1", + "1", + "0", "fakeService", "fakeOperation", "fakeResource", @@ -28,7 +28,7 @@ class DDApiIntegrationTest { false, "fakeType", Collections.emptyMap(), - new PendingTrace(TRACER, 1L, [:]), + new PendingTrace(TRACER, "1", [:]), TRACER) def api = new DDApi(DDAgentWriter.DEFAULT_HOSTNAME, DDAgentWriter.DEFAULT_PORT, v4())