Skip to content

Commit 8d2f57b

Browse files
Fix Scalatest tracing for tests that are reported asynchronously
1 parent 2d7d791 commit 8d2f57b

File tree

1 file changed

+24
-4
lines changed

1 file changed

+24
-4
lines changed

dd-java-agent/instrumentation/scalatest/src/main/java/datadog/trace/instrumentation/scalatest/ScalatestInstrumentation.java

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
11
package datadog.trace.instrumentation.scalatest;
22

3+
import static datadog.trace.agent.tooling.bytebuddy.matcher.HierarchyMatchers.implementsInterface;
34
import static datadog.trace.agent.tooling.bytebuddy.matcher.NameMatchers.named;
45
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
56
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
67

78
import com.google.auto.service.AutoService;
89
import datadog.trace.agent.tooling.Instrumenter;
910
import datadog.trace.agent.tooling.InstrumenterModule;
11+
import datadog.trace.bootstrap.CallDepthThreadLocalMap;
1012
import java.util.Set;
1113
import net.bytebuddy.asm.Advice;
14+
import net.bytebuddy.description.type.TypeDescription;
15+
import net.bytebuddy.matcher.ElementMatcher;
16+
import org.scalatest.Reporter;
1217
import org.scalatest.events.Event;
1318

1419
@AutoService(InstrumenterModule.class)
1520
public class ScalatestInstrumentation extends InstrumenterModule.CiVisibility
16-
implements Instrumenter.ForSingleType, Instrumenter.HasMethodAdvice {
21+
implements Instrumenter.ForTypeHierarchy, Instrumenter.HasMethodAdvice {
1722

1823
public ScalatestInstrumentation() {
1924
super("ci-visibility", "scalatest");
@@ -25,8 +30,13 @@ public boolean isApplicable(Set<TargetSystem> enabledSystems) {
2530
}
2631

2732
@Override
28-
public String instrumentedType() {
29-
return "org.scalatest.DispatchReporter";
33+
public String hierarchyMarkerType() {
34+
return "org.scalatest.Reporter";
35+
}
36+
37+
@Override
38+
public ElementMatcher<TypeDescription> hierarchyMatcher() {
39+
return implementsInterface(named(hierarchyMarkerType()));
3040
}
3141

3242
@Override
@@ -51,8 +61,13 @@ public void methodAdvice(MethodTransformer transformer) {
5161
public static class DispatchEventAdvice {
5262
@Advice.OnMethodEnter
5363
public static void onDispatchEvent(@Advice.Argument(value = 0) Event event) {
64+
if (CallDepthThreadLocalMap.incrementCallDepth(Reporter.class) != 0) {
65+
// nested call
66+
return;
67+
}
68+
5469
// Instead of registering our reporter using Scalatest's standard "-C" argument,
55-
// we hook into internal dispatch reporter.
70+
// we hook into internal reporter.
5671
// The reason is that Scalatest invokes registered reporters in a separate thread,
5772
// while we need to process events in the thread where they originate.
5873
// This is required because test span has to be active in the thread where
@@ -61,5 +76,10 @@ public static void onDispatchEvent(@Advice.Argument(value = 0) Event event) {
6176
// could be properly associated with it.
6277
DatadogReporter.handle(event);
6378
}
79+
80+
@Advice.OnMethodExit
81+
public static void afterDispatchEvent() {
82+
CallDepthThreadLocalMap.decrementCallDepth(Reporter.class);
83+
}
6484
}
6585
}

0 commit comments

Comments
 (0)