diff --git a/dd-trace-core/src/main/java/datadog/trace/core/CoreSpan.java b/dd-trace-core/src/main/java/datadog/trace/core/CoreSpan.java index 68db791825a..ce088ee9512 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/CoreSpan.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/CoreSpan.java @@ -68,6 +68,13 @@ public interface CoreSpan> { CharSequence getType(); + /** + * Runs early {@link datadog.trace.core.tagprocessor.TagsPostProcessor} like base service and peer + * service computation. Such tags are needed before span serialization so they can’t be processed + * lazily as part of the {@link #processTagsAndBaggage(MetadataConsumer)} API. + */ + void processServiceTags(); + void processTagsAndBaggage(MetadataConsumer consumer); T setSamplingPriority(int samplingPriority, int samplingMechanism); 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 4c81a579f83..59603f8819a 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 @@ -1109,6 +1109,12 @@ void write(final List trace) { if (writtenTrace.isEmpty()) { return; } + + // run early tag postprocessors before publishing to the metrics writer since peer / base + // service are needed + for (DDSpan span : writtenTrace) { + span.processServiceTags(); + } boolean forceKeep = metricsAggregator.publish(writtenTrace); TraceCollector traceCollector = writtenTrace.get(0).context().getTraceCollector(); diff --git a/dd-trace-core/src/main/java/datadog/trace/core/DDSpan.java b/dd-trace-core/src/main/java/datadog/trace/core/DDSpan.java index 2c282f15a57..2a463042d34 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/DDSpan.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/DDSpan.java @@ -694,7 +694,7 @@ public String getSpanType() { @Override public TagMap getTags() { - // This is an imutable copy of the tags + // This is an immutable copy of the tags return context.getTags(); } @@ -703,6 +703,11 @@ public CharSequence getType() { return context.getSpanType(); } + @Override + public void processServiceTags() { + context.earlyProcessTags(links); + } + @Override public void processTagsAndBaggage(final MetadataConsumer consumer) { context.processTagsAndBaggage(consumer, longRunningVersion, links); diff --git a/dd-trace-core/src/main/java/datadog/trace/core/DDSpanContext.java b/dd-trace-core/src/main/java/datadog/trace/core/DDSpanContext.java index ed18aa1efc8..4c404ae0a38 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/DDSpanContext.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/DDSpanContext.java @@ -921,11 +921,17 @@ public void setMetaStruct(final String field, final T value) { } } + public void earlyProcessTags(List links) { + synchronized (unsafeTags) { + TagsPostProcessorFactory.eagerProcessor().processTags(unsafeTags, this, links); + } + } + public void processTagsAndBaggage( final MetadataConsumer consumer, int longRunningVersion, List links) { synchronized (unsafeTags) { // Tags - TagsPostProcessorFactory.instance().processTags(unsafeTags, this, links); + TagsPostProcessorFactory.lazyProcessor().processTags(unsafeTags, this, links); String linksTag = DDSpanLink.toTag(links); if (linksTag != null) { diff --git a/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/TagsPostProcessorFactory.java b/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/TagsPostProcessorFactory.java index 1753a52af4a..2687211e5b2 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/TagsPostProcessorFactory.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/TagsPostProcessorFactory.java @@ -9,12 +9,21 @@ public final class TagsPostProcessorFactory { private static boolean addRemoteHostname = true; private static class Lazy { - private static TagsPostProcessor create() { - final List processors = new ArrayList<>(7); + private static TagsPostProcessor eagerProcessor = createEagerChain(); + private static TagsPostProcessor lazyProcessor = createLazyChain(); + + private static TagsPostProcessor createEagerChain() { + final List processors = new ArrayList<>(2); processors.add(new PeerServiceCalculator()); if (addBaseService) { processors.add(new BaseServiceAdder(Config.get().getServiceName())); } + return new PostProcessorChain(processors.toArray(new TagsPostProcessor[0])); + } + + private static TagsPostProcessor createLazyChain() { + final List processors = new ArrayList<>(7); + processors.add(new QueryObfuscator(Config.get().getObfuscationQueryRegexp())); if (addRemoteHostname) { processors.add(new RemoteHostnameAdder(Config.get().getHostNameSupplier())); @@ -36,12 +45,14 @@ private static TagsPostProcessor create() { return new PostProcessorChain( processors.toArray(processors.toArray(new TagsPostProcessor[0]))); } + } - private static TagsPostProcessor instance = create(); + public static TagsPostProcessor eagerProcessor() { + return Lazy.eagerProcessor; } - public static TagsPostProcessor instance() { - return Lazy.instance; + public static TagsPostProcessor lazyProcessor() { + return Lazy.lazyProcessor; } /** @@ -51,7 +62,7 @@ public static TagsPostProcessor instance() { */ public static void withAddBaseService(boolean enabled) { addBaseService = enabled; - Lazy.instance = Lazy.create(); + Lazy.eagerProcessor = Lazy.createEagerChain(); } /** @@ -61,7 +72,7 @@ public static void withAddBaseService(boolean enabled) { */ public static void withAddRemoteHostname(boolean enabled) { addRemoteHostname = enabled; - Lazy.instance = Lazy.create(); + Lazy.lazyProcessor = Lazy.createLazyChain(); } /** Used for testing purposes. It reset the singleton and restore default options */ diff --git a/dd-trace-core/src/test/groovy/datadog/trace/common/metrics/SimpleSpan.groovy b/dd-trace-core/src/test/groovy/datadog/trace/common/metrics/SimpleSpan.groovy index 72250d64654..b16dd7a365e 100644 --- a/dd-trace-core/src/test/groovy/datadog/trace/common/metrics/SimpleSpan.groovy +++ b/dd-trace-core/src/test/groovy/datadog/trace/common/metrics/SimpleSpan.groovy @@ -206,6 +206,9 @@ class SimpleSpan implements CoreSpan { return type } + @Override + void processServiceTags() {} + @Override void processTagsAndBaggage(MetadataConsumer consumer) {} diff --git a/dd-trace-core/src/test/groovy/datadog/trace/common/writer/TraceGenerator.groovy b/dd-trace-core/src/test/groovy/datadog/trace/common/writer/TraceGenerator.groovy index 0183844dc7f..d6a736ed3fe 100644 --- a/dd-trace-core/src/test/groovy/datadog/trace/common/writer/TraceGenerator.groovy +++ b/dd-trace-core/src/test/groovy/datadog/trace/common/writer/TraceGenerator.groovy @@ -333,6 +333,9 @@ class TraceGenerator { return this.type } + @Override + void processServiceTags() {} + @Override void processTagsAndBaggage(MetadataConsumer consumer) { consumer.accept(metadata) diff --git a/dd-trace-core/src/traceAgentTest/groovy/TraceGenerator.groovy b/dd-trace-core/src/traceAgentTest/groovy/TraceGenerator.groovy index bc690a73ac0..1fabddd6e19 100644 --- a/dd-trace-core/src/traceAgentTest/groovy/TraceGenerator.groovy +++ b/dd-trace-core/src/traceAgentTest/groovy/TraceGenerator.groovy @@ -309,6 +309,9 @@ class TraceGenerator { return type } + @Override + void processServiceTags() {} + @Override void processTagsAndBaggage(MetadataConsumer consumer) { consumer.accept(metadata)