Merge pull request #791 from DataDog/mar-kolya/handle-scopes

Mar kolya/handle scopes
This commit is contained in:
Nikolay Martynov 2019-04-08 12:29:52 -04:00 committed by GitHub
commit 6ee172baaa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 380 additions and 301 deletions

View File

@ -34,8 +34,10 @@ public class TracingExecutionInterceptor implements ExecutionInterceptor {
public void beforeExecution( public void beforeExecution(
final Context.BeforeExecution context, final ExecutionAttributes executionAttributes) { final Context.BeforeExecution context, final ExecutionAttributes executionAttributes) {
final Span span = GlobalTracer.get().buildSpan("aws.command").start(); final Span span = GlobalTracer.get().buildSpan("aws.command").start();
DECORATE.afterStart(span); try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
executionAttributes.putAttribute(SPAN_ATTRIBUTE, span); DECORATE.afterStart(span);
executionAttributes.putAttribute(SPAN_ATTRIBUTE, span);
}
} }
@Override @Override

View File

@ -14,6 +14,7 @@ import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.api.DDTags; import datadog.trace.api.DDTags;
import datadog.trace.bootstrap.CallDepthThreadLocalMap; import datadog.trace.bootstrap.CallDepthThreadLocalMap;
import io.opentracing.Scope;
import io.opentracing.Span; import io.opentracing.Span;
import io.opentracing.noop.NoopSpan; import io.opentracing.noop.NoopSpan;
import io.opentracing.util.GlobalTracer; import io.opentracing.util.GlobalTracer;
@ -113,14 +114,16 @@ public class CouchbaseBucketInstrumentation extends Instrumenter.Default {
declaringClass.getSimpleName().replace("CouchbaseAsync", "").replace("DefaultAsync", ""); declaringClass.getSimpleName().replace("CouchbaseAsync", "").replace("DefaultAsync", "");
final String resourceName = className + "." + method.getName(); final String resourceName = className + "." + method.getName();
// just replace the no-op span. final Span span =
spanRef.set( GlobalTracer.get()
DECORATE.afterStart( .buildSpan("couchbase.call")
GlobalTracer.get() .withTag(DDTags.RESOURCE_NAME, resourceName)
.buildSpan("couchbase.call") .withTag("bucket", bucket)
.withTag(DDTags.RESOURCE_NAME, resourceName) .start();
.withTag("bucket", bucket) try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
.start())); // just replace the no-op span.
spanRef.set(DECORATE.afterStart(span));
}
} }
} }
@ -136,8 +139,10 @@ public class CouchbaseBucketInstrumentation extends Instrumenter.Default {
final Span span = spanRef.getAndSet(null); final Span span = spanRef.getAndSet(null);
if (span != null) { if (span != null) {
DECORATE.beforeFinish(span); try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
span.finish(); DECORATE.beforeFinish(span);
span.finish();
}
} }
} }
} }
@ -153,9 +158,11 @@ public class CouchbaseBucketInstrumentation extends Instrumenter.Default {
public void call(final Throwable throwable) { public void call(final Throwable throwable) {
final Span span = spanRef.getAndSet(null); final Span span = spanRef.getAndSet(null);
if (span != null) { if (span != null) {
DECORATE.onError(span, throwable); try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
DECORATE.beforeFinish(span); DECORATE.onError(span, throwable);
span.finish(); DECORATE.beforeFinish(span);
span.finish();
}
} }
} }
} }

View File

@ -14,6 +14,7 @@ import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.api.DDTags; import datadog.trace.api.DDTags;
import datadog.trace.bootstrap.CallDepthThreadLocalMap; import datadog.trace.bootstrap.CallDepthThreadLocalMap;
import io.opentracing.Scope;
import io.opentracing.Span; import io.opentracing.Span;
import io.opentracing.noop.NoopSpan; import io.opentracing.noop.NoopSpan;
import io.opentracing.util.GlobalTracer; import io.opentracing.util.GlobalTracer;
@ -108,13 +109,15 @@ public class CouchbaseClusterInstrumentation extends Instrumenter.Default {
declaringClass.getSimpleName().replace("CouchbaseAsync", "").replace("DefaultAsync", ""); declaringClass.getSimpleName().replace("CouchbaseAsync", "").replace("DefaultAsync", "");
final String resourceName = className + "." + method.getName(); final String resourceName = className + "." + method.getName();
// just replace the no-op span. final Span span =
spanRef.set( GlobalTracer.get()
DECORATE.afterStart( .buildSpan("couchbase.call")
GlobalTracer.get() .withTag(DDTags.RESOURCE_NAME, resourceName)
.buildSpan("couchbase.call") .start();
.withTag(DDTags.RESOURCE_NAME, resourceName) try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
.start())); // just replace the no-op span.
spanRef.set(DECORATE.afterStart(scope.span()));
}
} }
} }
@ -130,8 +133,10 @@ public class CouchbaseClusterInstrumentation extends Instrumenter.Default {
final Span span = spanRef.getAndSet(null); final Span span = spanRef.getAndSet(null);
if (span != null) { if (span != null) {
DECORATE.beforeFinish(span); try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
span.finish(); DECORATE.beforeFinish(span);
span.finish();
}
} }
} }
} }
@ -147,9 +152,11 @@ public class CouchbaseClusterInstrumentation extends Instrumenter.Default {
public void call(final Throwable throwable) { public void call(final Throwable throwable) {
final Span span = spanRef.getAndSet(null); final Span span = spanRef.getAndSet(null);
if (span != null) { if (span != null) {
DECORATE.onError(span, throwable); try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
DECORATE.beforeFinish(span); DECORATE.onError(span, throwable);
span.finish(); DECORATE.beforeFinish(span);
span.finish();
}
} }
} }
} }

View File

