diff --git a/dd-java-agent/testing/src/test/groovy/TraceCorrelationTest.groovy b/dd-java-agent/testing/src/test/groovy/TraceCorrelationTest.groovy new file mode 100644 index 0000000000..abcdc37eea --- /dev/null +++ b/dd-java-agent/testing/src/test/groovy/TraceCorrelationTest.groovy @@ -0,0 +1,25 @@ +import datadog.opentracing.DDSpan +import datadog.trace.agent.test.AgentTestRunner +import datadog.trace.api.CorrelationIdentifier +import io.opentracing.Scope +import io.opentracing.util.GlobalTracer + +class TraceCorrelationTest extends AgentTestRunner { + + def "access trace correlation only under trace" () { + when: + Scope scope = GlobalTracer.get().buildSpan("myspan").startActive(true) + DDSpan span = (DDSpan) scope.span() + + then: + CorrelationIdentifier.traceId == span.traceId + CorrelationIdentifier.spanId == span.spanId + + when: + scope.close() + + then: + 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 new file mode 100644 index 0000000000..d54e5ab679 --- /dev/null +++ b/dd-trace-api/src/main/java/datadog/trace/api/CorrelationIdentifier.java @@ -0,0 +1,45 @@ +package datadog.trace.api; + +import java.util.concurrent.atomic.AtomicReference; + +/** + * Utility class to access the active trace and span ids. + * + *

Intended for use with MDC frameworks. + */ +public class CorrelationIdentifier { + private static final AtomicReference provider = new AtomicReference<>(Provider.NO_OP); + + public static void registerIfAbsent(Provider p) { + if (p != null && p != Provider.NO_OP) { + provider.compareAndSet(Provider.NO_OP, p); + } + } + + public static long getTraceId() { + return provider.get().getTraceId(); + } + + public static long getSpanId() { + return provider.get().getSpanId(); + } + + public interface Provider { + long getTraceId(); + + long getSpanId(); + + Provider NO_OP = + new Provider() { + @Override + public long getTraceId() { + return 0; + } + + @Override + public long getSpanId() { + return 0; + } + }; + } +} 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 3ea6806b21..6e03e5a393 100644 --- a/dd-trace-ot/src/main/java/datadog/opentracing/DDTracer.java +++ b/dd-trace-ot/src/main/java/datadog/opentracing/DDTracer.java @@ -7,6 +7,7 @@ import datadog.opentracing.propagation.ExtractedContext; import datadog.opentracing.propagation.HTTPCodec; import datadog.opentracing.scopemanager.ContextualScopeManager; import datadog.opentracing.scopemanager.ScopeContext; +import datadog.trace.api.CorrelationIdentifier; import datadog.trace.api.interceptor.MutableSpan; import datadog.trace.api.interceptor.TraceInterceptor; import datadog.trace.api.sampling.PrioritySampling; @@ -147,6 +148,8 @@ public class DDTracer implements io.opentracing.Tracer { addDecorator(decorator); } + CorrelationIdentifier.registerIfAbsent(OTTraceCorrelation.INSTANCE); + log.info("New instance: {}", this); } diff --git a/dd-trace-ot/src/main/java/datadog/opentracing/OTTraceCorrelation.java b/dd-trace-ot/src/main/java/datadog/opentracing/OTTraceCorrelation.java new file mode 100644 index 0000000000..867ac448a8 --- /dev/null +++ b/dd-trace-ot/src/main/java/datadog/opentracing/OTTraceCorrelation.java @@ -0,0 +1,29 @@ +package datadog.opentracing; + +import datadog.trace.api.CorrelationIdentifier; +import io.opentracing.Span; +import io.opentracing.util.GlobalTracer; + +public class OTTraceCorrelation implements CorrelationIdentifier.Provider { + public static final OTTraceCorrelation INSTANCE = new OTTraceCorrelation(); + + private OTTraceCorrelation() {} + + @Override + public long getTraceId() { + final Span activeSpan = GlobalTracer.get().activeSpan(); + if (activeSpan instanceof DDSpan) { + return ((DDSpan) activeSpan).getTraceId(); + } + return 0; + } + + @Override + public long getSpanId() { + final Span activeSpan = GlobalTracer.get().activeSpan(); + if (activeSpan instanceof DDSpan) { + return ((DDSpan) activeSpan).getSpanId(); + } + return 0; + } +}