Split traces and add timeout to blockUntilChildSpanFinished
MODIFY
dd-java-agent/instrumentation/couchbase-2.0/src/test/groovy/springdata/CouchbaseSpringRepositoryTest.groovy
dd-java-agent/instrumentation/couchbase-2.0/src/test/groovy/springdata/CouchbaseSpringRepositoryTest.groovy
@@ -12,6 +12,9 @@ import spock.lang.Shared
import spock.lang.Unroll
import util.AbstractCouchbaseTest
+import static datadog.trace.agent.test.utils.TraceUtils.basicSpan
+import static datadog.trace.agent.test.utils.TraceUtils.runUnderTrace
+
@Unroll
class CouchbaseSpringRepositoryTest extends AbstractCouchbaseTest {
static final Closure<Doc> FIND
@@ -70,6 +73,10 @@ class CouchbaseSpringRepositoryTest extends AbstractCouchbaseTest {
TEST_WRITER.clear()
}
+ def cleanup() {
+ repo.deleteAll()
+ }
+
def "test empty repo"() {
when:
def result = repo.findAll()
@@ -85,65 +92,92 @@ class CouchbaseSpringRepositoryTest extends AbstractCouchbaseTest {
}
}
- def "test CRUD"() {
- when:
+ def "test save"() {
+ setup:
def doc = new Doc()
- then: // CREATE
- repo.save(doc) == doc
+ when:
+ def result = repo.save(doc)
- and:
+ then:
+ result == doc
assertTraces(1) {
trace(0, 1) {
assertCouchbaseCall(it, 0, "Bucket.upsert", bucketCouchbase.name())
}
}
- TEST_WRITER.clear()
+ }
- and: // RETRIEVE
- FIND(repo, "1") == doc
+ def "test save and retrieve"() {
+ setup:
+ def doc = new Doc()
+ def result
- and:
- assertTraces(1) {
- trace(0, 1) {
- assertCouchbaseCall(it, 0, "Bucket.get", bucketCouchbase.name())
+ when:
+ runUnderTrace("someTrace") {
+ repo.save(doc)
+ result = FIND(repo, "1")
+
+ blockUntilChildSpansFinished(2)
+ }
+
+ then: // RETRIEVE
+ result == doc
+ sortAndAssertTraces(1) {
+ trace(0, 3) {
+ basicSpan(it, 0, "someTrace")
+ assertCouchbaseCall(it, 2, "Bucket.upsert", bucketCouchbase.name(), span(0))
+ assertCouchbaseCall(it, 1, "Bucket.get", bucketCouchbase.name(), span(0))
+ }
}
}
- TEST_WRITER.clear()
+
+ def "test save and update"() {
+ setup:
+ def doc = new Doc()
when:
+ runUnderTrace("someTrace") {
+ repo.save(doc)
doc.data = "other data"
+ repo.save(doc)
- then: // UPDATE
- repo.save(doc) == doc
- repo.findAll().asList() == [doc]
-
- assertTraces(3) {
- trace(0, 1) {
- assertCouchbaseCall(it, 0, "Bucket.upsert", bucketCouchbase.name())
+ blockUntilChildSpansFinished(2)
}
- trace(1, 1) {
- assertCouchbaseCall(it, 0, "Bucket.query", bucketCouchbase.name())
+
+
+ then:
+ sortAndAssertTraces(1) {
+ trace(0, 3) {
+ basicSpan(it, 0, "someTrace")
+ assertCouchbaseCall(it, 1, "Bucket.upsert", bucketCouchbase.name(), span(0))
+ assertCouchbaseCall(it, 2, "Bucket.upsert", bucketCouchbase.name(), span(0))
}
- trace(2, 1) {
- assertCouchbaseCall(it, 0, "Bucket.get", bucketCouchbase.name())
}
}
- TEST_WRITER.clear()
+
+ def "save and delete"() {
+ setup:
+ def doc = new Doc()
+ def result
when: // DELETE
+ runUnderTrace("someTrace") {
+ repo.save(doc)
repo.delete("1")
+ result = repo.findAll().iterator().hasNext()
- then:
- !repo.findAll().iterator().hasNext()
-
- and:
- assertTraces(2) {
- trace(0, 1) {
- assertCouchbaseCall(it, 0, "Bucket.remove", bucketCouchbase.name())
+ blockUntilChildSpansFinished(3)
}
- trace(1, 1) {
- assertCouchbaseCall(it, 0, "Bucket.query", bucketCouchbase.name())
+
+ then:
+ assert !result
+ sortAndAssertTraces(1) {
+ trace(0, 4) {
+ basicSpan(it, 0, "someTrace")
+ assertCouchbaseCall(it, 3, "Bucket.upsert", bucketCouchbase.name(), span(0))
+ assertCouchbaseCall(it, 2, "Bucket.remove", bucketCouchbase.name(), span(0))
+ assertCouchbaseCall(it, 1, "Bucket.query", bucketCouchbase.name(), span(0))
}
}
}

MODIFY
dd-java-agent/instrumentation/couchbase-2.0/src/test/groovy/springdata/CouchbaseSpringTemplateTest.groovy
dd-java-agent/instrumentation/couchbase-2.0/src/test/groovy/springdata/CouchbaseSpringTemplateTest.groovy
@@ -10,6 +10,9 @@ import spock.lang.Shared
import spock.lang.Unroll
import util.AbstractCouchbaseTest
+import static datadog.trace.agent.test.utils.TraceUtils.basicSpan
+import static datadog.trace.agent.test.utils.TraceUtils.runUnderTrace
+
@Unroll
class CouchbaseSpringTemplateTest extends AbstractCouchbaseTest {
@@ -53,19 +56,25 @@ class CouchbaseSpringTemplateTest extends AbstractCouchbaseTest {
def "test write #name"() {
setup:
def doc = new Doc()
+ def result
when:
+ runUnderTrace("someTrace") {
template.save(doc)
- def result = template.findById("1", Doc)
+ result = template.findById("1", Doc)
+
+ blockUntilChildSpansFinished(2)
+ }
+
then:
result != null
- assertTraces(2) {
- trace(0, 1) {
- assertCouchbaseCall(it, 0, "Bucket.upsert", name)
- }
- trace(1, 1) {
- assertCouchbaseCall(it, 0, "Bucket.get", name)
+
+ sortAndAssertTraces(1) {
+ trace(0, 3) {
+ basicSpan(it, 0, "someTrace")
+ assertCouchbaseCall(it, 2, "Bucket.upsert", name, span(0))
+ assertCouchbaseCall(it, 1, "Bucket.get", name, span(0))
}
}
@@ -79,16 +88,20 @@ class CouchbaseSpringTemplateTest extends AbstractCouchbaseTest {
def doc = new Doc()
when:
+ runUnderTrace("someTrace") {
template.save(doc)
template.remove(doc)
- then:
- assertTraces(2) {
- trace(0, 1) {
- assertCouchbaseCall(it, 0, "Bucket.upsert", name)
+ blockUntilChildSpansFinished(2)
}
- trace(1, 1) {
- assertCouchbaseCall(it, 0, "Bucket.remove", name)
+
+
+ then:
+ sortAndAssertTraces(1) {
+ trace(0, 3) {
+ basicSpan(it, 0, "someTrace")
+ assertCouchbaseCall(it, 2, "Bucket.upsert", name, span(0))
+ assertCouchbaseCall(it, 1, "Bucket.remove", name, span(0))
}
}

MODIFY
dd-java-agent/instrumentation/couchbase-2.6/src/main/java/datadog/trace/instrumentation/couchbase/client/CouchbaseNetworkInstrumentation.java
dd-java-agent/instrumentation/couchbase-2.6/src/main/java/datadog/trace/instrumentation/couchbase/client/CouchbaseNetworkInstrumentation.java
@@ -68,10 +68,12 @@ public class CouchbaseNetworkInstrumentation extends Instrumenter.Default {
if (span != null) {
Tags.PEER_HOSTNAME.set(span, remoteHostname);
+ if (remoteSocket != null) {
final int splitIndex = remoteSocket.lastIndexOf(":");
if (splitIndex != -1) {
Tags.PEER_PORT.set(span, Integer.valueOf(remoteSocket.substring(splitIndex + 1)));
}
+ }
span.setTag("local.address", localSocket);
}

MODIFY
dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/AgentTestRunner.java
dd-java-agent/testing/src/main/groovy/datadog/trace/agent/test/AgentTestRunner.java
@@ -26,6 +26,7 @@ import java.util.List;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
@@ -61,6 +62,7 @@ import spock.lang.Specification;
@SpecMetadata(filename = "AgentTestRunner.java", line = 0)
@Slf4j
public abstract class AgentTestRunner extends Specification {
+ private static final long TIMEOUT_MILLIS = 10 * 1000;
/**
* For test runs, agent's global tracer will report to this list writer.
*
@@ -206,10 +208,15 @@ public abstract class AgentTestRunner extends Specification {
@SneakyThrows
public static void blockUntilChildSpansFinished(final int numberOfSpans) {
final Span span = io.opentracing.util.GlobalTracer.get().activeSpan();
+ final long deadline = System.currentTimeMillis() + TIMEOUT_MILLIS;
if (span instanceof DDSpan) {
final PendingTrace pendingTrace = ((DDSpan) span).context().getTrace();
while (pendingTrace.size() < numberOfSpans) {
+ if (System.currentTimeMillis() > deadline) {
+ throw new TimeoutException(
+ "Timed out waiting for child spans. Received: " + pendingTrace.size());
+ }
Thread.sleep(10);
}
}

MODIFY
dd-java-agent/testing/src/test/groovy/AgentTestRunnerTest.groovy
dd-java-agent/testing/src/test/groovy/AgentTestRunnerTest.groovy
@@ -10,6 +10,7 @@ import io.opentracing.Tracer
import spock.lang.Shared
import java.lang.reflect.Field
+import java.util.concurrent.TimeoutException
import static datadog.trace.agent.test.utils.TraceUtils.runUnderTrace
import static datadog.trace.api.Config.TRACE_CLASSES_EXCLUDE
@@ -67,6 +68,16 @@ class AgentTestRunnerTest extends AgentTestRunner {
bootstrapClassesIncorrectlyLoaded == []
}
+ def "waiting for child spans times out"() {
+ when:
+ runUnderTrace("parent") {
+ blockUntilChildSpansFinished(1)
+ }
+
+ then:
+ thrown(TimeoutException)
+ }
+
def "logging works"() {
when:
org.slf4j.LoggerFactory.getLogger(AgentTestRunnerTest).debug("hello")

Split traces and add timeout to blockUntilChildSpanFinished