Convert play instrumentation to instrumenter api (#4853)

This commit is contained in:
Lauri Tulmin 2021-12-09 23:35:42 +02:00 committed by GitHub
parent d6e69c746e
commit 231ab6bf59
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 114 additions and 78 deletions

View File

@ -7,18 +7,17 @@ package io.opentelemetry.javaagent.instrumentation.play.v2_4;
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.implementsInterface;
import static io.opentelemetry.javaagent.instrumentation.play.v2_4.PlayTracer.tracer;
import static io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge.currentContext;
import static io.opentelemetry.javaagent.instrumentation.play.v2_4.Play24Singletons.instrumenter;
import static io.opentelemetry.javaagent.instrumentation.play.v2_4.Play24Singletons.updateSpanNames;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.returns;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.api.tracer.ServerSpan;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
@ -55,7 +54,12 @@ public class ActionInstrumentation implements TypeInstrumentation {
@Advice.Argument(0) Request<?> req,
@Advice.Local("otelContext") Context context,
@Advice.Local("otelScope") Scope scope) {
context = tracer().startSpan("play.request", SpanKind.INTERNAL);
Context parentContext = currentContext();
if (!instrumenter().shouldStart(parentContext, null)) {
return;
}
context = instrumenter().start(parentContext, null);
scope = context.makeCurrent();
}
@ -67,18 +71,15 @@ public class ActionInstrumentation implements TypeInstrumentation {
@Advice.Return(readOnly = false) Future<Result> responseFuture,
@Advice.Local("otelContext") Context context,
@Advice.Local("otelScope") Scope scope) {
// Call onRequest on return after tags are populated.
tracer().updateSpanName(Java8BytecodeBridge.spanFromContext(context), req);
// set the span name on the upstream akka/netty span
tracer().updateSpanName(ServerSpan.fromContextOrNull(context), req);
scope.close();
updateSpanNames(context, req);
// span finished in RequestCompleteCallback
if (throwable == null) {
responseFuture.onComplete(
new RequestCompleteCallback(context), ((Action<?>) thisAction).executionContext());
} else {
tracer().endExceptionally(context, throwable);
instrumenter().end(context, null, null, throwable);
}
}
}

View File

@ -0,0 +1,53 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.play.v2_4;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.api.tracer.ServerSpan;
import play.api.mvc.Request;
import scala.Option;
public final class Play24Singletons {
private static final String SPAN_NAME = "play.request";
private static final Instrumenter<Void, Void> INSTRUMENTER =
Instrumenter.<Void, Void>builder(
GlobalOpenTelemetry.get(), "io.opentelemetry.play-2.4", s -> SPAN_NAME)
.newInstrumenter();
public static Instrumenter<Void, Void> instrumenter() {
return INSTRUMENTER;
}
public static void updateSpanNames(Context context, Request<?> request) {
String route = getRoute(request);
if (route == null) {
return;
}
Span.fromContext(context).updateName(route);
// set the span name on the upstream akka/netty span
Span serverSpan = ServerSpan.fromContextOrNull(context);
if (serverSpan != null) {
serverSpan.updateName(route);
}
}
private static String getRoute(Request<?> request) {
if (request != null) {
Option<String> pathOption = request.tags().get("ROUTE_PATTERN");
if (!pathOption.isEmpty()) {
return pathOption.get();
}
}
return null;
}
private Play24Singletons() {}
}

View File

@ -1,34 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.play.v2_4;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.instrumentation.api.tracer.BaseTracer;
import play.api.mvc.Request;
import scala.Option;
public class PlayTracer extends BaseTracer {
private static final PlayTracer TRACER = new PlayTracer();
public static PlayTracer tracer() {
return TRACER;
}
public void updateSpanName(Span span, Request<?> request) {
if (request != null) {
Option<String> pathOption = request.tags().get("ROUTE_PATTERN");
if (!pathOption.isEmpty()) {
String path = pathOption.get();
span.updateName(path);
}
}
}
@Override
protected String getInstrumentationName() {
return "io.opentelemetry.play-2.4";
}
}

View File

