From 96f79a8abaf3a56e22f8d3771949c6b18f72fb6e Mon Sep 17 00:00:00 2001 From: Gary Huang Date: Thu, 19 Jul 2018 13:44:57 -0400 Subject: [PATCH] Change the internal storage and handling of trace ID, span ID, and parent IDs' to use String instead of long primitive. This will allow the java agent to receive unsigned 64 bit integers without overflow. Also upgraded MsgPack to handle the serialization of such Strings as numbers in JSONs. --- .../trace/api/CorrelationIdentifier.java | 16 +- dd-trace-ot/dd-trace-ot.gradle | 2 +- .../main/java/datadog/opentracing/DDSpan.java | 33 +++- .../datadog/opentracing/DDSpanContext.java | 18 +- .../java/datadog/opentracing/DDTracer.java | 12 +- .../opentracing/OTTraceCorrelation.java | 8 +- .../datadog/opentracing/PendingTrace.java | 10 +- .../propagation/ExtractedContext.java | 12 +- .../opentracing/propagation/HTTPCodec.java | 10 +- .../datadog/trace/common/writer/DDApi.java | 4 +- .../trace/common/writer/LoggingWriter.java | 4 +- .../opentracing/DDSpanBuilderTest.groovy | 8 +- .../DDSpanSerializationTest.groovy | 8 +- .../datadog/opentracing/DDSpanTest.groovy | 8 +- .../opentracing/OTTraceCorrelationTest.groovy | 4 +- .../opentracing/PendingTraceTest.groovy | 7 +- .../datadog/opentracing/SpanFactory.groovy | 28 +-- .../decorators/URLAsResourceNameTest.groovy | 8 +- .../propagation/HTTPCodecTest.groovy | 166 +++++++++++++++++- .../groovy/DDApiIntegrationTest.groovy | 8 +- 20 files changed, 277 insertions(+), 97 deletions(-) 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 174ac7fef2..4045c14b38 100644 --- a/dd-trace-ot/dd-trace-ot.gradle +++ b/dd-trace-ot/dd-trace-ot.gradle @@ -33,7 +33,7 @@ dependencies { compile deps.jackson compile deps.slf4j - compile group: 'org.msgpack', name: 'jackson-dataformat-msgpack', version: '0.8.2' + compile group: 'org.msgpack', name: 'jackson-dataformat-msgpack', version: '0.8.16' 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..3da77989fb 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, @@ -111,15 +111,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 26af9f2629..24b9d3e22c 100644 --- a/dd-trace-ot/src/main/java/datadog/opentracing/DDTracer.java +++ b/dd-trace-ot/src/main/java/datadog/opentracing/DDTracer.java @@ -456,9 +456,9 @@ public class DDTracer implements io.opentracing.Tracer { return this; } - private long generateNewId() { + private String generateNewId() { // 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)); } /** @@ -468,9 +468,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; @@ -512,7 +512,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); 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 aa44c123f1..4d15758d0c 100644 --- a/dd-trace-ot/src/main/java/datadog/opentracing/PendingTrace.java +++ b/dd-trace-ot/src/main/java/datadog/opentracing/PendingTrace.java @@ -29,7 +29,7 @@ public class PendingTrace extends ConcurrentLinkedDeque { } private final DDTracer tracer; - private final long traceId; + private final String traceId; // TODO: consider moving these time fields into DDTracer to ensure that traces have precise relative time /** Trace start time in nano seconds measured up to a millisecond accuracy */ @@ -47,7 +47,7 @@ public class PendingTrace extends ConcurrentLinkedDeque { /** Ensure a trace is never written multiple times */ private final AtomicBoolean isWritten = new AtomicBoolean(false); - PendingTrace(final DDTracer tracer, final long traceId) { + PendingTrace(final DDTracer tracer, final String traceId) { this.tracer = tracer; this.traceId = traceId; @@ -72,7 +72,7 @@ public class PendingTrace extends ConcurrentLinkedDeque { } public void registerSpan(final DDSpan span) { - if (span.context().getTraceId() != traceId) { + if (!traceId.equals(span.context().getTraceId())) { log.debug("{} - span registered for wrong trace ({})", span, traceId); return; } @@ -90,7 +90,7 @@ public class PendingTrace extends ConcurrentLinkedDeque { } private void expireSpan(final DDSpan span) { - if (span.context().getTraceId() != traceId) { + if (!traceId.equals(span.context().getTraceId())) { log.debug("{} - span expired for wrong trace ({})", span, traceId); return; } @@ -111,7 +111,7 @@ public class PendingTrace extends ConcurrentLinkedDeque { log.debug("{} - added to trace, but not complete.", span); return; } - if (traceId != span.getTraceId()) { + 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..b542240740 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 @@ -48,16 +48,16 @@ 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()); + traceId = entry.getValue(); } else if (key.equalsIgnoreCase(SPAN_ID_KEY)) { - spanId = Long.parseLong(entry.getValue()); + spanId = entry.getValue(); } else if (key.startsWith(OT_BAGGAGE_PREFIX)) { if (baggage.isEmpty()) { baggage = new HashMap<>(); @@ -75,7 +75,7 @@ public class HTTPCodec implements Codec { } } ExtractedContext context = null; - if (traceId != 0L) { + if (!traceId.equals("0")) { context = new ExtractedContext(traceId, spanId, samplingPriority, baggage, tags); context.lockSamplingPriority(); 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/main/java/datadog/trace/common/writer/LoggingWriter.java b/dd-trace-ot/src/main/java/datadog/trace/common/writer/LoggingWriter.java index c1bb70c0a0..0e822ba970 100644 --- a/dd-trace-ot/src/main/java/datadog/trace/common/writer/LoggingWriter.java +++ b/dd-trace-ot/src/main/java/datadog/trace/common/writer/LoggingWriter.java @@ -12,9 +12,9 @@ public class LoggingWriter implements Writer { @Override public void write(final List trace) { try { - log.info("write(trace): {}", serializer.writeValueAsString(trace)); + log.info("Write(trace): {}", serializer.writeValueAsString(trace)); } catch (final Exception e) { - log.error("error writing(trace): {}", trace); + log.error("Error writing(trace) with message: {}. trace: {}", e.getMessage(), trace); } } 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 c507671dcc..03d81a7968 100644 --- a/dd-trace-ot/src/test/groovy/datadog/opentracing/DDSpanBuilderTest.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/opentracing/DDSpanBuilderTest.groovy @@ -113,14 +113,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.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" @@ -237,8 +237,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 e7908849fb..26b11b434c 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 610743e59b..2f7d2bc712 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 2f1d7f94ca..7c3bf7c1df 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 207e0d62bb..ffb8841d4d 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 ea76b81659..e70a430a43 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 2a34b9b713..3ebb8a90de 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 @@ -28,9 +28,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 +44,7 @@ class HTTPCodecTest extends Specification { false, "fakeType", null, - new PendingTrace(tracer, 1L), + new PendingTrace(tracer, "1"), tracer) final Map carrier = new HashMap<>() @@ -64,6 +64,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 +171,72 @@ 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"] + context.getSamplingPriority() == samplingPriority + + where: + samplingPriority | _ + 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 largeTraceId = "18446744073709551615" + String largeSpanId = "18446744073709551614" + 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"] diff --git a/dd-trace-ot/src/traceAgentTest/groovy/DDApiIntegrationTest.groovy b/dd-trace-ot/src/traceAgentTest/groovy/DDApiIntegrationTest.groovy index 83f0123003..e9b8e99a06 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())