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(
final Context.BeforeExecution context, final ExecutionAttributes executionAttributes) {
final Span span = GlobalTracer.get().buildSpan("aws.command").start();
DECORATE.afterStart(span);
executionAttributes.putAttribute(SPAN_ATTRIBUTE, span);
try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
DECORATE.afterStart(span);
executionAttributes.putAttribute(SPAN_ATTRIBUTE, span);
}
}
@Override

View File

@ -14,6 +14,7 @@ import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.api.DDTags;
import datadog.trace.bootstrap.CallDepthThreadLocalMap;
import io.opentracing.Scope;
import io.opentracing.Span;
import io.opentracing.noop.NoopSpan;
import io.opentracing.util.GlobalTracer;
@ -113,14 +114,16 @@ public class CouchbaseBucketInstrumentation extends Instrumenter.Default {
declaringClass.getSimpleName().replace("CouchbaseAsync", "").replace("DefaultAsync", "");
final String resourceName = className + "." + method.getName();
// just replace the no-op span.
spanRef.set(
DECORATE.afterStart(
GlobalTracer.get()
.buildSpan("couchbase.call")
.withTag(DDTags.RESOURCE_NAME, resourceName)
.withTag("bucket", bucket)
.start()));
final Span span =
GlobalTracer.get()
.buildSpan("couchbase.call")
.withTag(DDTags.RESOURCE_NAME, resourceName)
.withTag("bucket", bucket)
.start();
try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
// 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);
if (span != null) {
DECORATE.beforeFinish(span);
span.finish();
try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
DECORATE.beforeFinish(span);
span.finish();
}
}
}
}
@ -153,9 +158,11 @@ public class CouchbaseBucketInstrumentation extends Instrumenter.Default {
public void call(final Throwable throwable) {
final Span span = spanRef.getAndSet(null);
if (span != null) {
DECORATE.onError(span, throwable);
DECORATE.beforeFinish(span);
span.finish();
try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
DECORATE.onError(span, throwable);
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.api.DDTags;
import datadog.trace.bootstrap.CallDepthThreadLocalMap;
import io.opentracing.Scope;
import io.opentracing.Span;
import io.opentracing.noop.NoopSpan;
import io.opentracing.util.GlobalTracer;
@ -108,13 +109,15 @@ public class CouchbaseClusterInstrumentation extends Instrumenter.Default {
declaringClass.getSimpleName().replace("CouchbaseAsync", "").replace("DefaultAsync", "");
final String resourceName = className + "." + method.getName();
// just replace the no-op span.
spanRef.set(
DECORATE.afterStart(
GlobalTracer.get()
.buildSpan("couchbase.call")
.withTag(DDTags.RESOURCE_NAME, resourceName)
.start()));
final Span span =
GlobalTracer.get()
.buildSpan("couchbase.call")
.withTag(DDTags.RESOURCE_NAME, resourceName)
.start();
try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
// 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);
if (span != null) {
DECORATE.beforeFinish(span);
span.finish();
try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
DECORATE.beforeFinish(span);
span.finish();
}
}
}
}
@ -147,9 +152,11 @@ public class CouchbaseClusterInstrumentation extends Instrumenter.Default {
public void call(final Throwable throwable) {
final Span span = spanRef.getAndSet(null);
if (span != null) {
DECORATE.onError(span, throwable);
DECORATE.beforeFinish(span);
span.finish();
try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
DECORATE.onError(span, throwable);
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.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import io.opentracing.Scope;
import io.opentracing.Span;
import io.opentracing.Tracer;
import io.opentracing.util.GlobalTracer;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
@ -58,88 +60,108 @@ public class TracingSession implements Session {
@Override
public ResultSet execute(final String query) {
final Span span = buildSpan(query);
ResultSet resultSet = null;
try {
resultSet = session.execute(query);
return resultSet;
} finally {
finishSpan(span, resultSet);
try (final Scope scope = startSpanWithScope(query)) {
try {
final ResultSet resultSet = session.execute(query);
beforeSpanFinish(scope.span(), resultSet);
return resultSet;
} catch (final RuntimeException e) {
beforeSpanFinish(scope.span(), e);
throw e;
} finally {
scope.span().finish();
}
}
}
@Override
public ResultSet execute(final String query, final Object... values) {
final Span span = buildSpan(query);
ResultSet resultSet = null;
try {
resultSet = session.execute(query, values);
return resultSet;
} finally {
finishSpan(span, resultSet);
try (final Scope scope = startSpanWithScope(query)) {
try {
final ResultSet resultSet = session.execute(query, values);
beforeSpanFinish(scope.span(), resultSet);
return resultSet;
} catch (final RuntimeException e) {
beforeSpanFinish(scope.span(), e);
throw e;
} finally {
scope.span().finish();
}
}
}
@Override
public ResultSet execute(final String query, final Map<String, Object> values) {
final Span span = buildSpan(query);
ResultSet resultSet = null;
try {
resultSet = session.execute(query, values);
return resultSet;
} finally {
finishSpan(span, resultSet);
try (final Scope scope = startSpanWithScope(query)) {
try {
final ResultSet resultSet = session.execute(query, values);
beforeSpanFinish(scope.span(), resultSet);
return resultSet;
} catch (final RuntimeException e) {
beforeSpanFinish(scope.span(), e);
throw e;
} finally {
scope.span().finish();
}
}
}
@Override
public ResultSet execute(final Statement statement) {
final String query = getQuery(statement);
final Span span = buildSpan(query);
ResultSet resultSet = null;
try {
resultSet = session.execute(statement);
return resultSet;
} finally {
finishSpan(span, resultSet);
try (final Scope scope = startSpanWithScope(query)) {
try {
final ResultSet resultSet = session.execute(statement);
beforeSpanFinish(scope.span(), resultSet);
return resultSet;
} catch (final RuntimeException e) {
beforeSpanFinish(scope.span(), e);
throw e;
} finally {
scope.span().finish();
}
}
}
@Override
public ResultSetFuture executeAsync(final String query) {
final Span span = buildSpan(query);
final ResultSetFuture future = session.executeAsync(query);
future.addListener(createListener(span, future), executorService);
try (final Scope scope = startSpanWithScope(query)) {
final ResultSetFuture future = session.executeAsync(query);
future.addListener(createListener(scope.span(), future), executorService);
return future;
return future;
}
}
@Override
public ResultSetFuture executeAsync(final String query, final Object... values) {
final Span span = buildSpan(query);
final ResultSetFuture future = session.executeAsync(query, values);
future.addListener(createListener(span, future), executorService);
try (final Scope scope = startSpanWithScope(query)) {
final ResultSetFuture future = session.executeAsync(query, values);
future.addListener(createListener(scope.span(), future), executorService);
return future;
return future;
}
}
@Override
public ResultSetFuture executeAsync(final String query, final Map<String, Object> values) {
final Span span = buildSpan(query);
final ResultSetFuture future = session.executeAsync(query, values);
future.addListener(createListener(span, future), executorService);
try (final Scope scope = startSpanWithScope(query)) {
final ResultSetFuture future = session.executeAsync(query, values);
future.addListener(createListener(scope.span(), future), executorService);
return future;
return future;
}
}
@Override
public ResultSetFuture executeAsync(final Statement statement) {
final String query = getQuery(statement);
final Span span = buildSpan(query);
final ResultSetFuture future = session.executeAsync(statement);
future.addListener(createListener(span, future), executorService);
try (final Scope scope = startSpanWithScope(query)) {
final ResultSetFuture future = session.executeAsync(statement);
future.addListener(createListener(scope.span(), future), executorService);
return future;
return future;
}
}
@Override
@ -202,32 +224,33 @@ public class TracingSession implements Session {
return new Runnable() {
@Override
public void run() {
try {
finishSpan(span, future.get());
try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
beforeSpanFinish(span, future.get());
} 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 Scope scope = tracer.scopeManager().activate(span, false);
DECORATE.afterStart(span);
DECORATE.onConnection(span, session);
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.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.beforeFinish(span);
span.finish();
}
}

View File

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

View File

@ -140,7 +140,7 @@ public class TracingServerInterceptor implements ServerInterceptor {
@Override
public void onCancel() {
// Finishes span.
try (final Scope scope = tracer.scopeManager().activate(span, true)) {
try (final Scope scope = tracer.scopeManager().activate(span, false)) {
if (scope instanceof TraceScope) {
((TraceScope) scope).setAsyncPropagation(true);
}
@ -149,19 +149,19 @@ public class TracingServerInterceptor implements ServerInterceptor {
if (scope instanceof TraceScope) {
((TraceScope) scope).setAsyncPropagation(false);
}
DECORATE.beforeFinish(span);
} catch (final Throwable e) {
DECORATE.onError(span, e);
throw e;
} finally {
DECORATE.beforeFinish(span);
span.finish();
throw e;
}
}
@Override
public void onComplete() {
// Finishes span.
try (final Scope scope = tracer.scopeManager().activate(span, true)) {
try (final Scope scope = tracer.scopeManager().activate(span, false)) {
if (scope instanceof TraceScope) {
((TraceScope) scope).setAsyncPropagation(true);
}
@ -169,12 +169,12 @@ public class TracingServerInterceptor implements ServerInterceptor {
if (scope instanceof TraceScope) {
((TraceScope) scope).setAsyncPropagation(false);
}
DECORATE.beforeFinish(span);
} catch (final Throwable e) {
DECORATE.onError(span, e);
throw e;
} finally {
DECORATE.beforeFinish(span);
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.ContextStore;
import datadog.trace.bootstrap.InstrumentationContext;
import io.opentracing.Scope;
import io.opentracing.Span;
import io.opentracing.Tracer;
import io.opentracing.propagation.Format;
@ -178,9 +179,11 @@ public class HttpUrlConnectionInstrumentation extends Instrumenter.Default {
public Span startSpan(final HttpURLConnection connection) {
final Tracer.SpanBuilder builder = GlobalTracer.get().buildSpan(OPERATION_NAME);
span = builder.start();
DECORATE.afterStart(span);
DECORATE.onRequest(span, connection);
return span;
try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
DECORATE.afterStart(span);
DECORATE.onRequest(span, connection);
return span;
}
}
public boolean hasSpan() {
@ -196,11 +199,13 @@ public class HttpUrlConnectionInstrumentation extends Instrumenter.Default {
}
public void finishSpan(final Throwable throwable) {
DECORATE.onError(span, throwable);
DECORATE.beforeFinish(span);
span.finish();
span = null;
finished = true;
try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
DECORATE.onError(span, throwable);
DECORATE.beforeFinish(span);
span.finish();
span = null;
finished = true;
}
}
public void finishSpan(final int responseCode) {
@ -210,11 +215,13 @@ public class HttpUrlConnectionInstrumentation extends Instrumenter.Default {
* (e.g. breaks getOutputStream).
*/
if (responseCode > 0) {
DECORATE.onResponse(span, responseCode);
DECORATE.beforeFinish(span);
span.finish();
span = null;
finished = true;
try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
DECORATE.onResponse(span, responseCode);
DECORATE.beforeFinish(span);
span.finish();
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.DDSpanTypes;
import datadog.trace.api.DDTags;
import io.opentracing.Scope;
import io.opentracing.Span;
import io.opentracing.tag.Tags;
import io.opentracing.util.GlobalTracer;
@ -65,17 +66,18 @@ public class UrlInstrumentation extends Instrumenter.Default {
.withTag(DDTags.SPAN_TYPE, DDSpanTypes.HTTP_CLIENT)
.withTag(Tags.COMPONENT.getKey(), COMPONENT)
.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.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.ERROR.set(span, true);
span.log(Collections.singletonMap(ERROR_OBJECT, throwable));
span.finish();
}
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)
public static void handleError(
@Advice.FieldValue("requestContext") final ClientRequest context,
@Advice.Return(readOnly = false) Future future) {
@Advice.Return(readOnly = false) Future<?> future) {
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)
public static void handleError(
@Advice.FieldValue("configuration") final ClientConfiguration context,
@Advice.Return(readOnly = false) Future future) {
@Advice.Return(readOnly = false) Future<?> future) {
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 datadog.trace.api.DDTags;
import io.opentracing.Scope;
import io.opentracing.Span;
import io.opentracing.propagation.Format;
import io.opentracing.util.GlobalTracer;
@ -21,24 +22,25 @@ public class ClientTracingFilter implements ClientRequestFilter, ClientResponseF
@Override
public void filter(final ClientRequestContext requestContext) {
final Span span =
GlobalTracer.get()
.buildSpan("jax-rs.client.call")
.withTag(DDTags.RESOURCE_NAME, requestContext.getMethod() + " jax-rs.client.call")
.start();
DECORATE.afterStart(span);
DECORATE.onRequest(span, requestContext);
try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
DECORATE.afterStart(span);
DECORATE.onRequest(span, requestContext);
log.debug("{} - client span started", span);
log.debug("{} - client span started", span);
GlobalTracer.get()
.inject(
span.context(),
Format.Builtin.HTTP_HEADERS,
new InjectAdapter(requestContext.getHeaders()));
GlobalTracer.get()
.inject(
span.context(),
Format.Builtin.HTTP_HEADERS,
new InjectAdapter(requestContext.getHeaders()));
requestContext.setProperty(SPAN_PROPERTY_NAME, span);
requestContext.setProperty(SPAN_PROPERTY_NAME, span);
}
}
@Override

View File

@ -10,6 +10,7 @@ import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter;
import io.opentracing.Scope;
import io.opentracing.Span;
import io.opentracing.SpanContext;
import io.opentracing.Tracer;
@ -92,15 +93,17 @@ public final class JMSMessageConsumerInstrumentation extends Instrumenter.Defaul
}
final Span span = spanBuilder.start();
CONSUMER_DECORATE.afterStart(span);
if (message == null) {
CONSUMER_DECORATE.onReceive(span, method);
} else {
CONSUMER_DECORATE.onConsume(span, message);
try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
CONSUMER_DECORATE.afterStart(span);
if (message == null) {
CONSUMER_DECORATE.onReceive(span, method);
} 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.DatabaseClientDecorator",
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.
// This bypasses the Builder instrumentation. Casting as a workaround.
final MongoClientOptions.Builder builder = (MongoClientOptions.Builder) dis;
final DDTracingCommandListener listener = new DDTracingCommandListener();
final TracingCommandListener listener = new TracingCommandListener();
builder.addCommandListener(listener);
}
}

View File

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

View File

@ -48,7 +48,7 @@ public final class MongoAsyncClientInstrumentation extends Instrumenter.Default
"datadog.trace.agent.decorator.ClientDecorator",
"datadog.trace.agent.decorator.DatabaseClientDecorator",
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.
// This bypasses the Builder instrumentation. Casting as a workaround.
final MongoClientSettings.Builder builder = (MongoClientSettings.Builder) dis;
final DDTracingCommandListener listener = new DDTracingCommandListener();
final TracingCommandListener listener = new TracingCommandListener();
builder.addCommandListener(listener);
}
}

View File

@ -1,7 +1,6 @@
package datadog.trace.instrumentation.netty40;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static io.opentracing.log.Fields.ERROR_OBJECT;
import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
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 datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.context.TraceScope;
import datadog.trace.instrumentation.netty40.server.NettyHttpServerDecorator;
import io.netty.channel.ChannelFuture;
import io.opentracing.Scope;
import io.opentracing.Span;
@ -83,18 +83,20 @@ public class ChannelFutureListenerInstrumentation extends Instrumenter.Default {
if (continuation == null) {
return null;
}
final TraceScope scope = continuation.activate();
final TraceScope parentScope = continuation.activate();
final Span errorSpan =
GlobalTracer.get()
.buildSpan("netty.connect")
.withTag(Tags.COMPONENT.getKey(), "netty")
.start();
Tags.ERROR.set(errorSpan, true);
errorSpan.log(singletonMap(ERROR_OBJECT, cause));
errorSpan.finish();
try (final Scope scope = GlobalTracer.get().scopeManager().activate(errorSpan, false)) {
NettyHttpServerDecorator.DECORATE.onError(errorSpan, cause);
NettyHttpServerDecorator.DECORATE.beforeFinish(errorSpan);
errorSpan.finish();
}
return scope;
return parentScope;
}
@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.ChannelPromise;
import io.netty.handler.codec.http.HttpRequest;
import io.opentracing.Scope;
import io.opentracing.Span;
import io.opentracing.propagation.Format;
import io.opentracing.util.GlobalTracer;
@ -24,40 +25,44 @@ public class HttpClientRequestTracingHandler extends ChannelOutboundHandlerAdapt
return;
}
TraceScope scope = null;
TraceScope parentScope = null;
final TraceScope.Continuation continuation =
ctx.channel().attr(AttributeKeys.PARENT_CONNECT_CONTINUATION_ATTRIBUTE_KEY).getAndRemove();
if (continuation != null) {
scope = continuation.activate();
parentScope = continuation.activate();
}
final HttpRequest request = (HttpRequest) msg;
final Span span = GlobalTracer.get().buildSpan("netty.client.request").start();
DECORATE.afterStart(span);
DECORATE.onRequest(span, request);
DECORATE.onPeerConnection(span, (InetSocketAddress) ctx.channel().remoteAddress());
try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
DECORATE.afterStart(span);
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.
if (!request.headers().contains("amz-sdk-invocation-id")) {
GlobalTracer.get()
.inject(
span.context(), Format.Builtin.HTTP_HEADERS, new NettyResponseInjectAdapter(request));
// AWS calls are often signed, so we can't add headers without breaking the signature.
if (!request.headers().contains("amz-sdk-invocation-id")) {
GlobalTracer.get()
.inject(
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);
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();
if (null != parentScope) {
parentScope.close();
}
}
}

View File

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

View File

@ -1,7 +1,6 @@
package datadog.trace.instrumentation.netty41;
import static datadog.trace.agent.tooling.ByteBuddyElementMatchers.safeHasSuperType;
import static io.opentracing.log.Fields.ERROR_OBJECT;
import static java.util.Collections.singletonMap;
import static net.bytebuddy.matcher.ElementMatchers.isInterface;
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 datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.context.TraceScope;
import datadog.trace.instrumentation.netty41.server.NettyHttpServerDecorator;
import io.netty.channel.ChannelFuture;
import io.opentracing.Scope;
import io.opentracing.Span;
@ -83,18 +83,20 @@ public class ChannelFutureListenerInstrumentation extends Instrumenter.Default {
if (continuation == null) {
return null;
}
final TraceScope scope = continuation.activate();
final TraceScope parentScope = continuation.activate();
final Span errorSpan =
GlobalTracer.get()
.buildSpan("netty.connect")
.withTag(Tags.COMPONENT.getKey(), "netty")
.start();
Tags.ERROR.set(errorSpan, true);
errorSpan.log(singletonMap(ERROR_OBJECT, cause));
errorSpan.finish();
try (final Scope scope = GlobalTracer.get().scopeManager().activate(errorSpan, false)) {
NettyHttpServerDecorator.DECORATE.onError(errorSpan, cause);
NettyHttpServerDecorator.DECORATE.beforeFinish(errorSpan);
errorSpan.finish();
}
return scope;
return parentScope;
}
@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.ChannelPromise;
import io.netty.handler.codec.http.HttpRequest;
import io.opentracing.Scope;
import io.opentracing.Span;
import io.opentracing.propagation.Format;
import io.opentracing.util.GlobalTracer;
@ -24,40 +25,44 @@ public class HttpClientRequestTracingHandler extends ChannelOutboundHandlerAdapt
return;
}
TraceScope scope = null;
TraceScope parentScope = null;
final TraceScope.Continuation continuation =
ctx.channel().attr(AttributeKeys.PARENT_CONNECT_CONTINUATION_ATTRIBUTE_KEY).getAndRemove();
if (continuation != null) {
scope = continuation.activate();
parentScope = continuation.activate();
}
final HttpRequest request = (HttpRequest) msg;
final Span span = GlobalTracer.get().buildSpan("netty.client.request").start();
DECORATE.afterStart(span);
DECORATE.onRequest(span, request);
DECORATE.onPeerConnection(span, (InetSocketAddress) ctx.channel().remoteAddress());
try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
DECORATE.afterStart(span);
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.
if (!request.headers().contains("amz-sdk-invocation-id")) {
GlobalTracer.get()
.inject(
span.context(), Format.Builtin.HTTP_HEADERS, new NettyResponseInjectAdapter(request));
// AWS calls are often signed, so we can't add headers without breaking the signature.
if (!request.headers().contains("amz-sdk-invocation-id")) {
GlobalTracer.get()
.inject(
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);
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();
if (null != parentScope) {
parentScope.close();
}
}
}

View File

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

View File

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

View File

@ -189,10 +189,11 @@ public class RabbitChannelInstrumentation extends Instrumenter.Default {
public static class ChannelGetAdvice {
@Advice.OnMethodEnter
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);
// 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();
}
@ -201,13 +202,13 @@ public class RabbitChannelInstrumentation extends Instrumenter.Default {
@Advice.This final Channel channel,
@Advice.Argument(0) final String queue,
@Advice.Enter final long startTime,
@Advice.Local("placeholderScope") final Scope scope,
@Advice.Local("placeholderScope") final Scope placeholderScope,
@Advice.Local("callDepth") final int callDepth,
@Advice.Return final GetResponse response,
@Advice.Thrown final Throwable throwable) {
if (scope.span() instanceof NoopSpan) {
scope.close();
if (placeholderScope.span() instanceof NoopSpan) {
placeholderScope.close();
}
if (callDepth > 0) {
@ -236,6 +237,8 @@ public class RabbitChannelInstrumentation extends Instrumenter.Default {
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 =
GlobalTracer.get()
.buildSpan("amqp.command")
@ -244,13 +247,16 @@ public class RabbitChannelInstrumentation extends Instrumenter.Default {
.withTag("message.size", length)
.withTag(Tags.PEER_PORT.getKey(), connection.getPort())
.start();
CONSUMER_DECORATE.afterStart(span);
CONSUMER_DECORATE.onGet(span, queue);
CONSUMER_DECORATE.onPeerConnection(span, connection.getAddress());
CONSUMER_DECORATE.onError(span, throwable);
CONSUMER_DECORATE.beforeFinish(span);
span.finish();
CallDepthThreadLocalMap.reset(Channel.class);
try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
CONSUMER_DECORATE.afterStart(span);
CONSUMER_DECORATE.onGet(span, queue);
CONSUMER_DECORATE.onPeerConnection(span, connection.getAddress());
CONSUMER_DECORATE.onError(span, throwable);
CONSUMER_DECORATE.beforeFinish(span);
} 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 io.opentracing.Scope;
import io.opentracing.Span;
import io.opentracing.util.GlobalTracer;
import java.util.concurrent.CancellationException;
@ -29,40 +30,47 @@ public abstract class CompletionListener<T> {
public CompletionListener(final MemcachedConnection connection, final String methodName) {
this.connection = connection;
span = GlobalTracer.get().buildSpan(OPERATION_NAME).start();
DECORATE.afterStart(span);
DECORATE.onConnection(span, connection);
DECORATE.onOperation(span, methodName);
try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
DECORATE.afterStart(span);
DECORATE.onConnection(span, connection);
DECORATE.onOperation(span, methodName);
}
}
protected void closeAsyncSpan(final T future) {
try {
processResult(span, future);
} catch (final CancellationException e) {
span.setTag(DB_COMMAND_CANCELLED, true);
} catch (final ExecutionException e) {
if (e.getCause() instanceof CancellationException) {
// Looks like underlying OperationFuture wraps CancellationException into ExecutionException
try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
try {
processResult(span, future);
} catch (final CancellationException e) {
span.setTag(DB_COMMAND_CANCELLED, true);
} else {
DECORATE.onError(span, e.getCause());
} catch (final ExecutionException e) {
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) {
DECORATE.onError(span, thrown);
DECORATE.beforeFinish(span);
span.finish();
try (final Scope scope = GlobalTracer.get().scopeManager().activate(span, false)) {
DECORATE.onError(span, thrown);
DECORATE.beforeFinish(span);
span.finish();
}
}
protected abstract void processResult(Span span, T future)

View File

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

View File

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