@ -15,8 +15,10 @@ import com.datastax.driver.core.Statement;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import io.opentracing.Scope;
import io.opentracing.Span; import io.opentracing.Span;
import io.opentracing.Tracer; import io.opentracing.Tracer;
import io.opentracing.util.GlobalTracer;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
@ -58,88 +60,108 @@ public class TracingSession implements Session {
@Override @Override
public ResultSet execute(final String query) { public ResultSet execute(final String query) {
final Span span = buildSpan(query); try (final Scope scope = startSpanWithScope(query)) {
ResultSet resultSet = null; try {
try { final ResultSet resultSet = session.execute(query);
resultSet = session.execute(query); beforeSpanFinish(scope.span(), resultSet);
return resultSet; return resultSet;
} finally { } catch (final RuntimeException e) {
finishSpan(span, resultSet); beforeSpanFinish(scope.span(), e);
throw e;
} finally {
scope.span().finish();
}
} }
} }
@Override @Override
public ResultSet execute(final String query, final Object... values) { public ResultSet execute(final String query, final Object... values) {
final Span span = buildSpan(query); try (final Scope scope = startSpanWithScope(query)) {
ResultSet resultSet = null; try {
try { final ResultSet resultSet = session.execute(query, values);
resultSet = session.execute(query, values); beforeSpanFinish(scope.span(), resultSet);
return resultSet; return resultSet;
} finally { } catch (final RuntimeException e) {
finishSpan(span, resultSet); beforeSpanFinish(scope.span(), e);
throw e;
} finally {
scope.span().finish();
}
} }
} }
@Override @Override
public ResultSet execute(final String query, final Map<String, Object> values) { public ResultSet execute(final String query, final Map<String, Object> values) {
final Span span = buildSpan(query); try (final Scope scope = startSpanWithScope(query)) {
ResultSet resultSet = null; try {
try { final ResultSet resultSet = session.execute(query, values);
resultSet = session.execute(query, values); beforeSpanFinish(scope.span(), resultSet);
return resultSet; return resultSet;
} finally { } catch (final RuntimeException e) {
finishSpan(span, resultSet); beforeSpanFinish(scope.span(), e);
throw e;
} finally {
scope.span().finish();
}
} }
} }
@Override @Override
public ResultSet execute(final Statement statement) { public ResultSet execute(final Statement statement) {
final String query = getQuery(statement); final String query = getQuery(statement);
final Span span = buildSpan(query); try (final Scope scope = startSpanWithScope(query)) {
ResultSet resultSet = null; try {
try { final ResultSet resultSet = session.execute(statement);
resultSet = session.execute(statement); beforeSpanFinish(scope.span(), resultSet);
return resultSet; return resultSet;
} finally { } catch (final RuntimeException e) {
finishSpan(span, resultSet); beforeSpanFinish(scope.span(), e);
throw e;
} finally {
scope.span().finish();
}
} }
} }
@Override @Override
public ResultSetFuture executeAsync(final String query) { public ResultSetFuture executeAsync(final String query) {
final Span span = buildSpan(query); try (final Scope scope = startSpanWithScope(query)) {
final ResultSetFuture future = session.executeAsync(query); final ResultSetFuture future = session.executeAsync(query);
future.addListener(createListener(span, future), executorService); future.addListener(createListener(scope.span(), future), executorService);
return future; return future;
}
} }
@Override @Override
public ResultSetFuture executeAsync(final String query, final Object... values) { public ResultSetFuture executeAsync(final String query, final Object... values) {
final Span span = buildSpan(query); try (final Scope scope = startSpanWithScope(query)) {
final ResultSetFuture future = session.executeAsync(query, values); final ResultSetFuture future = session.executeAsync(query, values);
future.addListener(createListener(span, future), executorService); future.addListener(createListener(scope.span(), future), executorService);
return future; return future;
}
} }
@Override @Override
public ResultSetFuture executeAsync(final String query, final Map<String, Object> values) { public ResultSetFuture executeAsync(final String query, final Map<String, Object> values) {
final Span span = buildSpan(query); try (final Scope scope = startSpanWithScope(query)) {
final ResultSetFuture future = session.executeAsync(query, values); final ResultSetFuture future = session.executeAsync(query, values);
future.addListener(createListener(span, future), executorService); future.addListener(createListener(scope.span(), future), executorService);
return future; return future;
}
} }
@Override @Override
public ResultSetFuture executeAsync(final Statement statement) { public ResultSetFuture executeAsync(final Statement statement) {
final String query = getQuery(statement); final String query = getQuery(statement);
final Span span = buildSpan(query); try (final Scope scope = startSpanWithScope(query)) {
final ResultSetFuture future = session.executeAsync(statement); final ResultSetFuture future = session.executeAsync(statement);
future.addListener(createListener(span, future), executorService); future.addListener(createListener(scope.span(), future), executorService);
return future; return future;
}
} }
@Override @Override
@ -202,32 +224,33 @@ public class TracingSession implements Session {
return new Runnable() { return new Runnable() {
@Override @Override
public void run() { public void run() {
try { try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
finishSpan(span, future.get()); beforeSpanFinish(span, future.get());
} catch (final InterruptedException | ExecutionException e) { } catch (final InterruptedException | ExecutionException e) {
finishSpan(span, e); beforeSpanFinish(span, e);
} finally {
span.finish();
} }
} }
}; };
} }
private Span buildSpan(final String query) { private Scope startSpanWithScope(final String query) {
final Span span = tracer.buildSpan("cassandra.execute").start(); final Span span = tracer.buildSpan("cassandra.execute").start();
final Scope scope = tracer.scopeManager().activate(span, false);
DECORATE.afterStart(span); DECORATE.afterStart(span);
DECORATE.onConnection(span, session); DECORATE.onConnection(span, session);
DECORATE.onStatement(span, query); DECORATE.onStatement(span, query);
return span; return scope;
} }
private static void finishSpan(final Span span, final ResultSet resultSet) { private static void beforeSpanFinish(final Span span, final ResultSet resultSet) {
DECORATE.onResponse(span, resultSet); DECORATE.onResponse(span, resultSet);
DECORATE.beforeFinish(span); DECORATE.beforeFinish(span);
span.finish();
} }
private static void finishSpan(final Span span, final Exception e) { private static void beforeSpanFinish(final Span span, final Exception e) {
DECORATE.onError(span, e); DECORATE.onError(span, e);
DECORATE.beforeFinish(span); DECORATE.beforeFinish(span);
span.finish();
} }
} }

View File

