Update play-2.4 to new agent api

This commit is contained in:
Trask Stalnaker 2019-10-19 11:57:46 -07:00
parent 9d51a80eae
commit 4691396d11
4 changed files with 48 additions and 63 deletions

View File

@ -1,14 +1,16 @@
package datadog.trace.instrumentation.play24;
import static datadog.trace.instrumentation.api.AgentTracer.activateSpan;
import static datadog.trace.instrumentation.api.AgentTracer.activeSpan;
import static datadog.trace.instrumentation.api.AgentTracer.propagate;
import static datadog.trace.instrumentation.api.AgentTracer.startSpan;
import static datadog.trace.instrumentation.play24.PlayHeaders.GETTER;
import static datadog.trace.instrumentation.play24.PlayHttpServerDecorator.DECORATE;
import datadog.trace.context.TraceScope;
import io.opentracing.Scope;
import io.opentracing.Span;
import io.opentracing.SpanContext;
import io.opentracing.propagation.Format;
import datadog.trace.instrumentation.api.AgentScope;
import datadog.trace.instrumentation.api.AgentSpan;
import datadog.trace.instrumentation.api.AgentSpan.Context;
import io.opentracing.tag.Tags;
import io.opentracing.util.GlobalTracer;
import net.bytebuddy.asm.Advice;
import play.api.mvc.Action;
import play.api.mvc.Request;
@ -17,43 +19,32 @@ import scala.concurrent.Future;
public class PlayAdvice {
@Advice.OnMethodEnter(suppress = Throwable.class)
public static Scope startSpan(@Advice.Argument(0) final Request req) {
final Scope scope;
if (GlobalTracer.get().activeSpan() == null) {
final SpanContext extractedContext;
if (GlobalTracer.get().scopeManager().active() == null) {
extractedContext =
GlobalTracer.get().extract(Format.Builtin.HTTP_HEADERS, new PlayHeaders(req));
} else {
extractedContext = null;
}
scope =
GlobalTracer.get()
.buildSpan("play.request")
.asChildOf(extractedContext)
.startActive(false);
public static AgentScope onEnter(@Advice.Argument(0) final Request req) {
final AgentSpan span;
if (activeSpan() == null) {
final Context extractedContext = propagate().extract(req, GETTER);
span = startSpan("play.request", extractedContext);
} else {
// An upstream framework (e.g. akka-http, netty) has already started the span.
// Do not extract the context.
scope = GlobalTracer.get().buildSpan("play.request").startActive(false);
span = startSpan("play.request");
}
DECORATE.afterStart(scope);
DECORATE.onConnection(scope.span(), req);
DECORATE.afterStart(span);
DECORATE.onConnection(span, req);
if (GlobalTracer.get().scopeManager().active() instanceof TraceScope) {
((TraceScope) GlobalTracer.get().scopeManager().active()).setAsyncPropagation(true);
}
final AgentScope scope = activateSpan(span, false);
scope.setAsyncPropagation(true);
return scope;
}
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void stopTraceOnResponse(
@Advice.Enter final Scope playControllerScope,
@Advice.Enter final AgentScope playControllerScope,
@Advice.This final Object thisAction,
@Advice.Thrown final Throwable throwable,
@Advice.Argument(0) final Request req,
@Advice.Return(readOnly = false) final Future<Result> responseFuture) {
final Span playControllerSpan = playControllerScope.span();
final AgentSpan playControllerSpan = playControllerScope.span();
// Call onRequest on return after tags are populated.
DECORATE.onRequest(playControllerSpan, req);
@ -64,13 +55,13 @@ public class PlayAdvice {
((Action) thisAction).executionContext());
} else {
DECORATE.onError(playControllerSpan, throwable);
Tags.HTTP_STATUS.set(playControllerSpan, 500);
playControllerSpan.setTag(Tags.HTTP_STATUS.getKey(), 500);
DECORATE.beforeFinish(playControllerSpan);
playControllerSpan.finish();
}
playControllerScope.close();
final Span rootSpan = GlobalTracer.get().activeSpan();
final AgentSpan rootSpan = activeSpan();
// set the resource name on the upstream akka/netty span
DECORATE.onRequest(rootSpan, req);
}

View File

@ -1,33 +1,26 @@
package datadog.trace.instrumentation.play24;
import io.opentracing.propagation.TextMap;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import datadog.trace.instrumentation.api.AgentPropagation;
import play.api.mvc.Request;
import scala.Tuple2;
import scala.Option;
import scala.collection.JavaConversions;
public class PlayHeaders implements TextMap {
private final Request request;
public class PlayHeaders implements AgentPropagation.Getter<Request> {
public PlayHeaders(final Request request) {
this.request = request;
public static final PlayHeaders GETTER = new PlayHeaders();
@Override
public Iterable<String> keys(final Request carrier) {
return JavaConversions.asJavaIterable(carrier.headers().keys());
}
@Override
public Iterator<Map.Entry<String, String>> iterator() {
final scala.collection.Map scalaMap = request.headers().toSimpleMap();
final Map<String, String> javaMap = new HashMap<>(scalaMap.size());
final scala.collection.Iterator<Tuple2<String, String>> scalaIterator = scalaMap.iterator();
while (scalaIterator.hasNext()) {
final Tuple2<String, String> tuple = scalaIterator.next();
javaMap.put(tuple._1(), tuple._2());
public String get(final Request carrier, final String key) {
final Option<String> option = carrier.headers().get(key);
if (option.isDefined()) {
return option.get();
} else {
return null;
}
return javaMap.entrySet().iterator();
}
@Override
public void put(final String s, final String s1) {
throw new IllegalStateException("play headers can only be extracted");
}
}

View File

@ -2,7 +2,7 @@ package datadog.trace.instrumentation.play24;
import datadog.trace.agent.decorator.HttpServerDecorator;
import datadog.trace.api.DDTags;
import io.opentracing.Span;
import datadog.trace.instrumentation.api.AgentSpan;
import io.opentracing.tag.Tags;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.UndeclaredThrowableException;
@ -58,7 +58,7 @@ public class PlayHttpServerDecorator extends HttpServerDecorator<Request, Reques
}
@Override
public Span onRequest(final Span span, final Request request) {
public AgentSpan onRequest(final AgentSpan span, final Request request) {
super.onRequest(span, request);
if (request != null) {
// more about routes here:
@ -73,8 +73,8 @@ public class PlayHttpServerDecorator extends HttpServerDecorator<Request, Reques
}
@Override
public Span onError(final Span span, Throwable throwable) {
Tags.HTTP_STATUS.set(span, 500);
public AgentSpan onError(final AgentSpan span, Throwable throwable) {
span.setTag(Tags.HTTP_STATUS.getKey(), 500);
if (throwable != null
// This can be moved to instanceof check when using Java 8.
&& throwable.getClass().getName().equals("java.util.concurrent.CompletionException")

View File

@ -1,19 +1,19 @@
package datadog.trace.instrumentation.play24;
import static datadog.trace.instrumentation.api.AgentTracer.activeScope;
import static datadog.trace.instrumentation.play24.PlayHttpServerDecorator.DECORATE;
import datadog.trace.context.TraceScope;
import io.opentracing.Span;
import io.opentracing.util.GlobalTracer;
import datadog.trace.instrumentation.api.AgentSpan;
import lombok.extern.slf4j.Slf4j;
import play.api.mvc.Result;
import scala.util.Try;
@Slf4j
public class RequestCompleteCallback extends scala.runtime.AbstractFunction1<Try<Result>, Object> {
private final Span span;
private final AgentSpan span;
public RequestCompleteCallback(final Span span) {
public RequestCompleteCallback(final AgentSpan span) {
this.span = span;
}
@ -26,8 +26,9 @@ public class RequestCompleteCallback extends scala.runtime.AbstractFunction1<Try
DECORATE.onResponse(span, result.get());
}
DECORATE.beforeFinish(span);
if (GlobalTracer.get().scopeManager().active() instanceof TraceScope) {
((TraceScope) GlobalTracer.get().scopeManager().active()).setAsyncPropagation(false);
final TraceScope scope = activeScope();
if (scope != null) {
scope.setAsyncPropagation(false);
}
} catch (final Throwable t) {
log.debug("error in play instrumentation", t);