Merge pull request #126 from DataDog/tyler/ot-proposal

Changes required for supporting OT 0.31.0
This commit is contained in:
Tyler Benson 2018-01-16 11:06:24 -05:00 committed by GitHub
commit 55c8fddf28
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
56 changed files with 702 additions and 893 deletions

View File

@ -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);
}

View File

@ -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)

View File

@ -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<DDBaseSpan<?>> serverTrace = writer.get(0)
final List<DDSpan> serverTrace = writer.get(0)
serverTrace.size() == 1
final List<DDBaseSpan<?>> clientTrace = writer.get(1)
final List<DDSpan> 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<DDBaseSpan<?>> clientTrace = writer.get(0)
final List<DDSpan> 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

View File

@ -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<DDBaseSpan<?>> trace) {
void write(final List<DDSpan> trace) {
add(trace)
JettyServletTest.latch.countDown()
}

View File

@ -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() {

View File

@ -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());

View File

@ -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());

View File

@ -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());

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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"

View File

@ -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();
}
}
}

View File

@ -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();
}
}
}

View File

@ -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();
}
}
}

View File

@ -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();
}
}
}

View File

@ -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();
}
}
}

View File

@ -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();
}
}
}

View File

@ -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();
}
}
}

View File

@ -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();
}
}
}

View File

@ -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
}

View File

@ -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(

View File

@ -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
}

View File

@ -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();
}
}
}

View File

@ -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();
}
}
}

View File

@ -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
}

View File

@ -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(),

View File

@ -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(),

View File

@ -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);
}
}
}

View File

@ -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();
}
}
}

View File

@ -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 <T extends Object> Object runUnderTrace(
final String rootOperationName, final Callable<T> 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();
}
}

View File

@ -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

View File

@ -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;
}
}

View File

@ -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<S extends BaseSpan> implements BaseSpan<S> {
/** 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<DDBaseSpan<?>> 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<String, ?> 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<String, ?> 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<String, ?> 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<String, String> getMeta() {
final Map<String, String> meta = new HashMap<>();
for (final Entry<String, String> entry : context().getBaggageItems().entrySet()) {
meta.put(entry.getKey(), entry.getValue());
}
for (final Entry<String, Object> 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<String, Object> 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();
}
}

View File

@ -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;
* <p>Spans are created by the {@link DDTracer#buildSpan}. This implementation adds some features
* according to the DD agent.
*/
public class DDSpan extends DDBaseSpan<Span> 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<Span> 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<DDSpan> 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<String, ?> 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<String, ?> 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<String, ?> 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<String, String> getMeta() {
final Map<String, String> meta = new HashMap<>();
for (final Map.Entry<String, String> entry : context().getBaggageItems().entrySet()) {
meta.put(entry.getKey(), entry.getValue());
}
for (final Map.Entry<String, Object> 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<String, Object> 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();
}
}

View File

@ -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<DDBaseSpan<?>> trace;
private final Queue<DDSpan> 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<String, Object> tags,
final Queue<DDBaseSpan<?>> trace,
final Queue<DDSpan> trace,
final DDTracer tracer) {
this.traceId = traceId;
@ -165,7 +165,7 @@ public class DDSpanContext implements io.opentracing.SpanContext {
}
@JsonIgnore
public Queue<DDBaseSpan<?>> getTrace() {
public Queue<DDSpan> getTrace() {
return this.trace;
}

View File

@ -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<DDBaseSpan<?>> trace) {
public void write(final Queue<DDSpan> 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<String, String> baggage;
final Queue<DDBaseSpan<?>> parentTrace;
final Queue<DDSpan> 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) {

View File

@ -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;

View File

@ -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<String, Pattern> skipTagsPatterns = new HashMap<>();
@Override
public boolean sample(final DDBaseSpan<?> span) {
public boolean sample(final DDSpan span) {
// Filter by tag values
for (final Entry<String, Pattern> 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);
}

View File

@ -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;
}

View File

@ -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.
*
* <p>
*
* <p>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;

View File

@ -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 {

View File

@ -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<List<DDBaseSpan<?>>> traces;
private final WriterQueue<List<DDSpan>> traces;
private boolean queueFullReported = false;
@ -68,10 +68,10 @@ public class DDAgentWriter implements Writer {
}
public DDAgentWriter(final DDApi api) {
this(api, new WriterQueue<List<DDBaseSpan<?>>>(DEFAULT_MAX_TRACES));
this(api, new WriterQueue<List<DDSpan>>(DEFAULT_MAX_TRACES));
}
public DDAgentWriter(final DDApi api, final WriterQueue<List<DDBaseSpan<?>>> queue) {
public DDAgentWriter(final DDApi api, final WriterQueue<List<DDSpan>> 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<DDBaseSpan<?>> trace) {
final List<DDBaseSpan<?>> removed = traces.add(trace);
public void write(final List<DDSpan> trace) {
final List<DDSpan> 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<List<DDBaseSpan<?>>> payload = traces.getAll();
final List<List<DDSpan>> payload = traces.getAll();
if (log.isDebugEnabled()) {
int nbSpans = 0;

View File

@ -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<List<DDBaseSpan<?>>> traces) {
public boolean sendTraces(final List<List<DDSpan>> traces) {
return putContent("traces", tracesEndpoint, traces, traces.size());
}

View File

@ -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<List<DDBaseSpan<?>>> implements Writer {
public class ListWriter extends CopyOnWriteArrayList<List<DDSpan>> implements Writer {
private final List<CountDownLatch> latches = new LinkedList<>();
public List<DDBaseSpan<?>> firstTrace() {
public List<DDSpan> firstTrace() {
return get(0);
}
@Override
public void write(final List<DDBaseSpan<?>> trace) {
public void write(final List<DDSpan> trace) {
synchronized (latches) {
add(trace);
for (final CountDownLatch latch : latches) {

View File

@ -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<DDBaseSpan<?>> trace) {
public void write(final List<DDSpan> trace) {
log.info("write(trace): {}", trace);
}

View File

@ -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<DDBaseSpan<?>> trace);
void write(List<DDSpan> trace);
/**
* Report additional service information to the endpoint

View File

@ -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)
}
}

View File

@ -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<List<DDBaseSpan<?>>>(capacity)
def traces = new WriterQueue<List<DDSpan>>(capacity)
def writer = new DDAgentWriter(Mock(DDApi), traces)
when:

View File

@ -25,7 +25,7 @@ public class DDTracerTest {
// Rate 0.5
when(sampler.sample(any(DDSpan.class))).thenReturn(true).thenReturn(false);
final Queue<DDBaseSpan<?>> spans = new LinkedList<>();
final Queue<DDSpan> spans = new LinkedList<>();
spans.add(span);
spans.add(span);
spans.add(span);

View File

@ -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;

View File

@ -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();

View File

@ -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);
}
}

View File

@ -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";
});

View File

@ -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",