@ -5,7 +5,7 @@
package io.opentelemetry.javaagent.instrumentation.play.v2_4;
import static io.opentelemetry.javaagent.instrumentation.play.v2_4.PlayTracer.tracer;
import static io.opentelemetry.javaagent.instrumentation.play.v2_4.Play24Singletons.instrumenter;
import io.opentelemetry.context.Context;
import org.slf4j.Logger;
@ -27,11 +27,7 @@ public class RequestCompleteCallback extends AbstractFunction1<Try<Result>, Obje
@Override
public Object apply(Try<Result> result) {
try {
if (result.isFailure()) {
tracer().endExceptionally(context, result.failed().get());
} else {
tracer().end(context);
}
instrumenter().end(context, null, null, result.isFailure() ? result.failed().get() : null);
} catch (Throwable t) {
logger.debug("error in play instrumentation", t);
}

View File

@ -7,18 +7,17 @@ package io.opentelemetry.javaagent.instrumentation.play.v2_6;
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.implementsInterface;
import static io.opentelemetry.javaagent.instrumentation.play.v2_6.PlayTracer.tracer;
import static io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge.currentContext;
import static io.opentelemetry.javaagent.instrumentation.play.v2_6.Play26Singletons.instrumenter;
import static io.opentelemetry.javaagent.instrumentation.play.v2_6.Play26Singletons.updateSpanNames;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.returns;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.api.tracer.ServerSpan;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
@ -55,7 +54,12 @@ public class ActionInstrumentation implements TypeInstrumentation {
@Advice.Argument(0) Request<?> req,
@Advice.Local("otelContext") Context context,
@Advice.Local("otelScope") Scope scope) {
context = tracer().startSpan("play.request", SpanKind.INTERNAL);
Context parentContext = currentContext();
if (!instrumenter().shouldStart(parentContext, null)) {
return;
}
context = instrumenter().start(parentContext, null);
scope = context.makeCurrent();
}
@ -67,12 +71,9 @@ public class ActionInstrumentation implements TypeInstrumentation {
@Advice.Return(readOnly = false) Future<Result> responseFuture,
@Advice.Local("otelContext") Context context,
@Advice.Local("otelScope") Scope scope) {
// Call onRequest on return after tags are populated.
tracer().updateSpanName(Java8BytecodeBridge.spanFromContext(context), req);
// set the span name on the upstream akka/netty span
tracer().updateSpanName(ServerSpan.fromContextOrNull(context), req);
scope.close();
updateSpanNames(context, req);
if (throwable == null) {
// span is finished when future completes
// not using responseFuture.onComplete() because that doesn't guarantee this handler span
@ -81,7 +82,7 @@ public class ActionInstrumentation implements TypeInstrumentation {
ResponseFutureWrapper.wrap(
responseFuture, context, ((Action<?>) thisAction).executionContext());
} else {
tracer().endExceptionally(context, throwable);
instrumenter().end(context, null, null, throwable);
}
}
}

View File

@ -5,8 +5,11 @@
package io.opentelemetry.javaagent.instrumentation.play.v2_6;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.instrumentation.api.tracer.BaseTracer;
import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.api.tracer.ServerSpan;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.annotation.Nullable;
@ -16,12 +19,13 @@ import play.libs.typedmap.TypedKey;
import play.routing.Router;
import scala.Option;
public class PlayTracer extends BaseTracer {
private static final PlayTracer TRACER = new PlayTracer();
public final class Play26Singletons {
public static PlayTracer tracer() {
return TRACER;
}
private static final String SPAN_NAME = "play.request";
private static final Instrumenter<Void, Void> INSTRUMENTER =
Instrumenter.<Void, Void>builder(
GlobalOpenTelemetry.get(), "io.opentelemetry.play-2.6", s -> SPAN_NAME)
.newInstrumenter();
@Nullable private static final Method typedKeyGetUnderlying;
@ -44,7 +48,25 @@ public class PlayTracer extends BaseTracer {
typedKeyGetUnderlying = typedKeyGetUnderlyingCheck;
}
public void updateSpanName(Span span, Request request) {
public static Instrumenter<Void, Void> instrumenter() {
return INSTRUMENTER;
}
public static void updateSpanNames(Context context, Request<?> request) {
String route = getRoute(request);
if (route == null) {
return;
}
Span.fromContext(context).updateName(route);
// set the span name on the upstream akka/netty span
Span serverSpan = ServerSpan.fromContextOrNull(context);
if (serverSpan != null) {
serverSpan.updateName(route);
}
}
private static String getRoute(Request<?> request) {
if (request != null) {
// more about routes here:
// https://github.com/playframework/playframework/blob/master/documentation/manual/releases/release26/migration26/Migration26.md
@ -62,14 +84,11 @@ public class PlayTracer extends BaseTracer {
}
}
if (defOption != null && !defOption.isEmpty()) {
String path = defOption.get().path();
span.updateName(path);
return defOption.get().path();
}
}
return null;
}
@Override
protected String getInstrumentationName() {
return "io.opentelemetry.play-2.6";
}
private Play26Singletons() {}
}

View File

@ -5,7 +5,7 @@
package io.opentelemetry.javaagent.instrumentation.play.v2_6;
import static io.opentelemetry.javaagent.instrumentation.play.v2_6.PlayTracer.tracer;
import static io.opentelemetry.javaagent.instrumentation.play.v2_6.Play26Singletons.instrumenter;
import io.opentelemetry.context.Context;
import play.api.mvc.Result;
@ -22,14 +22,14 @@ public class ResponseFutureWrapper {
new AbstractFunction1<Result, Result>() {
@Override
public Result apply(Result result) {
tracer().end(context);
instrumenter().end(context, null, null, null);
return result;
}
},
new AbstractFunction1<Throwable, Throwable>() {
@Override
public Throwable apply(Throwable throwable) {
tracer().endExceptionally(context, throwable);
instrumenter().end(context, null, null, throwable);
return throwable;
}
},