@ -16,6 +16,7 @@ import io.opentracing.Scope;
import io.opentracing.Span; import io.opentracing.Span;
import io.opentracing.Tracer; import io.opentracing.Tracer;
import io.opentracing.propagation.Format; import io.opentracing.propagation.Format;
import io.opentracing.util.GlobalTracer;
public class TracingClientInterceptor implements ClientInterceptor { public class TracingClientInterceptor implements ClientInterceptor {
@ -36,20 +37,22 @@ public class TracingClientInterceptor implements ClientInterceptor {
.buildSpan("grpc.client") .buildSpan("grpc.client")
.withTag(DDTags.RESOURCE_NAME, method.getFullMethodName()) .withTag(DDTags.RESOURCE_NAME, method.getFullMethodName())
.start(); .start();
DECORATE.afterStart(span); try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
DECORATE.afterStart(span);
final ClientCall<ReqT, RespT> result; final ClientCall<ReqT, RespT> result;
try (final Scope ignore = tracer.scopeManager().activate(span, false)) { try {
// call other interceptors // call other interceptors
result = next.newCall(method, callOptions); result = next.newCall(method, callOptions);
} catch (final Throwable e) { } catch (final Throwable e) {
DECORATE.onError(span, e); DECORATE.onError(span, e);
DECORATE.beforeFinish(span); DECORATE.beforeFinish(span);
span.finish(); span.finish();
throw e; throw e;
}
return new TracingClientCall<>(tracer, span, result);
} }
return new TracingClientCall<>(tracer, span, result);
} }
static final class TracingClientCall<ReqT, RespT> static final class TracingClientCall<ReqT, RespT>
@ -128,14 +131,14 @@ public class TracingClientInterceptor implements ClientInterceptor {
public void onClose(final Status status, final Metadata trailers) { public void onClose(final Status status, final Metadata trailers) {
DECORATE.onClose(span, status); DECORATE.onClose(span, status);
// Finishes span. // Finishes span.
try (final Scope ignored = tracer.scopeManager().activate(span, true)) { try (final Scope ignored = tracer.scopeManager().activate(span, false)) {
delegate().onClose(status, trailers); delegate().onClose(status, trailers);
DECORATE.beforeFinish(span);
} catch (final Throwable e) { } catch (final Throwable e) {
DECORATE.onError(span, e); DECORATE.onError(span, e);
throw e;
} finally {
DECORATE.beforeFinish(span); DECORATE.beforeFinish(span);
span.finish(); span.finish();
throw e;
} }
} }

View File

@ -140,7 +140,7 @@ public class TracingServerInterceptor implements ServerInterceptor {
@Override @Override
public void onCancel() { public void onCancel() {
// Finishes span. // Finishes span.
try (final Scope scope = tracer.scopeManager().activate(span, true)) { try (final Scope scope = tracer.scopeManager().activate(span, false)) {
if (scope instanceof TraceScope) { if (scope instanceof TraceScope) {
((TraceScope) scope).setAsyncPropagation(true); ((TraceScope) scope).setAsyncPropagation(true);
} }
@ -149,19 +149,19 @@ public class TracingServerInterceptor implements ServerInterceptor {
if (scope instanceof TraceScope) { if (scope instanceof TraceScope) {
((TraceScope) scope).setAsyncPropagation(false); ((TraceScope) scope).setAsyncPropagation(false);
} }
DECORATE.beforeFinish(span);
} catch (final Throwable e) { } catch (final Throwable e) {
DECORATE.onError(span, e); DECORATE.onError(span, e);
throw e;
} finally {
DECORATE.beforeFinish(span); DECORATE.beforeFinish(span);
span.finish(); span.finish();
throw e;
} }
} }
@Override @Override
public void onComplete() { public void onComplete() {
// Finishes span. // Finishes span.
try (final Scope scope = tracer.scopeManager().activate(span, true)) { try (final Scope scope = tracer.scopeManager().activate(span, false)) {
if (scope instanceof TraceScope) { if (scope instanceof TraceScope) {
((TraceScope) scope).setAsyncPropagation(true); ((TraceScope) scope).setAsyncPropagation(true);
} }
@ -169,12 +169,12 @@ public class TracingServerInterceptor implements ServerInterceptor {
if (scope instanceof TraceScope) { if (scope instanceof TraceScope) {
((TraceScope) scope).setAsyncPropagation(false); ((TraceScope) scope).setAsyncPropagation(false);
} }
DECORATE.beforeFinish(span);
} catch (final Throwable e) { } catch (final Throwable e) {
DECORATE.onError(span, e); DECORATE.onError(span, e);
throw e;
} finally {
DECORATE.beforeFinish(span); DECORATE.beforeFinish(span);
span.finish(); span.finish();
throw e;
} }
} }

View File

@ -13,6 +13,7 @@ import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.bootstrap.CallDepthThreadLocalMap; import datadog.trace.bootstrap.CallDepthThreadLocalMap;
import datadog.trace.bootstrap.ContextStore; import datadog.trace.bootstrap.ContextStore;
import datadog.trace.bootstrap.InstrumentationContext; import datadog.trace.bootstrap.InstrumentationContext;
import io.opentracing.Scope;
import io.opentracing.Span; import io.opentracing.Span;
import io.opentracing.Tracer; import io.opentracing.Tracer;
import io.opentracing.propagation.Format; import io.opentracing.propagation.Format;
@ -178,9 +179,11 @@ public class HttpUrlConnectionInstrumentation extends Instrumenter.Default {
public Span startSpan(final HttpURLConnection connection) { public Span startSpan(final HttpURLConnection connection) {
final Tracer.SpanBuilder builder = GlobalTracer.get().buildSpan(OPERATION_NAME); final Tracer.SpanBuilder builder = GlobalTracer.get().buildSpan(OPERATION_NAME);
span = builder.start(); span = builder.start();
DECORATE.afterStart(span); try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
DECORATE.onRequest(span, connection); DECORATE.afterStart(span);
return span; DECORATE.onRequest(span, connection);
return span;
}
} }
public boolean hasSpan() { public boolean hasSpan() {
@ -196,11 +199,13 @@ public class HttpUrlConnectionInstrumentation extends Instrumenter.Default {
} }
public void finishSpan(final Throwable throwable) { public void finishSpan(final Throwable throwable) {
DECORATE.onError(span, throwable); try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
DECORATE.beforeFinish(span); DECORATE.onError(span, throwable);
span.finish(); DECORATE.beforeFinish(span);
span = null; span.finish();
finished = true; span = null;
finished = true;
}
} }
public void finishSpan(final int responseCode) { public void finishSpan(final int responseCode) {
@ -210,11 +215,13 @@ public class HttpUrlConnectionInstrumentation extends Instrumenter.Default {
* (e.g. breaks getOutputStream). * (e.g. breaks getOutputStream).
*/ */
if (responseCode > 0) { if (responseCode > 0) {
DECORATE.onResponse(span, responseCode); try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
DECORATE.beforeFinish(span); DECORATE.onResponse(span, responseCode);
span.finish(); DECORATE.beforeFinish(span);
span = null; span.finish();
finished = true; span = null;
finished = true;
}
} }
} }
} }

View File

@ -12,6 +12,7 @@ import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.api.Config; import datadog.trace.api.Config;
import datadog.trace.api.DDSpanTypes; import datadog.trace.api.DDSpanTypes;
import datadog.trace.api.DDTags; import datadog.trace.api.DDTags;
import io.opentracing.Scope;
import io.opentracing.Span; import io.opentracing.Span;
import io.opentracing.tag.Tags; import io.opentracing.tag.Tags;
import io.opentracing.util.GlobalTracer; import io.opentracing.util.GlobalTracer;
@ -65,17 +66,18 @@ public class UrlInstrumentation extends Instrumenter.Default {
.withTag(DDTags.SPAN_TYPE, DDSpanTypes.HTTP_CLIENT) .withTag(DDTags.SPAN_TYPE, DDSpanTypes.HTTP_CLIENT)
.withTag(Tags.COMPONENT.getKey(), COMPONENT) .withTag(Tags.COMPONENT.getKey(), COMPONENT)
.start(); .start();
try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
Tags.HTTP_URL.set(span, url.toString());
Tags.PEER_PORT.set(span, url.getPort() == -1 ? 80 : url.getPort());
Tags.PEER_HOSTNAME.set(span, url.getHost());
if (Config.get().isHttpClientSplitByDomain()) {
span.setTag(DDTags.SERVICE_NAME, url.getHost());
}
Tags.HTTP_URL.set(span, url.toString()); Tags.ERROR.set(span, true);
Tags.PEER_PORT.set(span, url.getPort() == -1 ? 80 : url.getPort()); span.log(Collections.singletonMap(ERROR_OBJECT, throwable));
Tags.PEER_HOSTNAME.set(span, url.getHost()); span.finish();
if (Config.get().isHttpClientSplitByDomain()) {
span.setTag(DDTags.SERVICE_NAME, url.getHost());
} }
Tags.ERROR.set(span, true);
span.log(Collections.singletonMap(ERROR_OBJECT, throwable));
span.finish();
} }
} }
} }

