Convert play instrumentation to instrumenter api (#4853)
This commit is contained in:
parent
d6e69c746e
commit
231ab6bf59
|
@ -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.hasClassesNamed;
|
||||||
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.implementsInterface;
|
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.named;
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.returns;
|
import static net.bytebuddy.matcher.ElementMatchers.returns;
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
|
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
|
||||||
|
|
||||||
import io.opentelemetry.api.trace.SpanKind;
|
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.context.Scope;
|
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.TypeInstrumentation;
|
||||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
||||||
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
|
|
||||||
import net.bytebuddy.asm.Advice;
|
import net.bytebuddy.asm.Advice;
|
||||||
import net.bytebuddy.description.type.TypeDescription;
|
import net.bytebuddy.description.type.TypeDescription;
|
||||||
import net.bytebuddy.matcher.ElementMatcher;
|
import net.bytebuddy.matcher.ElementMatcher;
|
||||||
|
@ -55,7 +54,12 @@ public class ActionInstrumentation implements TypeInstrumentation {
|
||||||
@Advice.Argument(0) Request<?> req,
|
@Advice.Argument(0) Request<?> req,
|
||||||
@Advice.Local("otelContext") Context context,
|
@Advice.Local("otelContext") Context context,
|
||||||
@Advice.Local("otelScope") Scope scope) {
|
@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();
|
scope = context.makeCurrent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,18 +71,15 @@ public class ActionInstrumentation implements TypeInstrumentation {
|
||||||
@Advice.Return(readOnly = false) Future<Result> responseFuture,
|
@Advice.Return(readOnly = false) Future<Result> responseFuture,
|
||||||
@Advice.Local("otelContext") Context context,
|
@Advice.Local("otelContext") Context context,
|
||||||
@Advice.Local("otelScope") Scope scope) {
|
@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();
|
scope.close();
|
||||||
|
|
||||||
|
updateSpanNames(context, req);
|
||||||
// span finished in RequestCompleteCallback
|
// span finished in RequestCompleteCallback
|
||||||
if (throwable == null) {
|
if (throwable == null) {
|
||||||
responseFuture.onComplete(
|
responseFuture.onComplete(
|
||||||
new RequestCompleteCallback(context), ((Action<?>) thisAction).executionContext());
|
new RequestCompleteCallback(context), ((Action<?>) thisAction).executionContext());
|
||||||
} else {
|
} else {
|
||||||
tracer().endExceptionally(context, throwable);
|
instrumenter().end(context, null, null, throwable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() {}
|
||||||
|
}
|
|
@ -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";
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
package io.opentelemetry.javaagent.instrumentation.play.v2_4;
|
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 io.opentelemetry.context.Context;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -27,11 +27,7 @@ public class RequestCompleteCallback extends AbstractFunction1<Try<Result>, Obje
|
||||||
@Override
|
@Override
|
||||||
public Object apply(Try<Result> result) {
|
public Object apply(Try<Result> result) {
|
||||||
try {
|
try {
|
||||||
if (result.isFailure()) {
|
instrumenter().end(context, null, null, result.isFailure() ? result.failed().get() : null);
|
||||||
tracer().endExceptionally(context, result.failed().get());
|
|
||||||
} else {
|
|
||||||
tracer().end(context);
|
|
||||||
}
|
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
logger.debug("error in play instrumentation", t);
|
logger.debug("error in play instrumentation", t);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.hasClassesNamed;
|
||||||
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.implementsInterface;
|
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.named;
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.returns;
|
import static net.bytebuddy.matcher.ElementMatchers.returns;
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
|
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
|
||||||
|
|
||||||
import io.opentelemetry.api.trace.SpanKind;
|
|
||||||
import io.opentelemetry.context.Context;
|
import io.opentelemetry.context.Context;
|
||||||
import io.opentelemetry.context.Scope;
|
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.TypeInstrumentation;
|
||||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
|
||||||
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
|
|
||||||
import net.bytebuddy.asm.Advice;
|
import net.bytebuddy.asm.Advice;
|
||||||
import net.bytebuddy.description.type.TypeDescription;
|
import net.bytebuddy.description.type.TypeDescription;
|
||||||
import net.bytebuddy.matcher.ElementMatcher;
|
import net.bytebuddy.matcher.ElementMatcher;
|
||||||
|
@ -55,7 +54,12 @@ public class ActionInstrumentation implements TypeInstrumentation {
|
||||||
@Advice.Argument(0) Request<?> req,
|
@Advice.Argument(0) Request<?> req,
|
||||||
@Advice.Local("otelContext") Context context,
|
@Advice.Local("otelContext") Context context,
|
||||||
@Advice.Local("otelScope") Scope scope) {
|
@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();
|
scope = context.makeCurrent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,12 +71,9 @@ public class ActionInstrumentation implements TypeInstrumentation {
|
||||||
@Advice.Return(readOnly = false) Future<Result> responseFuture,
|
@Advice.Return(readOnly = false) Future<Result> responseFuture,
|
||||||
@Advice.Local("otelContext") Context context,
|
@Advice.Local("otelContext") Context context,
|
||||||
@Advice.Local("otelScope") Scope scope) {
|
@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();
|
scope.close();
|
||||||
|
|
||||||
|
updateSpanNames(context, req);
|
||||||
if (throwable == null) {
|
if (throwable == null) {
|
||||||
// span is finished when future completes
|
// span is finished when future completes
|
||||||
// not using responseFuture.onComplete() because that doesn't guarantee this handler span
|
// not using responseFuture.onComplete() because that doesn't guarantee this handler span
|
||||||
|
@ -81,7 +82,7 @@ public class ActionInstrumentation implements TypeInstrumentation {
|
||||||
ResponseFutureWrapper.wrap(
|
ResponseFutureWrapper.wrap(
|
||||||
responseFuture, context, ((Action<?>) thisAction).executionContext());
|
responseFuture, context, ((Action<?>) thisAction).executionContext());
|
||||||
} else {
|
} else {
|
||||||
tracer().endExceptionally(context, throwable);
|
instrumenter().end(context, null, null, throwable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,11 @@
|
||||||
|
|
||||||
package io.opentelemetry.javaagent.instrumentation.play.v2_6;
|
package io.opentelemetry.javaagent.instrumentation.play.v2_6;
|
||||||
|
|
||||||
|
import io.opentelemetry.api.GlobalOpenTelemetry;
|
||||||
import io.opentelemetry.api.trace.Span;
|
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.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
@ -16,12 +19,13 @@ import play.libs.typedmap.TypedKey;
|
||||||
import play.routing.Router;
|
import play.routing.Router;
|
||||||
import scala.Option;
|
import scala.Option;
|
||||||
|
|
||||||
public class PlayTracer extends BaseTracer {
|
public final class Play26Singletons {
|
||||||
private static final PlayTracer TRACER = new PlayTracer();
|
|
||||||
|
|
||||||
public static PlayTracer tracer() {
|
private static final String SPAN_NAME = "play.request";
|
||||||
return TRACER;
|
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;
|
@Nullable private static final Method typedKeyGetUnderlying;
|
||||||
|
|
||||||
|
@ -44,7 +48,25 @@ public class PlayTracer extends BaseTracer {
|
||||||
typedKeyGetUnderlying = typedKeyGetUnderlyingCheck;
|
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) {
|
if (request != null) {
|
||||||
// more about routes here:
|
// more about routes here:
|
||||||
// https://github.com/playframework/playframework/blob/master/documentation/manual/releases/release26/migration26/Migration26.md
|
// 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()) {
|
if (defOption != null && !defOption.isEmpty()) {
|
||||||
String path = defOption.get().path();
|
return defOption.get().path();
|
||||||
span.updateName(path);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private Play26Singletons() {}
|
||||||
protected String getInstrumentationName() {
|
|
||||||
return "io.opentelemetry.play-2.6";
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
package io.opentelemetry.javaagent.instrumentation.play.v2_6;
|
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 io.opentelemetry.context.Context;
|
||||||
import play.api.mvc.Result;
|
import play.api.mvc.Result;
|
||||||
|
@ -22,14 +22,14 @@ public class ResponseFutureWrapper {
|
||||||
new AbstractFunction1<Result, Result>() {
|
new AbstractFunction1<Result, Result>() {
|
||||||
@Override
|
@Override
|
||||||
public Result apply(Result result) {
|
public Result apply(Result result) {
|
||||||
tracer().end(context);
|
instrumenter().end(context, null, null, null);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new AbstractFunction1<Throwable, Throwable>() {
|
new AbstractFunction1<Throwable, Throwable>() {
|
||||||
@Override
|
@Override
|
||||||
public Throwable apply(Throwable throwable) {
|
public Throwable apply(Throwable throwable) {
|
||||||
tracer().endExceptionally(context, throwable);
|
instrumenter().end(context, null, null, throwable);
|
||||||
return throwable;
|
return throwable;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue