Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import datadog.trace.api.Config;
import datadog.trace.api.ConfigDefaults;
import datadog.trace.api.DDTags;
import datadog.trace.api.KnownTagCodec;
import datadog.trace.api.Pair;
import datadog.trace.api.TagMap;
import datadog.trace.api.config.GeneralConfig;
Expand All @@ -41,6 +42,7 @@
import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString;
import datadog.trace.core.DDSpanContext;
import java.net.URI;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nonnull;
Expand Down Expand Up @@ -77,9 +79,9 @@ public TagInterceptor(
boolean jeeSplitByDeployment) {
this.isServiceNameSetByUser = isServiceNameSetByUser;
this.inferredServiceName = inferredServiceName;
this.splitServiceTags = splitServiceTags;
this.splitServiceTags = withCanonicalNames(splitServiceTags);
this.ruleFlags = ruleFlags;
splitByServletContext = splitServiceTags.contains(SERVLET_CONTEXT);
splitByServletContext = this.splitServiceTags.contains(SERVLET_CONTEXT);

shouldSet404ResourceName =
ruleFlags.isEnabled(URL_AS_RESOURCE_NAME)
Expand All @@ -89,6 +91,25 @@ public TagInterceptor(
this.jeeSplitByDeployment = jeeSplitByDeployment;
}

/**
* Adds the Datadog name of each configured tag: entries set on the span builder arrive under it,
* so a tag configured by its OpenTelemetry name (e.g. {@code db.system}) would otherwise be
* missed.
*/
private static Set<String> withCanonicalNames(Set<String> tags) {
Set<String> result = null;
for (String tag : tags) {
String canonical = KnownTagCodec.canonicalTagName(tag);
if (!canonical.equals(tag) && !tags.contains(canonical)) {
if (result == null) {
result = new HashSet<>(tags);
}
result.add(canonical);
}
}
return result == null ? tags : result;
}

public boolean needsIntercept(TagMap map) {
for (TagMap.EntryReader entry : map) {
if (needsIntercept(entry.tag())) return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import static datadog.trace.bootstrap.instrumentation.api.Tags.HTTP_STATUS;
import static datadog.trace.bootstrap.instrumentation.api.Tags.HTTP_URL;
import static datadog.trace.test.junit.utils.config.WithConfigExtension.injectSysConfig;
import static java.util.Collections.emptyMap;
import static java.util.Collections.emptySet;
import static java.util.Collections.singletonMap;
import static org.junit.jupiter.api.Assertions.assertEquals;
Expand Down Expand Up @@ -48,8 +49,11 @@
import datadog.trace.test.junit.utils.config.WithConfig;
import datadog.trace.test.junit.utils.converter.ConfigDefaultsConverter;
import datadog.trace.test.junit.utils.converter.TagsConverter;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -190,15 +194,52 @@ void mappingCausesServletContextToNotChangeServiceName(String serviceName) {
assertEquals("new-service", span.getServiceName());
}

@TableTest({
"scenario | configured | tag | expectedBuilder | expectedSetter",
"configured by OTel name | db.system | db.system | split | split ",
"configured by Datadog name | db.type | db.type | split | split ",
"Datadog config, OTel tag | db.type | db.system | split | my-service ",
"OTel config, Datadog tag | db.system | db.type | split | split ",
"custom tag | custom.tag | custom.tag | split | split ",
"unconfigured tag | db.system | other.tag | my-service | my-service ",
"empty configuration | '' | db.system | my-service | my-service ",
"both names, OTel tag | db.system,db.type | db.system | split | split ",
"both names, Datadog tag | db.system,db.type | db.type | split | split ",
"custom tag survives expansion | db.system,custom.tag | custom.tag | split | split ",
"first of two renamed tags | db.system,db.operation.name | db.type | split | split ",
"second of two renamed tags | db.system,db.operation.name | db.operation | split | split "
})
void splitByTagsMatchesCanonicalAndOriginalNames(
String configured, String tag, String expectedBuilder, String expectedSetter) {
Set<String> configuredTags =
configured.isEmpty() ? emptySet() : new HashSet<>(Arrays.asList(configured.split(",")));
CoreTracer tracer = createSplittingTracer(configuredTags, emptyMap());

AgentSpan builderSpan = tracer.buildSpan("datadog", "some span").withTag(tag, "split").start();
AgentSpan setterSpan = tracer.buildSpan("datadog", "some span").start();
setterSpan.setTag(tag, "split");

assertEquals(expectedBuilder, builderSpan.getServiceName());
assertEquals(expectedSetter, setterSpan.getServiceName());

CoreTracer defaultTagTracer = createSplittingTracer(configuredTags, singletonMap(tag, "split"));
AgentSpan defaultTagSpan = defaultTagTracer.buildSpan("datadog", "some span").start();

assertEquals(expectedBuilder, defaultTagSpan.getServiceName());
}
Comment thread
bric3 marked this conversation as resolved.

private CoreTracer createSplittingTracer(String tag) {
return createSplittingTracer(Collections.singleton(tag), emptyMap());
}

private CoreTracer createSplittingTracer(Set<String> tags, Map<String, String> defaultSpanTags) {
return tracerBuilder()
.serviceName("my-service")
.writer(new LoggingWriter())
.sampler(new AllSampler())
// equivalent to split-by-tags: tag
.tagInterceptor(
new TagInterceptor(
true, "my-service", Collections.singleton(tag), new RuleFlags(), false))
.defaultSpanTags(defaultSpanTags)
// equivalent to split-by-tags: tags
.tagInterceptor(new TagInterceptor(true, "my-service", tags, new RuleFlags(), false))
.build();
}

Expand Down
Loading