View File

@ -81,9 +81,9 @@ public final class JerseyClientConnectionErrorInstrumentation extends Instrument
@Advice.OnMethodExit(suppress = Throwable.class) @Advice.OnMethodExit(suppress = Throwable.class)
public static void handleError( public static void handleError(
@Advice.FieldValue("requestContext") final ClientRequest context, @Advice.FieldValue("requestContext") final ClientRequest context,
@Advice.Return(readOnly = false) Future future) { @Advice.Return(readOnly = false) Future<?> future) {
if (!(future instanceof WrappedFuture)) { if (!(future instanceof WrappedFuture)) {
future = new WrappedFuture(future, context); future = new WrappedFuture<>(future, context);
} }
} }
} }

View File

@ -81,9 +81,9 @@ public final class ResteasyClientConnectionErrorInstrumentation extends Instrume
@Advice.OnMethodExit(suppress = Throwable.class) @Advice.OnMethodExit(suppress = Throwable.class)
public static void handleError( public static void handleError(
@Advice.FieldValue("configuration") final ClientConfiguration context, @Advice.FieldValue("configuration") final ClientConfiguration context,
@Advice.Return(readOnly = false) Future future) { @Advice.Return(readOnly = false) Future<?> future) {
if (!(future instanceof WrappedFuture)) { if (!(future instanceof WrappedFuture)) {
future = new WrappedFuture(future, context); future = new WrappedFuture<>(future, context);
} }
} }
} }

View File

@ -3,6 +3,7 @@ package datadog.trace.instrumentation.jaxrs;
import static datadog.trace.instrumentation.jaxrs.JaxRsClientDecorator.DECORATE; import static datadog.trace.instrumentation.jaxrs.JaxRsClientDecorator.DECORATE;
import datadog.trace.api.DDTags; import datadog.trace.api.DDTags;
import io.opentracing.Scope;
import io.opentracing.Span; import io.opentracing.Span;
import io.opentracing.propagation.Format; import io.opentracing.propagation.Format;
import io.opentracing.util.GlobalTracer; import io.opentracing.util.GlobalTracer;
@ -21,24 +22,25 @@ public class ClientTracingFilter implements ClientRequestFilter, ClientResponseF
@Override @Override
public void filter(final ClientRequestContext requestContext) { public void filter(final ClientRequestContext requestContext) {
final Span span = final Span span =
GlobalTracer.get() GlobalTracer.get()
.buildSpan("jax-rs.client.call") .buildSpan("jax-rs.client.call")
.withTag(DDTags.RESOURCE_NAME, requestContext.getMethod() + " jax-rs.client.call") .withTag(DDTags.RESOURCE_NAME, requestContext.getMethod() + " jax-rs.client.call")
.start(); .start();
DECORATE.afterStart(span); try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
DECORATE.onRequest(span, requestContext); DECORATE.afterStart(span);
DECORATE.onRequest(span, requestContext);
log.debug("{} - client span started", span); log.debug("{} - client span started", span);
GlobalTracer.get() GlobalTracer.get()
.inject( .inject(
span.context(), span.context(),
Format.Builtin.HTTP_HEADERS, Format.Builtin.HTTP_HEADERS,
new InjectAdapter(requestContext.getHeaders())); new InjectAdapter(requestContext.getHeaders()));
requestContext.setProperty(SPAN_PROPERTY_NAME, span); requestContext.setProperty(SPAN_PROPERTY_NAME, span);
}
} }
@Override @Override

View File

@ -10,6 +10,7 @@ import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.agent.tooling.Instrumenter;
import io.opentracing.Scope;
import io.opentracing.Span; import io.opentracing.Span;
import io.opentracing.SpanContext; import io.opentracing.SpanContext;
import io.opentracing.Tracer; import io.opentracing.Tracer;
@ -92,15 +93,17 @@ public final class JMSMessageConsumerInstrumentation extends Instrumenter.Defaul
} }
final Span span = spanBuilder.start(); final Span span = spanBuilder.start();
CONSUMER_DECORATE.afterStart(span); try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
if (message == null) { CONSUMER_DECORATE.afterStart(span);
CONSUMER_DECORATE.onReceive(span, method); if (message == null) {
} else { CONSUMER_DECORATE.onReceive(span, method);
CONSUMER_DECORATE.onConsume(span, message); } else {
CONSUMER_DECORATE.onConsume(span, message);
}
CONSUMER_DECORATE.onError(span, throwable);
CONSUMER_DECORATE.beforeFinish(span);
span.finish();
} }
CONSUMER_DECORATE.onError(span, throwable);
CONSUMER_DECORATE.beforeFinish(span);
span.finish();
} }
} }
} }

View File

