From 326577d7df99af8d26b797695e0fc8d16536f5a4 Mon Sep 17 00:00:00 2001 From: Tyler Benson Date: Tue, 5 Feb 2019 14:49:07 -0800 Subject: [PATCH] Remove codec for inject/extract In preparation for OT 0.32 support. --- .../java/datadog/opentracing/DDTracer.java | 40 ++-- .../opentracing/propagation/Codec.java | 46 ----- .../propagation/DatadogHttpCodec.java | 150 +++++++++++++++ .../opentracing/propagation/HTTPCodec.java | 147 --------------- ...groovy => DatadogHttpExtractorTest.groovy} | 172 ++---------------- .../DatadogHttpInjectorTest.groovy | 151 +++++++++++++++ .../groovy/datadog/trace/DDTracerTest.groovy | 2 +- 7 files changed, 330 insertions(+), 378 deletions(-) delete mode 100644 dd-trace-ot/src/main/java/datadog/opentracing/propagation/Codec.java create mode 100644 dd-trace-ot/src/main/java/datadog/opentracing/propagation/DatadogHttpCodec.java delete mode 100644 dd-trace-ot/src/main/java/datadog/opentracing/propagation/HTTPCodec.java rename dd-trace-ot/src/test/groovy/datadog/opentracing/propagation/{HTTPCodecTest.groovy => DatadogHttpExtractorTest.groovy} (53%) create mode 100644 dd-trace-ot/src/test/groovy/datadog/opentracing/propagation/DatadogHttpInjectorTest.groovy 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 8ce78609ab..5f4d91ed91 100644 --- a/dd-trace-ot/src/main/java/datadog/opentracing/DDTracer.java +++ b/dd-trace-ot/src/main/java/datadog/opentracing/DDTracer.java @@ -2,9 +2,8 @@ package datadog.opentracing; import datadog.opentracing.decorators.AbstractDecorator; import datadog.opentracing.decorators.DDDecoratorsFactory; -import datadog.opentracing.propagation.Codec; +import datadog.opentracing.propagation.DatadogHttpCodec; import datadog.opentracing.propagation.ExtractedContext; -import datadog.opentracing.propagation.HTTPCodec; import datadog.opentracing.propagation.TagContext; import datadog.opentracing.scopemanager.ContextualScopeManager; import datadog.opentracing.scopemanager.ScopeContext; @@ -24,6 +23,7 @@ import io.opentracing.ScopeManager; import io.opentracing.Span; import io.opentracing.SpanContext; import io.opentracing.propagation.Format; +import io.opentracing.propagation.TextMap; import java.io.Closeable; import java.util.ArrayList; import java.util.Collection; @@ -84,7 +84,9 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace return Integer.compare(o1.priority(), o2.priority()); } }); - private final CodecRegistry registry; + + private final DatadogHttpCodec.Injector injector; + private final DatadogHttpCodec.Extractor extractor; private final AtomicInteger traceCount; @@ -238,9 +240,9 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace // The JVM is already shutting down. } - registry = new CodecRegistry(); - registry.register(Format.Builtin.HTTP_HEADERS, new HTTPCodec(taggedHeaders)); - registry.register(Format.Builtin.TEXT_MAP, new HTTPCodec(taggedHeaders)); + injector = new DatadogHttpCodec.Injector(); + extractor = new DatadogHttpCodec.Extractor(taggedHeaders); + if (this.writer instanceof DDAgentWriter) { final DDApi api = ((DDAgentWriter) this.writer).getApi(); traceCount = api.getTraceCounter(); @@ -332,24 +334,21 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace @Override public void inject(final SpanContext spanContext, final Format format, final T carrier) { - - final Codec codec = registry.get(format); - if (codec == null) { + if (!(carrier instanceof TextMap)) { log.debug("Unsupported format for propagation - {}", format.getClass().getName()); } else { - codec.inject((DDSpanContext) spanContext, carrier); + injector.inject((DDSpanContext) spanContext, (TextMap) carrier); } } @Override public SpanContext extract(final Format format, final T carrier) { - final Codec codec = registry.get(format); - if (codec == null) { + if (!(carrier instanceof TextMap)) { log.debug("Unsupported format for propagation - {}", format.getClass().getName()); + return null; } else { - return codec.extract(carrier); + return extractor.extract((TextMap) carrier); } - return null; } /** @@ -452,19 +451,6 @@ public class DDTracer implements io.opentracing.Tracer, Closeable, datadog.trace return Config.get().getPartialFlushMinSpans(); } - private static class CodecRegistry { - - private final Map, Codec> codecs = new HashMap<>(); - - Codec get(final Format format) { - return (Codec) codecs.get(format); - } - - public void register(final Format format, final Codec codec) { - codecs.put(format, codec); - } - } - /** Spans are built using this builder */ public class DDSpanBuilder implements SpanBuilder { private final ScopeManager scopeManager; diff --git a/dd-trace-ot/src/main/java/datadog/opentracing/propagation/Codec.java b/dd-trace-ot/src/main/java/datadog/opentracing/propagation/Codec.java deleted file mode 100644 index c6b513e5b1..0000000000 --- a/dd-trace-ot/src/main/java/datadog/opentracing/propagation/Codec.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2016, Uber Technologies, Inc - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package datadog.opentracing.propagation; - -import datadog.opentracing.DDSpanContext; -import io.opentracing.SpanContext; - -/** A codec is a simple object that can encode and decode a span context through a carrier */ -public interface Codec { - - /** - * Serialize the span context using the provided carrier - * - * @param context - * @param carrier - */ - void inject(DDSpanContext context, T carrier); - - /** - * Given a carrier, retrieve (rebuild) a span context. This context built will be use as the - * parent - * - * @param carrier - * @return the span context - */ - SpanContext extract(T carrier); -} diff --git a/dd-trace-ot/src/main/java/datadog/opentracing/propagation/DatadogHttpCodec.java b/dd-trace-ot/src/main/java/datadog/opentracing/propagation/DatadogHttpCodec.java new file mode 100644 index 0000000000..7babbb0f0d --- /dev/null +++ b/dd-trace-ot/src/main/java/datadog/opentracing/propagation/DatadogHttpCodec.java @@ -0,0 +1,150 @@ +package datadog.opentracing.propagation; + +import datadog.opentracing.DDSpanContext; +import datadog.trace.api.sampling.PrioritySampling; +import io.opentracing.SpanContext; +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; +import java.util.HashMap; +import java.util.Map; +import lombok.extern.slf4j.Slf4j; + +/** A codec designed for HTTP transport via headers */ +@Slf4j +public class DatadogHttpCodec { + + // 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"; + private static final String SAMPLING_PRIORITY_KEY = "x-datadog-sampling-priority"; + + public static class Injector { + + public void inject(final DDSpanContext context, final TextMap carrier) { + carrier.put(TRACE_ID_KEY, String.valueOf(context.getTraceId())); + carrier.put(SPAN_ID_KEY, String.valueOf(context.getSpanId())); + if (context.lockSamplingPriority()) { + carrier.put(SAMPLING_PRIORITY_KEY, String.valueOf(context.getSamplingPriority())); + } + + for (final Map.Entry entry : context.baggageItems()) { + carrier.put(OT_BAGGAGE_PREFIX + entry.getKey(), encode(entry.getValue())); + } + log.debug("{} - Parent context injected", context.getTraceId()); + } + + private String encode(final String value) { + String encoded = value; + try { + encoded = URLEncoder.encode(value, "UTF-8"); + } catch (final UnsupportedEncodingException e) { + log.info("Failed to encode value - {}", value); + } + return encoded; + } + } + + public static class Extractor { + private final Map taggedHeaders; + + public Extractor(final Map taggedHeaders) { + this.taggedHeaders = new HashMap<>(); + for (final Map.Entry mapping : taggedHeaders.entrySet()) { + this.taggedHeaders.put(mapping.getKey().trim().toLowerCase(), mapping.getValue()); + } + } + + public SpanContext extract(final TextMap carrier) { + + Map baggage = Collections.emptyMap(); + Map tags = Collections.emptyMap(); + String traceId = "0"; + String spanId = "0"; + int samplingPriority = PrioritySampling.UNSET; + + for (final Map.Entry entry : carrier) { + final String key = entry.getKey().toLowerCase(); + final String val = entry.getValue(); + + if (val == null) { + continue; + } + + 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(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(val)); + } + } + + SpanContext context = null; + if (!"0".equals(traceId)) { + final ExtractedContext ctx = + new ExtractedContext(traceId, spanId, samplingPriority, baggage, tags); + ctx.lockSamplingPriority(); + + log.debug("{} - Parent context extracted", ctx.getTraceId()); + context = ctx; + } else if (!tags.isEmpty()) { + context = new TagContext(tags); + } + + return context; + } + + private String decode(final String value) { + String decoded = value; + try { + decoded = URLDecoder.decode(value, "UTF-8"); + } catch (final UnsupportedEncodingException e) { + log.info("Failed to decode value - {}", value); + } + 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(final String val) throws IllegalArgumentException { + try { + final 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 (final 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/opentracing/propagation/HTTPCodec.java b/dd-trace-ot/src/main/java/datadog/opentracing/propagation/HTTPCodec.java deleted file mode 100644 index 7dd0676241..0000000000 --- a/dd-trace-ot/src/main/java/datadog/opentracing/propagation/HTTPCodec.java +++ /dev/null @@ -1,147 +0,0 @@ -package datadog.opentracing.propagation; - -import datadog.opentracing.DDSpanContext; -import datadog.trace.api.sampling.PrioritySampling; -import io.opentracing.SpanContext; -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; -import java.util.HashMap; -import java.util.Map; -import lombok.extern.slf4j.Slf4j; - -/** A codec designed for HTTP transport via headers */ -@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"; - private static final String SAMPLING_PRIORITY_KEY = "x-datadog-sampling-priority"; - - private final Map taggedHeaders; - - public HTTPCodec(final Map taggedHeaders) { - this.taggedHeaders = new HashMap<>(); - for (final Map.Entry mapping : taggedHeaders.entrySet()) { - this.taggedHeaders.put(mapping.getKey().trim().toLowerCase(), mapping.getValue()); - } - } - - @Override - public void inject(final DDSpanContext context, final TextMap carrier) { - carrier.put(TRACE_ID_KEY, String.valueOf(context.getTraceId())); - carrier.put(SPAN_ID_KEY, String.valueOf(context.getSpanId())); - if (context.lockSamplingPriority()) { - carrier.put(SAMPLING_PRIORITY_KEY, String.valueOf(context.getSamplingPriority())); - } - - for (final Map.Entry entry : context.baggageItems()) { - carrier.put(OT_BAGGAGE_PREFIX + entry.getKey(), encode(entry.getValue())); - } - log.debug("{} - Parent context injected", context.getTraceId()); - } - - @Override - public SpanContext extract(final TextMap carrier) { - - Map baggage = Collections.emptyMap(); - Map tags = Collections.emptyMap(); - String traceId = "0"; - String spanId = "0"; - int samplingPriority = PrioritySampling.UNSET; - - for (final Map.Entry entry : carrier) { - final String key = entry.getKey().toLowerCase(); - final String val = entry.getValue(); - - if (val == null) { - continue; - } - - 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(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(val)); - } - } - - SpanContext context = null; - if (!"0".equals(traceId)) { - final ExtractedContext ctx = - new ExtractedContext(traceId, spanId, samplingPriority, baggage, tags); - ctx.lockSamplingPriority(); - - log.debug("{} - Parent context extracted", ctx.getTraceId()); - context = ctx; - } else if (!tags.isEmpty()) { - context = new TagContext(tags); - } - - return context; - } - - private String encode(final String value) { - String encoded = value; - try { - encoded = URLEncoder.encode(value, "UTF-8"); - } catch (final UnsupportedEncodingException e) { - log.info("Failed to encode value - {}", value); - } - return encoded; - } - - private String decode(final String value) { - String decoded = value; - try { - decoded = URLDecoder.decode(value, "UTF-8"); - } catch (final UnsupportedEncodingException e) { - log.info("Failed to decode value - {}", value); - } - 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(final String val) throws IllegalArgumentException { - try { - final 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 (final 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/test/groovy/datadog/opentracing/propagation/HTTPCodecTest.groovy b/dd-trace-ot/src/test/groovy/datadog/opentracing/propagation/DatadogHttpExtractorTest.groovy similarity index 53% rename from dd-trace-ot/src/test/groovy/datadog/opentracing/propagation/HTTPCodecTest.groovy rename to dd-trace-ot/src/test/groovy/datadog/opentracing/propagation/DatadogHttpExtractorTest.groovy index d61008bee5..afcb039390 100644 --- a/dd-trace-ot/src/test/groovy/datadog/opentracing/propagation/HTTPCodecTest.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/opentracing/propagation/DatadogHttpExtractorTest.groovy @@ -1,160 +1,18 @@ package datadog.opentracing.propagation -import datadog.opentracing.DDSpanContext -import datadog.opentracing.DDTracer -import datadog.opentracing.PendingTrace import datadog.trace.api.sampling.PrioritySampling -import datadog.trace.common.writer.ListWriter import io.opentracing.propagation.TextMapExtractAdapter -import io.opentracing.propagation.TextMapInjectAdapter -import spock.lang.Shared import spock.lang.Specification -import static datadog.opentracing.propagation.HTTPCodec.BIG_INTEGER_UINT64_MAX +import static datadog.opentracing.propagation.DatadogHttpCodec.BIG_INTEGER_UINT64_MAX +import static datadog.opentracing.propagation.DatadogHttpCodec.OT_BAGGAGE_PREFIX +import static datadog.opentracing.propagation.DatadogHttpCodec.SAMPLING_PRIORITY_KEY +import static datadog.opentracing.propagation.DatadogHttpCodec.SPAN_ID_KEY +import static datadog.opentracing.propagation.DatadogHttpCodec.TRACE_ID_KEY -class HTTPCodecTest extends Specification { - @Shared - private static final String OT_BAGGAGE_PREFIX = "ot-baggage-" - @Shared - private static final String TRACE_ID_KEY = "x-datadog-trace-id" - @Shared - private static final String SPAN_ID_KEY = "x-datadog-parent-id" - @Shared - private static final String SAMPLING_PRIORITY_KEY = "x-datadog-sampling-priority" +class DatadogHttpExtractorTest extends Specification { - HTTPCodec codec = new HTTPCodec(["SOME_HEADER": "some-tag"]) - - def "inject http headers"() { - setup: - def writer = new ListWriter() - def tracer = new DDTracer(writer) - final DDSpanContext mockedContext = - new DDSpanContext( - "1", - "2", - "0", - "fakeService", - "fakeOperation", - "fakeResource", - samplingPriority, - new HashMap() { - { - put("k1", "v1") - put("k2", "v2") - } - }, - false, - "fakeType", - null, - new PendingTrace(tracer, "1", [:]), - tracer) - - final Map carrier = new HashMap<>() - - codec.inject(mockedContext, new TextMapInjectAdapter(carrier)) - - expect: - carrier.get(TRACE_ID_KEY) == "1" - carrier.get(SPAN_ID_KEY) == "2" - 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 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 | _ - } + DatadogHttpCodec.Extractor extractor = new DatadogHttpCodec.Extractor(["SOME_HEADER": "some-tag"]) def "extract http headers"() { setup: @@ -170,7 +28,7 @@ class HTTPCodecTest extends Specification { actual.put(SAMPLING_PRIORITY_KEY, String.valueOf(samplingPriority)) } - final ExtractedContext context = codec.extract(new TextMapExtractAdapter(actual)) + final ExtractedContext context = extractor.extract(new TextMapExtractAdapter(actual)) expect: context.getTraceId() == "1" @@ -192,7 +50,7 @@ class HTTPCodecTest extends Specification { SOME_HEADER: "my-interesting-info", ] - TagContext context = codec.extract(new TextMapExtractAdapter(actual)) + TagContext context = extractor.extract(new TextMapExtractAdapter(actual)) expect: !(context instanceof ExtractedContext) @@ -201,7 +59,7 @@ class HTTPCodecTest extends Specification { def "extract empty headers returns null"() { expect: - codec.extract(new TextMapExtractAdapter(["ignored-header": "ignored-value"])) == null + extractor.extract(new TextMapExtractAdapter(["ignored-header": "ignored-value"])) == null } def "extract http headers with larger than Java long IDs"() { @@ -220,7 +78,7 @@ class HTTPCodecTest extends Specification { actual.put(SAMPLING_PRIORITY_KEY, String.valueOf(samplingPriority)) } - final ExtractedContext context = codec.extract(new TextMapExtractAdapter(actual)) + final ExtractedContext context = extractor.extract(new TextMapExtractAdapter(actual)) expect: context.getTraceId() == largeTraceId @@ -251,7 +109,7 @@ class HTTPCodecTest extends Specification { actual.put(SAMPLING_PRIORITY_KEY, String.valueOf(samplingPriority)) } - final ExtractedContext context = codec.extract(new TextMapExtractAdapter(actual)) + final ExtractedContext context = extractor.extract(new TextMapExtractAdapter(actual)) expect: context.getTraceId() == BIG_INTEGER_UINT64_MAX.toString() @@ -282,7 +140,7 @@ class HTTPCodecTest extends Specification { } when: - codec.extract(new TextMapExtractAdapter(actual)) + extractor.extract(new TextMapExtractAdapter(actual)) then: def iae = thrown(IllegalArgumentException) @@ -310,7 +168,7 @@ class HTTPCodecTest extends Specification { } when: - codec.extract(new TextMapExtractAdapter(actual)) + extractor.extract(new TextMapExtractAdapter(actual)) then: thrown(IllegalArgumentException) @@ -336,7 +194,7 @@ class HTTPCodecTest extends Specification { } when: - codec.extract(new TextMapExtractAdapter(actual)) + extractor.extract(new TextMapExtractAdapter(actual)) then: thrown(IllegalArgumentException) diff --git a/dd-trace-ot/src/test/groovy/datadog/opentracing/propagation/DatadogHttpInjectorTest.groovy b/dd-trace-ot/src/test/groovy/datadog/opentracing/propagation/DatadogHttpInjectorTest.groovy new file mode 100644 index 0000000000..86f3d2a7a5 --- /dev/null +++ b/dd-trace-ot/src/test/groovy/datadog/opentracing/propagation/DatadogHttpInjectorTest.groovy @@ -0,0 +1,151 @@ +package datadog.opentracing.propagation + +import datadog.opentracing.DDSpanContext +import datadog.opentracing.DDTracer +import datadog.opentracing.PendingTrace +import datadog.trace.api.sampling.PrioritySampling +import datadog.trace.common.writer.ListWriter +import io.opentracing.propagation.TextMapInjectAdapter +import spock.lang.Specification + +import static datadog.opentracing.propagation.DatadogHttpCodec.OT_BAGGAGE_PREFIX +import static datadog.opentracing.propagation.DatadogHttpCodec.SAMPLING_PRIORITY_KEY +import static datadog.opentracing.propagation.DatadogHttpCodec.SPAN_ID_KEY +import static datadog.opentracing.propagation.DatadogHttpCodec.TRACE_ID_KEY + +class DatadogHttpInjectorTest extends Specification { + + DatadogHttpCodec.Injector injector = new DatadogHttpCodec.Injector() + + def "inject http headers"() { + setup: + def writer = new ListWriter() + def tracer = new DDTracer(writer) + final DDSpanContext mockedContext = + new DDSpanContext( + "1", + "2", + "0", + "fakeService", + "fakeOperation", + "fakeResource", + samplingPriority, + new HashMap() { + { + put("k1", "v1") + put("k2", "v2") + } + }, + false, + "fakeType", + null, + new PendingTrace(tracer, "1", [:]), + tracer) + + final Map carrier = new HashMap<>() + + injector.inject(mockedContext, new TextMapInjectAdapter(carrier)) + + expect: + carrier.get(TRACE_ID_KEY) == "1" + carrier.get(SPAN_ID_KEY) == "2" + 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 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<>() + + injector.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<>() + + injector.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 | _ + } +} diff --git a/dd-trace-ot/src/test/groovy/datadog/trace/DDTracerTest.groovy b/dd-trace-ot/src/test/groovy/datadog/trace/DDTracerTest.groovy index 64ea1143f4..fe2f37a595 100644 --- a/dd-trace-ot/src/test/groovy/datadog/trace/DDTracerTest.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/trace/DDTracerTest.groovy @@ -78,7 +78,7 @@ class DDTracerTest extends Specification { when: def config = new Config() def tracer = new DDTracer(config) - def taggedHeaders = tracer.registry.codecs.values().first().taggedHeaders + def taggedHeaders = tracer.extractor.taggedHeaders then: tracer.defaultSpanTags == map