From b2b61e0c8c97bf835bcf81c39ee540f40e4c08db Mon Sep 17 00:00:00 2001 From: Tyler Benson Date: Thu, 7 Sep 2017 15:04:29 -0700 Subject: [PATCH] Changes required for supporting OT 0.31.0 Also updates all the contrib versions that we currently depend on to their 0.31.0 supporting versions. --- README.md | 4 +- .../agent/integration/TestHttpServer.groovy | 8 +- .../httpclient/ApacheHttpClientTest.groovy | 16 +- .../servlet/JettyServletTest.groovy | 4 +- .../servlet/TomcatServletTest.groovy | 6 +- .../annotation/TraceAnnotationsTest.java | 4 +- .../MongoAsyncClientInstrumentationTest.java | 4 +- .../MongoClientInstrumentationTest.java | 4 +- .../trace/agent/test/SayTracedHello.java | 11 +- .../apachehttpclient/DDTracingClientExec.java | 74 ++-- .../instrumentation/aws-sdk/aws-sdk.gradle | 2 +- .../datastax-cassandra-3.2.gradle | 2 +- .../test/groovy/CassandraClientTest.groovy | 6 +- .../PreparedStatementInstrumentation.java | 25 +- .../jdbc/StatementInstrumentation.java | 27 +- .../JMS1MessageConsumerInstrumentation.java | 10 +- .../JMS1MessageListenerInstrumentation.java | 33 +- .../JMS1MessageProducerInstrumentation.java | 40 ++- .../JMS2MessageConsumerInstrumentation.java | 11 +- .../JMS2MessageListenerInstrumentation.java | 33 +- .../JMS2MessageProducerInstrumentation.java | 39 +- .../instrumentation/okhttp-3/okhttp-3.gradle | 2 +- .../okhttp3/OkHttp3Instrumentation.java | 5 +- .../servlet-2/servlet-2.gradle | 2 +- .../servlet2/FilterChain2Instrumentation.java | 23 +- .../servlet2/HttpServlet2Instrumentation.java | 50 ++- .../servlet-3/servlet-3.gradle | 2 +- .../servlet3/FilterChain3Instrumentation.java | 47 ++- .../servlet3/HttpServlet3Instrumentation.java | 43 ++- .../springweb/SpringWebInstrumentation.java | 8 +- .../TraceAnnotationInstrumentation.java | 16 +- .../datadog/trace/agent/test/TestUtils.java | 14 +- dd-trace-ot/docs/opentracing-api.md | 6 +- .../java/datadog/trace/DDTraceBenchmark.java | 25 +- .../java/datadog/opentracing/DDBaseSpan.java | 339 ------------------ .../main/java/datadog/opentracing/DDSpan.java | 305 +++++++++++++++- .../datadog/opentracing/DDSpanContext.java | 6 +- .../java/datadog/opentracing/DDTracer.java | 51 +-- .../resolver/DDTracerResolver.java | 2 +- .../common/sampling/AbstractSampler.java | 6 +- .../trace/common/sampling/AllSampler.java | 4 +- .../trace/common/sampling/RateSampler.java | 6 +- .../trace/common/sampling/Sampler.java | 4 +- .../trace/common/writer/DDAgentWriter.java | 14 +- .../datadog/trace/common/writer/DDApi.java | 4 +- .../trace/common/writer/ListWriter.java | 8 +- .../trace/common/writer/LoggingWriter.java | 4 +- .../datadog/trace/common/writer/Writer.java | 4 +- .../trace/ActiveSpanContinuationTest.groovy | 188 ---------- .../trace/api/writer/DDAgentWriterTest.groovy | 4 +- .../datadog/opentracing/DDTracerTest.java | 2 +- .../resolver/TracerResolverTest.java | 2 +- .../dropwizard/client/TracedClient.java | 6 +- .../resources/SimpleCrudResource.java | 14 +- .../example/restspark/SparkApplication.java | 14 +- gradle/dependencies.gradle | 2 +- 56 files changed, 702 insertions(+), 893 deletions(-) delete mode 100644 dd-trace-ot/src/main/java/datadog/opentracing/DDBaseSpan.java delete mode 100644 dd-trace-ot/src/test/groovy/datadog/trace/ActiveSpanContinuationTest.groovy diff --git a/README.md b/README.md index 262c1c590a..bf1e3da0d1 100644 --- a/README.md +++ b/README.md @@ -187,7 +187,7 @@ class InstrumentedClass { // 2. If using the Java Agent (-javaagent;/path/to/agent.jar), do not instantiate the GlobalTracer; the Agent instantiates it for you Tracer tracer = io.opentracing.util.GlobalTracer.get(); - Span span = tracer.buildSpan("operation-name").startActive(); + Span span = tracer.buildSpan("operation-name").startActive(true); span.setTag(DDTags.SERVICE_NAME, "my-new-service"); // The code you're tracing @@ -207,7 +207,7 @@ class InstrumentedClass { void method0() { Tracer tracer = io.opentracing.util.GlobalTracer.get(); - try (ActiveSpan span = tracer.buildSpan("operation-name").startActive()) { + try (ActiveSpan span = tracer.buildSpan("operation-name").startActive(true)) { span.setTag(DDTags.SERVICE_NAME, "my-new-service"); Thread.sleep(1000); } diff --git a/dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/TestHttpServer.groovy b/dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/TestHttpServer.groovy index 8428a99925..2dfbbf992f 100644 --- a/dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/TestHttpServer.groovy +++ b/dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/TestHttpServer.groovy @@ -1,6 +1,6 @@ package datadog.trace.agent.integration -import io.opentracing.ActiveSpan +import io.opentracing.Scope import io.opentracing.SpanContext import io.opentracing.propagation.Format import io.opentracing.propagation.TextMap @@ -53,12 +53,12 @@ class TestHttpServer { final SpanContext extractedContext = GlobalTracer.get() .extract(Format.Builtin.HTTP_HEADERS, new RatpackResponseAdapter(context)) - ActiveSpan span = + Scope scope = GlobalTracer.get() .buildSpan("test-http-server") .asChildOf(extractedContext) - .startActive() - span.deactivate() + .startActive(true) + scope.close() } response.status(200).send(msg) diff --git a/dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/httpclient/ApacheHttpClientTest.groovy b/dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/httpclient/ApacheHttpClientTest.groovy index a11e75ecaf..4334bfcba6 100644 --- a/dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/httpclient/ApacheHttpClientTest.groovy +++ b/dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/httpclient/ApacheHttpClientTest.groovy @@ -1,6 +1,6 @@ package datadog.trace.agent.integration.httpclient -import datadog.opentracing.DDBaseSpan +import datadog.opentracing.DDSpan import datadog.opentracing.DDTracer import datadog.trace.agent.integration.TestHttpServer import datadog.trace.agent.test.TestUtils @@ -53,18 +53,18 @@ class ApacheHttpClientTest extends Specification { expect: // one trace on the server, one trace on the client writer.size() == 2 - final List> serverTrace = writer.get(0) + final List serverTrace = writer.get(0) serverTrace.size() == 1 - final List> clientTrace = writer.get(1) + final List clientTrace = writer.get(1) clientTrace.size() == 3 clientTrace.get(0).getOperationName() == "someTrace" // our instrumentation makes 2 spans for apache-httpclient - final DDBaseSpan localSpan = clientTrace.get(1) + final DDSpan localSpan = clientTrace.get(1) localSpan.getTags()[Tags.COMPONENT.getKey()] == "apache-httpclient" localSpan.getOperationName() == "GET" - final DDBaseSpan clientSpan = clientTrace.get(2) + final DDSpan clientSpan = clientTrace.get(2) clientSpan.getOperationName() == "GET" clientSpan.getTags()[Tags.HTTP_METHOD.getKey()] == "GET" clientSpan.getTags()[Tags.HTTP_STATUS.getKey()] == 200 @@ -100,15 +100,15 @@ class ApacheHttpClientTest extends Specification { expect: // only one trace (client). writer.size() == 1 - final List> clientTrace = writer.get(0) + final List clientTrace = writer.get(0) clientTrace.size() == 3 clientTrace.get(0).getOperationName() == "someTrace" // our instrumentation makes 2 spans for apache-httpclient - final DDBaseSpan localSpan = clientTrace.get(1) + final DDSpan localSpan = clientTrace.get(1) localSpan.getTags()[Tags.COMPONENT.getKey()] == "apache-httpclient" localSpan.getOperationName() == "GET" - final DDBaseSpan clientSpan = clientTrace.get(2) + final DDSpan clientSpan = clientTrace.get(2) clientSpan.getOperationName() == "GET" clientSpan.getTags()[Tags.HTTP_METHOD.getKey()] == "GET" clientSpan.getTags()[Tags.HTTP_STATUS.getKey()] == 200 diff --git a/dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/servlet/JettyServletTest.groovy b/dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/servlet/JettyServletTest.groovy index 62d491fad4..8b5d53b282 100644 --- a/dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/servlet/JettyServletTest.groovy +++ b/dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/servlet/JettyServletTest.groovy @@ -1,6 +1,6 @@ package datadog.trace.agent.integration.servlet -import datadog.opentracing.DDBaseSpan +import datadog.opentracing.DDSpan import datadog.opentracing.DDTracer import datadog.trace.common.writer.ListWriter import io.opentracing.util.GlobalTracer @@ -43,7 +43,7 @@ class JettyServletTest extends Specification { ListWriter writer = new ListWriter() { @Override - void write(final List> trace) { + void write(final List trace) { add(trace) JettyServletTest.latch.countDown() } diff --git a/dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/servlet/TomcatServletTest.groovy b/dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/servlet/TomcatServletTest.groovy index 9b00cf603e..4f686117f8 100644 --- a/dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/servlet/TomcatServletTest.groovy +++ b/dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/servlet/TomcatServletTest.groovy @@ -45,7 +45,7 @@ class TomcatServletTest extends Specification { } appContext = tomcatServer.addWebapp("", applicationDir.getAbsolutePath()) // Speed up startup by disabling jar scanning: - appContext.getJarScanner().setJarScanFilter(new JarScanFilter(){ + appContext.getJarScanner().setJarScanFilter(new JarScanFilter() { @Override boolean check(JarScanType jarScanType, String jarName) { return false @@ -147,9 +147,9 @@ class TomcatServletTest extends Specification { span.context().tags.size() == 11 where: - path | expectedResponse + path | expectedResponse //"async" | "Hello Async" // FIXME: I can't seem get the async error handler to trigger - "sync" | "Hello Sync" + "sync" | "Hello Sync" } private static int randomOpenPort() { diff --git a/dd-java-agent-ittests/src/test/java/datadog/trace/agent/instrumentation/annotation/TraceAnnotationsTest.java b/dd-java-agent-ittests/src/test/java/datadog/trace/agent/instrumentation/annotation/TraceAnnotationsTest.java index c3415aa93d..e45d853298 100644 --- a/dd-java-agent-ittests/src/test/java/datadog/trace/agent/instrumentation/annotation/TraceAnnotationsTest.java +++ b/dd-java-agent-ittests/src/test/java/datadog/trace/agent/instrumentation/annotation/TraceAnnotationsTest.java @@ -2,7 +2,7 @@ package datadog.trace.agent.instrumentation.annotation; import static org.assertj.core.api.Assertions.assertThat; -import datadog.opentracing.DDBaseSpan; +import datadog.opentracing.DDSpan; import datadog.opentracing.DDTracer; import datadog.opentracing.decorators.ErrorFlag; import datadog.trace.agent.test.SayTracedHello; @@ -73,7 +73,7 @@ public class TraceAnnotationsTest { final StringWriter errorString = new StringWriter(); error.printStackTrace(new PrintWriter(errorString)); - final DDBaseSpan span = writer.firstTrace().get(0); + final DDSpan span = writer.firstTrace().get(0); assertThat(span.getOperationName()).isEqualTo("ERROR"); assertThat(span.getTags().get("error")).isEqualTo(true); assertThat(span.getTags().get("error.msg")).isEqualTo(error.getMessage()); diff --git a/dd-java-agent-ittests/src/test/java/datadog/trace/agent/integration/MongoAsyncClientInstrumentationTest.java b/dd-java-agent-ittests/src/test/java/datadog/trace/agent/integration/MongoAsyncClientInstrumentationTest.java index 8928af993a..b29bf6f555 100644 --- a/dd-java-agent-ittests/src/test/java/datadog/trace/agent/integration/MongoAsyncClientInstrumentationTest.java +++ b/dd-java-agent-ittests/src/test/java/datadog/trace/agent/integration/MongoAsyncClientInstrumentationTest.java @@ -8,7 +8,7 @@ import com.mongodb.async.SingleResultCallback; import com.mongodb.async.client.MongoClient; import com.mongodb.async.client.MongoClients; import com.mongodb.async.client.MongoDatabase; -import datadog.opentracing.DDBaseSpan; +import datadog.opentracing.DDSpan; import datadog.opentracing.DDTracer; import datadog.trace.agent.test.TestUtils; import datadog.trace.common.writer.ListWriter; @@ -103,7 +103,7 @@ public class MongoAsyncClientInstrumentationTest { final String createCollectionQuery = "{ \"create\" : \"asyncCollection\", \"autoIndexId\" : \"?\", \"capped\" : \"?\" }"; - final DDBaseSpan trace0 = writer.get(0).get(0); + final DDSpan trace0 = writer.get(0).get(0); Assert.assertEquals("mongo.query", trace0.getOperationName()); Assert.assertEquals(createCollectionQuery, trace0.getResourceName()); Assert.assertEquals("mongodb", trace0.getType()); diff --git a/dd-java-agent-ittests/src/test/java/datadog/trace/agent/integration/MongoClientInstrumentationTest.java b/dd-java-agent-ittests/src/test/java/datadog/trace/agent/integration/MongoClientInstrumentationTest.java index 79db3a7e51..5e083f6fdf 100644 --- a/dd-java-agent-ittests/src/test/java/datadog/trace/agent/integration/MongoClientInstrumentationTest.java +++ b/dd-java-agent-ittests/src/test/java/datadog/trace/agent/integration/MongoClientInstrumentationTest.java @@ -3,7 +3,7 @@ package datadog.trace.agent.integration; import com.mongodb.MongoClient; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; -import datadog.opentracing.DDBaseSpan; +import datadog.opentracing.DDSpan; import datadog.opentracing.DDTracer; import datadog.trace.agent.test.TestUtils; import datadog.trace.common.writer.ListWriter; @@ -100,7 +100,7 @@ public class MongoClientInstrumentationTest { final String createCollectionQuery = "{ \"create\" : \"testCollection\", \"autoIndexId\" : \"?\", \"capped\" : \"?\" }"; - final DDBaseSpan trace0 = writer.get(0).get(0); + final DDSpan trace0 = writer.get(0).get(0); Assert.assertEquals("mongo.query", trace0.getOperationName()); Assert.assertEquals(createCollectionQuery, trace0.getResourceName()); Assert.assertEquals("mongodb", trace0.getType()); diff --git a/dd-java-agent-ittests/src/test/java/datadog/trace/agent/test/SayTracedHello.java b/dd-java-agent-ittests/src/test/java/datadog/trace/agent/test/SayTracedHello.java index 07df563ce2..4680d21449 100644 --- a/dd-java-agent-ittests/src/test/java/datadog/trace/agent/test/SayTracedHello.java +++ b/dd-java-agent-ittests/src/test/java/datadog/trace/agent/test/SayTracedHello.java @@ -9,20 +9,23 @@ public class SayTracedHello { @Trace public static String sayHello() { - new StringTag(DDTags.SERVICE_NAME).set(GlobalTracer.get().activeSpan(), "test"); + new StringTag(DDTags.SERVICE_NAME) + .set(GlobalTracer.get().scopeManager().active().span(), "test"); return "hello!"; } @Trace(operationName = "SAY_HA") public static String sayHA() { - new StringTag(DDTags.SERVICE_NAME).set(GlobalTracer.get().activeSpan(), "test"); - new StringTag(DDTags.SPAN_TYPE).set(GlobalTracer.get().activeSpan(), "DB"); + new StringTag(DDTags.SERVICE_NAME) + .set(GlobalTracer.get().scopeManager().active().span(), "test"); + new StringTag(DDTags.SPAN_TYPE).set(GlobalTracer.get().scopeManager().active().span(), "DB"); return "HA!!"; } @Trace(operationName = "NEW_TRACE") public static String sayHELLOsayHA() { - new StringTag(DDTags.SERVICE_NAME).set(GlobalTracer.get().activeSpan(), "test2"); + new StringTag(DDTags.SERVICE_NAME) + .set(GlobalTracer.get().scopeManager().active().span(), "test2"); return sayHello() + sayHA(); } diff --git a/dd-java-agent/instrumentation/apache-httpclient-4.3/src/main/java/datadog/trace/instrumentation/apachehttpclient/DDTracingClientExec.java b/dd-java-agent/instrumentation/apache-httpclient-4.3/src/main/java/datadog/trace/instrumentation/apachehttpclient/DDTracingClientExec.java index 5675856701..f763b20c18 100644 --- a/dd-java-agent/instrumentation/apache-httpclient-4.3/src/main/java/datadog/trace/instrumentation/apachehttpclient/DDTracingClientExec.java +++ b/dd-java-agent/instrumentation/apache-httpclient-4.3/src/main/java/datadog/trace/instrumentation/apachehttpclient/DDTracingClientExec.java @@ -1,6 +1,7 @@ package datadog.trace.instrumentation.apachehttpclient; -import io.opentracing.ActiveSpan; +import io.opentracing.Scope; +import io.opentracing.Span; import io.opentracing.Tracer; import io.opentracing.propagation.Format; import io.opentracing.propagation.TextMap; @@ -48,10 +49,10 @@ public class DDTracingClientExec implements ClientExecChain { private final Tracer tracer; public DDTracingClientExec( - ClientExecChain clientExecChain, - RedirectStrategy redirectStrategy, - boolean redirectHandlingDisabled, - Tracer tracer) { + final ClientExecChain clientExecChain, + final RedirectStrategy redirectStrategy, + final boolean redirectHandlingDisabled, + final Tracer tracer) { this.requestExecutor = clientExecChain; this.redirectStrategy = redirectStrategy; this.redirectHandlingDisabled = redirectHandlingDisabled; @@ -60,30 +61,30 @@ public class DDTracingClientExec implements ClientExecChain { @Override public CloseableHttpResponse execute( - HttpRoute route, - HttpRequestWrapper request, - HttpClientContext clientContext, - HttpExecutionAware execAware) + final HttpRoute route, + final HttpRequestWrapper request, + final HttpClientContext clientContext, + final HttpExecutionAware execAware) throws IOException, HttpException { - ActiveSpan localSpan = clientContext.getAttribute(ACTIVE_SPAN, ActiveSpan.class); + Scope localScope = clientContext.getAttribute(ACTIVE_SPAN, Scope.class); CloseableHttpResponse response = null; try { - if (localSpan == null) { - localSpan = createLocalSpan(request, clientContext); + if (localScope == null) { + localScope = createLocalScope(request, clientContext); } - return (response = createNetworkSpan(localSpan, route, request, clientContext, execAware)); - } catch (Exception e) { - localSpan.deactivate(); + return (response = createNetworkSpan(localScope, route, request, clientContext, execAware)); + } catch (final Exception e) { + localScope.close(); throw e; } finally { if (response != null) { /** * This exec runs after {@link org.apache.http.impl.execchain.RedirectExec} which loops * until there is no redirect or reaches max redirect count. {@link RedirectStrategy} is - * used to decide whether localSpan should be finished or not. If there is a redirect - * localSpan is not finished and redirect is logged. + * used to decide whether localScope should be finished or not. If there is a redirect + * localScope is not finished and redirect is logged. */ Integer redirectCount = clientContext.getAttribute(REDIRECT_COUNT, Integer.class); if (!redirectHandlingDisabled @@ -92,37 +93,40 @@ public class DDTracingClientExec implements ClientExecChain { && ++redirectCount < clientContext.getRequestConfig().getMaxRedirects()) { clientContext.setAttribute(REDIRECT_COUNT, redirectCount); } else { - localSpan.deactivate(); + localScope.close(); } } } } - private ActiveSpan createLocalSpan(HttpRequest httpRequest, HttpClientContext clientContext) { - Tracer.SpanBuilder spanBuilder = + private Scope createLocalScope( + final HttpRequest httpRequest, final HttpClientContext clientContext) { + final Tracer.SpanBuilder spanBuilder = tracer .buildSpan(httpRequest.getRequestLine().getMethod()) .withTag(Tags.COMPONENT.getKey(), COMPONENT_NAME); - ActiveSpan localSpan = spanBuilder.startActive(); - clientContext.setAttribute(ACTIVE_SPAN, localSpan); + final Scope scope = spanBuilder.startActive(true); + clientContext.setAttribute(ACTIVE_SPAN, scope); clientContext.setAttribute(REDIRECT_COUNT, 0); - return localSpan; + return scope; } private CloseableHttpResponse createNetworkSpan( - ActiveSpan parentSpan, - HttpRoute route, - HttpRequestWrapper request, - HttpClientContext clientContext, - HttpExecutionAware execAware) + final Scope parentScope, + final HttpRoute route, + final HttpRequestWrapper request, + final HttpClientContext clientContext, + final HttpExecutionAware execAware) throws IOException, HttpException { - ActiveSpan networkSpan = + final Scope networkScope = tracer .buildSpan(request.getMethod()) .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT) - .asChildOf(parentSpan) - .startActive(); + .asChildOf(parentScope.span()) + .startActive(true); + + final Span networkSpan = networkScope.span(); tracer.inject( networkSpan.context(), Format.Builtin.HTTP_HEADERS, new HttpHeadersInjectAdapter(request)); @@ -148,20 +152,20 @@ public class DDTracingClientExec implements ClientExecChain { throw e; } finally { - networkSpan.deactivate(); + networkScope.close(); } } public static class HttpHeadersInjectAdapter implements TextMap { - private HttpRequest httpRequest; + private final HttpRequest httpRequest; - public HttpHeadersInjectAdapter(HttpRequest httpRequest) { + public HttpHeadersInjectAdapter(final HttpRequest httpRequest) { this.httpRequest = httpRequest; } @Override - public void put(String key, String value) { + public void put(final String key, final String value) { httpRequest.addHeader(key, value); } diff --git a/dd-java-agent/instrumentation/aws-sdk/aws-sdk.gradle b/dd-java-agent/instrumentation/aws-sdk/aws-sdk.gradle index 5ed377a2fe..02fd22e88d 100644 --- a/dd-java-agent/instrumentation/aws-sdk/aws-sdk.gradle +++ b/dd-java-agent/instrumentation/aws-sdk/aws-sdk.gradle @@ -17,7 +17,7 @@ apply from: "${rootDir}/gradle/java.gradle" dependencies { compileOnly group: 'com.amazonaws', name: 'aws-java-sdk-core', version: '1.11.119' - compile('io.opentracing.contrib:opentracing-aws-sdk:0.0.2') { + compile('io.opentracing.contrib:opentracing-aws-sdk:0.0.3-RC1') { transitive = false } diff --git a/dd-java-agent/instrumentation/datastax-cassandra-3.2/datastax-cassandra-3.2.gradle b/dd-java-agent/instrumentation/datastax-cassandra-3.2/datastax-cassandra-3.2.gradle index f5407792e3..55617fbefd 100644 --- a/dd-java-agent/instrumentation/datastax-cassandra-3.2/datastax-cassandra-3.2.gradle +++ b/dd-java-agent/instrumentation/datastax-cassandra-3.2/datastax-cassandra-3.2.gradle @@ -33,7 +33,7 @@ apply from: "${rootDir}/gradle/java.gradle" dependencies { compileOnly group: 'com.datastax.cassandra', name: 'cassandra-driver-core', version: '3.2.0' - compile('io.opentracing.contrib:opentracing-cassandra-driver:0.0.2') { + compile('io.opentracing.contrib:opentracing-cassandra-driver:0.0.3-RC1') { transitive = false } diff --git a/dd-java-agent/instrumentation/datastax-cassandra-3.2/src/test/groovy/CassandraClientTest.groovy b/dd-java-agent/instrumentation/datastax-cassandra-3.2/src/test/groovy/CassandraClientTest.groovy index 186684990f..178046d80d 100644 --- a/dd-java-agent/instrumentation/datastax-cassandra-3.2/src/test/groovy/CassandraClientTest.groovy +++ b/dd-java-agent/instrumentation/datastax-cassandra-3.2/src/test/groovy/CassandraClientTest.groovy @@ -1,6 +1,6 @@ import com.datastax.driver.core.Cluster import com.datastax.driver.core.Session -import datadog.opentracing.DDBaseSpan +import datadog.opentracing.DDSpan import datadog.opentracing.DDTracer import datadog.trace.agent.test.AgentTestRunner import io.opentracing.tag.Tags @@ -31,7 +31,7 @@ class CassandraClientTest extends AgentTestRunner { expect: session.getClass().getName().endsWith("contrib.cassandra.TracingSession") TEST_WRITER.size() == 5 - final DDBaseSpan selectTrace = TEST_WRITER.get(TEST_WRITER.size() - 1).get(0) + final DDSpan selectTrace = TEST_WRITER.get(TEST_WRITER.size() - 1).get(0) selectTrace.getServiceName() == DDTracer.UNASSIGNED_DEFAULT_SERVICE_NAME selectTrace.getOperationName() == "execute" @@ -67,7 +67,7 @@ class CassandraClientTest extends AgentTestRunner { expect: session.getClass().getName().endsWith("contrib.cassandra.TracingSession") - final DDBaseSpan selectTrace = TEST_WRITER.get(TEST_WRITER.size() - 1).get(0) + final DDSpan selectTrace = TEST_WRITER.get(TEST_WRITER.size() - 1).get(0) selectTrace.getServiceName() == DDTracer.UNASSIGNED_DEFAULT_SERVICE_NAME selectTrace.getOperationName() == "execute" diff --git a/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/PreparedStatementInstrumentation.java b/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/PreparedStatementInstrumentation.java index c3a8dd5308..c0444590a1 100644 --- a/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/PreparedStatementInstrumentation.java +++ b/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/PreparedStatementInstrumentation.java @@ -12,8 +12,9 @@ import com.google.auto.service.AutoService; import datadog.trace.agent.tooling.DDAdvice; import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.api.DDTags; -import io.opentracing.ActiveSpan; -import io.opentracing.NoopActiveSpanSource; +import io.opentracing.Scope; +import io.opentracing.Span; +import io.opentracing.noop.NoopScopeManager; import io.opentracing.tag.Tags; import io.opentracing.util.GlobalTracer; import java.sql.Connection; @@ -41,14 +42,14 @@ public final class PreparedStatementInstrumentation implements Instrumenter { public static class PreparedStatementAdvice { @Advice.OnMethodEnter(suppress = Throwable.class) - public static ActiveSpan startSpan(@Advice.This final PreparedStatement statement) { + public static Scope startSpan(@Advice.This final PreparedStatement statement) { final String sql = ConnectionInstrumentation.preparedStatements.get(statement); final Connection connection; try { connection = statement.getConnection(); } catch (final Throwable e) { // Had some problem getting the connection. - return NoopActiveSpanSource.NoopActiveSpan.INSTANCE; + return NoopScopeManager.NoopScope.INSTANCE; } ConnectionInstrumentation.DBInfo dbInfo = @@ -56,9 +57,10 @@ public final class PreparedStatementInstrumentation implements Instrumenter { if (dbInfo == null) { dbInfo = ConnectionInstrumentation.DBInfo.UNKNOWN; } + final Scope scope = + GlobalTracer.get().buildSpan(dbInfo.getType() + ".query").startActive(true); - final ActiveSpan span = - GlobalTracer.get().buildSpan(dbInfo.getType() + ".query").startActive(); + final Span span = scope.span(); Tags.DB_TYPE.set(span, dbInfo.getType()); Tags.SPAN_KIND.set(span, Tags.SPAN_KIND_CLIENT); Tags.COMPONENT.set(span, "java-jdbc-prepared_statement"); @@ -72,17 +74,18 @@ public final class PreparedStatementInstrumentation implements Instrumenter { if (dbInfo.getUser() != null) { Tags.DB_USER.set(span, dbInfo.getUser()); } - return span; + return scope; } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) public static void stopSpan( - @Advice.Enter final ActiveSpan activeSpan, @Advice.Thrown final Throwable throwable) { + @Advice.Enter final Scope scope, @Advice.Thrown final Throwable throwable) { if (throwable != null) { - Tags.ERROR.set(activeSpan, true); - activeSpan.log(Collections.singletonMap("error.object", throwable)); + final Span span = scope.span(); + Tags.ERROR.set(span, true); + span.log(Collections.singletonMap("error.object", throwable)); } - activeSpan.deactivate(); + scope.close(); } } } diff --git a/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/StatementInstrumentation.java b/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/StatementInstrumentation.java index d3c3760fee..471fc346b0 100644 --- a/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/StatementInstrumentation.java +++ b/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/StatementInstrumentation.java @@ -12,8 +12,9 @@ import com.google.auto.service.AutoService; import datadog.trace.agent.tooling.DDAdvice; import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.api.DDTags; -import io.opentracing.ActiveSpan; -import io.opentracing.NoopActiveSpanSource; +import io.opentracing.Scope; +import io.opentracing.Span; +import io.opentracing.noop.NoopScopeManager; import io.opentracing.tag.Tags; import io.opentracing.util.GlobalTracer; import java.sql.Connection; @@ -40,14 +41,14 @@ public final class StatementInstrumentation implements Instrumenter { public static class StatementAdvice { @Advice.OnMethodEnter(suppress = Throwable.class) - public static ActiveSpan startSpan( + public static Scope startSpan( @Advice.Argument(0) final String sql, @Advice.This final Statement statement) { final Connection connection; try { connection = statement.getConnection(); } catch (final Throwable e) { // Had some problem getting the connection. - return NoopActiveSpanSource.NoopActiveSpan.INSTANCE; + return NoopScopeManager.NoopScope.INSTANCE; } ConnectionInstrumentation.DBInfo dbInfo = @@ -56,8 +57,11 @@ public final class StatementInstrumentation implements Instrumenter { dbInfo = ConnectionInstrumentation.DBInfo.UNKNOWN; } - final ActiveSpan span = - GlobalTracer.get().buildSpan(dbInfo.getType() + ".query").startActive(); + final Scope scope = + GlobalTracer.get().buildSpan(dbInfo.getType() + ".query").startActive(true); + + final Span span = scope.span(); + Tags.DB_TYPE.set(span, dbInfo.getType()); Tags.SPAN_KIND.set(span, Tags.SPAN_KIND_CLIENT); Tags.COMPONENT.set(span, "java-jdbc-statement"); @@ -71,17 +75,18 @@ public final class StatementInstrumentation implements Instrumenter { if (dbInfo.getUser() != null) { Tags.DB_USER.set(span, dbInfo.getUser()); } - return span; + return scope; } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) public static void stopSpan( - @Advice.Enter final ActiveSpan activeSpan, @Advice.Thrown final Throwable throwable) { + @Advice.Enter final Scope scope, @Advice.Thrown final Throwable throwable) { if (throwable != null) { - Tags.ERROR.set(activeSpan, true); - activeSpan.log(Collections.singletonMap("error.object", throwable)); + final Span span = scope.span(); + Tags.ERROR.set(span, true); + span.log(Collections.singletonMap("error.object", throwable)); } - activeSpan.deactivate(); + scope.close(); } } } diff --git a/dd-java-agent/instrumentation/jms-1/src/main/java/datadog/trace/instrumentation/jms1/JMS1MessageConsumerInstrumentation.java b/dd-java-agent/instrumentation/jms-1/src/main/java/datadog/trace/instrumentation/jms1/JMS1MessageConsumerInstrumentation.java index 684ae3ff17..a9d07e8671 100644 --- a/dd-java-agent/instrumentation/jms-1/src/main/java/datadog/trace/instrumentation/jms1/JMS1MessageConsumerInstrumentation.java +++ b/dd-java-agent/instrumentation/jms-1/src/main/java/datadog/trace/instrumentation/jms1/JMS1MessageConsumerInstrumentation.java @@ -15,7 +15,8 @@ import datadog.trace.agent.tooling.HelperInjector; import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.api.DDTags; import datadog.trace.instrumentation.jms.util.MessagePropertyTextMap; -import io.opentracing.ActiveSpan; +import io.opentracing.Scope; +import io.opentracing.Span; import io.opentracing.SpanContext; import io.opentracing.propagation.Format; import io.opentracing.tag.Tags; @@ -69,7 +70,7 @@ public final class JMS1MessageConsumerInstrumentation implements Instrumenter { final SpanContext extractedContext = GlobalTracer.get().extract(Format.Builtin.TEXT_MAP, new MessagePropertyTextMap(message)); - final ActiveSpan span = + final Scope scope = GlobalTracer.get() .buildSpan("jms.consume") .asChildOf(extractedContext) @@ -78,14 +79,15 @@ public final class JMS1MessageConsumerInstrumentation implements Instrumenter { .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CONSUMER) .withTag("span.origin.type", consumer.getClass().getName()) .withStartTimestamp(TimeUnit.MILLISECONDS.toMicros(startTime)) - .startActive(); + .startActive(true); + final Span span = scope.span(); if (throwable != null) { Tags.ERROR.set(span, Boolean.TRUE); span.log(Collections.singletonMap("error.object", throwable)); } span.setTag(DDTags.RESOURCE_NAME, "Consumed from " + toResourceName(message, null)); - span.deactivate(); + scope.close(); } } } diff --git a/dd-java-agent/instrumentation/jms-1/src/main/java/datadog/trace/instrumentation/jms1/JMS1MessageListenerInstrumentation.java b/dd-java-agent/instrumentation/jms-1/src/main/java/datadog/trace/instrumentation/jms1/JMS1MessageListenerInstrumentation.java index c788a56634..36a0779826 100644 --- a/dd-java-agent/instrumentation/jms-1/src/main/java/datadog/trace/instrumentation/jms1/JMS1MessageListenerInstrumentation.java +++ b/dd-java-agent/instrumentation/jms-1/src/main/java/datadog/trace/instrumentation/jms1/JMS1MessageListenerInstrumentation.java @@ -14,7 +14,8 @@ import datadog.trace.agent.tooling.DDAdvice; import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.api.DDTags; import datadog.trace.instrumentation.jms.util.MessagePropertyTextMap; -import io.opentracing.ActiveSpan; +import io.opentracing.Scope; +import io.opentracing.Span; import io.opentracing.SpanContext; import io.opentracing.propagation.Format; import io.opentracing.tag.Tags; @@ -48,36 +49,34 @@ public final class JMS1MessageListenerInstrumentation implements Instrumenter { public static class MessageListenerAdvice { @Advice.OnMethodEnter(suppress = Throwable.class) - public static ActiveSpan startSpan( + public static Scope startSpan( @Advice.Argument(0) final Message message, @Advice.This final MessageListener listener) { final SpanContext extractedContext = GlobalTracer.get().extract(Format.Builtin.TEXT_MAP, new MessagePropertyTextMap(message)); - final ActiveSpan span = - GlobalTracer.get() - .buildSpan("jms.onMessage") - .asChildOf(extractedContext) - .withTag(DDTags.SERVICE_NAME, "jms") - .withTag(DDTags.RESOURCE_NAME, "Received from " + toResourceName(message, null)) - .withTag(Tags.COMPONENT.getKey(), "jms1") - .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CONSUMER) - .withTag("span.origin.type", listener.getClass().getName()) - .startActive(); - - return span; + return GlobalTracer.get() + .buildSpan("jms.onMessage") + .asChildOf(extractedContext) + .withTag(DDTags.SERVICE_NAME, "jms") + .withTag(DDTags.RESOURCE_NAME, "Received from " + toResourceName(message, null)) + .withTag(Tags.COMPONENT.getKey(), "jms1") + .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CONSUMER) + .withTag("span.origin.type", listener.getClass().getName()) + .startActive(true); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) public static void stopSpan( - @Advice.Enter final ActiveSpan span, @Advice.Thrown final Throwable throwable) { + @Advice.Enter final Scope scope, @Advice.Thrown final Throwable throwable) { - if (span != null) { + if (scope != null) { if (throwable != null) { + final Span span = scope.span(); Tags.ERROR.set(span, Boolean.TRUE); span.log(Collections.singletonMap("error.object", throwable)); } - span.deactivate(); + scope.close(); } } } diff --git a/dd-java-agent/instrumentation/jms-1/src/main/java/datadog/trace/instrumentation/jms1/JMS1MessageProducerInstrumentation.java b/dd-java-agent/instrumentation/jms-1/src/main/java/datadog/trace/instrumentation/jms1/JMS1MessageProducerInstrumentation.java index 7121a362f5..21e8ecf599 100644 --- a/dd-java-agent/instrumentation/jms-1/src/main/java/datadog/trace/instrumentation/jms1/JMS1MessageProducerInstrumentation.java +++ b/dd-java-agent/instrumentation/jms-1/src/main/java/datadog/trace/instrumentation/jms1/JMS1MessageProducerInstrumentation.java @@ -14,7 +14,8 @@ import datadog.trace.agent.tooling.DDAdvice; import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.api.DDTags; import datadog.trace.instrumentation.jms.util.MessagePropertyTextMap; -import io.opentracing.ActiveSpan; +import io.opentracing.Scope; +import io.opentracing.Span; import io.opentracing.propagation.Format; import io.opentracing.tag.Tags; import io.opentracing.util.GlobalTracer; @@ -53,7 +54,7 @@ public final class JMS1MessageProducerInstrumentation implements Instrumenter { public static class ProducerAdvice { @Advice.OnMethodEnter(suppress = Throwable.class) - public static ActiveSpan startSpan( + public static Scope startSpan( @Advice.Argument(0) final Message message, @Advice.This final MessageProducer producer) { Destination defaultDestination; try { @@ -61,7 +62,7 @@ public final class JMS1MessageProducerInstrumentation implements Instrumenter { } catch (final JMSException e) { defaultDestination = null; } - final ActiveSpan span = + final Scope scope = GlobalTracer.get() .buildSpan("jms.produce") .withTag(DDTags.SERVICE_NAME, "jms") @@ -71,24 +72,26 @@ public final class JMS1MessageProducerInstrumentation implements Instrumenter { .withTag(Tags.COMPONENT.getKey(), "jms1") .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_PRODUCER) .withTag("span.origin.type", producer.getClass().getName()) - .startActive(); + .startActive(true); GlobalTracer.get() - .inject(span.context(), Format.Builtin.TEXT_MAP, new MessagePropertyTextMap(message)); + .inject( + scope.span().context(), Format.Builtin.TEXT_MAP, new MessagePropertyTextMap(message)); - return span; + return scope; } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) public static void stopSpan( - @Advice.Enter final ActiveSpan span, @Advice.Thrown final Throwable throwable) { + @Advice.Enter final Scope scope, @Advice.Thrown final Throwable throwable) { - if (span != null) { + if (scope != null) { if (throwable != null) { + final Span span = scope.span(); Tags.ERROR.set(span, Boolean.TRUE); span.log(Collections.singletonMap("error.object", throwable)); } - span.deactivate(); + scope.close(); } } } @@ -96,11 +99,11 @@ public final class JMS1MessageProducerInstrumentation implements Instrumenter { public static class ProducerWithDestinationAdvice { @Advice.OnMethodEnter(suppress = Throwable.class) - public static ActiveSpan startSpan( + public static Scope startSpan( @Advice.Argument(0) final Destination destination, @Advice.Argument(1) final Message message, @Advice.This final MessageProducer producer) { - final ActiveSpan span = + final Scope scope = GlobalTracer.get() .buildSpan("jms.produce") .withTag(DDTags.SERVICE_NAME, "jms") @@ -108,23 +111,26 @@ public final class JMS1MessageProducerInstrumentation implements Instrumenter { .withTag(Tags.COMPONENT.getKey(), "jms1") .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_PRODUCER) .withTag("span.origin.type", producer.getClass().getName()) - .startActive(); + .startActive(true); GlobalTracer.get() - .inject(span.context(), Format.Builtin.TEXT_MAP, new MessagePropertyTextMap(message)); - return span; + .inject( + scope.span().context(), Format.Builtin.TEXT_MAP, new MessagePropertyTextMap(message)); + + return scope; } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) public static void stopSpan( - @Advice.Enter final ActiveSpan span, @Advice.Thrown final Throwable throwable) { + @Advice.Enter final Scope scope, @Advice.Thrown final Throwable throwable) { - if (span != null) { + if (scope != null) { if (throwable != null) { + final Span span = scope.span(); Tags.ERROR.set(span, Boolean.TRUE); span.log(Collections.singletonMap("error.object", throwable)); } - span.deactivate(); + scope.close(); } } } diff --git a/dd-java-agent/instrumentation/jms-2/src/main/java/datadog/trace/instrumentation/jms2/JMS2MessageConsumerInstrumentation.java b/dd-java-agent/instrumentation/jms-2/src/main/java/datadog/trace/instrumentation/jms2/JMS2MessageConsumerInstrumentation.java index 2ef79e1232..f218070aac 100644 --- a/dd-java-agent/instrumentation/jms-2/src/main/java/datadog/trace/instrumentation/jms2/JMS2MessageConsumerInstrumentation.java +++ b/dd-java-agent/instrumentation/jms-2/src/main/java/datadog/trace/instrumentation/jms2/JMS2MessageConsumerInstrumentation.java @@ -15,7 +15,8 @@ import datadog.trace.agent.tooling.HelperInjector; import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.api.DDTags; import datadog.trace.instrumentation.jms.util.MessagePropertyTextMap; -import io.opentracing.ActiveSpan; +import io.opentracing.Scope; +import io.opentracing.Span; import io.opentracing.SpanContext; import io.opentracing.propagation.Format; import io.opentracing.tag.Tags; @@ -69,7 +70,7 @@ public final class JMS2MessageConsumerInstrumentation implements Instrumenter { final SpanContext extractedContext = GlobalTracer.get().extract(Format.Builtin.TEXT_MAP, new MessagePropertyTextMap(message)); - final ActiveSpan span = + final Scope scope = GlobalTracer.get() .buildSpan("jms.consume") .asChildOf(extractedContext) @@ -78,14 +79,16 @@ public final class JMS2MessageConsumerInstrumentation implements Instrumenter { .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CONSUMER) .withTag("span.origin.type", consumer.getClass().getName()) .withStartTimestamp(TimeUnit.MILLISECONDS.toMicros(startTime)) - .startActive(); + .startActive(true); + + final Span span = scope.span(); if (throwable != null) { Tags.ERROR.set(span, Boolean.TRUE); span.log(Collections.singletonMap("error.object", throwable)); } span.setTag(DDTags.RESOURCE_NAME, "Consumed from " + toResourceName(message, null)); - span.deactivate(); + scope.close(); } } } diff --git a/dd-java-agent/instrumentation/jms-2/src/main/java/datadog/trace/instrumentation/jms2/JMS2MessageListenerInstrumentation.java b/dd-java-agent/instrumentation/jms-2/src/main/java/datadog/trace/instrumentation/jms2/JMS2MessageListenerInstrumentation.java index 40245abdab..777f6d79d2 100644 --- a/dd-java-agent/instrumentation/jms-2/src/main/java/datadog/trace/instrumentation/jms2/JMS2MessageListenerInstrumentation.java +++ b/dd-java-agent/instrumentation/jms-2/src/main/java/datadog/trace/instrumentation/jms2/JMS2MessageListenerInstrumentation.java @@ -14,7 +14,8 @@ import datadog.trace.agent.tooling.DDAdvice; import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.api.DDTags; import datadog.trace.instrumentation.jms.util.MessagePropertyTextMap; -import io.opentracing.ActiveSpan; +import io.opentracing.Scope; +import io.opentracing.Span; import io.opentracing.SpanContext; import io.opentracing.propagation.Format; import io.opentracing.tag.Tags; @@ -48,36 +49,34 @@ public final class JMS2MessageListenerInstrumentation implements Instrumenter { public static class MessageListenerAdvice { @Advice.OnMethodEnter(suppress = Throwable.class) - public static ActiveSpan startSpan( + public static Scope startSpan( @Advice.Argument(0) final Message message, @Advice.This final MessageListener listener) { final SpanContext extractedContext = GlobalTracer.get().extract(Format.Builtin.TEXT_MAP, new MessagePropertyTextMap(message)); - final ActiveSpan span = - GlobalTracer.get() - .buildSpan("jms.onMessage") - .asChildOf(extractedContext) - .withTag(DDTags.SERVICE_NAME, "jms") - .withTag(DDTags.RESOURCE_NAME, "Received from " + toResourceName(message, null)) - .withTag(Tags.COMPONENT.getKey(), "jms2") - .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CONSUMER) - .withTag("span.origin.type", listener.getClass().getName()) - .startActive(); - - return span; + return GlobalTracer.get() + .buildSpan("jms.onMessage") + .asChildOf(extractedContext) + .withTag(DDTags.SERVICE_NAME, "jms") + .withTag(DDTags.RESOURCE_NAME, "Received from " + toResourceName(message, null)) + .withTag(Tags.COMPONENT.getKey(), "jms2") + .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CONSUMER) + .withTag("span.origin.type", listener.getClass().getName()) + .startActive(true); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) public static void stopSpan( - @Advice.Enter final ActiveSpan span, @Advice.Thrown final Throwable throwable) { + @Advice.Enter final Scope scope, @Advice.Thrown final Throwable throwable) { - if (span != null) { + if (scope != null) { if (throwable != null) { + final Span span = scope.span(); Tags.ERROR.set(span, Boolean.TRUE); span.log(Collections.singletonMap("error.object", throwable)); } - span.deactivate(); + scope.close(); } } } diff --git a/dd-java-agent/instrumentation/jms-2/src/main/java/datadog/trace/instrumentation/jms2/JMS2MessageProducerInstrumentation.java b/dd-java-agent/instrumentation/jms-2/src/main/java/datadog/trace/instrumentation/jms2/JMS2MessageProducerInstrumentation.java index 290797c399..ef2a821656 100644 --- a/dd-java-agent/instrumentation/jms-2/src/main/java/datadog/trace/instrumentation/jms2/JMS2MessageProducerInstrumentation.java +++ b/dd-java-agent/instrumentation/jms-2/src/main/java/datadog/trace/instrumentation/jms2/JMS2MessageProducerInstrumentation.java @@ -14,7 +14,8 @@ import datadog.trace.agent.tooling.DDAdvice; import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.api.DDTags; import datadog.trace.instrumentation.jms.util.MessagePropertyTextMap; -import io.opentracing.ActiveSpan; +import io.opentracing.Scope; +import io.opentracing.Span; import io.opentracing.propagation.Format; import io.opentracing.tag.Tags; import io.opentracing.util.GlobalTracer; @@ -53,7 +54,7 @@ public final class JMS2MessageProducerInstrumentation implements Instrumenter { public static class ProducerAdvice { @Advice.OnMethodEnter(suppress = Throwable.class) - public static ActiveSpan startSpan( + public static Scope startSpan( @Advice.Argument(0) final Message message, @Advice.This final MessageProducer producer) { Destination defaultDestination; try { @@ -61,7 +62,7 @@ public final class JMS2MessageProducerInstrumentation implements Instrumenter { } catch (final JMSException e) { defaultDestination = null; } - final ActiveSpan span = + final Scope scope = GlobalTracer.get() .buildSpan("jms.produce") .withTag(DDTags.SERVICE_NAME, "jms") @@ -71,24 +72,26 @@ public final class JMS2MessageProducerInstrumentation implements Instrumenter { .withTag(Tags.COMPONENT.getKey(), "jms2") .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_PRODUCER) .withTag("span.origin.type", producer.getClass().getName()) - .startActive(); + .startActive(true); GlobalTracer.get() - .inject(span.context(), Format.Builtin.TEXT_MAP, new MessagePropertyTextMap(message)); + .inject( + scope.span().context(), Format.Builtin.TEXT_MAP, new MessagePropertyTextMap(message)); - return span; + return scope; } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) public static void stopSpan( - @Advice.Enter final ActiveSpan span, @Advice.Thrown final Throwable throwable) { + @Advice.Enter final Scope scope, @Advice.Thrown final Throwable throwable) { - if (span != null) { + if (scope != null) { if (throwable != null) { + final Span span = scope.span(); Tags.ERROR.set(span, Boolean.TRUE); span.log(Collections.singletonMap("error.object", throwable)); } - span.deactivate(); + scope.close(); } } } @@ -96,11 +99,11 @@ public final class JMS2MessageProducerInstrumentation implements Instrumenter { public static class ProducerWithDestinationAdvice { @Advice.OnMethodEnter(suppress = Throwable.class) - public static ActiveSpan startSpan( + public static Scope startSpan( @Advice.Argument(0) final Destination destination, @Advice.Argument(1) final Message message, @Advice.This final MessageProducer producer) { - final ActiveSpan span = + final Scope scope = GlobalTracer.get() .buildSpan("jms.produce") .withTag(DDTags.SERVICE_NAME, "jms") @@ -108,23 +111,25 @@ public final class JMS2MessageProducerInstrumentation implements Instrumenter { .withTag(Tags.COMPONENT.getKey(), "jms2") .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_PRODUCER) .withTag("span.origin.type", producer.getClass().getName()) - .startActive(); + .startActive(true); GlobalTracer.get() - .inject(span.context(), Format.Builtin.TEXT_MAP, new MessagePropertyTextMap(message)); - return span; + .inject( + scope.span().context(), Format.Builtin.TEXT_MAP, new MessagePropertyTextMap(message)); + return scope; } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) public static void stopSpan( - @Advice.Enter final ActiveSpan span, @Advice.Thrown final Throwable throwable) { + @Advice.Enter final Scope scope, @Advice.Thrown final Throwable throwable) { - if (span != null) { + if (scope != null) { if (throwable != null) { + final Span span = scope.span(); Tags.ERROR.set(span, Boolean.TRUE); span.log(Collections.singletonMap("error.object", throwable)); } - span.deactivate(); + scope.close(); } } } diff --git a/dd-java-agent/instrumentation/okhttp-3/okhttp-3.gradle b/dd-java-agent/instrumentation/okhttp-3/okhttp-3.gradle index 35880e87dc..1a93040493 100644 --- a/dd-java-agent/instrumentation/okhttp-3/okhttp-3.gradle +++ b/dd-java-agent/instrumentation/okhttp-3/okhttp-3.gradle @@ -16,7 +16,7 @@ apply from: "${rootDir}/gradle/java.gradle" dependencies { compileOnly group: 'com.squareup.okhttp3', name: 'okhttp', version: '3.0.0' - compile('io.opentracing.contrib:opentracing-okhttp3:0.0.5') { + compile('io.opentracing.contrib:opentracing-okhttp3:0.1.0-RC1') { transitive = false } diff --git a/dd-java-agent/instrumentation/okhttp-3/src/main/java/datadog/trace/instrumentation/okhttp3/OkHttp3Instrumentation.java b/dd-java-agent/instrumentation/okhttp-3/src/main/java/datadog/trace/instrumentation/okhttp3/OkHttp3Instrumentation.java index ed9b0d760c..465a196457 100644 --- a/dd-java-agent/instrumentation/okhttp-3/src/main/java/datadog/trace/instrumentation/okhttp3/OkHttp3Instrumentation.java +++ b/dd-java-agent/instrumentation/okhttp-3/src/main/java/datadog/trace/instrumentation/okhttp3/OkHttp3Instrumentation.java @@ -36,10 +36,7 @@ public class OkHttp3Instrumentation implements Instrumenter { "io.opentracing.contrib.okhttp3.RequestBuilderInjectAdapter", "io.opentracing.contrib.okhttp3.TracingCallFactory", "io.opentracing.contrib.okhttp3.TracingCallFactory$NetworkInterceptor", - "io.opentracing.contrib.okhttp3.TracingCallFactory$1", - "io.opentracing.contrib.okhttp3.concurrent.TracingExecutorService", - "io.opentracing.contrib.okhttp3.concurrent.TracedCallable", - "io.opentracing.contrib.okhttp3.concurrent.TracedRunnable")) + "io.opentracing.contrib.okhttp3.TracingCallFactory$1")) .transform( DDAdvice.create() .advice( diff --git a/dd-java-agent/instrumentation/servlet-2/servlet-2.gradle b/dd-java-agent/instrumentation/servlet-2/servlet-2.gradle index 497574f764..be88e6984c 100644 --- a/dd-java-agent/instrumentation/servlet-2/servlet-2.gradle +++ b/dd-java-agent/instrumentation/servlet-2/servlet-2.gradle @@ -14,7 +14,7 @@ apply from: "${rootDir}/gradle/java.gradle" dependencies { compileOnly group: 'javax.servlet', name: 'servlet-api', version: '2.3' - compile('io.opentracing.contrib:opentracing-web-servlet-filter:0.0.9') { + compile('io.opentracing.contrib:opentracing-web-servlet-filter:0.1.0-RC1') { transitive = false } diff --git a/dd-java-agent/instrumentation/servlet-2/src/main/java/datadog/trace/instrumentation/servlet2/FilterChain2Instrumentation.java b/dd-java-agent/instrumentation/servlet-2/src/main/java/datadog/trace/instrumentation/servlet2/FilterChain2Instrumentation.java index 007d889da1..cc1b5c568f 100644 --- a/dd-java-agent/instrumentation/servlet-2/src/main/java/datadog/trace/instrumentation/servlet2/FilterChain2Instrumentation.java +++ b/dd-java-agent/instrumentation/servlet-2/src/main/java/datadog/trace/instrumentation/servlet2/FilterChain2Instrumentation.java @@ -12,7 +12,8 @@ import com.google.auto.service.AutoService; import datadog.trace.agent.tooling.DDAdvice; import datadog.trace.agent.tooling.HelperInjector; import datadog.trace.agent.tooling.Instrumenter; -import io.opentracing.ActiveSpan; +import io.opentracing.Scope; +import io.opentracing.Span; import io.opentracing.SpanContext; import io.opentracing.contrib.web.servlet.filter.HttpServletRequestExtractAdapter; import io.opentracing.contrib.web.servlet.filter.ServletFilterSpanDecorator; @@ -62,8 +63,9 @@ public final class FilterChain2Instrumentation implements Instrumenter { public static class FilterChain2Advice { @Advice.OnMethodEnter(suppress = Throwable.class) - public static ActiveSpan startSpan(@Advice.Argument(0) final ServletRequest req) { - if (GlobalTracer.get().activeSpan() != null || !(req instanceof HttpServletRequest)) { + public static Scope startSpan(@Advice.Argument(0) final ServletRequest req) { + if (GlobalTracer.get().scopeManager().active() != null + || !(req instanceof HttpServletRequest)) { // doFilter is called by each filter. We only want to time outer-most. return null; } @@ -74,26 +76,27 @@ public final class FilterChain2Instrumentation implements Instrumenter { Format.Builtin.HTTP_HEADERS, new HttpServletRequestExtractAdapter((HttpServletRequest) req)); - final ActiveSpan span = + final Scope scope = GlobalTracer.get() .buildSpan(FILTER_CHAIN_OPERATION_NAME) .asChildOf(extractedContext) .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_SERVER) - .startActive(); + .startActive(true); - ServletFilterSpanDecorator.STANDARD_TAGS.onRequest((HttpServletRequest) req, span); - return span; + ServletFilterSpanDecorator.STANDARD_TAGS.onRequest((HttpServletRequest) req, scope.span()); + return scope; } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) public static void stopSpan( @Advice.Argument(0) final ServletRequest request, @Advice.Argument(1) final ServletResponse response, - @Advice.Enter final ActiveSpan span, + @Advice.Enter final Scope scope, @Advice.Thrown final Throwable throwable) { - if (span != null) { + if (scope != null) { if (request instanceof HttpServletRequest && response instanceof HttpServletResponse) { + final Span span = scope.span(); final HttpServletRequest req = (HttpServletRequest) request; final HttpServletResponse resp = (HttpServletResponse) response; @@ -104,7 +107,7 @@ public final class FilterChain2Instrumentation implements Instrumenter { ServletFilterSpanDecorator.STANDARD_TAGS.onResponse(req, resp, span); } } - span.deactivate(); + scope.close(); } } } diff --git a/dd-java-agent/instrumentation/servlet-2/src/main/java/datadog/trace/instrumentation/servlet2/HttpServlet2Instrumentation.java b/dd-java-agent/instrumentation/servlet-2/src/main/java/datadog/trace/instrumentation/servlet2/HttpServlet2Instrumentation.java index a468825fa3..56a665afbc 100644 --- a/dd-java-agent/instrumentation/servlet-2/src/main/java/datadog/trace/instrumentation/servlet2/HttpServlet2Instrumentation.java +++ b/dd-java-agent/instrumentation/servlet-2/src/main/java/datadog/trace/instrumentation/servlet2/HttpServlet2Instrumentation.java @@ -12,7 +12,8 @@ import com.google.auto.service.AutoService; import datadog.trace.agent.tooling.DDAdvice; import datadog.trace.agent.tooling.HelperInjector; import datadog.trace.agent.tooling.Instrumenter; -import io.opentracing.ActiveSpan; +import io.opentracing.Scope; +import io.opentracing.Span; import io.opentracing.SpanContext; import io.opentracing.contrib.web.servlet.filter.HttpServletRequestExtractAdapter; import io.opentracing.contrib.web.servlet.filter.ServletFilterSpanDecorator; @@ -20,6 +21,8 @@ import io.opentracing.propagation.Format; import io.opentracing.tag.Tags; import io.opentracing.util.GlobalTracer; import java.util.Collections; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import net.bytebuddy.agent.builder.AgentBuilder; @@ -60,42 +63,51 @@ public final class HttpServlet2Instrumentation implements Instrumenter { public static class HttpServlet2Advice { @Advice.OnMethodEnter(suppress = Throwable.class) - public static ActiveSpan startSpan(@Advice.Argument(0) final HttpServletRequest req) { - if (GlobalTracer.get().activeSpan() != null) { - // Tracing might already be applied by the FilterChain. If so ignore this. + public static Scope startSpan(@Advice.Argument(0) final ServletRequest req) { + if (GlobalTracer.get().scopeManager().active() != null + || !(req instanceof HttpServletRequest)) { + // doFilter is called by each filter. We only want to time outer-most. return null; } final SpanContext extractedContext = GlobalTracer.get() - .extract(Format.Builtin.HTTP_HEADERS, new HttpServletRequestExtractAdapter(req)); + .extract( + Format.Builtin.HTTP_HEADERS, + new HttpServletRequestExtractAdapter((HttpServletRequest) req)); - final ActiveSpan span = + final Scope scope = GlobalTracer.get() .buildSpan(SERVLET_OPERATION_NAME) .asChildOf(extractedContext) .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_SERVER) - .startActive(); + .startActive(true); - ServletFilterSpanDecorator.STANDARD_TAGS.onRequest(req, span); - return span; + ServletFilterSpanDecorator.STANDARD_TAGS.onRequest((HttpServletRequest) req, scope.span()); + return scope; } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) public static void stopSpan( - @Advice.Argument(0) final HttpServletRequest req, - @Advice.Argument(1) final HttpServletResponse resp, - @Advice.Enter final ActiveSpan span, + @Advice.Argument(0) final ServletRequest request, + @Advice.Argument(1) final ServletResponse response, + @Advice.Enter final Scope scope, @Advice.Thrown final Throwable throwable) { - if (span != null) { - if (throwable != null) { - ServletFilterSpanDecorator.STANDARD_TAGS.onError(req, resp, throwable, span); - span.log(Collections.singletonMap("error.object", throwable)); - } else { - ServletFilterSpanDecorator.STANDARD_TAGS.onResponse(req, resp, span); + if (scope != null) { + if (request instanceof HttpServletRequest && response instanceof HttpServletResponse) { + final Span span = scope.span(); + final HttpServletRequest req = (HttpServletRequest) request; + final HttpServletResponse resp = (HttpServletResponse) response; + + if (throwable != null) { + ServletFilterSpanDecorator.STANDARD_TAGS.onError(req, resp, throwable, span); + span.log(Collections.singletonMap("error.object", throwable)); + } else { + ServletFilterSpanDecorator.STANDARD_TAGS.onResponse(req, resp, span); + } } - span.deactivate(); + scope.close(); } } } diff --git a/dd-java-agent/instrumentation/servlet-3/servlet-3.gradle b/dd-java-agent/instrumentation/servlet-3/servlet-3.gradle index cd054b36f2..2b51871262 100644 --- a/dd-java-agent/instrumentation/servlet-3/servlet-3.gradle +++ b/dd-java-agent/instrumentation/servlet-3/servlet-3.gradle @@ -15,7 +15,7 @@ apply from: "${rootDir}/gradle/java.gradle" dependencies { compileOnly group: 'javax.servlet', name: 'javax.servlet-api', version: '3.0.1' - compile('io.opentracing.contrib:opentracing-web-servlet-filter:0.0.9') { + compile('io.opentracing.contrib:opentracing-web-servlet-filter:0.1.0-RC1') { transitive = false } diff --git a/dd-java-agent/instrumentation/servlet-3/src/main/java/datadog/trace/instrumentation/servlet3/FilterChain3Instrumentation.java b/dd-java-agent/instrumentation/servlet-3/src/main/java/datadog/trace/instrumentation/servlet3/FilterChain3Instrumentation.java index f0b2530221..acb5414eb3 100644 --- a/dd-java-agent/instrumentation/servlet-3/src/main/java/datadog/trace/instrumentation/servlet3/FilterChain3Instrumentation.java +++ b/dd-java-agent/instrumentation/servlet-3/src/main/java/datadog/trace/instrumentation/servlet3/FilterChain3Instrumentation.java @@ -12,7 +12,8 @@ import com.google.auto.service.AutoService; import datadog.trace.agent.tooling.DDAdvice; import datadog.trace.agent.tooling.HelperInjector; import datadog.trace.agent.tooling.Instrumenter; -import io.opentracing.ActiveSpan; +import io.opentracing.Scope; +import io.opentracing.Span; import io.opentracing.SpanContext; import io.opentracing.contrib.web.servlet.filter.HttpServletRequestExtractAdapter; import io.opentracing.contrib.web.servlet.filter.ServletFilterSpanDecorator; @@ -56,16 +57,16 @@ public final class FilterChain3Instrumentation implements Instrumenter { .and(takesArgument(0, named("javax.servlet.ServletRequest"))) .and(takesArgument(1, named("javax.servlet.ServletResponse"))) .and(isPublic()), - HttpServlet3Advice.class.getName())) + FilterChain3Advice.class.getName())) .asDecorator(); } - public static class HttpServlet3Advice { + public static class FilterChain3Advice { @Advice.OnMethodEnter(suppress = Throwable.class) - public static ActiveSpan startSpan(@Advice.Argument(0) final ServletRequest req) { + public static Scope startSpan(@Advice.Argument(0) final ServletRequest req) { if (GlobalTracer.get().activeSpan() != null || !(req instanceof HttpServletRequest)) { - // doFilter is called by each filter. We only want to time outer-most. + // Tracing might already be applied by the FilterChain. If so ignore this. return null; } @@ -75,63 +76,61 @@ public final class FilterChain3Instrumentation implements Instrumenter { Format.Builtin.HTTP_HEADERS, new HttpServletRequestExtractAdapter((HttpServletRequest) req)); - final ActiveSpan span = + final Scope scope = GlobalTracer.get() .buildSpan(SERVLET_OPERATION_NAME) .asChildOf(extractedContext) .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_SERVER) - .startActive(); + .startActive(false); - ServletFilterSpanDecorator.STANDARD_TAGS.onRequest((HttpServletRequest) req, span); - return span; + ServletFilterSpanDecorator.STANDARD_TAGS.onRequest((HttpServletRequest) req, scope.span()); + return scope; } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) public static void stopSpan( @Advice.Argument(0) final ServletRequest request, @Advice.Argument(1) final ServletResponse response, - @Advice.Enter final ActiveSpan span, + @Advice.Enter final Scope scope, @Advice.Thrown final Throwable throwable) { - if (span != null) { + if (scope != null) { if (request instanceof HttpServletRequest && response instanceof HttpServletResponse) { final HttpServletRequest req = (HttpServletRequest) request; final HttpServletResponse resp = (HttpServletResponse) response; + final Span span = scope.span(); if (throwable != null) { ServletFilterSpanDecorator.STANDARD_TAGS.onError(req, resp, throwable, span); span.log(Collections.singletonMap("error.object", throwable)); + scope.close(); + scope.span().finish(); // Finish the span manually since finishSpanOnClose was false } else if (req.isAsyncStarted()) { - final ActiveSpan.Continuation cont = span.capture(); final AtomicBoolean activated = new AtomicBoolean(false); // what if async is already finished? This would not be called - req.getAsyncContext().addListener(new TagSettingAsyncListener(activated, cont, span)); + req.getAsyncContext().addListener(new TagSettingAsyncListener(activated, span)); } else { ServletFilterSpanDecorator.STANDARD_TAGS.onResponse(req, resp, span); + scope.close(); + scope.span().finish(); // Finish the span manually since finishSpanOnClose was false } } - span.deactivate(); } } public static class TagSettingAsyncListener implements AsyncListener { private final AtomicBoolean activated; - private final ActiveSpan.Continuation cont; - private final ActiveSpan span; + private final Span span; - public TagSettingAsyncListener( - final AtomicBoolean activated, - final ActiveSpan.Continuation cont, - final ActiveSpan span) { + public TagSettingAsyncListener(final AtomicBoolean activated, final Span span) { this.activated = activated; - this.cont = cont; this.span = span; } @Override public void onComplete(final AsyncEvent event) throws IOException { if (activated.compareAndSet(false, true)) { - try (ActiveSpan activeSpan = cont.activate()) { + try (Scope scope = GlobalTracer.get().scopeManager().activate(span, true)) { ServletFilterSpanDecorator.STANDARD_TAGS.onResponse( (HttpServletRequest) event.getSuppliedRequest(), (HttpServletResponse) event.getSuppliedResponse(), @@ -143,7 +142,7 @@ public final class FilterChain3Instrumentation implements Instrumenter { @Override public void onTimeout(final AsyncEvent event) throws IOException { if (activated.compareAndSet(false, true)) { - try (ActiveSpan activeSpan = cont.activate()) { + try (Scope scope = GlobalTracer.get().scopeManager().activate(span, true)) { ServletFilterSpanDecorator.STANDARD_TAGS.onTimeout( (HttpServletRequest) event.getSuppliedRequest(), (HttpServletResponse) event.getSuppliedResponse(), @@ -156,7 +155,7 @@ public final class FilterChain3Instrumentation implements Instrumenter { @Override public void onError(final AsyncEvent event) throws IOException { if (event.getThrowable() != null && activated.compareAndSet(false, true)) { - try (ActiveSpan activeSpan = cont.activate()) { + try (Scope scope = GlobalTracer.get().scopeManager().activate(span, true)) { ServletFilterSpanDecorator.STANDARD_TAGS.onError( (HttpServletRequest) event.getSuppliedRequest(), (HttpServletResponse) event.getSuppliedResponse(), diff --git a/dd-java-agent/instrumentation/servlet-3/src/main/java/datadog/trace/instrumentation/servlet3/HttpServlet3Instrumentation.java b/dd-java-agent/instrumentation/servlet-3/src/main/java/datadog/trace/instrumentation/servlet3/HttpServlet3Instrumentation.java index 81fb9bcafe..8d10b14868 100644 --- a/dd-java-agent/instrumentation/servlet-3/src/main/java/datadog/trace/instrumentation/servlet3/HttpServlet3Instrumentation.java +++ b/dd-java-agent/instrumentation/servlet-3/src/main/java/datadog/trace/instrumentation/servlet3/HttpServlet3Instrumentation.java @@ -12,7 +12,8 @@ import com.google.auto.service.AutoService; import datadog.trace.agent.tooling.DDAdvice; import datadog.trace.agent.tooling.HelperInjector; import datadog.trace.agent.tooling.Instrumenter; -import io.opentracing.ActiveSpan; +import io.opentracing.Scope; +import io.opentracing.Span; import io.opentracing.SpanContext; import io.opentracing.contrib.web.servlet.filter.HttpServletRequestExtractAdapter; import io.opentracing.contrib.web.servlet.filter.ServletFilterSpanDecorator; @@ -61,8 +62,8 @@ public final class HttpServlet3Instrumentation implements Instrumenter { public static class HttpServlet3Advice { @Advice.OnMethodEnter(suppress = Throwable.class) - public static ActiveSpan startSpan(@Advice.Argument(0) final HttpServletRequest req) { - if (GlobalTracer.get().activeSpan() != null) { + public static Scope startSpan(@Advice.Argument(0) final HttpServletRequest req) { + if (GlobalTracer.get().scopeManager().active() != null) { // Tracing might already be applied by the FilterChain. If so ignore this. return null; } @@ -71,58 +72,56 @@ public final class HttpServlet3Instrumentation implements Instrumenter { GlobalTracer.get() .extract(Format.Builtin.HTTP_HEADERS, new HttpServletRequestExtractAdapter(req)); - final ActiveSpan span = + final Scope scope = GlobalTracer.get() .buildSpan(SERVLET_OPERATION_NAME) .asChildOf(extractedContext) .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_SERVER) - .startActive(); + .startActive(false); - ServletFilterSpanDecorator.STANDARD_TAGS.onRequest(req, span); - return span; + ServletFilterSpanDecorator.STANDARD_TAGS.onRequest(req, scope.span()); + return scope; } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) public static void stopSpan( @Advice.Argument(0) final HttpServletRequest req, @Advice.Argument(1) final HttpServletResponse resp, - @Advice.Enter final ActiveSpan span, + @Advice.Enter final Scope scope, @Advice.Thrown final Throwable throwable) { - if (span != null) { + if (scope != null) { + final Span span = scope.span(); if (throwable != null) { ServletFilterSpanDecorator.STANDARD_TAGS.onError(req, resp, throwable, span); span.log(Collections.singletonMap("error.object", throwable)); + scope.close(); + scope.span().finish(); // Finish the span manually since finishSpanOnClose was false } else if (req.isAsyncStarted()) { - final ActiveSpan.Continuation cont = span.capture(); final AtomicBoolean activated = new AtomicBoolean(false); // what if async is already finished? This would not be called - req.getAsyncContext().addListener(new TagSettingAsyncListener(activated, cont, span)); + req.getAsyncContext().addListener(new TagSettingAsyncListener(activated, span)); } else { ServletFilterSpanDecorator.STANDARD_TAGS.onResponse(req, resp, span); + scope.close(); + scope.span().finish(); // Finish the span manually since finishSpanOnClose was false } - span.deactivate(); } } public static class TagSettingAsyncListener implements AsyncListener { private final AtomicBoolean activated; - private final ActiveSpan.Continuation cont; - private final ActiveSpan span; + private final Span span; - public TagSettingAsyncListener( - final AtomicBoolean activated, - final ActiveSpan.Continuation cont, - final ActiveSpan span) { + public TagSettingAsyncListener(final AtomicBoolean activated, final Span span) { this.activated = activated; - this.cont = cont; this.span = span; } @Override public void onComplete(final AsyncEvent event) throws IOException { if (activated.compareAndSet(false, true)) { - try (ActiveSpan activeSpan = cont.activate()) { + try (Scope scope = GlobalTracer.get().scopeManager().activate(span, true)) { ServletFilterSpanDecorator.STANDARD_TAGS.onResponse( (HttpServletRequest) event.getSuppliedRequest(), (HttpServletResponse) event.getSuppliedResponse(), @@ -134,7 +133,7 @@ public final class HttpServlet3Instrumentation implements Instrumenter { @Override public void onTimeout(final AsyncEvent event) throws IOException { if (activated.compareAndSet(false, true)) { - try (ActiveSpan activeSpan = cont.activate()) { + try (Scope scope = GlobalTracer.get().scopeManager().activate(span, true)) { ServletFilterSpanDecorator.STANDARD_TAGS.onTimeout( (HttpServletRequest) event.getSuppliedRequest(), (HttpServletResponse) event.getSuppliedResponse(), @@ -147,7 +146,7 @@ public final class HttpServlet3Instrumentation implements Instrumenter { @Override public void onError(final AsyncEvent event) throws IOException { if (event.getThrowable() != null && activated.compareAndSet(false, true)) { - try (ActiveSpan activeSpan = cont.activate()) { + try (Scope scope = GlobalTracer.get().scopeManager().activate(span, true)) { ServletFilterSpanDecorator.STANDARD_TAGS.onError( (HttpServletRequest) event.getSuppliedRequest(), (HttpServletResponse) event.getSuppliedResponse(), diff --git a/dd-java-agent/instrumentation/spring-web/src/main/java/datadog/trace/instrumentation/springweb/SpringWebInstrumentation.java b/dd-java-agent/instrumentation/spring-web/src/main/java/datadog/trace/instrumentation/springweb/SpringWebInstrumentation.java index 75cb684e63..b4aaf9e4b3 100644 --- a/dd-java-agent/instrumentation/spring-web/src/main/java/datadog/trace/instrumentation/springweb/SpringWebInstrumentation.java +++ b/dd-java-agent/instrumentation/spring-web/src/main/java/datadog/trace/instrumentation/springweb/SpringWebInstrumentation.java @@ -14,7 +14,7 @@ import com.google.auto.service.AutoService; import datadog.trace.agent.tooling.DDAdvice; import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.api.DDTags; -import io.opentracing.ActiveSpan; +import io.opentracing.Scope; import io.opentracing.util.GlobalTracer; import java.sql.PreparedStatement; import java.util.Map; @@ -52,13 +52,13 @@ public final class SpringWebInstrumentation implements Instrumenter { @Advice.OnMethodEnter(suppress = Throwable.class) public static void nameResource(@Advice.Argument(0) final HttpServletRequest request) { - final ActiveSpan span = GlobalTracer.get().activeSpan(); - if (span != null) { + final Scope scope = GlobalTracer.get().scopeManager().active(); + if (scope != null) { final String method = request.getMethod(); final String bestMatchingPattern = request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE).toString(); final String resourceName = method + " " + bestMatchingPattern; - span.setTag(DDTags.RESOURCE_NAME, resourceName); + scope.span().setTag(DDTags.RESOURCE_NAME, resourceName); } } } diff --git a/dd-java-agent/instrumentation/trace-annotation/src/main/java/datadog/trace/instrumentation/trace_annotation/TraceAnnotationInstrumentation.java b/dd-java-agent/instrumentation/trace-annotation/src/main/java/datadog/trace/instrumentation/trace_annotation/TraceAnnotationInstrumentation.java index 83da1ce943..696fb96f9a 100644 --- a/dd-java-agent/instrumentation/trace-annotation/src/main/java/datadog/trace/instrumentation/trace_annotation/TraceAnnotationInstrumentation.java +++ b/dd-java-agent/instrumentation/trace-annotation/src/main/java/datadog/trace/instrumentation/trace_annotation/TraceAnnotationInstrumentation.java @@ -8,7 +8,8 @@ import com.google.auto.service.AutoService; import datadog.trace.agent.tooling.DDAdvice; import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.api.Trace; -import io.opentracing.ActiveSpan; +import io.opentracing.Scope; +import io.opentracing.Span; import io.opentracing.tag.Tags; import io.opentracing.util.GlobalTracer; import java.lang.reflect.Method; @@ -35,24 +36,25 @@ public final class TraceAnnotationInstrumentation implements Instrumenter { public static class TraceAdvice { @Advice.OnMethodEnter(suppress = Throwable.class) - public static ActiveSpan startSpan(@Advice.Origin final Method method) { + public static Scope startSpan(@Advice.Origin final Method method) { final Trace trace = method.getAnnotation(Trace.class); String operationName = trace == null ? null : trace.operationName(); if (operationName == null || operationName.isEmpty()) { operationName = method.getDeclaringClass().getSimpleName() + "." + method.getName(); } - return GlobalTracer.get().buildSpan(operationName).startActive(); + return GlobalTracer.get().buildSpan(operationName).startActive(true); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) public static void stopSpan( - @Advice.Enter final ActiveSpan activeSpan, @Advice.Thrown final Throwable throwable) { + @Advice.Enter final Scope scope, @Advice.Thrown final Throwable throwable) { if (throwable != null) { - Tags.ERROR.set(activeSpan, true); - activeSpan.log(Collections.singletonMap("error.object", throwable)); + final Span span = scope.span(); + Tags.ERROR.set(span, true); + span.log(Collections.singletonMap("error.object", throwable)); } - activeSpan.deactivate(); + scope.close(); } } } diff --git a/dd-java-agent/testing/src/main/java/datadog/trace/agent/test/TestUtils.java b/dd-java-agent/testing/src/main/java/datadog/trace/agent/test/TestUtils.java index c94f497cbc..2f2bed5fe6 100644 --- a/dd-java-agent/testing/src/main/java/datadog/trace/agent/test/TestUtils.java +++ b/dd-java-agent/testing/src/main/java/datadog/trace/agent/test/TestUtils.java @@ -1,7 +1,7 @@ package datadog.trace.agent.test; import datadog.trace.agent.tooling.Utils; -import io.opentracing.ActiveSpan; +import io.opentracing.Scope; import io.opentracing.Tracer; import io.opentracing.util.GlobalTracer; import java.io.File; @@ -55,15 +55,13 @@ public class TestUtils { public static Object runUnderTrace( final String rootOperationName, final Callable r) { - final ActiveSpan rootSpan = GlobalTracer.get().buildSpan(rootOperationName).startActive(); + final Scope scope = GlobalTracer.get().buildSpan(rootOperationName).startActive(true); try { - try { - return r.call(); - } catch (final Exception e) { - throw new IllegalStateException(e); - } + return r.call(); + } catch (final Exception e) { + throw new IllegalStateException(e); } finally { - rootSpan.deactivate(); + scope.close(); } } diff --git a/dd-trace-ot/docs/opentracing-api.md b/dd-trace-ot/docs/opentracing-api.md index 4ed799cb35..ccc5ae3113 100644 --- a/dd-trace-ot/docs/opentracing-api.md +++ b/dd-trace-ot/docs/opentracing-api.md @@ -48,7 +48,7 @@ accessible through the method `buildSpan(String operationName)` to serve this pu ```java // Create a new Span with the operation name "componentTracking" - ActiveSpan current = tracer.buildSpan("componentTracking").startActive(); + ActiveSpan current = tracer.buildSpan("componentTracking").startActive(true); ``` This example creates a simple span referenced "componentTracking". The `startActive()` method starts a new span and sets it @@ -94,7 +94,7 @@ OpenTracing defines a [standard set of tags](https://github.com/opentracing/spec buildSpan("componentTracking") .withTag("custom-meta", "some-useful-value") .withTag(Tags.COMPONENT, "my-component-mysql") - .startActive(); + .startActive(true); // Somewhere further in the code @@ -154,7 +154,7 @@ Spans are associated across processes in a trace via the `Tracer.extract` and `T ```java // On the start of a new trace in an application, associate incoming request with existing traces. SpanContext spanCtx = tracer.extract(Format.Builtin.HTTP_HEADERS, someTextMapInstance); - ActiveSpan currentSpan = tracer.buildSpan("componentTracking").asChildOf(spanCtx).startActive(); + ActiveSpan currentSpan = tracer.buildSpan("componentTracking").asChildOf(spanCtx).startActive(true); ``` ```java diff --git a/dd-trace-ot/src/jmh/java/datadog/trace/DDTraceBenchmark.java b/dd-trace-ot/src/jmh/java/datadog/trace/DDTraceBenchmark.java index 15551c630d..f175c11114 100644 --- a/dd-trace-ot/src/jmh/java/datadog/trace/DDTraceBenchmark.java +++ b/dd-trace-ot/src/jmh/java/datadog/trace/DDTraceBenchmark.java @@ -2,21 +2,20 @@ package datadog.trace; import datadog.opentracing.DDTracer; import datadog.trace.common.writer.ListWriter; -import io.opentracing.ActiveSpan; import io.opentracing.Span; import io.opentracing.Tracer; import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.Scope; import org.openjdk.jmh.annotations.State; public class DDTraceBenchmark { public static String SPAN_NAME = "span-benchmark"; - @State(Scope.Thread) + @State(org.openjdk.jmh.annotations.Scope.Thread) public static class TraceState { public ListWriter traceCollector = new ListWriter(); public Tracer tracer = new DDTracer(traceCollector); - public ActiveSpan activeSpan = tracer.buildSpan(SPAN_NAME).startActive(); + // TODO: this will need to be fixed if we want backwards compatibility for older versions... + public io.opentracing.Scope scope = tracer.buildSpan(SPAN_NAME).startActive(true); } @Benchmark @@ -38,23 +37,13 @@ public class DDTraceBenchmark { @Benchmark public Object testBuildStartSpanActive(final TraceState state) { - return state.tracer.buildSpan(SPAN_NAME).startActive(); + return state.tracer.buildSpan(SPAN_NAME).startActive(true); } @Benchmark public Object testFullActiveSpan(final TraceState state) { - final ActiveSpan activeSpan = state.tracer.buildSpan(SPAN_NAME).startActive(); - activeSpan.deactivate(); - return activeSpan; - } - - @Benchmark - public Object testContinuationCapture(final TraceState state) { - return state.activeSpan.capture(); - } - - @Benchmark - public Object testContinuationActivate(final TraceState state) { - return state.activeSpan.capture().activate(); + final io.opentracing.Scope scope = state.tracer.buildSpan(SPAN_NAME).startActive(true); + scope.close(); + return scope; } } diff --git a/dd-trace-ot/src/main/java/datadog/opentracing/DDBaseSpan.java b/dd-trace-ot/src/main/java/datadog/opentracing/DDBaseSpan.java deleted file mode 100644 index b961aab924..0000000000 --- a/dd-trace-ot/src/main/java/datadog/opentracing/DDBaseSpan.java +++ /dev/null @@ -1,339 +0,0 @@ -package datadog.opentracing; - -import com.fasterxml.jackson.annotation.JsonGetter; -import com.fasterxml.jackson.annotation.JsonIgnore; -import datadog.trace.api.DDTags; -import datadog.trace.common.util.Clock; -import io.opentracing.BaseSpan; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Queue; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; - -@Slf4j -public abstract class DDBaseSpan implements BaseSpan { - - /** The context attached to the span */ - protected final DDSpanContext context; - /** StartTime stores the creation time of the span in milliseconds */ - protected long startTimeMicro; - /** StartTimeNano stores the only the nanoseconds for more accuracy */ - protected long startTimeNano; - /** The duration in nanoseconds computed using the startTimeMicro and startTimeNano */ - protected long durationNano; - - /** - * A simple constructor. Currently, users have - * - * @param timestampMicro if set, use this time instead of the auto-generated time - * @param context the context - */ - protected DDBaseSpan(final long timestampMicro, final DDSpanContext context) { - - this.context = context; - - // record the start time in nano (current milli + nano delta) - if (timestampMicro == 0L) { - this.startTimeMicro = Clock.currentMicroTime(); - } else { - this.startTimeMicro = timestampMicro; - } - this.startTimeNano = Clock.currentNanoTicks(); - - // track each span of the trace - this.context.getTrace().add(this); - } - - public final void finish() { - finish(Clock.currentMicroTime()); - } - - public final void finish(final long stoptimeMicros) { - // Ensure that duration is at least 1. Less than 1 is possible due to our use of system clock instead of nano time. - this.durationNano = - Math.max(1, TimeUnit.MICROSECONDS.toNanos(stoptimeMicros - this.startTimeMicro)); - afterFinish(); - } - - /** - * Close the span. If the current span is the parent, check if each child has also been closed If - * not, warned it - */ - protected final void afterFinish() { - log.debug("{} - Closing the span.", this); - - // warn if one of the parent's children is not finished - if (this.isRootSpan()) { - final Queue> spans = this.context().getTrace(); - - for (final DDBaseSpan span : spans) { - if (span.getDurationNano() == 0L) { - log.warn( - "{} - The parent span is marked as finished but this span isn't. You have to close each children.", - this); - } - } - this.context.getTracer().write(this.context.getTrace()); - log.debug("{} - Write the trace", this); - } - } - - /** - * Check if the span is the root parent. It means that the traceId is the same as the spanId - * - * @return true if root, false otherwise - */ - protected final boolean isRootSpan() { - - if (context().getTrace().isEmpty()) { - return false; - } - // First item of the array AND tracer set - final DDBaseSpan first = context().getTrace().peek(); - return first.context().getSpanId() == this.context().getSpanId() - && this.context.getTracer() != null; - } - - public void setErrorMeta(final Throwable error) { - context.setErrorFlag(true); - - setTag(DDTags.ERROR_MSG, error.getMessage()); - setTag(DDTags.ERROR_TYPE, error.getClass().getName()); - - final StringWriter errorString = new StringWriter(); - error.printStackTrace(new PrintWriter(errorString)); - setTag(DDTags.ERROR_STACK, errorString.toString()); - } - - private boolean extractError(final Map map) { - if (map.get("error.object") instanceof Throwable) { - final Throwable error = (Throwable) map.get("error.object"); - setErrorMeta(error); - return true; - } - return false; - } - - /* (non-Javadoc) - * @see io.opentracing.BaseSpan#setTag(java.lang.String, java.lang.String) - */ - @Override - public final S setTag(final String tag, final String value) { - this.context().setTag(tag, (Object) value); - return thisInstance(); - } - - /* (non-Javadoc) - * @see io.opentracing.BaseSpan#setTag(java.lang.String, boolean) - */ - @Override - public final S setTag(final String tag, final boolean value) { - this.context().setTag(tag, (Object) value); - return thisInstance(); - } - - /* (non-Javadoc) - * @see io.opentracing.BaseSpan#setTag(java.lang.String, java.lang.Number) - */ - @Override - public final S setTag(final String tag, final Number value) { - this.context().setTag(tag, (Object) value); - return thisInstance(); - } - - /* (non-Javadoc) - * @see io.opentracing.BaseSpan#context() - */ - @Override - public final DDSpanContext context() { - return this.context; - } - - /* (non-Javadoc) - * @see io.opentracing.BaseSpan#getBaggageItem(java.lang.String) - */ - @Override - public final String getBaggageItem(final String key) { - return this.context.getBaggageItem(key); - } - - /* (non-Javadoc) - * @see io.opentracing.BaseSpan#setBaggageItem(java.lang.String, java.lang.String) - */ - @Override - public final S setBaggageItem(final String key, final String value) { - this.context.setBaggageItem(key, value); - return thisInstance(); - } - - /* (non-Javadoc) - * @see io.opentracing.BaseSpan#setOperationName(java.lang.String) - */ - @Override - public final S setOperationName(final String operationName) { - this.context().setOperationName(operationName); - return thisInstance(); - } - - /* (non-Javadoc) - * @see io.opentracing.BaseSpan#log(java.util.Map) - */ - @Override - public final S log(final Map map) { - if (!extractError(map)) { - log.debug("`log` method is not implemented. Doing nothing"); - } - return thisInstance(); - } - - /* (non-Javadoc) - * @see io.opentracing.BaseSpan#log(long, java.util.Map) - */ - @Override - public final S log(final long l, final Map map) { - if (!extractError(map)) { - log.debug("`log` method is not implemented. Doing nothing"); - } - return thisInstance(); - } - - /* (non-Javadoc) - * @see io.opentracing.BaseSpan#log(java.lang.String) - */ - @Override - public final S log(final String s) { - log.debug("`log` method is not implemented. Provided log: {}", s); - return thisInstance(); - } - - /* (non-Javadoc) - * @see io.opentracing.BaseSpan#log(long, java.lang.String) - */ - @Override - public final S log(final long l, final String s) { - log.debug("`log` method is not implemented. Provided log: {}", s); - return thisInstance(); - } - - /* (non-Javadoc) - * @see io.opentracing.BaseSpan#log(java.lang.String, java.lang.Object) - */ - @Override - public final S log(final String s, final Object o) { - log.debug("`log` method is not implemented. Provided log: {}", s); - return thisInstance(); - } - - /* (non-Javadoc) - * @see io.opentracing.BaseSpan#log(long, java.lang.String, java.lang.Object) - */ - @Override - public final S log(final long l, final String s, final Object o) { - log.debug("`log` method is not implemented. Provided log: {}", s); - return thisInstance(); - } - - public final S setServiceName(final String serviceName) { - this.context().setServiceName(serviceName); - return thisInstance(); - } - - public final S setResourceName(final String resourceName) { - this.context().setResourceName(resourceName); - return thisInstance(); - } - - public final S setSpanType(final String type) { - this.context().setSpanType(type); - return thisInstance(); - } - - protected abstract S thisInstance(); - - // Getters and JSON serialisation instructions - - /** - * Meta merges baggage and tags (stringified values) - * - * @return merged context baggage and tags - */ - @JsonGetter - public Map getMeta() { - final Map meta = new HashMap<>(); - for (final Entry entry : context().getBaggageItems().entrySet()) { - meta.put(entry.getKey(), entry.getValue()); - } - for (final Entry entry : getTags().entrySet()) { - meta.put(entry.getKey(), String.valueOf(entry.getValue())); - } - return meta; - } - - @JsonGetter("start") - public long getStartTime() { - return startTimeMicro * 1000L; - } - - @JsonGetter("duration") - public long getDurationNano() { - return durationNano; - } - - @JsonGetter("service") - public String getServiceName() { - return context.getServiceName(); - } - - @JsonGetter("trace_id") - public long getTraceId() { - return context.getTraceId(); - } - - @JsonGetter("span_id") - public long getSpanId() { - return context.getSpanId(); - } - - @JsonGetter("parent_id") - public long getParentId() { - return context.getParentId(); - } - - @JsonGetter("resource") - public String getResourceName() { - return context.getResourceName(); - } - - @JsonGetter("name") - public String getOperationName() { - return context.getOperationName(); - } - - @JsonIgnore - public Map getTags() { - return this.context().getTags(); - } - - @JsonGetter - public String getType() { - return context.getSpanType(); - } - - @JsonGetter - public int getError() { - return context.getErrorFlag() ? 1 : 0; - } - - @Override - public String toString() { - return new StringBuilder() - .append(context.toString()) - .append(", duration_ns=") - .append(durationNano) - .toString(); - } -} diff --git a/dd-trace-ot/src/main/java/datadog/opentracing/DDSpan.java b/dd-trace-ot/src/main/java/datadog/opentracing/DDSpan.java index 5307594d81..a8400fd7ac 100644 --- a/dd-trace-ot/src/main/java/datadog/opentracing/DDSpan.java +++ b/dd-trace-ot/src/main/java/datadog/opentracing/DDSpan.java @@ -1,6 +1,17 @@ package datadog.opentracing; +import com.fasterxml.jackson.annotation.JsonGetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import datadog.trace.api.DDTags; +import datadog.trace.common.util.Clock; import io.opentracing.Span; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.HashMap; +import java.util.Map; +import java.util.Queue; +import java.util.concurrent.TimeUnit; +import lombok.extern.slf4j.Slf4j; /** * Represents an in-flight span in the opentracing system. @@ -8,7 +19,17 @@ import io.opentracing.Span; *

Spans are created by the {@link DDTracer#buildSpan}. This implementation adds some features * according to the DD agent. */ -public class DDSpan extends DDBaseSpan implements Span { +@Slf4j +public class DDSpan implements Span { + + /** The context attached to the span */ + protected final DDSpanContext context; + /** StartTime stores the creation time of the span in milliseconds */ + protected long startTimeMicro; + /** StartTimeNano stores the only the nanoseconds for more accuracy */ + protected long startTimeNano; + /** The duration in nanoseconds computed using the startTimeMicro and startTimeNano */ + protected long durationNano; /** * A simple constructor. Currently, users have @@ -17,11 +38,289 @@ public class DDSpan extends DDBaseSpan implements Span { * @param context the context */ protected DDSpan(final long timestampMicro, final DDSpanContext context) { - super(timestampMicro, context); + + this.context = context; + + // record the start time in nano (current milli + nano delta) + if (timestampMicro == 0L) { + this.startTimeMicro = Clock.currentMicroTime(); + } else { + this.startTimeMicro = timestampMicro; + } + this.startTimeNano = Clock.currentNanoTicks(); + + // track each span of the trace + this.context.getTrace().add(this); } @Override - protected DDSpan thisInstance() { + public final void finish() { + finish(Clock.currentMicroTime()); + } + + @Override + public final void finish(final long stoptimeMicros) { + // Ensure that duration is at least 1. Less than 1 is possible due to our use of system clock instead of nano time. + this.durationNano = + Math.max(1, TimeUnit.MICROSECONDS.toNanos(stoptimeMicros - this.startTimeMicro)); + afterFinish(); + } + + /** + * Close the span. If the current span is the parent, check if each child has also been closed If + * not, warned it + */ + protected final void afterFinish() { + log.debug("{} - Closing the span.", this); + + // warn if one of the parent's children is not finished + if (this.isRootSpan()) { + final Queue spans = this.context().getTrace(); + + for (final DDSpan span : spans) { + if (span.getDurationNano() == 0L) { + log.warn( + "{} - The parent span is marked as finished but this span isn't. You have to close each children.", + this); + } + } + this.context.getTracer().write(this.context.getTrace()); + log.debug("{} - Write the trace", this); + } + } + + /** + * Check if the span is the root parent. It means that the traceId is the same as the spanId + * + * @return true if root, false otherwise + */ + protected final boolean isRootSpan() { + + if (context().getTrace().isEmpty()) { + return false; + } + // First item of the array AND tracer set + final DDSpan first = context().getTrace().peek(); + return first.context().getSpanId() == this.context().getSpanId() + && this.context.getTracer() != null; + } + + public void setErrorMeta(final Throwable error) { + context.setErrorFlag(true); + + setTag(DDTags.ERROR_MSG, error.getMessage()); + setTag(DDTags.ERROR_TYPE, error.getClass().getName()); + + final StringWriter errorString = new StringWriter(); + error.printStackTrace(new PrintWriter(errorString)); + setTag(DDTags.ERROR_STACK, errorString.toString()); + } + + private boolean extractError(final Map map) { + if (map.get("error.object") instanceof Throwable) { + final Throwable error = (Throwable) map.get("error.object"); + setErrorMeta(error); + return true; + } + return false; + } + + /* (non-Javadoc) + * @see io.opentracing.BaseSpan#setTag(java.lang.String, java.lang.String) + */ + @Override + public final Span setTag(final String tag, final String value) { + this.context().setTag(tag, (Object) value); return this; } + + /* (non-Javadoc) + * @see io.opentracing.BaseSpan#setTag(java.lang.String, boolean) + */ + @Override + public final Span setTag(final String tag, final boolean value) { + this.context().setTag(tag, (Object) value); + return this; + } + + /* (non-Javadoc) + * @see io.opentracing.BaseSpan#setTag(java.lang.String, java.lang.Number) + */ + @Override + public final Span setTag(final String tag, final Number value) { + this.context().setTag(tag, (Object) value); + return this; + } + + /* (non-Javadoc) + * @see io.opentracing.BaseSpan#context() + */ + @Override + public final DDSpanContext context() { + return this.context; + } + + /* (non-Javadoc) + * @see io.opentracing.BaseSpan#getBaggageItem(java.lang.String) + */ + @Override + public final String getBaggageItem(final String key) { + return this.context.getBaggageItem(key); + } + + /* (non-Javadoc) + * @see io.opentracing.BaseSpan#setBaggageItem(java.lang.String, java.lang.String) + */ + @Override + public final DDSpan setBaggageItem(final String key, final String value) { + this.context.setBaggageItem(key, value); + return this; + } + + /* (non-Javadoc) + * @see io.opentracing.BaseSpan#setOperationName(java.lang.String) + */ + @Override + public final DDSpan setOperationName(final String operationName) { + this.context().setOperationName(operationName); + return this; + } + + /* (non-Javadoc) + * @see io.opentracing.BaseSpan#log(java.util.Map) + */ + @Override + public final DDSpan log(final Map map) { + if (!extractError(map)) { + log.debug("`log` method is not implemented. Doing nothing"); + } + return this; + } + + /* (non-Javadoc) + * @see io.opentracing.BaseSpan#log(long, java.util.Map) + */ + @Override + public final DDSpan log(final long l, final Map map) { + if (!extractError(map)) { + log.debug("`log` method is not implemented. Doing nothing"); + } + return this; + } + + /* (non-Javadoc) + * @see io.opentracing.BaseSpan#log(java.lang.String) + */ + @Override + public final DDSpan log(final String s) { + log.debug("`log` method is not implemented. Provided log: {}", s); + return this; + } + + /* (non-Javadoc) + * @see io.opentracing.BaseSpan#log(long, java.lang.String) + */ + @Override + public final DDSpan log(final long l, final String s) { + log.debug("`log` method is not implemented. Provided log: {}", s); + return this; + } + + public final DDSpan setServiceName(final String serviceName) { + this.context().setServiceName(serviceName); + return this; + } + + public final DDSpan setResourceName(final String resourceName) { + this.context().setResourceName(resourceName); + return this; + } + + public final DDSpan setSpanType(final String type) { + this.context().setSpanType(type); + return this; + } + + // Getters and JSON serialisation instructions + + /** + * Meta merges baggage and tags (stringified values) + * + * @return merged context baggage and tags + */ + @JsonGetter + public Map getMeta() { + final Map meta = new HashMap<>(); + for (final Map.Entry entry : context().getBaggageItems().entrySet()) { + meta.put(entry.getKey(), entry.getValue()); + } + for (final Map.Entry entry : getTags().entrySet()) { + meta.put(entry.getKey(), String.valueOf(entry.getValue())); + } + return meta; + } + + @JsonGetter("start") + public long getStartTime() { + return startTimeMicro * 1000L; + } + + @JsonGetter("duration") + public long getDurationNano() { + return durationNano; + } + + @JsonGetter("service") + public String getServiceName() { + return context.getServiceName(); + } + + @JsonGetter("trace_id") + public long getTraceId() { + return context.getTraceId(); + } + + @JsonGetter("span_id") + public long getSpanId() { + return context.getSpanId(); + } + + @JsonGetter("parent_id") + public long getParentId() { + return context.getParentId(); + } + + @JsonGetter("resource") + public String getResourceName() { + return context.getResourceName(); + } + + @JsonGetter("name") + public String getOperationName() { + return context.getOperationName(); + } + + @JsonIgnore + public Map getTags() { + return this.context().getTags(); + } + + @JsonGetter + public String getType() { + return context.getSpanType(); + } + + @JsonGetter + public int getError() { + return context.getErrorFlag() ? 1 : 0; + } + + @Override + public String toString() { + return new StringBuilder() + .append(context.toString()) + .append(", duration_ns=") + .append(durationNano) + .toString(); + } } diff --git a/dd-trace-ot/src/main/java/datadog/opentracing/DDSpanContext.java b/dd-trace-ot/src/main/java/datadog/opentracing/DDSpanContext.java index 514b984f21..b353955050 100644 --- a/dd-trace-ot/src/main/java/datadog/opentracing/DDSpanContext.java +++ b/dd-trace-ot/src/main/java/datadog/opentracing/DDSpanContext.java @@ -32,7 +32,7 @@ public class DDSpanContext implements io.opentracing.SpanContext { private final String threadName = Thread.currentThread().getName(); private final long threadId = Thread.currentThread().getId(); /** The collection of all span related to this one */ - private final Queue> trace; + private final Queue trace; // DD attributes /** For technical reasons, the ref to the original tracer */ @@ -64,7 +64,7 @@ public class DDSpanContext implements io.opentracing.SpanContext { final boolean errorFlag, final String spanType, final Map tags, - final Queue> trace, + final Queue trace, final DDTracer tracer) { this.traceId = traceId; @@ -165,7 +165,7 @@ public class DDSpanContext implements io.opentracing.SpanContext { } @JsonIgnore - public Queue> getTrace() { + public Queue getTrace() { return this.trace; } diff --git a/dd-trace-ot/src/main/java/datadog/opentracing/DDTracer.java b/dd-trace-ot/src/main/java/datadog/opentracing/DDTracer.java index b3bc989daf..38fdfd0a63 100644 --- a/dd-trace-ot/src/main/java/datadog/opentracing/DDTracer.java +++ b/dd-trace-ot/src/main/java/datadog/opentracing/DDTracer.java @@ -11,12 +11,12 @@ import datadog.trace.common.Service; import datadog.trace.common.sampling.AllSampler; import datadog.trace.common.sampling.Sampler; import datadog.trace.common.writer.Writer; -import io.opentracing.ActiveSpan; -import io.opentracing.ActiveSpanSource; -import io.opentracing.BaseSpan; +import io.opentracing.Scope; +import io.opentracing.ScopeManager; +import io.opentracing.Span; import io.opentracing.SpanContext; import io.opentracing.propagation.Format; -import io.opentracing.util.ThreadLocalActiveSpanSource; +import io.opentracing.util.ThreadLocalScopeManager; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -29,7 +29,7 @@ import lombok.extern.slf4j.Slf4j; /** DDTracer makes it easy to send traces and span to DD using the OpenTracing API. */ @Slf4j -public class DDTracer extends ThreadLocalActiveSpanSource implements io.opentracing.Tracer { +public class DDTracer extends ThreadLocalScopeManager implements io.opentracing.Tracer { public static final String UNASSIGNED_DEFAULT_SERVICE_NAME = "unnamed-java-app"; @@ -110,6 +110,17 @@ public class DDTracer extends ThreadLocalActiveSpanSource implements io.opentrac spanContextDecorators.put(decorator.getMatchingTag(), list); } + @Override + public ScopeManager scopeManager() { + return this; + } + + @Override + public Span activeSpan() { + final Scope active = active(); + return active == null ? null : active.span(); + } + @Override public DDSpanBuilder buildSpan(final String operationName) { return new DDSpanBuilder(operationName, this); @@ -144,7 +155,7 @@ public class DDTracer extends ThreadLocalActiveSpanSource implements io.opentrac * * @param trace a list of the spans related to the same trace */ - public void write(final Queue> trace) { + public void write(final Queue trace) { if (trace.isEmpty()) { return; } @@ -212,7 +223,7 @@ public class DDTracer extends ThreadLocalActiveSpanSource implements io.opentrac /** Spans are built using this builder */ public class DDSpanBuilder implements SpanBuilder { - private final ActiveSpanSource spanSource; + private final ScopeManager scopeManager; /** Each span must have an operationName according to the opentracing specification */ private final String operationName; @@ -225,16 +236,16 @@ public class DDTracer extends ThreadLocalActiveSpanSource implements io.opentrac private String resourceName; private boolean errorFlag; private String spanType; - private boolean ignoreActiveSpan = false; + private boolean ignoreScope = false; - public DDSpanBuilder(final String operationName, final ActiveSpanSource spanSource) { + public DDSpanBuilder(final String operationName, final ScopeManager scopeManager) { this.operationName = operationName; - this.spanSource = spanSource; + this.scopeManager = scopeManager; } @Override public SpanBuilder ignoreActiveSpan() { - this.ignoreActiveSpan = true; + this.ignoreScope = true; return this; } @@ -243,11 +254,11 @@ public class DDTracer extends ThreadLocalActiveSpanSource implements io.opentrac } @Override - public ActiveSpan startActive() { + public Scope startActive(final boolean finishSpanOnClose) { final DDSpan span = startSpan(); - final ActiveSpan activeSpan = spanSource.makeActive(span); + final Scope scope = scopeManager.activate(span, finishSpanOnClose); log.debug("Starting a new active span: {}", span); - return activeSpan; + return scope; } @Override @@ -320,7 +331,7 @@ public class DDTracer extends ThreadLocalActiveSpanSource implements io.opentrac } @Override - public DDSpanBuilder asChildOf(final BaseSpan span) { + public DDSpanBuilder asChildOf(final Span span) { return asChildOf(span == null ? null : span.context()); } @@ -361,14 +372,14 @@ public class DDTracer extends ThreadLocalActiveSpanSource implements io.opentrac final long spanId = generateNewId(); final long parentSpanId; final Map baggage; - final Queue> parentTrace; + final Queue parentTrace; final DDSpanContext context; SpanContext parentContext = this.parent; - if (parentContext == null && !ignoreActiveSpan) { - // use the ActiveSpan as parent unless overridden or ignored. - final ActiveSpan activeSpan = activeSpan(); - if (activeSpan != null) parentContext = activeSpan.context(); + if (parentContext == null && !ignoreScope) { + // use the Scope as parent unless overridden or ignored. + final Scope scope = active(); + if (scope != null) parentContext = scope.span().context(); } if (parentContext instanceof DDSpanContext) { diff --git a/dd-trace-ot/src/main/java/datadog/opentracing/resolver/DDTracerResolver.java b/dd-trace-ot/src/main/java/datadog/opentracing/resolver/DDTracerResolver.java index c3fe2c7166..98fee6a923 100644 --- a/dd-trace-ot/src/main/java/datadog/opentracing/resolver/DDTracerResolver.java +++ b/dd-trace-ot/src/main/java/datadog/opentracing/resolver/DDTracerResolver.java @@ -2,9 +2,9 @@ package datadog.opentracing.resolver; import com.google.auto.service.AutoService; import datadog.opentracing.DDTracer; -import io.opentracing.NoopTracerFactory; import io.opentracing.Tracer; import io.opentracing.contrib.tracerresolver.TracerResolver; +import io.opentracing.noop.NoopTracerFactory; import io.opentracing.util.GlobalTracer; import lombok.extern.slf4j.Slf4j; diff --git a/dd-trace-ot/src/main/java/datadog/trace/common/sampling/AbstractSampler.java b/dd-trace-ot/src/main/java/datadog/trace/common/sampling/AbstractSampler.java index e81d487993..b659a17bd7 100644 --- a/dd-trace-ot/src/main/java/datadog/trace/common/sampling/AbstractSampler.java +++ b/dd-trace-ot/src/main/java/datadog/trace/common/sampling/AbstractSampler.java @@ -1,6 +1,6 @@ package datadog.trace.common.sampling; -import datadog.opentracing.DDBaseSpan; +import datadog.opentracing.DDSpan; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; @@ -12,7 +12,7 @@ public abstract class AbstractSampler implements Sampler { protected Map skipTagsPatterns = new HashMap<>(); @Override - public boolean sample(final DDBaseSpan span) { + public boolean sample(final DDSpan span) { // Filter by tag values for (final Entry entry : skipTagsPatterns.entrySet()) { @@ -39,5 +39,5 @@ public abstract class AbstractSampler implements Sampler { skipTagsPatterns.put(tag, skipPattern); } - protected abstract boolean doSample(DDBaseSpan span); + protected abstract boolean doSample(DDSpan span); } diff --git a/dd-trace-ot/src/main/java/datadog/trace/common/sampling/AllSampler.java b/dd-trace-ot/src/main/java/datadog/trace/common/sampling/AllSampler.java index 1075fde125..d0e2c820f6 100644 --- a/dd-trace-ot/src/main/java/datadog/trace/common/sampling/AllSampler.java +++ b/dd-trace-ot/src/main/java/datadog/trace/common/sampling/AllSampler.java @@ -1,12 +1,12 @@ package datadog.trace.common.sampling; -import datadog.opentracing.DDBaseSpan; +import datadog.opentracing.DDSpan; /** Sampler that always says yes... */ public class AllSampler extends AbstractSampler { @Override - public boolean doSample(final DDBaseSpan span) { + public boolean doSample(final DDSpan span) { return true; } diff --git a/dd-trace-ot/src/main/java/datadog/trace/common/sampling/RateSampler.java b/dd-trace-ot/src/main/java/datadog/trace/common/sampling/RateSampler.java index 9e6518546a..bf7e807673 100644 --- a/dd-trace-ot/src/main/java/datadog/trace/common/sampling/RateSampler.java +++ b/dd-trace-ot/src/main/java/datadog/trace/common/sampling/RateSampler.java @@ -1,14 +1,12 @@ package datadog.trace.common.sampling; import com.google.auto.service.AutoService; -import datadog.opentracing.DDBaseSpan; +import datadog.opentracing.DDSpan; import lombok.extern.slf4j.Slf4j; /** * This sampler sample the traces at a predefined rate. * - *

- * *

Keep (100 * `sample_rate`)% of the traces. It samples randomly, its main purpose is to reduce * the integration footprint. */ @@ -42,7 +40,7 @@ public class RateSampler extends AbstractSampler { } @Override - public boolean doSample(final DDBaseSpan span) { + public boolean doSample(final DDSpan span) { final boolean sample = Math.random() <= this.sampleRate; log.debug("{} - Span is sampled: {}", span, sample); return sample; diff --git a/dd-trace-ot/src/main/java/datadog/trace/common/sampling/Sampler.java b/dd-trace-ot/src/main/java/datadog/trace/common/sampling/Sampler.java index 23af235089..8059bbc871 100644 --- a/dd-trace-ot/src/main/java/datadog/trace/common/sampling/Sampler.java +++ b/dd-trace-ot/src/main/java/datadog/trace/common/sampling/Sampler.java @@ -1,6 +1,6 @@ package datadog.trace.common.sampling; -import datadog.opentracing.DDBaseSpan; +import datadog.opentracing.DDSpan; import datadog.trace.common.DDTraceConfig; import java.util.Properties; import lombok.extern.slf4j.Slf4j; @@ -16,7 +16,7 @@ public interface Sampler { * @param span the parent span with its context * @return true when the trace/spans has to be reported/written */ - boolean sample(DDBaseSpan span); + boolean sample(DDSpan span); @Slf4j final class Builder { diff --git a/dd-trace-ot/src/main/java/datadog/trace/common/writer/DDAgentWriter.java b/dd-trace-ot/src/main/java/datadog/trace/common/writer/DDAgentWriter.java index d44405d7eb..b304d12285 100644 --- a/dd-trace-ot/src/main/java/datadog/trace/common/writer/DDAgentWriter.java +++ b/dd-trace-ot/src/main/java/datadog/trace/common/writer/DDAgentWriter.java @@ -2,7 +2,7 @@ package datadog.trace.common.writer; import com.google.auto.service.AutoService; import com.google.common.util.concurrent.ThreadFactoryBuilder; -import datadog.opentracing.DDBaseSpan; +import datadog.opentracing.DDSpan; import datadog.trace.common.Service; import java.util.List; import java.util.Map; @@ -59,7 +59,7 @@ public class DDAgentWriter implements Writer { private final DDApi api; /** In memory collection of traces waiting for departure */ - private final WriterQueue>> traces; + private final WriterQueue> traces; private boolean queueFullReported = false; @@ -68,10 +68,10 @@ public class DDAgentWriter implements Writer { } public DDAgentWriter(final DDApi api) { - this(api, new WriterQueue>>(DEFAULT_MAX_TRACES)); + this(api, new WriterQueue>(DEFAULT_MAX_TRACES)); } - public DDAgentWriter(final DDApi api, final WriterQueue>> queue) { + public DDAgentWriter(final DDApi api, final WriterQueue> queue) { super(); this.api = api; traces = queue; @@ -81,8 +81,8 @@ public class DDAgentWriter implements Writer { * @see datadog.trace.Writer#write(java.util.List) */ @Override - public void write(final List> trace) { - final List> removed = traces.add(trace); + public void write(final List trace) { + final List removed = traces.add(trace); if (removed != null && !queueFullReported) { log.debug("Queue is full, traces will be discarded, queue size: {}", DEFAULT_MAX_TRACES); queueFullReported = true; @@ -173,7 +173,7 @@ public class DDAgentWriter implements Writer { return 0L; } - final List>> payload = traces.getAll(); + final List> payload = traces.getAll(); if (log.isDebugEnabled()) { int nbSpans = 0; diff --git a/dd-trace-ot/src/main/java/datadog/trace/common/writer/DDApi.java b/dd-trace-ot/src/main/java/datadog/trace/common/writer/DDApi.java index d29ea601f4..558915a1f8 100644 --- a/dd-trace-ot/src/main/java/datadog/trace/common/writer/DDApi.java +++ b/dd-trace-ot/src/main/java/datadog/trace/common/writer/DDApi.java @@ -2,7 +2,7 @@ package datadog.trace.common.writer; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.util.concurrent.RateLimiter; -import datadog.opentracing.DDBaseSpan; +import datadog.opentracing.DDSpan; import datadog.opentracing.DDTraceOTInfo; import datadog.trace.common.Service; import java.io.IOException; @@ -42,7 +42,7 @@ public class DDApi { * @param traces the traces to be sent * @return the staus code returned */ - public boolean sendTraces(final List>> traces) { + public boolean sendTraces(final List> traces) { return putContent("traces", tracesEndpoint, traces, traces.size()); } diff --git a/dd-trace-ot/src/main/java/datadog/trace/common/writer/ListWriter.java b/dd-trace-ot/src/main/java/datadog/trace/common/writer/ListWriter.java index f23c5224c4..cd92de12cb 100644 --- a/dd-trace-ot/src/main/java/datadog/trace/common/writer/ListWriter.java +++ b/dd-trace-ot/src/main/java/datadog/trace/common/writer/ListWriter.java @@ -1,6 +1,6 @@ package datadog.trace.common.writer; -import datadog.opentracing.DDBaseSpan; +import datadog.opentracing.DDSpan; import datadog.trace.common.Service; import java.util.LinkedList; import java.util.List; @@ -9,15 +9,15 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CountDownLatch; /** List writer used by tests mostly */ -public class ListWriter extends CopyOnWriteArrayList>> implements Writer { +public class ListWriter extends CopyOnWriteArrayList> implements Writer { private final List latches = new LinkedList<>(); - public List> firstTrace() { + public List firstTrace() { return get(0); } @Override - public void write(final List> trace) { + public void write(final List trace) { synchronized (latches) { add(trace); for (final CountDownLatch latch : latches) { diff --git a/dd-trace-ot/src/main/java/datadog/trace/common/writer/LoggingWriter.java b/dd-trace-ot/src/main/java/datadog/trace/common/writer/LoggingWriter.java index 3cbd4d5823..5e043a467e 100644 --- a/dd-trace-ot/src/main/java/datadog/trace/common/writer/LoggingWriter.java +++ b/dd-trace-ot/src/main/java/datadog/trace/common/writer/LoggingWriter.java @@ -1,7 +1,7 @@ package datadog.trace.common.writer; import com.google.auto.service.AutoService; -import datadog.opentracing.DDBaseSpan; +import datadog.opentracing.DDSpan; import datadog.trace.common.Service; import java.util.List; import java.util.Map; @@ -12,7 +12,7 @@ import lombok.extern.slf4j.Slf4j; public class LoggingWriter implements Writer { @Override - public void write(final List> trace) { + public void write(final List trace) { log.info("write(trace): {}", trace); } diff --git a/dd-trace-ot/src/main/java/datadog/trace/common/writer/Writer.java b/dd-trace-ot/src/main/java/datadog/trace/common/writer/Writer.java index 9c48379151..afa89fddaa 100644 --- a/dd-trace-ot/src/main/java/datadog/trace/common/writer/Writer.java +++ b/dd-trace-ot/src/main/java/datadog/trace/common/writer/Writer.java @@ -1,6 +1,6 @@ package datadog.trace.common.writer; -import datadog.opentracing.DDBaseSpan; +import datadog.opentracing.DDSpan; import datadog.trace.common.DDTraceConfig; import datadog.trace.common.Service; import java.util.List; @@ -18,7 +18,7 @@ public interface Writer { * * @param trace the list of spans to write */ - void write(List> trace); + void write(List trace); /** * Report additional service information to the endpoint diff --git a/dd-trace-ot/src/test/groovy/datadog/trace/ActiveSpanContinuationTest.groovy b/dd-trace-ot/src/test/groovy/datadog/trace/ActiveSpanContinuationTest.groovy deleted file mode 100644 index 05a4602a61..0000000000 --- a/dd-trace-ot/src/test/groovy/datadog/trace/ActiveSpanContinuationTest.groovy +++ /dev/null @@ -1,188 +0,0 @@ -package datadog.trace - -import datadog.opentracing.DDTracer -import datadog.trace.common.writer.ListWriter -import io.opentracing.util.ThreadLocalActiveSpan -import spock.lang.Ignore -import spock.lang.Specification - -import java.util.concurrent.Phaser -import java.util.concurrent.atomic.AtomicInteger - -class ActiveSpanContinuationTest extends Specification { - - def traceCollector = new ListWriter() - def tracer = new DDTracer(traceCollector) - def activeSpan = tracer.buildSpan("test").startActive() - AtomicInteger continuationCount - - def setup() { - def field = ThreadLocalActiveSpan.getDeclaredField("refCount") - field.setAccessible(true) - continuationCount = field.get(activeSpan) - } - - def "calling activate from multiple continuations at once with no child spans tracks separately"() { - setup: - def phaser = new Phaser() - phaser.register() - - for (int i = 0; i < count; i++) { - phaser.register() - def capture = activeSpan.capture() - new Thread({ - phaser.arriveAndAwaitAdvance() - def activeSpan = capture.activate() - phaser.arriveAndAwaitAdvance() - activeSpan.deactivate() - }).start() - } - - activeSpan.deactivate() // allow the trace to be reported when all continuations deactivate - - when: - phaser.arriveAndAwaitAdvance() //allow threads to activate capture - - then: - traceCollector == [] - - when: - phaser.arriveAndAwaitAdvance() //allow threads to deactivate their span - - then: - traceCollector.waitForTraces(1) - traceCollector.size() == 1 - traceCollector.firstTrace().size() == 1 - - where: - count = new Random().nextInt(50) + 5 - } - - def "concurrent threads with manual spans and continuations report correctly"() { - setup: - def phaser = new Phaser() - phaser.register() - - for (int i = 0; i < count; i++) { - String spanName = "child " + i - phaser.register() - def capture = activeSpan.capture() - new Thread({ - phaser.arriveAndAwaitAdvance() - def activeSpan = capture.activate() - def childSpan = tracer.buildSpan(spanName).startManual() - phaser.arriveAndAwaitAdvance() - childSpan.finish() - activeSpan.deactivate() - }).start() - } - - expect: - continuationCount.get() == count + 1 - - when: - activeSpan.deactivate() // allow the trace to be reported when all continuations deactivate - phaser.arriveAndAwaitAdvance() //allow threads to activate capture - - then: - continuationCount.get() == count - traceCollector == [] - - when: - phaser.arriveAndAwaitAdvance() //allow threads to deactivate their span - - then: - traceCollector.waitForTraces(1) - continuationCount.get() == 0 - traceCollector.size() == 1 - def trace = traceCollector.remove(0) - def parent = trace.remove(0) - - trace.size() == count - parent.context.parentId == 0 - - trace.every { - it.context.parentId == parent.context.spanId - } - - where: - count = new Random().nextInt(50) + 5 - } - - def "concurrent threads with active spans and continuations report correctly"() { - setup: - def phaser = new Phaser() - phaser.register() - - for (int i = 0; i < count; i++) { - String spanName = "child " + i - phaser.register() - def capture = activeSpan.capture() - new Thread({ - phaser.arriveAndAwaitAdvance() - def activeSpan = capture.activate() - def childSpan = tracer.buildSpan(spanName).startActive() - phaser.arriveAndAwaitAdvance() - childSpan.deactivate() - activeSpan.deactivate() - phaser.arriveAndDeregister() - }).start() - } - - expect: - continuationCount.get() == count + 1 - - when: - activeSpan.deactivate() // allow the trace to be reported when all continuations deactivate - phaser.arriveAndAwaitAdvance() //allow threads to activate capture - - then: - continuationCount.get() == count - traceCollector == [] - - when: - phaser.arriveAndAwaitAdvance() //allow threads to deactivate their span - phaser.arriveAndAwaitAdvance() // wait till all threads have deactivated - - then: - traceCollector.waitForTraces(1) - continuationCount.get() == 0 - traceCollector.size() == 1 - def trace = traceCollector.remove(0) - def parent = trace.remove(0) - - trace.size() == count - parent.context.parentId == 0 - - trace.every { - it.context.parentId == parent.context.spanId - } - - where: - count = new Random().nextInt(50) + 5 - } - - @Ignore("Not yet implemented in ThreadLocalActiveSpan.Continuation") - def "calling activate more than once results in an error"() { - setup: - def capture = activeSpan.capture() - - when: - activeSpan.deactivate() - - then: - traceCollector == [] - - when: - capture.activate().deactivate() - // parent span should be finished at this point. - then: - traceCollector == [] - - when: - capture.activate().deactivate() - - then: - thrown(RuntimeException) - } -} diff --git a/dd-trace-ot/src/test/groovy/datadog/trace/api/writer/DDAgentWriterTest.groovy b/dd-trace-ot/src/test/groovy/datadog/trace/api/writer/DDAgentWriterTest.groovy index 801cd8bf7e..f37dc34ff8 100644 --- a/dd-trace-ot/src/test/groovy/datadog/trace/api/writer/DDAgentWriterTest.groovy +++ b/dd-trace-ot/src/test/groovy/datadog/trace/api/writer/DDAgentWriterTest.groovy @@ -1,6 +1,6 @@ package datadog.trace.api.writer -import datadog.opentracing.DDBaseSpan +import datadog.opentracing.DDSpan import datadog.trace.common.writer.DDAgentWriter import datadog.trace.common.writer.DDApi import datadog.trace.common.writer.WriterQueue @@ -46,7 +46,7 @@ class DDAgentWriterTest extends Specification { def "check if trace has been added by force"() { setup: - def traces = new WriterQueue>>(capacity) + def traces = new WriterQueue>(capacity) def writer = new DDAgentWriter(Mock(DDApi), traces) when: diff --git a/dd-trace-ot/src/test/java/datadog/opentracing/DDTracerTest.java b/dd-trace-ot/src/test/java/datadog/opentracing/DDTracerTest.java index 010523d406..993b4e141e 100644 --- a/dd-trace-ot/src/test/java/datadog/opentracing/DDTracerTest.java +++ b/dd-trace-ot/src/test/java/datadog/opentracing/DDTracerTest.java @@ -25,7 +25,7 @@ public class DDTracerTest { // Rate 0.5 when(sampler.sample(any(DDSpan.class))).thenReturn(true).thenReturn(false); - final Queue> spans = new LinkedList<>(); + final Queue spans = new LinkedList<>(); spans.add(span); spans.add(span); spans.add(span); diff --git a/dd-trace-ot/src/test/java/datadog/opentracing/resolver/TracerResolverTest.java b/dd-trace-ot/src/test/java/datadog/opentracing/resolver/TracerResolverTest.java index 1511696dc1..5fbed7c73c 100644 --- a/dd-trace-ot/src/test/java/datadog/opentracing/resolver/TracerResolverTest.java +++ b/dd-trace-ot/src/test/java/datadog/opentracing/resolver/TracerResolverTest.java @@ -6,9 +6,9 @@ import datadog.opentracing.DDTracer; import datadog.opentracing.decorators.AbstractDecorator; import datadog.opentracing.decorators.HTTPComponent; import datadog.opentracing.decorators.URLAsResourceName; -import io.opentracing.NoopTracerFactory; import io.opentracing.Tracer; import io.opentracing.contrib.tracerresolver.TracerResolver; +import io.opentracing.noop.NoopTracerFactory; import io.opentracing.util.GlobalTracer; import java.lang.reflect.Field; import java.util.List; diff --git a/examples/dropwizard-mongo-client/src/main/java/datadog/example/dropwizard/client/TracedClient.java b/examples/dropwizard-mongo-client/src/main/java/datadog/example/dropwizard/client/TracedClient.java index 36fe313ee9..2b05b65bf1 100644 --- a/examples/dropwizard-mongo-client/src/main/java/datadog/example/dropwizard/client/TracedClient.java +++ b/examples/dropwizard-mongo-client/src/main/java/datadog/example/dropwizard/client/TracedClient.java @@ -2,7 +2,7 @@ package datadog.example.dropwizard.client; import datadog.trace.api.DDTags; import datadog.trace.api.Trace; -import io.opentracing.ActiveSpan; +import io.opentracing.Scope; import io.opentracing.Tracer; import io.opentracing.util.GlobalTracer; import java.io.IOException; @@ -25,8 +25,8 @@ public class TracedClient { @Trace private static void executeCall() throws IOException { final Tracer tracer = GlobalTracer.get(); - final ActiveSpan activeSpan = tracer.activeSpan(); - activeSpan.setTag(DDTags.SERVICE_NAME, "http.client"); + final Scope scope = tracer.scopeManager().active(); + scope.span().setTag(DDTags.SERVICE_NAME, "http.client"); final OkHttpClient client = new OkHttpClient().newBuilder().build(); final Request request = new Request.Builder().url("http://localhost:8080/demo/").build(); diff --git a/examples/dropwizard-mongo-client/src/main/java/datadog/example/dropwizard/resources/SimpleCrudResource.java b/examples/dropwizard-mongo-client/src/main/java/datadog/example/dropwizard/resources/SimpleCrudResource.java index e7dab297d0..ed1061cde2 100644 --- a/examples/dropwizard-mongo-client/src/main/java/datadog/example/dropwizard/resources/SimpleCrudResource.java +++ b/examples/dropwizard-mongo-client/src/main/java/datadog/example/dropwizard/resources/SimpleCrudResource.java @@ -6,7 +6,7 @@ import com.mongodb.client.MongoCursor; import com.mongodb.client.MongoDatabase; import datadog.example.dropwizard.api.Book; import datadog.trace.api.Trace; -import io.opentracing.ActiveSpan; +import io.opentracing.Scope; import io.opentracing.util.GlobalTracer; import java.util.ArrayList; import java.util.List; @@ -113,9 +113,9 @@ public class SimpleCrudResource { */ @Trace(operationName = "database.before") public void beforeDB() throws InterruptedException { - final ActiveSpan currentSpan = GlobalTracer.get().activeSpan(); - if (currentSpan != null) { - currentSpan.setTag("status", "started"); + final Scope scope = GlobalTracer.get().scopeManager().active(); + if (scope != null) { + scope.span().setTag("status", "started"); Thread.sleep(10); } } @@ -127,9 +127,9 @@ public class SimpleCrudResource { */ @Trace(operationName = "database.after") public void afterDB() throws InterruptedException { - final ActiveSpan currentSpan = GlobalTracer.get().activeSpan(); - if (currentSpan != null) { - currentSpan.setTag("status", "started"); + final Scope scope = GlobalTracer.get().scopeManager().active(); + if (scope != null) { + scope.span().setTag("status", "started"); Thread.sleep(10); } } diff --git a/examples/rest-spark/src/main/java/datadog/example/restspark/SparkApplication.java b/examples/rest-spark/src/main/java/datadog/example/restspark/SparkApplication.java index 797df5b23b..145bbe1702 100644 --- a/examples/rest-spark/src/main/java/datadog/example/restspark/SparkApplication.java +++ b/examples/rest-spark/src/main/java/datadog/example/restspark/SparkApplication.java @@ -4,7 +4,7 @@ import static spark.Spark.get; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; -import io.opentracing.ActiveSpan; +import io.opentracing.Scope; import io.opentracing.Tracer; import java.util.Arrays; import org.bson.Document; @@ -25,7 +25,7 @@ public class SparkApplication { get( "/key/:id", (req, res) -> { - try (ActiveSpan activeSpan = mTracer.buildSpan("spark.request").startActive()) { + try (Scope scope = mTracer.buildSpan("spark.request").startActive(true)) { final String id = req.params(":id"); // create a collection @@ -43,8 +43,8 @@ public class SparkApplication { System.out.println(collection.count()); // add some metadata to the request Span - activeSpan.setTag("http.status_code", res.status()); - activeSpan.setTag("http.url", req.url()); + scope.span().setTag("http.status_code", res.status()); + scope.span().setTag("http.url", req.url()); return "Stored!"; } @@ -52,11 +52,11 @@ public class SparkApplication { get( "/users/:id", (req, res) -> { - try (ActiveSpan activeSpan = mTracer.buildSpan("spark.request").startActive()) { + try (Scope scope = mTracer.buildSpan("spark.request").startActive(true)) { // this endpoint tests the 404 decorator res.status(404); - activeSpan.setTag("http.status_code", res.status()); - activeSpan.setTag("http.url", req.url()); + scope.span().setTag("http.status_code", res.status()); + scope.span().setTag("http.url", req.url()); } return "404"; }); diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index 3e81ad31be..589dae951e 100644 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -3,7 +3,7 @@ def spockGroovyVer = GroovySystem.version.replaceAll(/\.\d+$/, '') ext { version = [ - opentracing: '0.30.0', + opentracing: '0.31.0', slf4j : "1.7.25", guava : "23.0",