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 4c404ae0a38..30d6cf8c55f 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 @@ -1018,6 +1018,9 @@ public String toString() { if (measured) { s.append(" *measured*"); } + if (topLevel) { + s.append(" *top_level*"); + } synchronized (unsafeTags) { s.append(" tags=").append(new TreeMap<>(getTags())); diff --git a/dd-trace-core/src/test/groovy/datadog/trace/core/DDSpanContextTest.groovy b/dd-trace-core/src/test/groovy/datadog/trace/core/DDSpanContextTest.groovy index 1cdaa33d668..22bc295d9b6 100644 --- a/dd-trace-core/src/test/groovy/datadog/trace/core/DDSpanContextTest.groovy +++ b/dd-trace-core/src/test/groovy/datadog/trace/core/DDSpanContextTest.groovy @@ -312,6 +312,37 @@ class DDSpanContextTest extends DDCoreSpecification { context.toString().contains("id=-") == false } + def "toString includes top_level flag"() { + setup: + def parent = tracer.buildSpan("parentOperation") + .withServiceName("parentService") + .withResourceName("parentResource") + .start() + + // Child span with different service name should be top-level + def topLevelSpan = tracer.buildSpan("childOperation") + .withServiceName("childService") + .withResourceName("childResource") + .asChildOf(parent.context()) + .start() + + // Child span with same service name should not be top-level + def nonTopLevelSpan = tracer.buildSpan("childOperation2") + .withServiceName("parentService") + .withResourceName("childResource2") + .asChildOf(parent.context()) + .start() + + def topLevelContext = topLevelSpan.context() as DDSpanContext + def nonTopLevelContext = nonTopLevelSpan.context() as DDSpanContext + + expect: + topLevelContext.isTopLevel() == true + topLevelContext.toString().contains("*top_level*") == true + nonTopLevelContext.isTopLevel() == false + nonTopLevelContext.toString().contains("*top_level*") == false + } + static void assertTagmap(Map source, Map comparison, boolean removeThread = false) { def sourceWithoutCommonTags = new HashMap(source) sourceWithoutCommonTags.remove("runtime-id")