diff --git a/components/context/src/main/java/datadog/context/propagation/CompositePropagator.java b/components/context/src/main/java/datadog/context/propagation/CompositePropagator.java index b24af3bd05b..9484b2a8054 100644 --- a/components/context/src/main/java/datadog/context/propagation/CompositePropagator.java +++ b/components/context/src/main/java/datadog/context/propagation/CompositePropagator.java @@ -14,8 +14,8 @@ class CompositePropagator implements Propagator { @Override public void inject(Context context, C carrier, CarrierSetter setter) { - for (Propagator propagator : this.propagators) { - propagator.inject(context, carrier, setter); + for (int i = this.propagators.length - 1; i >= 0; i--) { + this.propagators[i].inject(context, carrier, setter); } } diff --git a/components/context/src/main/java/datadog/context/propagation/Propagators.java b/components/context/src/main/java/datadog/context/propagation/Propagators.java index d29867251b5..cbf1bd0ae5f 100644 --- a/components/context/src/main/java/datadog/context/propagation/Propagators.java +++ b/components/context/src/main/java/datadog/context/propagation/Propagators.java @@ -78,7 +78,8 @@ public static Propagator noop() { * Creates a composite propagator. * * @param propagators the elements that composes the returned propagator. - * @return the composite propagator that will apply the propagators in their given order. + * @return the composite propagator that will apply the propagators in their given order for + * context extraction, and reverse given order for context injection. */ public static Propagator composite(Propagator... propagators) { if (propagators.length == 0) { diff --git a/dd-trace-core/build.gradle b/dd-trace-core/build.gradle index e3c34a531f0..cfc50ded09b 100644 --- a/dd-trace-core/build.gradle +++ b/dd-trace-core/build.gradle @@ -48,6 +48,10 @@ excludedClassesCoverage += [ 'datadog.trace.core.TracingConfigPoller.Updater', // covered with dd-trace-core/src/test/groovy/datadog/trace/core/datastreams/CheckpointerTest.groovy 'datadog.trace.core.datastreams.DefaultDataStreamsMonitoring', + // TODO CorePropagation will be removed during context refactoring + 'datadog.trace.core.propagation.CorePropagation', + // TODO DSM propagator will be tested once fully migrated + 'datadog.trace.core.datastreams.DataStreamPropagator' ] addTestSuite('traceAgentTest') diff --git a/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java b/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java index 1c21645e5d2..09d578d06d0 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/CoreTracer.java @@ -5,6 +5,7 @@ import static datadog.trace.api.DDTags.DJM_ENABLED; import static datadog.trace.api.DDTags.DSM_ENABLED; import static datadog.trace.api.DDTags.PROFILING_CONTEXT_ENGINE; +import static datadog.trace.bootstrap.instrumentation.api.AgentPropagation.DSM_CONCERN; import static datadog.trace.bootstrap.instrumentation.api.AgentPropagation.STANDALONE_ASM_CONCERN; import static datadog.trace.bootstrap.instrumentation.api.AgentPropagation.TRACING_CONCERN; import static datadog.trace.bootstrap.instrumentation.api.AgentPropagation.XRAY_TRACING_CONCERN; @@ -32,7 +33,6 @@ import datadog.trace.api.InstrumenterConfig; import datadog.trace.api.StatsDClient; import datadog.trace.api.TraceConfig; -import datadog.trace.api.TracePropagationStyle; import datadog.trace.api.config.GeneralConfig; import datadog.trace.api.experimental.DataStreamsCheckpointer; import datadog.trace.api.flare.TracerFlare; @@ -79,7 +79,6 @@ import datadog.trace.common.writer.WriterFactory; import datadog.trace.common.writer.ddintake.DDIntakeTraceInterceptor; import datadog.trace.context.TraceScope; -import datadog.trace.core.datastreams.DataStreamContextInjector; import datadog.trace.core.datastreams.DataStreamsMonitoring; import datadog.trace.core.datastreams.DefaultDataStreamsMonitoring; import datadog.trace.core.flare.TracerFlarePoller; @@ -715,27 +714,25 @@ private CoreTracer( sharedCommunicationObjects.whenReady(this.dataStreamsMonitoring::start); - // Create default extractor from config if not provided and decorate it with DSM extractor - HttpCodec.Extractor builtExtractor = - extractor == null ? HttpCodec.createExtractor(config, this::captureTraceConfig) : extractor; - builtExtractor = this.dataStreamsMonitoring.extractor(builtExtractor); - // Create all HTTP injectors plus the DSM one - Map injectors = - HttpCodec.allInjectorsFor(config, invertMap(baggageMapping)); - DataStreamContextInjector dataStreamContextInjector = this.dataStreamsMonitoring.injector(); - // Store all propagators to propagation - this.propagation = - new CorePropagation(builtExtractor, injector, injectors, dataStreamContextInjector); + // Store all propagators to propagation -- only DSM injection left + this.propagation = new CorePropagation(this.dataStreamsMonitoring.injector()); + // Register context propagators + HttpCodec.Extractor tracingExtractor = + extractor == null ? HttpCodec.createExtractor(config, this::captureTraceConfig) : extractor; + TracingPropagator tracingPropagator = new TracingPropagator(injector, tracingExtractor); // Check if standalone AppSec is enabled: // If enabled, use the standalone AppSec propagator by default that will limit tracing concern // injection and delegate to the tracing propagator if needed, // If disabled, the most common case, use the usual tracing propagator by default. boolean standaloneAppSec = config.isAppSecStandaloneEnabled(); + boolean dsm = config.isDataStreamsEnabled(); Propagators.register(STANDALONE_ASM_CONCERN, new StandaloneAsmPropagator(), standaloneAppSec); - Propagators.register( - TRACING_CONCERN, new TracingPropagator(injector, extractor), !standaloneAppSec); + Propagators.register(TRACING_CONCERN, tracingPropagator, !standaloneAppSec); Propagators.register(XRAY_TRACING_CONCERN, new XRayPropagator(config), false); + if (dsm) { + Propagators.register(DSM_CONCERN, this.dataStreamsMonitoring.propagator()); + } this.tagInterceptor = null == tagInterceptor ? new TagInterceptor(new RuleFlags(config)) : tagInterceptor; diff --git a/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamPropagator.java b/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamPropagator.java new file mode 100644 index 00000000000..7fdedfad381 --- /dev/null +++ b/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamPropagator.java @@ -0,0 +1,83 @@ +package datadog.trace.core.datastreams; + +import datadog.context.Context; +import datadog.context.propagation.CarrierSetter; +import datadog.context.propagation.CarrierVisitor; +import datadog.context.propagation.Propagator; +import datadog.trace.api.TraceConfig; +import datadog.trace.api.time.TimeSource; +import datadog.trace.bootstrap.instrumentation.api.AgentSpan; +import datadog.trace.bootstrap.instrumentation.api.AgentSpanContext; +import datadog.trace.bootstrap.instrumentation.api.PathwayContext; +import datadog.trace.bootstrap.instrumentation.api.TagContext; +import java.util.function.Supplier; +import javax.annotation.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; + +// TODO Javadoc +@ParametersAreNonnullByDefault +public class DataStreamPropagator implements Propagator { + private final Supplier traceConfigSupplier; + private final TimeSource timeSource; + private final long hashOfKnownTags; + private final String serviceNameOverride; + + public DataStreamPropagator( + Supplier traceConfigSupplier, + TimeSource timeSource, + long hashOfKnownTags, + String serviceNameOverride) { + this.traceConfigSupplier = traceConfigSupplier; + this.timeSource = timeSource; + this.hashOfKnownTags = hashOfKnownTags; + this.serviceNameOverride = serviceNameOverride; + } + + @Override + public void inject(Context context, C carrier, CarrierSetter setter) { + // TODO Still in CorePropagation, not migrated yet + } + + @Override + public Context extract(Context context, C carrier, CarrierVisitor visitor) { + // TODO Pathway context needs to be stored into its own context element + // Get span context to store pathway context into + TagContext spanContext = getSpanContextOrNull(context); + PathwayContext pathwayContext; + // Ensure if DSM is enabled and look for pathway context + if (isDsmEnabled(spanContext) + && (pathwayContext = extractDsmPathwayContext(carrier, visitor)) != null) { + // Store pathway context into span context + if (spanContext == null) { + spanContext = new TagContext(); + AgentSpan span = AgentSpan.fromSpanContext(spanContext); + context = Context.root().with(span); + } + spanContext.withPathwayContext(pathwayContext); + } + return context; + } + + private TagContext getSpanContextOrNull(Context context) { + AgentSpan extractedSpan = AgentSpan.fromContext(context); + AgentSpanContext extractedSpanContext; + if (extractedSpan != null + && (extractedSpanContext = extractedSpan.context()) instanceof TagContext) { + return (TagContext) extractedSpanContext; + } + return null; + } + + private boolean isDsmEnabled(@Nullable TagContext tagContext) { + TraceConfig traceConfig = tagContext == null ? null : tagContext.getTraceConfig(); + if (traceConfig == null) { + traceConfig = this.traceConfigSupplier.get(); + } + return traceConfig.isDataStreamsEnabled(); + } + + private PathwayContext extractDsmPathwayContext(C carrier, CarrierVisitor visitor) { + return DefaultPathwayContext.extract( + carrier, visitor, this.timeSource, this.hashOfKnownTags, this.serviceNameOverride); + } +} diff --git a/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamsMonitoring.java b/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamsMonitoring.java index c7039bac92e..0571eff5f08 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamsMonitoring.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DataStreamsMonitoring.java @@ -1,5 +1,6 @@ package datadog.trace.core.datastreams; +import datadog.context.propagation.Propagator; import datadog.trace.api.experimental.DataStreamsContextCarrier; import datadog.trace.bootstrap.instrumentation.api.AgentDataStreamsMonitoring; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; @@ -10,6 +11,13 @@ public interface DataStreamsMonitoring extends AgentDataStreamsMonitoring, AutoCloseable { void start(); + /** + * Gets the propagator for DSM concern. + * + * @return The propagator for DSM concern. + */ + Propagator propagator(); + /** * Get a context extractor that support {@link PathwayContext} extraction. * diff --git a/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DefaultDataStreamsMonitoring.java b/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DefaultDataStreamsMonitoring.java index 00b9c4504b4..2c8a897e762 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DefaultDataStreamsMonitoring.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DefaultDataStreamsMonitoring.java @@ -14,6 +14,7 @@ import datadog.communication.ddagent.DDAgentFeaturesDiscovery; import datadog.communication.ddagent.SharedCommunicationObjects; +import datadog.context.propagation.Propagator; import datadog.trace.api.Config; import datadog.trace.api.TraceConfig; import datadog.trace.api.WellKnownTags; @@ -200,6 +201,12 @@ public PathwayContext newPathwayContext() { } } + @Override + public Propagator propagator() { + return new DataStreamPropagator( + this.traceConfigSupplier, this.timeSource, this.hashOfKnownTags, getThreadServiceName()); + } + @Override public HttpCodec.Extractor extractor(HttpCodec.Extractor delegate) { return new DataStreamContextExtractor( diff --git a/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DefaultPathwayContext.java b/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DefaultPathwayContext.java index 3f3ddf9d725..b95a65926dc 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DefaultPathwayContext.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/datastreams/DefaultPathwayContext.java @@ -7,10 +7,10 @@ import com.datadoghq.sketch.ddsketch.encoding.ByteArrayInput; import com.datadoghq.sketch.ddsketch.encoding.GrowingByteArrayOutput; import com.datadoghq.sketch.ddsketch.encoding.VarEncodingHelper; +import datadog.context.propagation.CarrierVisitor; import datadog.trace.api.Config; import datadog.trace.api.WellKnownTags; import datadog.trace.api.time.TimeSource; -import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; import datadog.trace.bootstrap.instrumentation.api.PathwayContext; import datadog.trace.bootstrap.instrumentation.api.StatsPoint; import datadog.trace.util.FNV64Hash; @@ -26,6 +26,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; +import java.util.function.BiConsumer; import java.util.function.Consumer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -267,7 +268,7 @@ public String toString() { } } - private static class PathwayContextExtractor implements AgentPropagation.KeyClassifier { + private static class PathwayContextExtractor implements BiConsumer { private final TimeSource timeSource; private final long hashOfKnownTags; private final String serviceNameOverride; @@ -281,27 +282,25 @@ private static class PathwayContextExtractor implements AgentPropagation.KeyClas } @Override - public boolean accept(String key, String value) { + public void accept(String key, String value) { if (PROPAGATION_KEY_BASE64.equalsIgnoreCase(key)) { try { extractedContext = decode(timeSource, hashOfKnownTags, serviceNameOverride, value); - } catch (IOException e) { - return false; + } catch (IOException ignored) { } } - return true; } } static DefaultPathwayContext extract( C carrier, - AgentPropagation.ContextVisitor getter, + CarrierVisitor getter, TimeSource timeSource, long hashOfKnownTags, String serviceNameOverride) { PathwayContextExtractor pathwayContextExtractor = new PathwayContextExtractor(timeSource, hashOfKnownTags, serviceNameOverride); - getter.forEachKey(carrier, pathwayContextExtractor); + getter.forEachKeyValue(carrier, pathwayContextExtractor); if (pathwayContextExtractor.extractedContext == null) { log.debug("No context extracted"); } else { diff --git a/dd-trace-core/src/main/java/datadog/trace/core/propagation/CorePropagation.java b/dd-trace-core/src/main/java/datadog/trace/core/propagation/CorePropagation.java index 75c3abb949c..90f43736c38 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/propagation/CorePropagation.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/propagation/CorePropagation.java @@ -1,81 +1,23 @@ package datadog.trace.core.propagation; -import datadog.trace.api.Config; -import datadog.trace.api.TracePropagationStyle; import datadog.trace.bootstrap.instrumentation.api.AgentPropagation; import datadog.trace.bootstrap.instrumentation.api.AgentSpan; -import datadog.trace.bootstrap.instrumentation.api.AgentSpanContext; -import datadog.trace.core.DDSpanContext; import datadog.trace.core.datastreams.DataStreamContextInjector; import java.util.LinkedHashMap; -import java.util.Map; public class CorePropagation implements AgentPropagation { - private final HttpCodec.Injector injector; - private final Map injectors; private final DataStreamContextInjector dataStreamContextInjector; - private final HttpCodec.Extractor extractor; /** * Constructor * - * @param extractor The context extractor. - * @param defaultInjector The default injector when no {@link TracePropagationStyle} given. - * @param injectors All the other injectors available for context injection. * @param dataStreamContextInjector The DSM context injector, as a specific object until generic * context injection is available. */ - public CorePropagation( - HttpCodec.Extractor extractor, - HttpCodec.Injector defaultInjector, - Map injectors, - DataStreamContextInjector dataStreamContextInjector) { - this.extractor = extractor; - this.injector = defaultInjector; - this.injectors = injectors; + public CorePropagation(DataStreamContextInjector dataStreamContextInjector) { this.dataStreamContextInjector = dataStreamContextInjector; } - @Override - public void inject(final AgentSpan span, final C carrier, final Setter setter) { - inject(span.context(), carrier, setter, null); - } - - @Override - public void inject(AgentSpanContext context, C carrier, Setter setter) { - inject(context, carrier, setter, null); - } - - @Override - public void inject(AgentSpan span, C carrier, Setter setter, TracePropagationStyle style) { - inject(span.context(), carrier, setter, style); - } - - private void inject( - AgentSpanContext context, C carrier, Setter setter, TracePropagationStyle style) { - if (!(context instanceof DDSpanContext)) { - return; - } - - final DDSpanContext ddSpanContext = (DDSpanContext) context; - ddSpanContext.getTraceCollector().setSamplingPriorityIfNecessary(); - - /** - * If the experimental appsec standalone feature is enabled and appsec propagation is disabled - * (no ASM events), stop propagation - */ - if (Config.get().isAppSecStandaloneEnabled() - && !ddSpanContext.getPropagationTags().isAppsecPropagationEnabled()) { - return; - } - - if (null == style) { - injector.inject(ddSpanContext, carrier, setter); - } else { - injectors.get(style).inject(ddSpanContext, carrier, setter); - } - } - @Override public void injectPathwayContext( AgentSpan span, C carrier, Setter setter, LinkedHashMap sortedTags) { @@ -100,9 +42,4 @@ public void injectPathwayContextWithoutSendingStats( this.dataStreamContextInjector.injectPathwayContextWithoutSendingStats( span, carrier, setter, sortedTags); } - - @Override - public AgentSpanContext.Extracted extract(final C carrier, final ContextVisitor getter) { - return extractor.extract(carrier, getter); - } } diff --git a/dd-trace-core/src/test/groovy/datadog/trace/core/CoreTracerTest.groovy b/dd-trace-core/src/test/groovy/datadog/trace/core/CoreTracerTest.groovy index 5d7dc2b915f..ba781cf010c 100644 --- a/dd-trace-core/src/test/groovy/datadog/trace/core/CoreTracerTest.groovy +++ b/dd-trace-core/src/test/groovy/datadog/trace/core/CoreTracerTest.groovy @@ -19,8 +19,6 @@ import datadog.trace.common.sampling.Sampler import datadog.trace.common.writer.DDAgentWriter import datadog.trace.common.writer.ListWriter import datadog.trace.common.writer.LoggingWriter -import datadog.trace.core.datastreams.DataStreamContextExtractor -import datadog.trace.core.propagation.HttpCodec import datadog.trace.core.tagprocessor.TagsPostProcessorFactory import datadog.trace.core.test.DDCoreSpecification import okhttp3.HttpUrl @@ -55,9 +53,6 @@ class CoreTracerTest extends DDCoreSpecification { tracer.writer instanceof DDAgentWriter tracer.statsDClient != null && tracer.statsDClient != StatsDClient.NO_OP - tracer.propagate().injector instanceof HttpCodec.CompoundInjector - tracer.propagate().extractor instanceof DataStreamContextExtractor - cleanup: tracer.close() } diff --git a/dd-trace-core/src/test/groovy/datadog/trace/core/propagation/CorePropagationTest.groovy b/dd-trace-core/src/test/groovy/datadog/trace/core/propagation/CorePropagationTest.groovy deleted file mode 100644 index aa8bde29e1b..00000000000 --- a/dd-trace-core/src/test/groovy/datadog/trace/core/propagation/CorePropagationTest.groovy +++ /dev/null @@ -1,229 +0,0 @@ -package datadog.trace.core.propagation - -import datadog.trace.api.TracePropagationStyle -import datadog.trace.api.sampling.PrioritySampling -import datadog.trace.bootstrap.instrumentation.api.AgentPropagation -import datadog.trace.common.writer.LoggingWriter -import datadog.trace.core.ControllableSampler -import datadog.trace.core.datastreams.DataStreamContextInjector -import datadog.trace.core.test.DDCoreSpecification - -import static datadog.trace.api.TracePropagationStyle.B3MULTI -import static datadog.trace.api.TracePropagationStyle.DATADOG -import static datadog.trace.api.TracePropagationStyle.TRACECONTEXT -import static datadog.trace.api.sampling.PrioritySampling.SAMPLER_KEEP - -class CorePropagationTest extends DDCoreSpecification { - HttpCodec.Extractor extractor - HttpCodec.Injector datadogInjector - HttpCodec.Injector b3Injector - HttpCodec.Injector traceContextInjector - Map allInjectors - DataStreamContextInjector dataStreamContextInjector - AgentPropagation propagation - - def setup() { - extractor = Mock(HttpCodec.Extractor) - datadogInjector = Mock(HttpCodec.Injector) - b3Injector = Mock(HttpCodec.Injector) - traceContextInjector = Mock(HttpCodec.Injector) - allInjectors = [ - (DATADOG) : datadogInjector, - (B3MULTI) : b3Injector, - (TRACECONTEXT): traceContextInjector, - ] - dataStreamContextInjector = Mock(DataStreamContextInjector) - propagation = new CorePropagation(extractor, datadogInjector, allInjectors, dataStreamContextInjector) - } - - def 'test default injector for span'() { - setup: - def tracer = tracerBuilder().build() - def span = tracer.buildSpan('test', 'operation').start() - def setter = Mock(AgentPropagation.Setter) - def carrier = new Object() - - when: - propagation.inject(span, carrier, setter) - - then: - 1 * datadogInjector.inject(_, carrier, setter) - 0 * b3Injector.inject(_, carrier, setter) - 0 * traceContextInjector.inject(_, carrier, setter) - 0 * dataStreamContextInjector.injectPathwayContext(_, carrier, setter, _) - - cleanup: - span.finish() - tracer.close() - } - - def 'test default injector for span context'() { - setup: - def tracer = tracerBuilder().build() - def span = tracer.buildSpan("test", "operation").start() - def setter = Mock(AgentPropagation.Setter) - def carrier = new Object() - - when: - def spanContext = span.context() - propagation.inject(spanContext, carrier, setter) - - then: - 1 * datadogInjector.inject(_, carrier, setter) - 0 * b3Injector.inject(_, carrier, setter) - 0 * traceContextInjector.inject(_, carrier, setter) - 0 * dataStreamContextInjector.injectPathwayContext(_, carrier, setter, _) - - cleanup: - span.finish() - tracer.close() - } - - def 'test injector style selection'() { - setup: - def injector = allInjectors.get(style, datadogInjector) - def tracer = tracerBuilder().build() - def span = tracer.buildSpan('test', 'operation').start() - def setter = Mock(AgentPropagation.Setter) - def carrier = new Object() - - when: - propagation.inject(span, carrier, setter, style) - - then: - 1 * injector.inject(_, carrier, setter) - if (injector != datadogInjector) { - 0 * datadogInjector.inject(_, carrier, setter) - } - if (injector != b3Injector) { - 0 * b3Injector.inject(_, carrier, setter) - } - if (injector != traceContextInjector) { - 0 * traceContextInjector.inject(_, carrier, setter) - } - 0 * dataStreamContextInjector.injectPathwayContext(_, carrier, setter, _) - - cleanup: - span.finish() - tracer.close() - - where: - style << [DATADOG, B3MULTI, TRACECONTEXT, null] - } - - def 'test context extractor'() { - setup: - def getter = Mock(AgentPropagation.ContextVisitor) - def carrier = new Object() - - when: - propagation.extract(carrier, getter) - - then: - 1 * extractor.extract(carrier, getter) - } - - def 'span priority set when injecting'() { - given: - injectSysConfig('writer.type', 'LoggingWriter') - def tracer = tracerBuilder().build() - def setter = Mock(AgentPropagation.Setter) - def carrier = new Object() - - when: - def root = tracer.buildSpan('test', 'operation').start() - def child = tracer.buildSpan('test', 'my_child').asChildOf(root).start() - tracer.propagate().inject(child, carrier, setter) - - then: - root.getSamplingPriority() == SAMPLER_KEEP as int - child.getSamplingPriority() == root.getSamplingPriority() - 1 * setter.set(carrier, DatadogHttpCodec.SAMPLING_PRIORITY_KEY, String.valueOf(SAMPLER_KEEP)) - - cleanup: - child.finish() - root.finish() - tracer.close() - } - - def 'span priority only set after first injection'() { - given: - def sampler = new ControllableSampler() - def tracer = tracerBuilder().writer(new LoggingWriter()).sampler(sampler).build() - def setter = Mock(AgentPropagation.Setter) - def carrier = new Object() - - when: - def root = tracer.buildSpan('test', 'operation').start() - def child = tracer.buildSpan('test', 'my_child').asChildOf(root).start() - tracer.propagate().inject(child, carrier, setter) - - then: - root.getSamplingPriority() == SAMPLER_KEEP as int - child.getSamplingPriority() == root.getSamplingPriority() - 1 * setter.set(carrier, DatadogHttpCodec.SAMPLING_PRIORITY_KEY, String.valueOf(SAMPLER_KEEP)) - - when: - sampler.nextSamplingPriority = PrioritySampling.SAMPLER_DROP as int - def child2 = tracer.buildSpan('test', 'my_child2').asChildOf(root).start() - tracer.propagate().inject(child2, carrier, setter) - - then: - root.getSamplingPriority() == SAMPLER_KEEP as int - child.getSamplingPriority() == root.getSamplingPriority() - child2.getSamplingPriority() == root.getSamplingPriority() - 1 * setter.set(carrier, DatadogHttpCodec.SAMPLING_PRIORITY_KEY, String.valueOf(SAMPLER_KEEP)) - - cleanup: - child.finish() - child2.finish() - root.finish() - tracer.close() - } - - def "injection doesn't override set priority"() { - given: - def sampler = new ControllableSampler() - def tracer = tracerBuilder().writer(new LoggingWriter()).sampler(sampler).build() - def setter = Mock(AgentPropagation.Setter) - def carrier = new Object() - - when: - def root = tracer.buildSpan('test', 'operation').start() - def child = tracer.buildSpan('test', 'my_child').asChildOf(root).start() - child.setSamplingPriority(PrioritySampling.USER_DROP) - tracer.propagate().inject(child, carrier, setter) - - then: - root.getSamplingPriority() == PrioritySampling.USER_DROP as int - child.getSamplingPriority() == root.getSamplingPriority() - 1 * setter.set(carrier, DatadogHttpCodec.SAMPLING_PRIORITY_KEY, String.valueOf(PrioritySampling.USER_DROP)) - - cleanup: - child.finish() - root.finish() - tracer.close() - } - - def 'test ASM standalone billing stop propagation'() { - setup: - injectSysConfig("experimental.appsec.standalone.enabled", "true") - def tracer = tracerBuilder().build() - def span = tracer.buildSpan('test', 'operation').start() - def setter = Mock(AgentPropagation.Setter) - def carrier = new Object() - - when: - propagation.inject(span, carrier, setter) - - then: - 0 * datadogInjector.inject(_, carrier, setter) - 0 * b3Injector.inject(_, carrier, setter) - 0 * traceContextInjector.inject(_, carrier, setter) - 0 * dataStreamContextInjector.injectPathwayContext(_, carrier, setter, _) - - cleanup: - span.finish() - tracer.close() - } -} diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentPropagation.java b/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentPropagation.java index 1ed21c3840f..0fd8cbca94f 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentPropagation.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentPropagation.java @@ -1,11 +1,13 @@ package datadog.trace.bootstrap.instrumentation.api; import static datadog.context.propagation.Concern.named; +import static datadog.context.propagation.Concern.withPriority; +import datadog.context.Context; import datadog.context.propagation.CarrierSetter; import datadog.context.propagation.CarrierVisitor; import datadog.context.propagation.Concern; -import datadog.trace.api.TracePropagationStyle; +import datadog.context.propagation.Propagators; import java.util.LinkedHashMap; import java.util.function.BiConsumer; import javax.annotation.ParametersAreNonnullByDefault; @@ -14,12 +16,9 @@ public interface AgentPropagation { Concern TRACING_CONCERN = named("tracing"); Concern XRAY_TRACING_CONCERN = named("tracing-xray"); Concern STANDALONE_ASM_CONCERN = named("asm-standalone"); - - void inject(AgentSpan span, C carrier, Setter setter); - - void inject(AgentSpanContext context, C carrier, Setter setter); - - void inject(AgentSpan span, C carrier, Setter setter, TracePropagationStyle style); + // TODO DSM propagator should run after the other propagators as it stores the pathway context + // TODO into the span context for now. Remove priority after the migration is complete. + Concern DSM_CONCERN = withPriority("data-stream-monitoring", 110); // The input tags should be sorted. void injectPathwayContext( @@ -40,7 +39,11 @@ interface Setter extends CarrierSetter { void set(C carrier, String key, String value); } - AgentSpanContext.Extracted extract(C carrier, ContextVisitor getter); + default AgentSpanContext.Extracted extract(final C carrier, final ContextVisitor getter) { + Context extracted = Propagators.defaultPropagator().extract(Context.root(), carrier, getter); + AgentSpan extractedSpan = AgentSpan.fromContext(extracted); + return extractedSpan == null ? null : (AgentSpanContext.Extracted) extractedSpan.context(); + } interface KeyClassifier { boolean accept(String key, String value); diff --git a/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentTracer.java b/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentTracer.java index ac5e54d8f7a..c7a5f76a9e5 100644 --- a/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentTracer.java +++ b/internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/AgentTracer.java @@ -7,7 +7,6 @@ import datadog.trace.api.EndpointCheckpointer; import datadog.trace.api.EndpointTracker; import datadog.trace.api.TraceConfig; -import datadog.trace.api.TracePropagationStyle; import datadog.trace.api.experimental.DataStreamsCheckpointer; import datadog.trace.api.experimental.DataStreamsContextCarrier; import datadog.trace.api.gateway.CallbackProvider; @@ -585,17 +584,6 @@ public void updatePreferredServiceName(String serviceName) { static class NoopAgentPropagation implements AgentPropagation { static final NoopAgentPropagation INSTANCE = new NoopAgentPropagation(); - @Override - public void inject(final AgentSpan span, final C carrier, final Setter setter) {} - - @Override - public void inject( - final AgentSpanContext context, final C carrier, final Setter setter) {} - - @Override - public void inject( - AgentSpan span, C carrier, Setter setter, TracePropagationStyle style) {} - @Override public void injectPathwayContext( AgentSpan span, C carrier, Setter setter, LinkedHashMap sortedTags) {} @@ -612,11 +600,6 @@ public void injectPathwayContext( @Override public void injectPathwayContextWithoutSendingStats( AgentSpan span, C carrier, Setter setter, LinkedHashMap sortedTags) {} - - @Override - public AgentSpanContext.Extracted extract(final C carrier, final ContextVisitor getter) { - return NoopSpanContext.INSTANCE; - } } static class NoopContinuation implements AgentScope.Continuation { diff --git a/internal-api/src/test/groovy/datadog/trace/bootstrap/instrumentation/api/SpanLinkTest.groovy b/internal-api/src/test/groovy/datadog/trace/bootstrap/instrumentation/api/SpanLinkTest.groovy index 56057d8b16a..a1e9b93ca38 100644 --- a/internal-api/src/test/groovy/datadog/trace/bootstrap/instrumentation/api/SpanLinkTest.groovy +++ b/internal-api/src/test/groovy/datadog/trace/bootstrap/instrumentation/api/SpanLinkTest.groovy @@ -3,12 +3,12 @@ package datadog.trace.bootstrap.instrumentation.api import datadog.trace.api.DDSpanId import datadog.trace.api.DDTraceId -import datadog.trace.test.util.DDSpecification +import spock.lang.Specification import static datadog.trace.bootstrap.instrumentation.api.AgentSpanLink.DEFAULT_FLAGS import static datadog.trace.bootstrap.instrumentation.api.AgentSpanLink.SAMPLED_FLAG -class SpanLinkTest extends DDSpecification { +class SpanLinkTest extends Specification { def "test span link from context"() { setup: def traceId = DDTraceId.fromHex("11223344556677889900aabbccddeeff")