@ -48,7 +48,7 @@ public final class MongoClientInstrumentation extends Instrumenter.Default {
"datadog.trace.agent.decorator.ClientDecorator", "datadog.trace.agent.decorator.ClientDecorator",
"datadog.trace.agent.decorator.DatabaseClientDecorator", "datadog.trace.agent.decorator.DatabaseClientDecorator",
packageName + ".MongoClientDecorator", packageName + ".MongoClientDecorator",
packageName + ".DDTracingCommandListener" packageName + ".TracingCommandListener"
}; };
} }
@ -66,7 +66,7 @@ public final class MongoClientInstrumentation extends Instrumenter.Default {
// referencing "this" in the method args causes the class to load under a transformer. // referencing "this" in the method args causes the class to load under a transformer.
// This bypasses the Builder instrumentation. Casting as a workaround. // This bypasses the Builder instrumentation. Casting as a workaround.
final MongoClientOptions.Builder builder = (MongoClientOptions.Builder) dis; final MongoClientOptions.Builder builder = (MongoClientOptions.Builder) dis;
final DDTracingCommandListener listener = new DDTracingCommandListener(); final TracingCommandListener listener = new TracingCommandListener();
builder.addCommandListener(listener); builder.addCommandListener(listener);
} }
} }

View File

@ -6,6 +6,7 @@ import com.mongodb.event.CommandFailedEvent;
import com.mongodb.event.CommandListener; import com.mongodb.event.CommandListener;
import com.mongodb.event.CommandStartedEvent; import com.mongodb.event.CommandStartedEvent;
import com.mongodb.event.CommandSucceededEvent; import com.mongodb.event.CommandSucceededEvent;
import io.opentracing.Scope;
import io.opentracing.Span; import io.opentracing.Span;
import io.opentracing.util.GlobalTracer; import io.opentracing.util.GlobalTracer;
import java.util.Map; import java.util.Map;
@ -13,23 +14,25 @@ import java.util.concurrent.ConcurrentHashMap;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@Slf4j @Slf4j
public class DDTracingCommandListener implements CommandListener { public class TracingCommandListener implements CommandListener {
private final Map<Integer, Span> spanMap = new ConcurrentHashMap<>(); private final Map<Integer, Span> spanMap = new ConcurrentHashMap<>();
@Override @Override
public void commandStarted(final CommandStartedEvent event) { public void commandStarted(final CommandStartedEvent event) {
final Span span = GlobalTracer.get().buildSpan("mongo.query").start(); final Span span = GlobalTracer.get().buildSpan("mongo.query").start();
DECORATE.afterStart(span); try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
DECORATE.onConnection(span, event); DECORATE.afterStart(span);
if (event.getConnectionDescription() != null DECORATE.onConnection(span, event);
&& event.getConnectionDescription() != null if (event.getConnectionDescription() != null
&& event.getConnectionDescription().getServerAddress() != null) { && event.getConnectionDescription() != null
DECORATE.onPeerConnection( && event.getConnectionDescription().getServerAddress() != null) {
span, event.getConnectionDescription().getServerAddress().getSocketAddress()); DECORATE.onPeerConnection(
span, event.getConnectionDescription().getServerAddress().getSocketAddress());
}
DECORATE.onStatement(span, event.getCommand());
spanMap.put(event.getRequestId(), span);
} }
DECORATE.onStatement(span, event.getCommand());
spanMap.put(event.getRequestId(), span);
} }
@Override @Override

View File

@ -48,7 +48,7 @@ public final class MongoAsyncClientInstrumentation extends Instrumenter.Default
"datadog.trace.agent.decorator.ClientDecorator", "datadog.trace.agent.decorator.ClientDecorator",
"datadog.trace.agent.decorator.DatabaseClientDecorator", "datadog.trace.agent.decorator.DatabaseClientDecorator",
packageName + ".MongoClientDecorator", packageName + ".MongoClientDecorator",
packageName + ".DDTracingCommandListener" packageName + ".TracingCommandListener"
}; };
} }
@ -66,7 +66,7 @@ public final class MongoAsyncClientInstrumentation extends Instrumenter.Default
// referencing "this" in the method args causes the class to load under a transformer. // referencing "this" in the method args causes the class to load under a transformer.
// This bypasses the Builder instrumentation. Casting as a workaround. // This bypasses the Builder instrumentation. Casting as a workaround.
final MongoClientSettings.Builder builder = (MongoClientSettings.Builder) dis; final MongoClientSettings.Builder builder = (MongoClientSettings.Builder) dis;
final DDTracingCommandListener listener = new DDTracingCommandListener(); final TracingCommandListener listener = new TracingCommandListener();
builder.addCommandListener(listener); builder.addCommandListener(listener);
} }
} }

View File

@ -1,7 +1,6 @@
package datadog.trace.instrumentation.netty40; package datadog.trace.instrumentation.netty40;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType; import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static io.opentracing.log.Fields.ERROR_OBJECT;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isInterface; import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
@ -12,6 +11,7 @@ import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.context.TraceScope; import datadog.trace.context.TraceScope;
import datadog.trace.instrumentation.netty40.server.NettyHttpServerDecorator;
import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFuture;
import io.opentracing.Scope; import io.opentracing.Scope;
import io.opentracing.Span; import io.opentracing.Span;
@ -83,18 +83,20 @@ public class ChannelFutureListenerInstrumentation extends Instrumenter.Default {
if (continuation == null) { if (continuation == null) {
return null; return null;
} }
final TraceScope scope = continuation.activate(); final TraceScope parentScope = continuation.activate();
final Span errorSpan = final Span errorSpan =
GlobalTracer.get() GlobalTracer.get()
.buildSpan("netty.connect") .buildSpan("netty.connect")
.withTag(Tags.COMPONENT.getKey(), "netty") .withTag(Tags.COMPONENT.getKey(), "netty")
.start(); .start();
Tags.ERROR.set(errorSpan, true); try (final Scope scope = GlobalTracer.get().scopeManager().activate(errorSpan, false)) {
errorSpan.log(singletonMap(ERROR_OBJECT, cause)); NettyHttpServerDecorator.DECORATE.onError(errorSpan, cause);
errorSpan.finish(); NettyHttpServerDecorator.DECORATE.beforeFinish(errorSpan);
errorSpan.finish();
}
return scope; return parentScope;
} }
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)

View File

