Assert on executor span relationships
MODIFY
dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/executors/ExecutorInstrumentationTest.groovy
dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/executors/ExecutorInstrumentationTest.groovy
@@ -134,6 +134,11 @@ class ExecutorInstrumentationTest extends Specification {
expect:
trace.size() == expectedNumberOfSpans
+ trace[0].operationName == "ScalaConcurrentTests.traceWithFutureAndCallbacks"
+ findSpan(trace, "goodFuture").context().getParentId() == trace[0].context().getSpanId()
+ findSpan(trace, "badFuture").context().getParentId() == trace[0].context().getSpanId()
+ findSpan(trace, "successCallback").context().getParentId() == trace[0].context().getSpanId()
+ findSpan(trace, "failureCallback").context().getParentId() == trace[0].context().getSpanId()
}
def "scala propagates across futures with no traces"() {
@@ -145,6 +150,8 @@ class ExecutorInstrumentationTest extends Specification {
expect:
trace.size() == expectedNumberOfSpans
+ trace[0].operationName == "ScalaConcurrentTests.tracedAcrossThreadsWithNoTrace"
+ findSpan(trace, "callback").context().getParentId() == trace[0].context().getSpanId()
}
def "scala either promise completion"() {
@@ -157,6 +164,10 @@ class ExecutorInstrumentationTest extends Specification {
expect:
testWriter.size() == 1
trace.size() == expectedNumberOfSpans
+ trace[0].operationName == "ScalaConcurrentTests.traceWithPromises"
+ findSpan(trace, "keptPromise").context().getParentId() == trace[0].context().getSpanId()
+ findSpan(trace, "keptPromise2").context().getParentId() == trace[0].context().getSpanId()
+ findSpan(trace, "brokenPromise").context().getParentId() == trace[0].context().getSpanId()
}
def "scala first completed future"() {
@@ -169,5 +180,17 @@ class ExecutorInstrumentationTest extends Specification {
expect:
testWriter.size() == 1
trace.size() == expectedNumberOfSpans
+ findSpan(trace, "timeout1").context().getParentId() == trace[0].context().getSpanId()
+ findSpan(trace, "timeout2").context().getParentId() == trace[0].context().getSpanId()
+ findSpan(trace, "timeout3").context().getParentId() == trace[0].context().getSpanId()
+ }
+
+ private DDSpan findSpan(List<DDSpan> trace, String opName) {
+ for (DDSpan span : trace) {
+ if (span.getOperationName() == opName) {
+ return span
+ }
+ }
+ return null
}
}

MODIFY
dd-java-agent-ittests/src/test/java/datadog/trace/agent/integration/executors/AsyncChild.java
dd-java-agent-ittests/src/test/java/datadog/trace/agent/integration/executors/AsyncChild.java
@@ -23,10 +23,6 @@ public class AsyncChild implements Runnable, Callable {
blockThread.set(false);
}
- public int numberOfWorkers() {
- return numberOfWorkers.get();
- }
-
@Override
public void run() {
runImpl();

MODIFY
dd-java-agent/instrumentation/java-concurrent/src/main/java/datadog/trace/instrumentation/java/concurrent/ExecutorInstrumentation.java
dd-java-agent/instrumentation/java-concurrent/src/main/java/datadog/trace/instrumentation/java/concurrent/ExecutorInstrumentation.java
@@ -266,6 +266,7 @@ public final class ExecutorInstrumentation extends Instrumenter.Configurable {
}
}
+ /** Utils for pulling DatadogWrapper out of Future instances. */
public static class ConcurrentUtils {
private static Map<Class<?>, Field> fieldCache = new ConcurrentHashMap<>();
private static String[] wrapperFields = {"runnable", "callable"};

Assert on executor span relationships