Update akka-http-10.0 to new agent api
MODIFY
dd-java-agent/instrumentation/akka-http-10.0/akka-http-10.0.gradle
dd-java-agent/instrumentation/akka-http-10.0/akka-http-10.0.gradle
@@ -70,7 +70,7 @@ muzzle {
}
dependencies {
- compileOnly group: 'com.typesafe.akka', name: 'akka-http_2.11', version: '10.0.0'
+ main_java8CompileOnly group: 'com.typesafe.akka', name: 'akka-http_2.11', version: '10.0.0'
compile project(':dd-trace-api')
compile project(':dd-java-agent:agent-tooling')

MODIFY
dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpClientInstrumentation.java
dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpClientInstrumentation.java
package datadog.trace.instrumentation.akkahttp;
import static datadog.trace.instrumentation.akkahttp.AkkaHttpClientDecorator.DECORATE;
+import static datadog.trace.instrumentation.api.AgentTracer.activateSpan;
+import static datadog.trace.instrumentation.api.AgentTracer.propagate;
+import static datadog.trace.instrumentation.api.AgentTracer.startSpan;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
@@ -11,13 +14,10 @@ import akka.http.scaladsl.model.HttpResponse;
import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.bootstrap.CallDepthThreadLocalMap;
-import io.opentracing.Scope;
-import io.opentracing.Span;
-import io.opentracing.propagation.Format;
-import io.opentracing.propagation.TextMap;
-import io.opentracing.util.GlobalTracer;
+import datadog.trace.instrumentation.api.AgentPropagation;
+import datadog.trace.instrumentation.api.AgentScope;
+import datadog.trace.instrumentation.api.AgentSpan;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.asm.Advice;
@@ -69,7 +69,7 @@ public final class AkkaHttpClientInstrumentation extends Instrumenter.Default {
public static class SingleRequestAdvice {
@Advice.OnMethodEnter(suppress = Throwable.class)
- public static Scope methodEnter(
+ public static AgentScope methodEnter(
@Advice.Argument(value = 0, readOnly = false) HttpRequest request) {
/*
Versions 10.0 and 10.1 have slightly different structure that is hard to distinguish so here
@@ -82,17 +82,17 @@ public final class AkkaHttpClientInstrumentation extends Instrumenter.Default {
return null;
}
- final Scope scope = GlobalTracer.get().buildSpan("akka-http.request").startActive(false);
- DECORATE.afterStart(scope.span());
- DECORATE.onRequest(scope.span(), request);
+ final AgentSpan span = startSpan("akka-http.request");
+ DECORATE.afterStart(span);
+ DECORATE.onRequest(span, request);
if (request != null) {
final AkkaHttpHeaders headers = new AkkaHttpHeaders(request);
- GlobalTracer.get().inject(scope.span().context(), Format.Builtin.HTTP_HEADERS, headers);
+ propagate().inject(span, request, headers);
// Request is immutable, so we have to assign new value once we update headers
request = headers.getRequest();
}
- return scope;
+ return activateSpan(span, false);
}
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
@@ -100,14 +100,14 @@ public final class AkkaHttpClientInstrumentation extends Instrumenter.Default {
@Advice.Argument(value = 0) final HttpRequest request,
@Advice.This final HttpExt thiz,
@Advice.Return final Future<HttpResponse> responseFuture,
- @Advice.Enter final Scope scope,
+ @Advice.Enter final AgentScope scope,
@Advice.Thrown final Throwable throwable) {
if (scope == null) {
return;
}
CallDepthThreadLocalMap.reset(HttpExt.class);
- final Span span = scope.span();
+ final AgentSpan span = scope.span();
if (throwable == null) {
responseFuture.onComplete(new OnCompleteHandler(span), thiz.system().dispatcher());
@@ -121,9 +121,9 @@ public final class AkkaHttpClientInstrumentation extends Instrumenter.Default {
}
public static class OnCompleteHandler extends AbstractFunction1<Try<HttpResponse>, Void> {
- private final Span span;
+ private final AgentSpan span;
- public OnCompleteHandler(final Span span) {
+ public OnCompleteHandler(final AgentSpan span) {
this.span = span;
}
@@ -140,7 +140,7 @@ public final class AkkaHttpClientInstrumentation extends Instrumenter.Default {
}
}
- public static class AkkaHttpHeaders implements TextMap {
+ public static class AkkaHttpHeaders implements AgentPropagation.Setter<HttpRequest> {
private HttpRequest request;
public AkkaHttpHeaders(final HttpRequest request) {
@@ -148,15 +148,9 @@ public final class AkkaHttpClientInstrumentation extends Instrumenter.Default {
}
@Override
- public Iterator<Map.Entry<String, String>> iterator() {
- throw new UnsupportedOperationException(
- "This class should be used only with Tracer.inject()!");
- }
-
- @Override
- public void put(final String name, final String value) {
+ public void set(final HttpRequest carrier, final String key, final String value) {
// It looks like this cast is only needed in Java, Scala would have figured it out
- request = (HttpRequest) request.addHeader(RawHeader.create(name, value));
+ request = (HttpRequest) request.addHeader(RawHeader.create(key, value));
}
public HttpRequest getRequest() {

MODIFY
dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpServerInstrumentation.java
dd-java-agent/instrumentation/akka-http-10.0/src/main/java/datadog/trace/instrumentation/akkahttp/AkkaHttpServerInstrumentation.java
package datadog.trace.instrumentation.akkahttp;
import static datadog.trace.instrumentation.akkahttp.AkkaHttpServerDecorator.DECORATE;
+import static datadog.trace.instrumentation.akkahttp.AkkaHttpServerHeaders.GETTER;
+import static datadog.trace.instrumentation.api.AgentTracer.activateSpan;
+import static datadog.trace.instrumentation.api.AgentTracer.activeScope;
+import static datadog.trace.instrumentation.api.AgentTracer.propagate;
+import static datadog.trace.instrumentation.api.AgentTracer.startSpan;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
-import akka.http.javadsl.model.HttpHeader;
import akka.http.scaladsl.model.HttpRequest;
import akka.http.scaladsl.model.HttpResponse;
import akka.stream.Materializer;
import com.google.auto.service.AutoService;
import datadog.trace.agent.tooling.Instrumenter;
import datadog.trace.context.TraceScope;
-import io.opentracing.Scope;
-import io.opentracing.Span;
-import io.opentracing.SpanContext;
-import io.opentracing.propagation.Format;
-import io.opentracing.propagation.TextMap;
+import datadog.trace.instrumentation.api.AgentScope;
+import datadog.trace.instrumentation.api.AgentSpan;
import io.opentracing.tag.Tags;
-import io.opentracing.util.GlobalTracer;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.asm.Advice;
@@ -51,7 +50,7 @@ public final class AkkaHttpServerInstrumentation extends Instrumenter.Default {
AkkaHttpServerInstrumentation.class.getName() + "$DatadogAsyncWrapper",
AkkaHttpServerInstrumentation.class.getName() + "$DatadogAsyncWrapper$1",
AkkaHttpServerInstrumentation.class.getName() + "$DatadogAsyncWrapper$2",
- AkkaHttpServerInstrumentation.class.getName() + "$AkkaHttpServerHeaders",
+ packageName + ".AkkaHttpServerHeaders",
"datadog.trace.agent.decorator.BaseDecorator",
"datadog.trace.agent.decorator.ServerDecorator",
"datadog.trace.agent.decorator.HttpServerDecorator",
@@ -90,51 +89,45 @@ public final class AkkaHttpServerInstrumentation extends Instrumenter.Default {
@Advice.OnMethodEnter(suppress = Throwable.class)
public static void wrapHandler(
@Advice.Argument(value = 0, readOnly = false)
- Function1<HttpRequest, scala.concurrent.Future<HttpResponse>> handler,
+ Function1<HttpRequest, Future<HttpResponse>> handler,
@Advice.Argument(value = 7) final Materializer materializer) {
handler = new DatadogAsyncWrapper(handler, materializer.executionContext());
}
}
public static class DatadogWrapperHelper {
- public static Scope createSpan(final HttpRequest request) {
- final SpanContext extractedContext =
- GlobalTracer.get()
- .extract(Format.Builtin.HTTP_HEADERS, new AkkaHttpServerHeaders(request));
- final Scope scope =
- GlobalTracer.get()
- .buildSpan("akka-http.request")
- .ignoreActiveSpan()
- .asChildOf(extractedContext)
- .startActive(false);
-
- DECORATE.afterStart(scope.span());
- DECORATE.onConnection(scope.span(), request);
- DECORATE.onRequest(scope.span(), request);
-
- if (scope instanceof TraceScope) {
- ((TraceScope) scope).setAsyncPropagation(true);
- }
+ public static AgentScope createSpan(final HttpRequest request) {
+ final AgentSpan.Context extractedContext = propagate().extract(request, GETTER);
+ final AgentSpan span = startSpan("akka-http.request", extractedContext);
+
+ DECORATE.afterStart(span);
+ DECORATE.onConnection(span, request);
+ DECORATE.onRequest(span, request);
+
+ final AgentScope scope = activateSpan(span, false);
+ scope.setAsyncPropagation(true);
return scope;
}
- public static void finishSpan(final Span span, final HttpResponse response) {
+ public static void finishSpan(final AgentSpan span, final HttpResponse response) {
DECORATE.onResponse(span, response);
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);
}
span.finish();
}
- public static void finishSpan(final Span span, final Throwable t) {
+ public static void finishSpan(final AgentSpan span, final Throwable t) {
DECORATE.onError(span, t);
- Tags.HTTP_STATUS.set(span, 500);
+ span.setTag(Tags.HTTP_STATUS.getKey(), 500);
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);
}
span.finish();
}
@@ -149,7 +142,7 @@ public final class AkkaHttpServerInstrumentation extends Instrumenter.Default {
@Override
public HttpResponse apply(final HttpRequest request) {
- final Scope scope = DatadogWrapperHelper.createSpan(request);
+ final AgentScope scope = DatadogWrapperHelper.createSpan(request);
try {
final HttpResponse response = userHandler.apply(request);
scope.close();
@@ -177,7 +170,7 @@ public final class AkkaHttpServerInstrumentation extends Instrumenter.Default {
@Override
public Future<HttpResponse> apply(final HttpRequest request) {
- final Scope scope = DatadogWrapperHelper.createSpan(request);
+ final AgentScope scope = DatadogWrapperHelper.createSpan(request);
Future<HttpResponse> futureResponse = null;
try {
futureResponse = userHandler.apply(request);
@@ -207,28 +200,4 @@ public final class AkkaHttpServerInstrumentation extends Instrumenter.Default {
return wrapped;
}
}
-
- public static class AkkaHttpServerHeaders implements TextMap {
- private final HttpRequest request;
-
- public AkkaHttpServerHeaders(final HttpRequest request) {
- this.request = request;
- }
-
- @Override
- public Iterator<Map.Entry<String, String>> iterator() {
- final Map<String, String> javaMap = new HashMap<>(request.headers().size());
-
- for (final HttpHeader header : request.getHeaders()) {
- javaMap.put(header.name(), header.value());
- }
-
- return javaMap.entrySet().iterator();
- }
-
- @Override
- public void put(final String name, final String value) {
- throw new IllegalStateException("akka http server headers can only be extracted");
- }
- }
}

ADD
dd-java-agent/instrumentation/akka-http-10.0/src/main/java8/datadog/trace/instrumentation/akkahttp/AkkaHttpServerHeaders.java
+package datadog.trace.instrumentation.akkahttp;
+
+import akka.http.javadsl.model.HttpHeader;
+import akka.http.scaladsl.model.HttpRequest;
+import datadog.trace.instrumentation.api.AgentPropagation;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+public class AkkaHttpServerHeaders implements AgentPropagation.Getter<HttpRequest> {
+
+ public static final AkkaHttpServerHeaders GETTER = new AkkaHttpServerHeaders();
+
+ @Override
+ public List<String> keys(final HttpRequest carrier) {
+ final List<String> keys = new ArrayList<>();
+ for (final HttpHeader header : carrier.getHeaders()) {
+ keys.add(header.name());
+ }
+ return keys;
+ }
+
+ @Override
+ public String get(final HttpRequest carrier, final String key) {
+ final Optional<HttpHeader> header = carrier.getHeader(key);
+ if (header.isPresent()) {
+ return header.get().value();
+ } else {
+ return null;
+ }
+ }
+}

Update akka-http-10.0 to new agent api