@ -8,6 +8,7 @@ import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundHandlerAdapter; import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPromise; import io.netty.channel.ChannelPromise;
import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpRequest;
import io.opentracing.Scope;
import io.opentracing.Span; import io.opentracing.Span;
import io.opentracing.propagation.Format; import io.opentracing.propagation.Format;
import io.opentracing.util.GlobalTracer; import io.opentracing.util.GlobalTracer;
@ -24,40 +25,44 @@ public class HttpClientRequestTracingHandler extends ChannelOutboundHandlerAdapt
return; return;
} }
TraceScope scope = null; TraceScope parentScope = null;
final TraceScope.Continuation continuation = final TraceScope.Continuation continuation =
ctx.channel().attr(AttributeKeys.PARENT_CONNECT_CONTINUATION_ATTRIBUTE_KEY).getAndRemove(); ctx.channel().attr(AttributeKeys.PARENT_CONNECT_CONTINUATION_ATTRIBUTE_KEY).getAndRemove();
if (continuation != null) { if (continuation != null) {
scope = continuation.activate(); parentScope = continuation.activate();
} }
final HttpRequest request = (HttpRequest) msg; final HttpRequest request = (HttpRequest) msg;
final Span span = GlobalTracer.get().buildSpan("netty.client.request").start(); final Span span = GlobalTracer.get().buildSpan("netty.client.request").start();
DECORATE.afterStart(span); try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
DECORATE.onRequest(span, request); DECORATE.afterStart(span);
DECORATE.onPeerConnection(span, (InetSocketAddress) ctx.channel().remoteAddress()); DECORATE.onRequest(span, request);
DECORATE.onPeerConnection(span, (InetSocketAddress) ctx.channel().remoteAddress());
// AWS calls are often signed, so we can't add headers without breaking the signature. // AWS calls are often signed, so we can't add headers without breaking the signature.
if (!request.headers().contains("amz-sdk-invocation-id")) { if (!request.headers().contains("amz-sdk-invocation-id")) {
GlobalTracer.get() GlobalTracer.get()
.inject( .inject(
span.context(), Format.Builtin.HTTP_HEADERS, new NettyResponseInjectAdapter(request)); span.context(),
Format.Builtin.HTTP_HEADERS,
new NettyResponseInjectAdapter(request));
}
ctx.channel().attr(AttributeKeys.CLIENT_ATTRIBUTE_KEY).set(span);
try {
ctx.write(msg, prm);
} catch (final Throwable throwable) {
DECORATE.onError(span, throwable);
DECORATE.beforeFinish(span);
span.finish();
throw throwable;
}
} }
ctx.channel().attr(AttributeKeys.CLIENT_ATTRIBUTE_KEY).set(span); if (null != parentScope) {
parentScope.close();
try {
ctx.write(msg, prm);
} catch (final Throwable throwable) {
DECORATE.onError(span, throwable);
DECORATE.beforeFinish(span);
span.finish();
throw throwable;
}
if (null != scope) {
scope.close();
} }
} }
} }

View File

@ -29,31 +29,27 @@ public class HttpServerRequestTracingHandler extends ChannelInboundHandlerAdapte
GlobalTracer.get() GlobalTracer.get()
.extract(Format.Builtin.HTTP_HEADERS, new NettyRequestExtractAdapter(request)); .extract(Format.Builtin.HTTP_HEADERS, new NettyRequestExtractAdapter(request));
final Scope scope = final Span span =
GlobalTracer.get() GlobalTracer.get().buildSpan("netty.request").asChildOf(extractedContext).start();
.buildSpan("netty.request") try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
.asChildOf(extractedContext) DECORATE.afterStart(span);
.startActive(false); DECORATE.onRequest(span, request);
final Span span = scope.span(); DECORATE.onPeerConnection(span, remoteAddress);
DECORATE.afterStart(span);
DECORATE.onRequest(span, request);
DECORATE.onPeerConnection(span, remoteAddress);
if (scope instanceof TraceScope) { if (scope instanceof TraceScope) {
((TraceScope) scope).setAsyncPropagation(true); ((TraceScope) scope).setAsyncPropagation(true);
} }
ctx.channel().attr(AttributeKeys.SERVER_ATTRIBUTE_KEY).set(span); ctx.channel().attr(AttributeKeys.SERVER_ATTRIBUTE_KEY).set(span);
try { try {
ctx.fireChannelRead(msg); ctx.fireChannelRead(msg);
} catch (final Throwable throwable) { } catch (final Throwable throwable) {
DECORATE.onError(span, throwable); DECORATE.onError(span, throwable);
DECORATE.beforeFinish(span); DECORATE.beforeFinish(span);
span.finish(); // Finish the span manually since finishSpanOnClose was false span.finish(); // Finish the span manually since finishSpanOnClose was false
throw throwable; throw throwable;
} finally { }
scope.close();
} }
} }
} }

View File

@ -1,7 +1,6 @@
package datadog.trace.instrumentation.netty41; package datadog.trace.instrumentation.netty41;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType; import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static io.opentracing.log.Fields.ERROR_OBJECT;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isInterface; import static net.bytebuddy.matcher.ElementMatchers.isInterface;
import static net.bytebuddy.matcher.ElementMatchers.isMethod; import static net.bytebuddy.matcher.ElementMatchers.isMethod;
@ -12,6 +11,7 @@ import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import com.google.auto.service.AutoService; import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.context.TraceScope; import datadog.trace.context.TraceScope;
import datadog.trace.instrumentation.netty41.server.NettyHttpServerDecorator;
import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFuture;
import io.opentracing.Scope; import io.opentracing.Scope;
import io.opentracing.Span; import io.opentracing.Span;
@ -83,18 +83,20 @@ public class ChannelFutureListenerInstrumentation extends Instrumenter.Default {
if (continuation == null) { if (continuation == null) {
return null; return null;
} }
final TraceScope scope = continuation.activate(); final TraceScope parentScope = continuation.activate();
final Span errorSpan = final Span errorSpan =
GlobalTracer.get() GlobalTracer.get()
.buildSpan("netty.connect") .buildSpan("netty.connect")
.withTag(Tags.COMPONENT.getKey(), "netty") .withTag(Tags.COMPONENT.getKey(), "netty")
.start(); .start();
Tags.ERROR.set(errorSpan, true); try (final Scope scope = GlobalTracer.get().scopeManager().activate(errorSpan, false)) {
errorSpan.log(singletonMap(ERROR_OBJECT, cause)); NettyHttpServerDecorator.DECORATE.onError(errorSpan, cause);
errorSpan.finish(); NettyHttpServerDecorator.DECORATE.beforeFinish(errorSpan);
errorSpan.finish();
}
return scope; return parentScope;
} }
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)

View File

