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);