diff --git a/instrumentation/play/play-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_4/ActionInstrumentation.java b/instrumentation/play/play-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_4/ActionInstrumentation.java index 7b898adf2c..523dcb33d5 100644 --- a/instrumentation/play/play-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_4/ActionInstrumentation.java +++ b/instrumentation/play/play-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_4/ActionInstrumentation.java @@ -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 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); } } } diff --git a/instrumentation/play/play-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_4/Play24Singletons.java b/instrumentation/play/play-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_4/Play24Singletons.java new file mode 100644 index 0000000000..130465e75a --- /dev/null +++ b/instrumentation/play/play-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_4/Play24Singletons.java @@ -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 INSTRUMENTER = + Instrumenter.builder( + GlobalOpenTelemetry.get(), "io.opentelemetry.play-2.4", s -> SPAN_NAME) + .newInstrumenter(); + + public static Instrumenter 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 pathOption = request.tags().get("ROUTE_PATTERN"); + if (!pathOption.isEmpty()) { + return pathOption.get(); + } + } + return null; + } + + private Play24Singletons() {} +} diff --git a/instrumentation/play/play-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_4/PlayTracer.java b/instrumentation/play/play-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_4/PlayTracer.java deleted file mode 100644 index 2e0dc5adb1..0000000000 --- a/instrumentation/play/play-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_4/PlayTracer.java +++ /dev/null @@ -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 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"; - } -} diff --git a/instrumentation/play/play-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_4/RequestCompleteCallback.java b/instrumentation/play/play-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_4/RequestCompleteCallback.java index d2d089cebe..6c26fd2deb 100644 --- a/instrumentation/play/play-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_4/RequestCompleteCallback.java +++ b/instrumentation/play/play-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_4/RequestCompleteCallback.java @@ -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, Obje @Override public Object apply(Try 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); } diff --git a/instrumentation/play/play-2.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_6/ActionInstrumentation.java b/instrumentation/play/play-2.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_6/ActionInstrumentation.java index 6d68eb9472..27e977db57 100644 --- a/instrumentation/play/play-2.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_6/ActionInstrumentation.java +++ b/instrumentation/play/play-2.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_6/ActionInstrumentation.java @@ -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 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); } } } diff --git a/instrumentation/play/play-2.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_6/PlayTracer.java b/instrumentation/play/play-2.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_6/Play26Singletons.java similarity index 61% rename from instrumentation/play/play-2.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_6/PlayTracer.java rename to instrumentation/play/play-2.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_6/Play26Singletons.java index 31d196f387..1645b90b6e 100644 --- a/instrumentation/play/play-2.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_6/PlayTracer.java +++ b/instrumentation/play/play-2.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_6/Play26Singletons.java @@ -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 INSTRUMENTER = + Instrumenter.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 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() {} } diff --git a/instrumentation/play/play-2.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_6/ResponseFutureWrapper.java b/instrumentation/play/play-2.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_6/ResponseFutureWrapper.java index f440359f9d..f8d0b2542d 100644 --- a/instrumentation/play/play-2.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_6/ResponseFutureWrapper.java +++ b/instrumentation/play/play-2.6/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/play/v2_6/ResponseFutureWrapper.java @@ -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() { @Override public Result apply(Result result) { - tracer().end(context); + instrumenter().end(context, null, null, null); return result; } }, new AbstractFunction1() { @Override public Throwable apply(Throwable throwable) { - tracer().endExceptionally(context, throwable); + instrumenter().end(context, null, null, throwable); return throwable; } },