Merge pull request #126 from DataDog/tyler/ot-proposal
Changes required for supporting OT 0.31.0
This commit is contained in:
commit
55c8fddf28
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,14 +49,13 @@ 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()
|
||||
return GlobalTracer.get()
|
||||
.buildSpan("jms.onMessage")
|
||||
.asChildOf(extractedContext)
|
||||
.withTag(DDTags.SERVICE_NAME, "jms")
|
||||
|
@ -63,21 +63,20 @@ public final class JMS1MessageListenerInstrumentation implements Instrumenter {
|
|||
.withTag(Tags.COMPONENT.getKey(), "jms1")
|
||||
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CONSUMER)
|
||||
.withTag("span.origin.type", listener.getClass().getName())
|
||||
.startActive();
|
||||
|
||||
return span;
|
||||
.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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,14 +49,13 @@ 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()
|
||||
return GlobalTracer.get()
|
||||
.buildSpan("jms.onMessage")
|
||||
.asChildOf(extractedContext)
|
||||
.withTag(DDTags.SERVICE_NAME, "jms")
|
||||
|
@ -63,21 +63,20 @@ public final class JMS2MessageListenerInstrumentation implements Instrumenter {
|
|||
.withTag(Tags.COMPONENT.getKey(), "jms2")
|
||||
.withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CONSUMER)
|
||||
.withTag("span.origin.type", listener.getClass().getName())
|
||||
.startActive();
|
||||
|
||||
return span;
|
||||
.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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 (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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
try {
|
||||
final Scope scope = GlobalTracer.get().buildSpan(rootOperationName).startActive(true);
|
||||
try {
|
||||
return r.call();
|
||||
} catch (final Exception e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
} finally {
|
||||
rootSpan.deactivate();
|
||||
scope.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
});
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in New Issue