From 8e57e8754adc99ddc8ef22940ea6acda8424e3f0 Mon Sep 17 00:00:00 2001 From: Douglas Q Hawkins Date: Thu, 22 Oct 2026 22:26:36 -0400 Subject: [PATCH] Introduce SpanStorage for eager tag post-processors Eager post-processors run on the application thread as a span finishes. They now take a SpanStorage (a span's tags as stored) instead of a TagMap, and DDSpanContext implements SpanStorage directly, so no TagMap view needs to be built for them once span storage stops being a single TagMap. SpanStorage has its own verbs, load and store, apart from TagMap's get/set and the span's intercepted getTag/setTag, so DDSpanContext can offer the raw and the intercepted operations without a clash. Stores bypass interception; thread safety is left to each implementation (DDSpanContext's are unsynchronized, called under the tag lock). TagMap implements it too, through its own get and set, for standalone maps. This is the first slice: load, loadString and two stores. Co-Authored-By: Claude Opus 5.5 --- .../datadog/trace/core/DDSpanContext.java | 30 +++++++++++++++++-- .../tagprocessor/EagerPostProcessorChain.java | 24 +++++++++++++++ .../tagprocessor/EagerTagsPostProcessor.java | 21 +++++++++++++ .../HttpEndpointPostProcessor.java | 12 ++++---- .../core/tagprocessor/InternalTagsAdder.java | 11 +++---- .../tagprocessor/PeerServiceCalculator.java | 16 +++++----- .../TagsPostProcessorFactory.java | 10 +++---- .../java/datadog/trace/api/SpanStorage.java | 27 +++++++++++++++++ .../main/java/datadog/trace/api/TagMap.java | 25 +++++++++++++++- .../trace/api/endpoint/EndpointResolver.java | 9 +++--- .../trace/api/naming/NamingSchema.java | 4 +-- .../api/naming/v0/PeerServiceNamingV0.java | 4 +-- .../api/naming/v1/PeerServiceNamingV1.java | 21 ++++++------- .../api/endpoint/EndpointResolverTest.java | 23 +++++++------- 14 files changed, 179 insertions(+), 58 deletions(-) create mode 100644 dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/EagerPostProcessorChain.java create mode 100644 dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/EagerTagsPostProcessor.java create mode 100644 internal-api/src/main/java/datadog/trace/api/SpanStorage.java 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 1e236d3a120..8fdf11b8a85 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 @@ -18,6 +18,7 @@ import datadog.trace.api.KnownTagCodec; import datadog.trace.api.KnownTags; import datadog.trace.api.ProcessTags; +import datadog.trace.api.SpanStorage; import datadog.trace.api.TagMap; import datadog.trace.api.cache.DDCache; import datadog.trace.api.cache.DDCaches; @@ -68,7 +69,7 @@ * the associated Span instance */ public class DDSpanContext - implements AgentSpanContext, RequestContext, TraceSegment, ProfilerContext { + implements AgentSpanContext, RequestContext, TraceSegment, ProfilerContext, SpanStorage { private static final Logger log = LoggerFactory.getLogger(DDSpanContext.class); public static final String PRIORITY_SAMPLING_KEY = "_sampling_priority_v1"; @@ -1395,6 +1396,31 @@ Object getTag(final String key) { } } + /* + * SpanStorage: the span's tags, loaded and stored with no interception. + * Unsynchronized, like unsafeGetTag: callers hold the span's tag lock, as post-processing does. + */ + + @Override + public Object load(String tag) { + return unsafeTags.getObject(tag); + } + + @Override + public String loadString(String tag) { + return unsafeTags.getString(tag); + } + + @Override + public void store(String tag, Object value) { + unsafeTags.set(tag, value); + } + + @Override + public void store(TagMap.EntryReader entry) { + unsafeTags.set(entry); + } + /** * This is not thread-safe and must only be used when it can be guaranteed that the context will * not be mutated. This is internal API and must not be exposed to users. @@ -1500,7 +1526,7 @@ public void setMetaStruct(final String field, final T value) { void earlyProcessTags(AppendableSpanLinks links) { synchronized (unsafeTags) { - TagsPostProcessorFactory.eagerProcessor().processTags(unsafeTags, this, links); + TagsPostProcessorFactory.eagerProcessor().processTags(this, this, links); } } diff --git a/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/EagerPostProcessorChain.java b/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/EagerPostProcessorChain.java new file mode 100644 index 00000000000..f5ac6765293 --- /dev/null +++ b/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/EagerPostProcessorChain.java @@ -0,0 +1,24 @@ +package datadog.trace.core.tagprocessor; + +import datadog.trace.api.SpanStorage; +import datadog.trace.bootstrap.instrumentation.api.AppendableSpanLinks; +import datadog.trace.core.DDSpanContext; +import java.util.Objects; +import javax.annotation.Nonnull; + +/** Runs eager post-processors in order. */ +public final class EagerPostProcessorChain extends EagerTagsPostProcessor { + private final EagerTagsPostProcessor[] chain; + + public EagerPostProcessorChain(@Nonnull final EagerTagsPostProcessor... processors) { + chain = Objects.requireNonNull(processors); + } + + @Override + public void processTags( + SpanStorage storage, DDSpanContext spanContext, AppendableSpanLinks spanLinks) { + for (final EagerTagsPostProcessor processor : chain) { + processor.processTags(storage, spanContext, spanLinks); + } + } +} diff --git a/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/EagerTagsPostProcessor.java b/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/EagerTagsPostProcessor.java new file mode 100644 index 00000000000..54ace639c80 --- /dev/null +++ b/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/EagerTagsPostProcessor.java @@ -0,0 +1,21 @@ +package datadog.trace.core.tagprocessor; + +import datadog.trace.api.SpanStorage; +import datadog.trace.bootstrap.instrumentation.api.AppendableSpanLinks; +import datadog.trace.core.DDSpanContext; + +/** + * A tag post-processor run on the application thread as a span finishes. It works on the span's + * {@link SpanStorage} rather than a {@code TagMap}, so the span needn't build one for it. + */ +public abstract class EagerTagsPostProcessor { + /** + * Processes the span's tags. + * + * @param contents the span's contents to read and write; the caller holds the span's tag lock + * @param spanContext the span, for its other properties + * @param spanLinks the span's links + */ + public abstract void processTags( + SpanStorage storage, DDSpanContext spanContext, AppendableSpanLinks spanLinks); +} diff --git a/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/HttpEndpointPostProcessor.java b/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/HttpEndpointPostProcessor.java index c2e0dd72761..6e6f9cfd829 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/HttpEndpointPostProcessor.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/HttpEndpointPostProcessor.java @@ -4,7 +4,7 @@ import static datadog.trace.bootstrap.instrumentation.api.Tags.HTTP_ROUTE; import static datadog.trace.bootstrap.instrumentation.api.Tags.HTTP_URL; -import datadog.trace.api.TagMap; +import datadog.trace.api.SpanStorage; import datadog.trace.api.endpoint.EndpointResolver; import datadog.trace.api.internal.VisibleForTesting; import datadog.trace.bootstrap.instrumentation.api.AppendableSpanLinks; @@ -30,7 +30,7 @@ *
  • If {@code alwaysSimplifiedEndpoint=true}, always compute from URL regardless of route * */ -public class HttpEndpointPostProcessor extends TagsPostProcessor { +public class HttpEndpointPostProcessor extends EagerTagsPostProcessor { private static final Logger log = LoggerFactory.getLogger(HttpEndpointPostProcessor.class); private final EndpointResolver endpointResolver; @@ -55,19 +55,19 @@ public HttpEndpointPostProcessor() { @Override public void processTags( - TagMap unsafeTags, DDSpanContext spanContext, AppendableSpanLinks spanLinks) { + SpanStorage unsafeTags, DDSpanContext spanContext, AppendableSpanLinks spanLinks) { if (!endpointResolver.isEnabled()) { log.debug("EndpointResolver is not enabled, skipping HTTP endpoint post processing"); return; } - if (unsafeTags.getObject(HTTP_METHOD) == null) { + if (unsafeTags.load(HTTP_METHOD) == null) { return; } try { - String httpRoute = unsafeTags.getString(HTTP_ROUTE); - String httpUrl = unsafeTags.getString(HTTP_URL); + String httpRoute = unsafeTags.loadString(HTTP_ROUTE); + String httpUrl = unsafeTags.loadString(HTTP_URL); endpointResolver.resolveEndpoint(unsafeTags, httpRoute, httpUrl); } catch (Throwable t) { log.debug("Error processing HTTP endpoint for span {}", spanContext.getSpanId(), t); diff --git a/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/InternalTagsAdder.java b/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/InternalTagsAdder.java index 3e6b8b13192..afcf8c30438 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/InternalTagsAdder.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/InternalTagsAdder.java @@ -3,6 +3,7 @@ import static datadog.trace.bootstrap.instrumentation.api.Tags.VERSION; import datadog.trace.api.DDTags; +import datadog.trace.api.SpanStorage; import datadog.trace.api.TagMap; import datadog.trace.bootstrap.instrumentation.api.AppendableSpanLinks; import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString; @@ -10,7 +11,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; -public final class InternalTagsAdder extends TagsPostProcessor { +public final class InternalTagsAdder extends EagerTagsPostProcessor { private final UTF8BytesString ddService; // Prebuilt once to avoid per-span Entry allocation. @@ -28,7 +29,7 @@ public InternalTagsAdder(@Nonnull final String ddService, @Nullable final String @Override public void processTags( - TagMap unsafeTags, DDSpanContext spanContext, AppendableSpanLinks spanLinks) { + SpanStorage unsafeTags, DDSpanContext spanContext, AppendableSpanLinks spanLinks) { if (spanContext == null) { return; } @@ -36,13 +37,13 @@ public void processTags( if (!ddService.toString().equalsIgnoreCase(spanContext.getServiceName())) { if (baseServiceEntry != null) { // service name != DD_SERVICE - unsafeTags.set(baseServiceEntry); + unsafeTags.store(baseServiceEntry); } } else { // as per config consistency, the version tag is added across tracers only if // the service name is DD_SERVICE and version tag is not manually set - if (versionEntry != null && !unsafeTags.containsKey(VERSION)) { - unsafeTags.set(versionEntry); + if (versionEntry != null && unsafeTags.load(VERSION) == null) { + unsafeTags.store(versionEntry); } } } diff --git a/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/PeerServiceCalculator.java b/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/PeerServiceCalculator.java index 198e2c78f1c..8d5d0513962 100644 --- a/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/PeerServiceCalculator.java +++ b/dd-trace-core/src/main/java/datadog/trace/core/tagprocessor/PeerServiceCalculator.java @@ -2,7 +2,7 @@ import datadog.trace.api.Config; import datadog.trace.api.DDTags; -import datadog.trace.api.TagMap; +import datadog.trace.api.SpanStorage; import datadog.trace.api.internal.VisibleForTesting; import datadog.trace.api.naming.NamingSchema; import datadog.trace.api.naming.SpanNaming; @@ -12,7 +12,7 @@ import java.util.Map; import javax.annotation.Nonnull; -public final class PeerServiceCalculator extends TagsPostProcessor { +public final class PeerServiceCalculator extends EagerTagsPostProcessor { private final NamingSchema.ForPeerService peerServiceNaming; private final Map peerServiceMapping; @@ -34,8 +34,8 @@ public PeerServiceCalculator() { @Override public void processTags( - TagMap unsafeTags, DDSpanContext spanContext, AppendableSpanLinks spanLinks) { - Object peerService = unsafeTags.getObject(Tags.PEER_SERVICE); + SpanStorage unsafeTags, DDSpanContext spanContext, AppendableSpanLinks spanLinks) { + Object peerService = unsafeTags.load(Tags.PEER_SERVICE); // the user set it if (peerService != null) { if (canRemap) { @@ -46,18 +46,18 @@ public void processTags( // calculate the defaults (if any) peerServiceNaming.tags(unsafeTags); // only remap if the mapping is not empty (saves one get) - remapPeerService(unsafeTags, canRemap ? unsafeTags.getObject(Tags.PEER_SERVICE) : null); + remapPeerService(unsafeTags, canRemap ? unsafeTags.load(Tags.PEER_SERVICE) : null); return; } // we have no peer.service and we do not compute defaults. Leave the map untouched } - private void remapPeerService(TagMap unsafeTags, Object value) { + private void remapPeerService(SpanStorage unsafeTags, Object value) { if (value != null) { String mapped = peerServiceMapping.get(value); if (mapped != null) { - unsafeTags.put(Tags.PEER_SERVICE, mapped); - unsafeTags.put(DDTags.PEER_SERVICE_REMAPPED_FROM, value); + unsafeTags.store(Tags.PEER_SERVICE, mapped); + unsafeTags.store(DDTags.PEER_SERVICE_REMAPPED_FROM, value); } } } 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 08c52a2658a..2e3cd4ca345 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,11 +9,11 @@ public final class TagsPostProcessorFactory { private static boolean addRemoteHostname = true; private static class Lazy { - private static TagsPostProcessor eagerProcessor = createEagerChain(); + private static EagerTagsPostProcessor eagerProcessor = createEagerChain(); private static TagsPostProcessor lazyProcessor = createLazyChain(); - private static TagsPostProcessor createEagerChain() { - final List processors = new ArrayList<>(3); + private static EagerTagsPostProcessor createEagerChain() { + final List processors = new ArrayList<>(3); processors.add(new PeerServiceCalculator()); if (addInternalTags) { processors.add( @@ -24,7 +24,7 @@ private static TagsPostProcessor createEagerChain() { if (Config.get().isTraceResourceRenamingEnabled()) { processors.add(new HttpEndpointPostProcessor()); } - return new PostProcessorChain(processors.toArray(new TagsPostProcessor[0])); + return new EagerPostProcessorChain(processors.toArray(new EagerTagsPostProcessor[0])); } private static TagsPostProcessor createLazyChain() { @@ -54,7 +54,7 @@ private static TagsPostProcessor createLazyChain() { } } - public static TagsPostProcessor eagerProcessor() { + public static EagerTagsPostProcessor eagerProcessor() { return Lazy.eagerProcessor; } diff --git a/internal-api/src/main/java/datadog/trace/api/SpanStorage.java b/internal-api/src/main/java/datadog/trace/api/SpanStorage.java new file mode 100644 index 00000000000..09b2fab946d --- /dev/null +++ b/internal-api/src/main/java/datadog/trace/api/SpanStorage.java @@ -0,0 +1,27 @@ +package datadog.trace.api; + +/** + * A span's tags as stored, for the tracer core's processing pipeline: loads and stores go straight + * to storage, with no interception. Thread safety is up to the implementation; {@code + * DDSpanContext}'s expects the span's tag lock to be held. + * + *

    Its own verbs, {@code load} and {@code store}, keep it apart from {@link TagMap}'s {@code + * get}/{@code set} and the span's intercepted {@code getTag}/{@code setTag}, so a type can offer + * several of these without a clash. + * + *

    This is the first slice: only what the eager tag post-processors need. Id variants, typed + * loads and primitive stores come as more of the pipeline moves to it. + */ +public interface SpanStorage { + /** The tag's value, or null when it's absent. */ + Object load(String tag); + + /** The tag's value as a string, or null when it's absent. */ + String loadString(String tag); + + /** Stores the tag; a null value removes it. */ + void store(String tag, Object value); + + /** Stores the entry's tag; a null entry is a no-op. */ + void store(TagMap.EntryReader entry); +} diff --git a/internal-api/src/main/java/datadog/trace/api/TagMap.java b/internal-api/src/main/java/datadog/trace/api/TagMap.java index 296d52399a6..b4cc9997222 100644 --- a/internal-api/src/main/java/datadog/trace/api/TagMap.java +++ b/internal-api/src/main/java/datadog/trace/api/TagMap.java @@ -48,7 +48,8 @@ *

  • adaptive collision * */ -public final class TagMap implements Map, Iterable { +public final class TagMap + implements Map, Iterable, SpanStorage { /** Immutable empty TagMap - similar to {@link Collections#emptyMap()} */ // Frozen view over a length-1 array: bucket masking needs a power-of-two array length (size 0 // would fail with ArrayIndexOutOfBoundsException, size 1 works), and the private constructor @@ -1346,6 +1347,28 @@ public String getString(String tag) { return entry == null ? null : entry.stringValue(); } + /* SpanStorage, for standalone maps handed to the pipeline: TagMap's own get and set. */ + + @Override + public Object load(String tag) { + return this.getObject(tag); + } + + @Override + public String loadString(String tag) { + return this.getString(tag); + } + + @Override + public void store(String tag, Object value) { + this.set(tag, value); + } + + @Override + public void store(EntryReader entry) { + this.set(entry); + } + public boolean getBoolean(String tag) { return this.getBooleanOrDefault(tag, false); } diff --git a/internal-api/src/main/java/datadog/trace/api/endpoint/EndpointResolver.java b/internal-api/src/main/java/datadog/trace/api/endpoint/EndpointResolver.java index c5e47328734..30114ca2372 100644 --- a/internal-api/src/main/java/datadog/trace/api/endpoint/EndpointResolver.java +++ b/internal-api/src/main/java/datadog/trace/api/endpoint/EndpointResolver.java @@ -2,6 +2,7 @@ import static datadog.trace.bootstrap.instrumentation.api.Tags.HTTP_ENDPOINT; +import datadog.trace.api.SpanStorage; import javax.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -50,9 +51,7 @@ public EndpointResolver(boolean enabled, boolean alwaysSimplifiedEndpoint) { */ @Nullable public String resolveEndpoint( - java.util.Map unsafeTags, - @Nullable String httpRoute, - @Nullable String httpUrl) { + SpanStorage unsafeTags, @Nullable String httpRoute, @Nullable String httpUrl) { if (!enabled) { return null; } @@ -61,7 +60,7 @@ public String resolveEndpoint( if (alwaysSimplifiedEndpoint) { String endpoint = computeEndpoint(httpUrl); if (endpoint != null) { - unsafeTags.put(HTTP_ENDPOINT, endpoint); + unsafeTags.store(HTTP_ENDPOINT, endpoint); } return endpoint; } @@ -74,7 +73,7 @@ public String resolveEndpoint( // Compute endpoint from URL and tag the span String endpoint = computeEndpoint(httpUrl); if (endpoint != null) { - unsafeTags.put(HTTP_ENDPOINT, endpoint); + unsafeTags.store(HTTP_ENDPOINT, endpoint); } return endpoint; } diff --git a/internal-api/src/main/java/datadog/trace/api/naming/NamingSchema.java b/internal-api/src/main/java/datadog/trace/api/naming/NamingSchema.java index 9ddf3178f3b..b17b52bc58b 100644 --- a/internal-api/src/main/java/datadog/trace/api/naming/NamingSchema.java +++ b/internal-api/src/main/java/datadog/trace/api/naming/NamingSchema.java @@ -1,6 +1,6 @@ package datadog.trace.api.naming; -import datadog.trace.api.TagMap; +import datadog.trace.api.SpanStorage; import java.util.function.Supplier; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -232,7 +232,7 @@ interface ForPeerService { * @param unsafeTags the span tags. Map to be mutated */ @Nonnull - void tags(@Nonnull TagMap unsafeTags); + void tags(@Nonnull SpanStorage unsafeTags); } interface ForServer { diff --git a/internal-api/src/main/java/datadog/trace/api/naming/v0/PeerServiceNamingV0.java b/internal-api/src/main/java/datadog/trace/api/naming/v0/PeerServiceNamingV0.java index 3e76d657069..d802622205a 100644 --- a/internal-api/src/main/java/datadog/trace/api/naming/v0/PeerServiceNamingV0.java +++ b/internal-api/src/main/java/datadog/trace/api/naming/v0/PeerServiceNamingV0.java @@ -1,6 +1,6 @@ package datadog.trace.api.naming.v0; -import datadog.trace.api.TagMap; +import datadog.trace.api.SpanStorage; import datadog.trace.api.naming.NamingSchema; import javax.annotation.Nonnull; @@ -12,5 +12,5 @@ public boolean supports() { @Nonnull @Override - public void tags(@Nonnull final TagMap unsafeTags) {} + public void tags(@Nonnull final SpanStorage unsafeTags) {} } diff --git a/internal-api/src/main/java/datadog/trace/api/naming/v1/PeerServiceNamingV1.java b/internal-api/src/main/java/datadog/trace/api/naming/v1/PeerServiceNamingV1.java index 827a7489e09..021dbda7aee 100644 --- a/internal-api/src/main/java/datadog/trace/api/naming/v1/PeerServiceNamingV1.java +++ b/internal-api/src/main/java/datadog/trace/api/naming/v1/PeerServiceNamingV1.java @@ -1,7 +1,7 @@ package datadog.trace.api.naming.v1; import datadog.trace.api.DDTags; -import datadog.trace.api.TagMap; +import datadog.trace.api.SpanStorage; import datadog.trace.api.naming.NamingSchema; import datadog.trace.bootstrap.instrumentation.api.InstrumentationTags; import datadog.trace.bootstrap.instrumentation.api.Tags; @@ -53,8 +53,8 @@ public boolean supports() { return true; } - private void resolve(@Nonnull final TagMap unsafeTags) { - final Object component = unsafeTags.getObject(Tags.COMPONENT); + private void resolve(@Nonnull final SpanStorage unsafeTags) { + final Object component = unsafeTags.load(Tags.COMPONENT); // avoid issues with UTF8ByteString or others final String componentString = component == null ? null : component.toString(); final String override = overridesByComponent.get(componentString); @@ -71,14 +71,15 @@ private void resolve(@Nonnull final TagMap unsafeTags) { resolveBy(unsafeTags, DEFAULT_PRECURSORS); } - private boolean resolveBy(@Nonnull final TagMap unsafeTags, @Nullable final String[] precursors) { + private boolean resolveBy( + @Nonnull final SpanStorage unsafeTags, @Nullable final String[] precursors) { if (precursors == null) { return false; } Object value = null; String source = null; for (String precursor : precursors) { - value = unsafeTags.getObject(precursor); + value = unsafeTags.load(precursor); if (value != null) { // we have a match. Use the tag name for the source source = precursor; @@ -90,18 +91,18 @@ private boolean resolveBy(@Nonnull final TagMap unsafeTags, @Nullable final Stri return true; } - private void set(@Nonnull final TagMap unsafeTags, Object value, String source) { + private void set(@Nonnull final SpanStorage unsafeTags, Object value, String source) { if (value != null) { - unsafeTags.put(Tags.PEER_SERVICE, value); - unsafeTags.put(DDTags.PEER_SERVICE_SOURCE, source); + unsafeTags.store(Tags.PEER_SERVICE, value); + unsafeTags.store(DDTags.PEER_SERVICE_SOURCE, source); } } @Nonnull @Override - public void tags(@Nonnull final TagMap unsafeTags) { + public void tags(@Nonnull final SpanStorage unsafeTags) { // check span.kind eligibility - final Object kind = unsafeTags.getObject(Tags.SPAN_KIND); + final Object kind = unsafeTags.load(Tags.SPAN_KIND); if (Tags.SPAN_KIND_CLIENT.equals(kind) || Tags.SPAN_KIND_PRODUCER.equals(kind)) { // we can calculate the peer service now resolve(unsafeTags); diff --git a/internal-api/src/test/java/datadog/trace/api/endpoint/EndpointResolverTest.java b/internal-api/src/test/java/datadog/trace/api/endpoint/EndpointResolverTest.java index 10d6ad5b940..eeec260b9eb 100644 --- a/internal-api/src/test/java/datadog/trace/api/endpoint/EndpointResolverTest.java +++ b/internal-api/src/test/java/datadog/trace/api/endpoint/EndpointResolverTest.java @@ -6,8 +6,7 @@ import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; -import java.util.HashMap; -import java.util.Map; +import datadog.trace.api.TagMap; import org.junit.jupiter.api.Test; import org.tabletest.junit.TableTest; @@ -47,7 +46,7 @@ void computeEndpointDelegatesToEndpointSimplifier(String input, String expected) @Test void disabledResolverReturnsNull() { EndpointResolver resolver = new EndpointResolver(false, false); - Map unsafeTags = new HashMap<>(); + TagMap unsafeTags = TagMap.create(); String result = resolver.resolveEndpoint(unsafeTags, "/users", "http://example.com/users/123"); @@ -59,7 +58,7 @@ void disabledResolverReturnsNull() { @Test void alwaysSimplifiedEndpointComputesFromUrlEvenWithValidRoute() { EndpointResolver resolver = new EndpointResolver(true, true); - Map unsafeTags = new HashMap<>(); + TagMap unsafeTags = TagMap.create(); String result = resolver.resolveEndpoint(unsafeTags, "/users", "http://example.com/users/123"); @@ -71,7 +70,7 @@ void alwaysSimplifiedEndpointComputesFromUrlEvenWithValidRoute() { @Test void usesEligibleRouteWithoutTagging() { EndpointResolver resolver = new EndpointResolver(true, false); - Map unsafeTags = new HashMap<>(); + TagMap unsafeTags = TagMap.create(); String result = resolver.resolveEndpoint(unsafeTags, "/api/v1/users", "http://example.com/users/123"); @@ -91,7 +90,7 @@ void usesEligibleRouteWithoutTagging() { void computesEndpointAndTagsWhenRouteIsIneligible( String ineligibleRoute, String url, String expectedEndpoint) { EndpointResolver resolver = new EndpointResolver(true, false); - Map unsafeTags = new HashMap<>(); + TagMap unsafeTags = TagMap.create(); String result = resolver.resolveEndpoint(unsafeTags, ineligibleRoute, url); @@ -115,7 +114,7 @@ void isAlwaysSimplifiedEndpointReturnsConfigurationValue() { @Test void realWorldScenarioServiceWithRoute() { EndpointResolver resolver = new EndpointResolver(true, false); - Map unsafeTags = new HashMap<>(); + TagMap unsafeTags = TagMap.create(); // framework provides accurate route String result = @@ -132,7 +131,7 @@ void realWorldScenarioServiceWithRoute() { @Test void realWorldScenarioProxyWithoutRoute() { EndpointResolver resolver = new EndpointResolver(true, false); - Map unsafeTags = new HashMap<>(); + TagMap unsafeTags = TagMap.create(); // no route available (tracer in proxy) String result = @@ -147,7 +146,7 @@ void realWorldScenarioProxyWithoutRoute() { @Test void realWorldScenarioBadInstrumentationWithCatchAll() { EndpointResolver resolver = new EndpointResolver(true, false); - Map unsafeTags = new HashMap<>(); + TagMap unsafeTags = TagMap.create(); // instrumentation provides unhelpful catch-all route String result = @@ -161,7 +160,7 @@ void realWorldScenarioBadInstrumentationWithCatchAll() { @Test void realWorldScenarioTestingWithAlwaysSimplified() { EndpointResolver resolver = new EndpointResolver(true, true); - Map unsafeTags = new HashMap<>(); + TagMap unsafeTags = TagMap.create(); // testing mode to compare with backend inference String result = @@ -176,7 +175,7 @@ void realWorldScenarioTestingWithAlwaysSimplified() { @Test void edgeCaseMalformedUrlReturnsDefaultEndpoint() { EndpointResolver resolver = new EndpointResolver(true, false); - Map unsafeTags = new HashMap<>(); + TagMap unsafeTags = TagMap.create(); String result = resolver.resolveEndpoint(unsafeTags, null, "not-a-url"); @@ -189,7 +188,7 @@ void edgeCaseMalformedUrlReturnsDefaultEndpoint() { @Test void edgeCaseBothRouteAndUrlMissing() { EndpointResolver resolver = new EndpointResolver(true, false); - Map unsafeTags = new HashMap<>(); + TagMap unsafeTags = TagMap.create(); String result = resolver.resolveEndpoint(unsafeTags, null, null);