@ -8,6 +8,7 @@ import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundHandlerAdapter; import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPromise; import io.netty.channel.ChannelPromise;
import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpRequest;
import io.opentracing.Scope;
import io.opentracing.Span; import io.opentracing.Span;
import io.opentracing.propagation.Format; import io.opentracing.propagation.Format;
import io.opentracing.util.GlobalTracer; import io.opentracing.util.GlobalTracer;
@ -24,40 +25,44 @@ public class HttpClientRequestTracingHandler extends ChannelOutboundHandlerAdapt
return; return;
} }
TraceScope scope = null; TraceScope parentScope = null;
final TraceScope.Continuation continuation = final TraceScope.Continuation continuation =
ctx.channel().attr(AttributeKeys.PARENT_CONNECT_CONTINUATION_ATTRIBUTE_KEY).getAndRemove(); ctx.channel().attr(AttributeKeys.PARENT_CONNECT_CONTINUATION_ATTRIBUTE_KEY).getAndRemove();
if (continuation != null) { if (continuation != null) {
scope = continuation.activate(); parentScope = continuation.activate();
} }
final HttpRequest request = (HttpRequest) msg; final HttpRequest request = (HttpRequest) msg;
final Span span = GlobalTracer.get().buildSpan("netty.client.request").start(); final Span span = GlobalTracer.get().buildSpan("netty.client.request").start();
DECORATE.afterStart(span); try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
DECORATE.onRequest(span, request); DECORATE.afterStart(span);
DECORATE.onPeerConnection(span, (InetSocketAddress) ctx.channel().remoteAddress()); DECORATE.onRequest(span, request);
DECORATE.onPeerConnection(span, (InetSocketAddress) ctx.channel().remoteAddress());
// AWS calls are often signed, so we can't add headers without breaking the signature. // AWS calls are often signed, so we can't add headers without breaking the signature.
if (!request.headers().contains("amz-sdk-invocation-id")) { if (!request.headers().contains("amz-sdk-invocation-id")) {
GlobalTracer.get() GlobalTracer.get()
.inject( .inject(
span.context(), Format.Builtin.HTTP_HEADERS, new NettyResponseInjectAdapter(request)); span.context(),
Format.Builtin.HTTP_HEADERS,
new NettyResponseInjectAdapter(request));
}
ctx.channel().attr(AttributeKeys.CLIENT_ATTRIBUTE_KEY).set(span);
try {
ctx.write(msg, prm);
} catch (final Throwable throwable) {
DECORATE.onError(span, throwable);
DECORATE.beforeFinish(span);
span.finish();
throw throwable;
}
} }
ctx.channel().attr(AttributeKeys.CLIENT_ATTRIBUTE_KEY).set(span); if (null != parentScope) {
parentScope.close();
try {
ctx.write(msg, prm);
} catch (final Throwable throwable) {
DECORATE.onError(span, throwable);
DECORATE.beforeFinish(span);
span.finish();
throw throwable;
}
if (null != scope) {
scope.close();
} }
} }
} }

View File

@ -29,31 +29,27 @@ public class HttpServerRequestTracingHandler extends ChannelInboundHandlerAdapte
GlobalTracer.get() GlobalTracer.get()
.extract(Format.Builtin.HTTP_HEADERS, new NettyRequestExtractAdapter(request)); .extract(Format.Builtin.HTTP_HEADERS, new NettyRequestExtractAdapter(request));
final Scope scope = final Span span =
GlobalTracer.get() GlobalTracer.get().buildSpan("netty.request").asChildOf(extractedContext).start();
.buildSpan("netty.request") try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
.asChildOf(extractedContext) DECORATE.afterStart(span);
.startActive(false); DECORATE.onRequest(span, request);
final Span span = scope.span(); DECORATE.onPeerConnection(span, remoteAddress);
DECORATE.afterStart(span);
DECORATE.onRequest(span, request);
DECORATE.onPeerConnection(span, remoteAddress);
if (scope instanceof TraceScope) { if (scope instanceof TraceScope) {
((TraceScope) scope).setAsyncPropagation(true); ((TraceScope) scope).setAsyncPropagation(true);
} }
ctx.channel().attr(AttributeKeys.SERVER_ATTRIBUTE_KEY).set(span); ctx.channel().attr(AttributeKeys.SERVER_ATTRIBUTE_KEY).set(span);
try { try {
ctx.fireChannelRead(msg); ctx.fireChannelRead(msg);
} catch (final Throwable throwable) { } catch (final Throwable throwable) {
DECORATE.onError(span, throwable); DECORATE.onError(span, throwable);
DECORATE.beforeFinish(span); DECORATE.beforeFinish(span);
span.finish(); // Finish the span manually since finishSpanOnClose was false span.finish(); // Finish the span manually since finishSpanOnClose was false
throw throwable; throw throwable;
} finally { }
scope.close();
} }
} }
} }

View File

