Skip to content

Commit 3d8130d

Browse files
Support distributed traces in tests (#8078)
1 parent bdbc145 commit 3d8130d

File tree

9 files changed

+71
-85
lines changed

9 files changed

+71
-85
lines changed

dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/AbstractTestSession.java

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package datadog.trace.civisibility.domain;
22

3+
import static datadog.trace.api.TracePropagationStyle.NONE;
34
import static datadog.trace.api.civisibility.CIConstants.CI_VISIBILITY_INSTRUMENTATION_NAME;
45

56
import datadog.trace.api.Config;
@@ -17,9 +18,11 @@
1718
import datadog.trace.api.civisibility.telemetry.tag.IsHeadless;
1819
import datadog.trace.api.civisibility.telemetry.tag.IsUnsupportedCI;
1920
import datadog.trace.api.civisibility.telemetry.tag.Provider;
21+
import datadog.trace.api.sampling.PrioritySampling;
2022
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
2123
import datadog.trace.bootstrap.instrumentation.api.AgentTracer;
2224
import datadog.trace.bootstrap.instrumentation.api.InternalSpanTypes;
25+
import datadog.trace.bootstrap.instrumentation.api.TagContext;
2326
import datadog.trace.bootstrap.instrumentation.api.Tags;
2427
import datadog.trace.civisibility.codeowners.Codeowners;
2528
import datadog.trace.civisibility.decorator.TestDecorator;
@@ -65,7 +68,16 @@ public AbstractTestSession(
6568
// CI Test Cycle protocol requires session's trace ID and span ID to be the same
6669
IdGenerationStrategy idGenerationStrategy = config.getIdGenerationStrategy();
6770
DDTraceId traceId = idGenerationStrategy.generateTraceId();
68-
AgentSpan.Context traceContext = new TraceContext(traceId);
71+
AgentSpan.Context traceContext =
72+
new TagContext(
73+
CIConstants.CIAPP_TEST_ORIGIN,
74+
Collections.emptyMap(),
75+
null,
76+
null,
77+
PrioritySampling.UNSET,
78+
null,
79+
NONE,
80+
traceId);
6981

7082
AgentTracer.SpanBuilder spanBuilder =
7183
AgentTracer.get()

dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/TestImpl.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
2828
import datadog.trace.bootstrap.instrumentation.api.AgentTracer;
2929
import datadog.trace.bootstrap.instrumentation.api.InternalSpanTypes;
30+
import datadog.trace.bootstrap.instrumentation.api.TagContext;
3031
import datadog.trace.bootstrap.instrumentation.api.Tags;
3132
import datadog.trace.civisibility.codeowners.Codeowners;
3233
import datadog.trace.civisibility.decorator.TestDecorator;
@@ -35,6 +36,7 @@
3536
import datadog.trace.civisibility.source.SourceResolutionException;
3637
import java.lang.reflect.Method;
3738
import java.util.Collection;
39+
import java.util.Collections;
3840
import java.util.function.Consumer;
3941
import javax.annotation.Nullable;
4042
import org.slf4j.Logger;
@@ -85,11 +87,13 @@ public TestImpl(
8587

8688
this.context = new TestContextImpl(coverageStore);
8789

90+
AgentSpan.Context traceContext =
91+
new TagContext(CIConstants.CIAPP_TEST_ORIGIN, Collections.emptyMap());
8892
AgentTracer.SpanBuilder spanBuilder =
8993
AgentTracer.get()
9094
.buildSpan(CI_VISIBILITY_INSTRUMENTATION_NAME, testDecorator.component() + ".test")
9195
.ignoreActiveSpan()
92-
.asChildOf(null)
96+
.asChildOf(traceContext)
9397
.withRequestContextData(RequestContextSlot.CI_VISIBILITY, context);
9498

9599
if (startTime != null) {

dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/domain/TraceContext.java

-55
This file was deleted.

dd-trace-core/src/main/java/datadog/trace/civisibility/interceptor/CiVisibilityTraceInterceptor.java

+6-15
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
package datadog.trace.civisibility.interceptor;
22

3-
import datadog.trace.api.DDSpanTypes;
3+
import static datadog.trace.api.civisibility.CIConstants.CIAPP_TEST_ORIGIN;
4+
45
import datadog.trace.api.DDTags;
56
import datadog.trace.api.interceptor.AbstractTraceInterceptor;
67
import datadog.trace.api.interceptor.MutableSpan;
7-
import datadog.trace.bootstrap.instrumentation.api.UTF8BytesString;
88
import datadog.trace.core.DDSpan;
99
import datadog.trace.core.DDTraceCoreInfo;
1010
import java.util.Collection;
@@ -15,8 +15,6 @@ public class CiVisibilityTraceInterceptor extends AbstractTraceInterceptor {
1515
public static final CiVisibilityTraceInterceptor INSTANCE =
1616
new CiVisibilityTraceInterceptor(Priority.CI_VISIBILITY_TRACE);
1717

18-
static final UTF8BytesString CIAPP_TEST_ORIGIN = UTF8BytesString.create("ciapp-test");
19-
2018
protected CiVisibilityTraceInterceptor(Priority priority) {
2119
super(priority);
2220
}
@@ -33,20 +31,13 @@ public Collection<? extends MutableSpan> onTraceComplete(
3331

3432
final DDSpan spanToCheck = null == localRootSpan ? firstSpan : localRootSpan;
3533

36-
// If root span is not a CI visibility span, we drop the full trace.
37-
CharSequence type = spanToCheck.getType(); // Don't null pointer if there is no type
38-
if (type == null
39-
|| (!DDSpanTypes.TEST.contentEquals(type)
40-
&& !DDSpanTypes.TEST_SUITE_END.contentEquals(type)
41-
&& !DDSpanTypes.TEST_MODULE_END.contentEquals(type)
42-
&& !DDSpanTypes.TEST_SESSION_END.contentEquals(type))) {
34+
// If root span does not originate from CI visibility, we drop the full trace.
35+
CharSequence origin = spanToCheck.getOrigin();
36+
if (origin == null || !CIAPP_TEST_ORIGIN.contentEquals(origin)) {
4337
return Collections.emptyList();
4438
}
4539

46-
// If the trace belongs to a "test", we need to set the origin to `ciapp-test` and the
47-
// `library_version` tag for all spans.
48-
firstSpan.context().setOrigin(CIAPP_TEST_ORIGIN);
49-
firstSpan.setTag(DDTags.LIBRARY_VERSION_TAG_KEY, DDTraceCoreInfo.VERSION);
40+
// If the trace belongs to a "test", we need to set the `library_version` tag for all spans.
5041
for (MutableSpan span : trace) {
5142
span.setTag(DDTags.LIBRARY_VERSION_TAG_KEY, DDTraceCoreInfo.VERSION);
5243
}

dd-trace-core/src/main/java/datadog/trace/core/propagation/ContextInterpreter.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,8 @@ protected TagContext build() {
269269
baggage,
270270
samplingPriorityOrDefault(traceId, samplingPriority),
271271
traceConfig,
272-
style());
272+
style(),
273+
DDTraceId.ZERO);
273274
}
274275
}
275276
return null;

dd-trace-core/src/main/java/datadog/trace/core/propagation/ExtractedContext.java

+9-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,15 @@ public ExtractedContext(
4949
final PropagationTags propagationTags,
5050
final TraceConfig traceConfig,
5151
final TracePropagationStyle propagationStyle) {
52-
super(origin, tags, httpHeaders, baggage, samplingPriority, traceConfig, propagationStyle);
52+
super(
53+
origin,
54+
tags,
55+
httpHeaders,
56+
baggage,
57+
samplingPriority,
58+
traceConfig,
59+
propagationStyle,
60+
DDTraceId.ZERO);
5361
this.traceId = traceId;
5462
this.spanId = spanId;
5563
this.endToEndStartTime = endToEndStartTime;

dd-trace-core/src/test/groovy/datadog/trace/civisibility/interceptor/CiVisibilityTraceInterceptorTest.groovy

+27-7
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ package datadog.trace.civisibility.interceptor
22

33
import datadog.trace.api.DDSpanTypes
44
import datadog.trace.api.DDTags
5+
import datadog.trace.api.civisibility.CIConstants
56
import datadog.trace.common.writer.ListWriter
7+
import datadog.trace.core.DDSpanContext
68
import datadog.trace.core.test.DDCoreSpecification
79
import spock.lang.Timeout
810

@@ -16,31 +18,49 @@ class CiVisibilityTraceInterceptorTest extends DDCoreSpecification {
1618
tracer?.close()
1719
}
1820

19-
def "discard a trace that does not come from a test"() {
21+
def "discard a trace that does not come from ci app"() {
2022
tracer.addTraceInterceptor(CiVisibilityTraceInterceptor.INSTANCE)
2123
tracer.buildSpan("sample-span").start().finish()
2224

2325
expect:
2426
writer.size() == 0
2527
}
2628

27-
def "add ciapp origin and tracer version to spans of type #spanType"() {
29+
def "do not discard a trace that comes from ci app"() {
30+
tracer.addTraceInterceptor(CiVisibilityTraceInterceptor.INSTANCE)
31+
32+
def span = tracer.buildSpan("sample-span").start()
33+
((DDSpanContext) span.context()).origin = CIConstants.CIAPP_TEST_ORIGIN
34+
span.finish()
35+
36+
expect:
37+
writer.size() == 1
38+
}
39+
40+
def "add tracer version to spans of type #spanType"() {
2841
setup:
2942
tracer.addTraceInterceptor(CiVisibilityTraceInterceptor.INSTANCE)
3043

31-
tracer.buildSpan("sample-span").withSpanType(spanType).start().finish()
44+
45+
def span = tracer.buildSpan("sample-span").withSpanType(spanType).start()
46+
((DDSpanContext) span.context()).origin = CIConstants.CIAPP_TEST_ORIGIN
47+
span.finish()
3248
writer.waitForTraces(1)
3349

3450
expect:
3551
def trace = writer.firstTrace()
3652
trace.size() == 1
3753

38-
def span = trace[0]
54+
def receivedSpan = trace[0]
3955

40-
span.context().origin == CiVisibilityTraceInterceptor.CIAPP_TEST_ORIGIN
41-
span.getTag(DDTags.LIBRARY_VERSION_TAG_KEY) != null
56+
receivedSpan.getTag(DDTags.LIBRARY_VERSION_TAG_KEY) != null
4257

4358
where:
44-
spanType << [DDSpanTypes.TEST, DDSpanTypes.TEST_SUITE_END, DDSpanTypes.TEST_MODULE_END]
59+
spanType << [
60+
DDSpanTypes.TEST,
61+
DDSpanTypes.TEST_SUITE_END,
62+
DDSpanTypes.TEST_MODULE_END,
63+
DDSpanTypes.TEST_SESSION_END
64+
]
4565
}
4666
}

internal-api/src/main/java/datadog/trace/api/civisibility/CIConstants.java

+2
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,6 @@ public interface CIConstants {
1212
String CI_VISIBILITY_INSTRUMENTATION_NAME = "civisibility";
1313

1414
String FAIL_FAST_TEST_ORDER = "FAILFAST";
15+
16+
String CIAPP_TEST_ORIGIN = "ciapp-test";
1517
}

internal-api/src/main/java/datadog/trace/bootstrap/instrumentation/api/TagContext.java

+7-4
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,14 @@ public class TagContext implements AgentSpan.Context.Extracted {
3434
private final int samplingPriority;
3535
private final TraceConfig traceConfig;
3636
private final TracePropagationStyle propagationStyle;
37+
private final DDTraceId traceId;
3738

3839
public TagContext() {
3940
this(null, null);
4041
}
4142

42-
public TagContext(final String origin, final Map<String, String> tags) {
43-
this(origin, tags, null, null, PrioritySampling.UNSET, null, NONE);
43+
public TagContext(final CharSequence origin, final Map<String, String> tags) {
44+
this(origin, tags, null, null, PrioritySampling.UNSET, null, NONE, DDTraceId.ZERO);
4445
}
4546

4647
public TagContext(
@@ -50,7 +51,8 @@ public TagContext(
5051
final Map<String, String> baggage,
5152
final int samplingPriority,
5253
final TraceConfig traceConfig,
53-
final TracePropagationStyle propagationStyle) {
54+
final TracePropagationStyle propagationStyle,
55+
final DDTraceId traceId) {
5456
this.origin = origin;
5557
this.tags = tags;
5658
this.terminatedContextLinks = null;
@@ -59,6 +61,7 @@ public TagContext(
5961
this.samplingPriority = samplingPriority;
6062
this.traceConfig = traceConfig;
6163
this.propagationStyle = propagationStyle;
64+
this.traceId = traceId;
6265
}
6366

6467
public TraceConfig getTraceConfig() {
@@ -187,7 +190,7 @@ public Iterable<Map.Entry<String, String>> baggageItems() {
187190

188191
@Override
189192
public DDTraceId getTraceId() {
190-
return DDTraceId.ZERO;
193+
return traceId;
191194
}
192195

193196
@Override

0 commit comments

Comments
 (0)