@ -28,7 +28,7 @@ public class TracingCallFactory implements Call.Factory {
final Span span = GlobalTracer.get().buildSpan("okhttp.http").start(); final Span span = GlobalTracer.get().buildSpan("okhttp.http").start();
try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) { try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
DECORATE.afterStart(scope); DECORATE.afterStart(scope);
DECORATE.onRequest(scope.span(), request); DECORATE.onRequest(span, request);
/** In case of exception network interceptor is not called */ /** In case of exception network interceptor is not called */
final OkHttpClient.Builder okBuilder = okHttpClient.newBuilder(); final OkHttpClient.Builder okBuilder = okHttpClient.newBuilder();

View File

@ -189,10 +189,11 @@ public class RabbitChannelInstrumentation extends Instrumenter.Default {
public static class ChannelGetAdvice { public static class ChannelGetAdvice {
@Advice.OnMethodEnter @Advice.OnMethodEnter
public static long takeTimestamp( public static long takeTimestamp(
@Advice.Local("placeholderScope") Scope scope, @Advice.Local("callDepth") int callDepth) { @Advice.Local("placeholderScope") Scope placeholderScope,
@Advice.Local("callDepth") int callDepth) {
callDepth = CallDepthThreadLocalMap.incrementCallDepth(Channel.class); callDepth = CallDepthThreadLocalMap.incrementCallDepth(Channel.class);
// Don't want RabbitCommandInstrumentation to mess up our actual parent span. // Don't want RabbitCommandInstrumentation to mess up our actual parent span.
scope = GlobalTracer.get().scopeManager().activate(NoopSpan.INSTANCE, true); placeholderScope = GlobalTracer.get().scopeManager().activate(NoopSpan.INSTANCE, false);
return System.currentTimeMillis(); return System.currentTimeMillis();
} }
@ -201,13 +202,13 @@ public class RabbitChannelInstrumentation extends Instrumenter.Default {
@Advice.This final Channel channel, @Advice.This final Channel channel,
@Advice.Argument(0) final String queue, @Advice.Argument(0) final String queue,
@Advice.Enter final long startTime, @Advice.Enter final long startTime,
@Advice.Local("placeholderScope") final Scope scope, @Advice.Local("placeholderScope") final Scope placeholderScope,
@Advice.Local("callDepth") final int callDepth, @Advice.Local("callDepth") final int callDepth,
@Advice.Return final GetResponse response, @Advice.Return final GetResponse response,
@Advice.Thrown final Throwable throwable) { @Advice.Thrown final Throwable throwable) {
if (scope.span() instanceof NoopSpan) { if (placeholderScope.span() instanceof NoopSpan) {
scope.close(); placeholderScope.close();
} }
if (callDepth > 0) { if (callDepth > 0) {
@ -236,6 +237,8 @@ public class RabbitChannelInstrumentation extends Instrumenter.Default {
final Integer length = response == null ? null : response.getBody().length; final Integer length = response == null ? null : response.getBody().length;
// TODO: it would be better if we could actually have span wrapped into the scope started in
// OnMethodEnter
final Span span = final Span span =
GlobalTracer.get() GlobalTracer.get()
.buildSpan("amqp.command") .buildSpan("amqp.command")
@ -244,13 +247,16 @@ public class RabbitChannelInstrumentation extends Instrumenter.Default {
.withTag("message.size", length) .withTag("message.size", length)
.withTag(Tags.PEER_PORT.getKey(), connection.getPort()) .withTag(Tags.PEER_PORT.getKey(), connection.getPort())
.start(); .start();
CONSUMER_DECORATE.afterStart(span); try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
CONSUMER_DECORATE.onGet(span, queue); CONSUMER_DECORATE.afterStart(span);
CONSUMER_DECORATE.onPeerConnection(span, connection.getAddress()); CONSUMER_DECORATE.onGet(span, queue);
CONSUMER_DECORATE.onError(span, throwable); CONSUMER_DECORATE.onPeerConnection(span, connection.getAddress());
CONSUMER_DECORATE.beforeFinish(span); CONSUMER_DECORATE.onError(span, throwable);
span.finish(); CONSUMER_DECORATE.beforeFinish(span);
CallDepthThreadLocalMap.reset(Channel.class); } finally {
span.finish();
CallDepthThreadLocalMap.reset(Channel.class);
}
} }
} }

View File

@ -2,6 +2,7 @@ package datadog.trace.instrumentation.spymemcached;
import static datadog.trace.instrumentation.spymemcached.MemcacheClientDecorator.DECORATE; import static datadog.trace.instrumentation.spymemcached.MemcacheClientDecorator.DECORATE;
import io.opentracing.Scope;
import io.opentracing.Span; import io.opentracing.Span;
import io.opentracing.util.GlobalTracer; import io.opentracing.util.GlobalTracer;
import java.util.concurrent.CancellationException; import java.util.concurrent.CancellationException;
@ -29,40 +30,47 @@ public abstract class CompletionListener<T> {
public CompletionListener(final MemcachedConnection connection, final String methodName) { public CompletionListener(final MemcachedConnection connection, final String methodName) {
this.connection = connection; this.connection = connection;
span = GlobalTracer.get().buildSpan(OPERATION_NAME).start(); span = GlobalTracer.get().buildSpan(OPERATION_NAME).start();
DECORATE.afterStart(span); try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
DECORATE.onConnection(span, connection); DECORATE.afterStart(span);
DECORATE.onOperation(span, methodName); DECORATE.onConnection(span, connection);
DECORATE.onOperation(span, methodName);
}
} }
protected void closeAsyncSpan(final T future) { protected void closeAsyncSpan(final T future) {
try { try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
processResult(span, future); try {
} catch (final CancellationException e) { processResult(span, future);
span.setTag(DB_COMMAND_CANCELLED, true); } catch (final CancellationException e) {
} catch (final ExecutionException e) {
if (e.getCause() instanceof CancellationException) {
// Looks like underlying OperationFuture wraps CancellationException into ExecutionException
span.setTag(DB_COMMAND_CANCELLED, true); span.setTag(DB_COMMAND_CANCELLED, true);
} else { } catch (final ExecutionException e) {
DECORATE.onError(span, e.getCause()); if (e.getCause() instanceof CancellationException) {
// Looks like underlying OperationFuture wraps CancellationException into
// ExecutionException
span.setTag(DB_COMMAND_CANCELLED, true);
} else {
DECORATE.onError(span, e.getCause());
}
} catch (final InterruptedException e) {
// Avoid swallowing InterruptedException
DECORATE.onError(span, e);
Thread.currentThread().interrupt();
} catch (final Exception e) {
// This should never happen, just in case to make sure we cover all unexpected exceptions
DECORATE.onError(span, e);
} finally {
DECORATE.beforeFinish(span);
span.finish();
} }
} catch (final InterruptedException e) {
// Avoid swallowing InterruptedException
DECORATE.onError(span, e);
Thread.currentThread().interrupt();
} catch (final Exception e) {
// This should never happen, just in case to make sure we cover all unexpected exceptions
DECORATE.onError(span, e);
} finally {
DECORATE.beforeFinish(span);
span.finish();
} }
} }
protected void closeSyncSpan(final Throwable thrown) { protected void closeSyncSpan(final Throwable thrown) {
DECORATE.onError(span, thrown); try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
DECORATE.beforeFinish(span); DECORATE.onError(span, thrown);
span.finish(); DECORATE.beforeFinish(span);
span.finish();
}
} }
protected abstract void processResult(Span span, T future) protected abstract void processResult(Span span, T future)

View File

@ -49,7 +49,7 @@ public class MongoAsyncClientInstrumentationTest {
public void asyncClientHasListener() { public void asyncClientHasListener() {
Assert.assertEquals(1, client.getSettings().getCommandListeners().size()); Assert.assertEquals(1, client.getSettings().getCommandListeners().size());
Assert.assertEquals( Assert.assertEquals(
"DDTracingCommandListener", "TracingCommandListener",
client.getSettings().getCommandListeners().get(0).getClass().getSimpleName()); client.getSettings().getCommandListeners().get(0).getClass().getSimpleName());
} }

View File

@ -81,7 +81,7 @@ public class MongoClientInstrumentationTest {
public void syncClientHasListener() { public void syncClientHasListener() {
Assert.assertEquals(1, client.getMongoClientOptions().getCommandListeners().size()); Assert.assertEquals(1, client.getMongoClientOptions().getCommandListeners().size());
Assert.assertEquals( Assert.assertEquals(
"DDTracingCommandListener", "TracingCommandListener",
client.getMongoClientOptions().getCommandListeners().get(0).getClass().getSimpleName()); client.getMongoClientOptions().getCommandListeners().get(0).getClass().getSimpleName());
} }