diff --git a/instrumentation/async-http-client/async-http-client-1.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v1_9/AsyncHttpClientInstrumentationModule.java b/instrumentation/async-http-client/async-http-client-1.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v1_9/AsyncHttpClientInstrumentationModule.java index ea5fb41e71..a5c64bf4aa 100644 --- a/instrumentation/async-http-client/async-http-client-1.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v1_9/AsyncHttpClientInstrumentationModule.java +++ b/instrumentation/async-http-client/async-http-client-1.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v1_9/AsyncHttpClientInstrumentationModule.java @@ -10,10 +10,12 @@ import static java.util.Arrays.asList; import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import io.opentelemetry.javaagent.extension.instrumentation.internal.ExperimentalInstrumentationModule; import java.util.List; @AutoService(InstrumentationModule.class) -public class AsyncHttpClientInstrumentationModule extends InstrumentationModule { +public class AsyncHttpClientInstrumentationModule extends InstrumentationModule + implements ExperimentalInstrumentationModule { public AsyncHttpClientInstrumentationModule() { super("async-http-client", "async-http-client-1.9"); } @@ -22,4 +24,9 @@ public class AsyncHttpClientInstrumentationModule extends InstrumentationModule public List typeInstrumentations() { return asList(new RequestInstrumentation(), new ResponseInstrumentation()); } + + @Override + public boolean isIndyReady() { + return true; + } } diff --git a/instrumentation/async-http-client/async-http-client-1.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v1_9/AsyncHttpClientSingletons.java b/instrumentation/async-http-client/async-http-client-1.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v1_9/AsyncHttpClientSingletons.java index c886631a93..59f052b89d 100644 --- a/instrumentation/async-http-client/async-http-client-1.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v1_9/AsyncHttpClientSingletons.java +++ b/instrumentation/async-http-client/async-http-client-1.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v1_9/AsyncHttpClientSingletons.java @@ -5,9 +5,11 @@ package io.opentelemetry.javaagent.instrumentation.asynchttpclient.v1_9; +import com.ning.http.client.AsyncHandler; import com.ning.http.client.Request; import com.ning.http.client.Response; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.util.VirtualField; import io.opentelemetry.javaagent.bootstrap.internal.JavaagentHttpClientInstrumenters; public final class AsyncHttpClientSingletons { @@ -15,12 +17,16 @@ public final class AsyncHttpClientSingletons { private static final Instrumenter INSTRUMENTER; + public static final VirtualField, AsyncHandlerData> ASYNC_HANDLER_DATA; + static { INSTRUMENTER = JavaagentHttpClientInstrumenters.create( INSTRUMENTATION_NAME, new AsyncHttpClientHttpAttributesGetter(), HttpHeaderSetter.INSTANCE); + + ASYNC_HANDLER_DATA = VirtualField.find(AsyncHandler.class, AsyncHandlerData.class); } public static Instrumenter instrumenter() { diff --git a/instrumentation/async-http-client/async-http-client-1.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v1_9/RequestInstrumentation.java b/instrumentation/async-http-client/async-http-client-1.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v1_9/RequestInstrumentation.java index 09a99fe447..7b1fdadf52 100644 --- a/instrumentation/async-http-client/async-http-client-1.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v1_9/RequestInstrumentation.java +++ b/instrumentation/async-http-client/async-http-client-1.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v1_9/RequestInstrumentation.java @@ -6,6 +6,7 @@ package io.opentelemetry.javaagent.instrumentation.asynchttpclient.v1_9; import static io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge.currentContext; +import static io.opentelemetry.javaagent.instrumentation.asynchttpclient.v1_9.AsyncHttpClientSingletons.ASYNC_HANDLER_DATA; import static io.opentelemetry.javaagent.instrumentation.asynchttpclient.v1_9.AsyncHttpClientSingletons.instrumenter; import static net.bytebuddy.matcher.ElementMatchers.isPublic; import static net.bytebuddy.matcher.ElementMatchers.named; @@ -15,9 +16,9 @@ import com.ning.http.client.AsyncHandler; import com.ning.http.client.Request; import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; -import io.opentelemetry.instrumentation.api.util.VirtualField; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; +import javax.annotation.Nullable; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; @@ -42,24 +43,22 @@ public class RequestInstrumentation implements TypeInstrumentation { @SuppressWarnings("unused") public static class ExecuteAdvice { + @Nullable @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.Argument(0) Request request, - @Advice.Argument(1) AsyncHandler handler, - @Advice.Local("otelScope") Scope scope) { + public static Scope onEnter( + @Advice.Argument(0) Request request, @Advice.Argument(1) AsyncHandler handler) { Context parentContext = currentContext(); if (!instrumenter().shouldStart(parentContext, request)) { - return; + return null; } Context context = instrumenter().start(parentContext, request); - VirtualField.find(AsyncHandler.class, AsyncHandlerData.class) - .set(handler, AsyncHandlerData.create(parentContext, context, request)); - scope = context.makeCurrent(); + ASYNC_HANDLER_DATA.set(handler, AsyncHandlerData.create(parentContext, context, request)); + return context.makeCurrent(); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void onExit(@Advice.Local("otelScope") Scope scope) { + public static void onExit(@Advice.Enter @Nullable Scope scope) { if (scope != null) { scope.close(); } diff --git a/instrumentation/async-http-client/async-http-client-1.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v1_9/ResponseInstrumentation.java b/instrumentation/async-http-client/async-http-client-1.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v1_9/ResponseInstrumentation.java index 4920f26280..ffb2551ba7 100644 --- a/instrumentation/async-http-client/async-http-client-1.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v1_9/ResponseInstrumentation.java +++ b/instrumentation/async-http-client/async-http-client-1.9/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v1_9/ResponseInstrumentation.java @@ -6,6 +6,7 @@ package io.opentelemetry.javaagent.instrumentation.asynchttpclient.v1_9; import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed; +import static io.opentelemetry.javaagent.instrumentation.asynchttpclient.v1_9.AsyncHttpClientSingletons.ASYNC_HANDLER_DATA; import static io.opentelemetry.javaagent.instrumentation.asynchttpclient.v1_9.AsyncHttpClientSingletons.instrumenter; import static net.bytebuddy.matcher.ElementMatchers.hasSuperClass; import static net.bytebuddy.matcher.ElementMatchers.isPublic; @@ -13,10 +14,8 @@ import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import com.ning.http.client.AsyncCompletionHandler; -import com.ning.http.client.AsyncHandler; import com.ning.http.client.Response; import io.opentelemetry.context.Scope; -import io.opentelemetry.instrumentation.api.util.VirtualField; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; import net.bytebuddy.asm.Advice; @@ -54,13 +53,11 @@ public class ResponseInstrumentation implements TypeInstrumentation { public static Scope onEnter( @Advice.This AsyncCompletionHandler handler, @Advice.Argument(0) Response response) { - VirtualField, AsyncHandlerData> virtualField = - VirtualField.find(AsyncHandler.class, AsyncHandlerData.class); - AsyncHandlerData data = virtualField.get(handler); + AsyncHandlerData data = ASYNC_HANDLER_DATA.get(handler); if (data == null) { return null; } - virtualField.set(handler, null); + ASYNC_HANDLER_DATA.set(handler, null); instrumenter().end(data.getContext(), data.getRequest(), response, null); return data.getParentContext().makeCurrent(); } @@ -80,13 +77,11 @@ public class ResponseInstrumentation implements TypeInstrumentation { public static Scope onEnter( @Advice.This AsyncCompletionHandler handler, @Advice.Argument(0) Throwable throwable) { - VirtualField, AsyncHandlerData> virtualField = - VirtualField.find(AsyncHandler.class, AsyncHandlerData.class); - AsyncHandlerData data = virtualField.get(handler); + AsyncHandlerData data = ASYNC_HANDLER_DATA.get(handler); if (data == null) { return null; } - virtualField.set(handler, null); + ASYNC_HANDLER_DATA.set(handler, null); instrumenter().end(data.getContext(), data.getRequest(), null, throwable); return data.getParentContext().makeCurrent(); } diff --git a/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v2_0/AsyncCompletionHandlerInstrumentation.java b/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v2_0/AsyncCompletionHandlerInstrumentation.java index ca72391540..e60db93ba2 100644 --- a/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v2_0/AsyncCompletionHandlerInstrumentation.java +++ b/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v2_0/AsyncCompletionHandlerInstrumentation.java @@ -6,6 +6,7 @@ package io.opentelemetry.javaagent.instrumentation.asynchttpclient.v2_0; import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed; +import static io.opentelemetry.javaagent.instrumentation.asynchttpclient.v2_0.AsyncHttpClientSingletons.ASYNC_HANDLER_REQUEST_CONTEXT; import static io.opentelemetry.javaagent.instrumentation.asynchttpclient.v2_0.AsyncHttpClientSingletons.instrumenter; import static net.bytebuddy.matcher.ElementMatchers.hasSuperClass; import static net.bytebuddy.matcher.ElementMatchers.isPublic; @@ -13,14 +14,12 @@ import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import io.opentelemetry.context.Scope; -import io.opentelemetry.instrumentation.api.util.VirtualField; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; import org.asynchttpclient.AsyncCompletionHandler; -import org.asynchttpclient.AsyncHandler; import org.asynchttpclient.Response; public class AsyncCompletionHandlerInstrumentation implements TypeInstrumentation { @@ -54,13 +53,11 @@ public class AsyncCompletionHandlerInstrumentation implements TypeInstrumentatio public static Scope onEnter( @Advice.This AsyncCompletionHandler handler, @Advice.Argument(0) Response response) { - VirtualField, RequestContext> virtualField = - VirtualField.find(AsyncHandler.class, RequestContext.class); - RequestContext requestContext = virtualField.get(handler); + RequestContext requestContext = ASYNC_HANDLER_REQUEST_CONTEXT.get(handler); if (requestContext == null) { return null; } - virtualField.set(handler, null); + ASYNC_HANDLER_REQUEST_CONTEXT.set(handler, null); instrumenter().end(requestContext.getContext(), requestContext, response, null); return requestContext.getParentContext().makeCurrent(); } @@ -80,13 +77,11 @@ public class AsyncCompletionHandlerInstrumentation implements TypeInstrumentatio public static Scope onEnter( @Advice.This AsyncCompletionHandler handler, @Advice.Argument(0) Throwable throwable) { - VirtualField, RequestContext> virtualField = - VirtualField.find(AsyncHandler.class, RequestContext.class); - RequestContext requestContext = virtualField.get(handler); + RequestContext requestContext = ASYNC_HANDLER_REQUEST_CONTEXT.get(handler); if (requestContext == null) { return null; } - virtualField.set(handler, null); + ASYNC_HANDLER_REQUEST_CONTEXT.set(handler, null); instrumenter().end(requestContext.getContext(), requestContext, null, throwable); return requestContext.getParentContext().makeCurrent(); } diff --git a/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v2_0/AsyncHttpClientInstrumentation.java b/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v2_0/AsyncHttpClientInstrumentation.java index d4330cc701..882c7e0f4e 100644 --- a/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v2_0/AsyncHttpClientInstrumentation.java +++ b/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v2_0/AsyncHttpClientInstrumentation.java @@ -7,6 +7,7 @@ package io.opentelemetry.javaagent.instrumentation.asynchttpclient.v2_0; import static io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge.currentContext; import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.implementsInterface; +import static io.opentelemetry.javaagent.instrumentation.asynchttpclient.v2_0.AsyncHttpClientSingletons.ASYNC_HANDLER_REQUEST_CONTEXT; import static io.opentelemetry.javaagent.instrumentation.asynchttpclient.v2_0.AsyncHttpClientSingletons.instrumenter; import static net.bytebuddy.matcher.ElementMatchers.isPublic; import static net.bytebuddy.matcher.ElementMatchers.named; @@ -14,9 +15,9 @@ import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; -import io.opentelemetry.instrumentation.api.util.VirtualField; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; +import javax.annotation.Nullable; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; @@ -43,15 +44,14 @@ public class AsyncHttpClientInstrumentation implements TypeInstrumentation { @SuppressWarnings("unused") public static class ExecuteRequestAdvice { + @Nullable @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnter( - @Advice.Argument(0) Request request, - @Advice.Argument(1) AsyncHandler handler, - @Advice.Local("otelScope") Scope scope) { + public static Scope onEnter( + @Advice.Argument(0) Request request, @Advice.Argument(1) AsyncHandler handler) { Context parentContext = currentContext(); RequestContext requestContext = new RequestContext(parentContext, request); if (!instrumenter().shouldStart(parentContext, requestContext)) { - return; + return null; } Context context = instrumenter().start(parentContext, requestContext); @@ -70,12 +70,12 @@ public class AsyncHttpClientInstrumentation implements TypeInstrumentation { // 2.1, so the instrumentation module will need to be essentially duplicated (or a common // module introduced) - VirtualField.find(AsyncHandler.class, RequestContext.class).set(handler, requestContext); - scope = context.makeCurrent(); + ASYNC_HANDLER_REQUEST_CONTEXT.set(handler, requestContext); + return context.makeCurrent(); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void onExit(@Advice.Local("otelScope") Scope scope) { + public static void onExit(@Advice.Enter @Nullable Scope scope) { if (scope != null) { scope.close(); } diff --git a/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v2_0/AsyncHttpClientInstrumentationModule.java b/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v2_0/AsyncHttpClientInstrumentationModule.java index 56d9245955..756f19fde8 100644 --- a/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v2_0/AsyncHttpClientInstrumentationModule.java +++ b/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v2_0/AsyncHttpClientInstrumentationModule.java @@ -10,10 +10,12 @@ import static java.util.Arrays.asList; import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import io.opentelemetry.javaagent.extension.instrumentation.internal.ExperimentalInstrumentationModule; import java.util.List; @AutoService(InstrumentationModule.class) -public class AsyncHttpClientInstrumentationModule extends InstrumentationModule { +public class AsyncHttpClientInstrumentationModule extends InstrumentationModule + implements ExperimentalInstrumentationModule { public AsyncHttpClientInstrumentationModule() { super("async-http-client", "async-http-client-2.0"); } @@ -26,4 +28,9 @@ public class AsyncHttpClientInstrumentationModule extends InstrumentationModule new NettyRequestSenderInstrumentation(), new NettyResponseFutureInstrumentation()); } + + @Override + public boolean isIndyReady() { + return true; + } } diff --git a/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v2_0/AsyncHttpClientSingletons.java b/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v2_0/AsyncHttpClientSingletons.java index 2e140594f0..022b128e5e 100644 --- a/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v2_0/AsyncHttpClientSingletons.java +++ b/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v2_0/AsyncHttpClientSingletons.java @@ -5,14 +5,20 @@ package io.opentelemetry.javaagent.instrumentation.asynchttpclient.v2_0; +import io.opentelemetry.context.Context; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.util.VirtualField; import io.opentelemetry.javaagent.bootstrap.internal.JavaagentHttpClientInstrumenters; +import org.asynchttpclient.AsyncHandler; +import org.asynchttpclient.Request; import org.asynchttpclient.Response; public final class AsyncHttpClientSingletons { private static final String INSTRUMENTATION_NAME = "io.opentelemetry.async-http-client-2.0"; private static final Instrumenter INSTRUMENTER; + public static final VirtualField, RequestContext> ASYNC_HANDLER_REQUEST_CONTEXT; + public static final VirtualField REQUEST_CONTEXT; static { INSTRUMENTER = @@ -20,6 +26,9 @@ public final class AsyncHttpClientSingletons { INSTRUMENTATION_NAME, new AsyncHttpClientHttpAttributesGetter(), HttpHeaderSetter.INSTANCE); + + ASYNC_HANDLER_REQUEST_CONTEXT = VirtualField.find(AsyncHandler.class, RequestContext.class); + REQUEST_CONTEXT = VirtualField.find(Request.class, Context.class); } public static Instrumenter instrumenter() { diff --git a/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v2_0/NettyRequestSenderInstrumentation.java b/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v2_0/NettyRequestSenderInstrumentation.java index 1b7dbd535f..f682535d45 100644 --- a/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v2_0/NettyRequestSenderInstrumentation.java +++ b/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v2_0/NettyRequestSenderInstrumentation.java @@ -5,6 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.asynchttpclient.v2_0; +import static io.opentelemetry.javaagent.instrumentation.asynchttpclient.v2_0.AsyncHttpClientSingletons.ASYNC_HANDLER_REQUEST_CONTEXT; +import static io.opentelemetry.javaagent.instrumentation.asynchttpclient.v2_0.AsyncHttpClientSingletons.REQUEST_CONTEXT; import static net.bytebuddy.matcher.ElementMatchers.isPublic; import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.returns; @@ -12,14 +14,12 @@ import static net.bytebuddy.matcher.ElementMatchers.takesArgument; import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; -import io.opentelemetry.instrumentation.api.util.VirtualField; import io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; -import org.asynchttpclient.AsyncHandler; import org.asynchttpclient.Request; import org.asynchttpclient.netty.NettyResponseFuture; @@ -59,8 +59,7 @@ public class NettyRequestSenderInstrumentation implements TypeInstrumentation { @Advice.OnMethodEnter public static void attachContext(@Advice.Argument(0) Request request) { - VirtualField.find(Request.class, Context.class) - .set(request, Java8BytecodeBridge.currentContext()); + REQUEST_CONTEXT.set(request, Java8BytecodeBridge.currentContext()); } } @@ -70,7 +69,7 @@ public class NettyRequestSenderInstrumentation implements TypeInstrumentation { @Advice.OnMethodEnter public static Scope mountContext(@Advice.Argument(0) NettyResponseFuture responseFuture) { Request request = responseFuture.getCurrentRequest(); - Context context = VirtualField.find(Request.class, Context.class).get(request); + Context context = REQUEST_CONTEXT.get(request); return context == null ? null : context.makeCurrent(); } @@ -88,8 +87,7 @@ public class NettyRequestSenderInstrumentation implements TypeInstrumentation { @Advice.OnMethodExit public static void rememberNettyRequest(@Advice.Return NettyResponseFuture responseFuture) { RequestContext requestContext = - VirtualField.find(AsyncHandler.class, RequestContext.class) - .get(responseFuture.getAsyncHandler()); + ASYNC_HANDLER_REQUEST_CONTEXT.get(responseFuture.getAsyncHandler()); if (requestContext != null) { requestContext.setNettyRequest(responseFuture.getNettyRequest()); } diff --git a/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v2_0/NettyResponseFutureInstrumentation.java b/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v2_0/NettyResponseFutureInstrumentation.java index 61e3703382..bfd01e10ce 100644 --- a/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v2_0/NettyResponseFutureInstrumentation.java +++ b/instrumentation/async-http-client/async-http-client-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/asynchttpclient/v2_0/NettyResponseFutureInstrumentation.java @@ -14,6 +14,7 @@ import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; import java.util.concurrent.CompletableFuture; import net.bytebuddy.asm.Advice; +import net.bytebuddy.asm.Advice.AssignReturned; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; @@ -34,9 +35,10 @@ public class NettyResponseFutureInstrumentation implements TypeInstrumentation { @SuppressWarnings("unused") public static class WrapFutureAdvice { + @AssignReturned.ToReturned @Advice.OnMethodExit(suppress = Throwable.class) - public static void onExit(@Advice.Return(readOnly = false) CompletableFuture result) { - result = CompletableFutureWrapper.wrap(result, Java8BytecodeBridge.currentContext()); + public static CompletableFuture onExit(@Advice.Return CompletableFuture result) { + return CompletableFutureWrapper.wrap(result, Java8BytecodeBridge.currentContext()); } } } diff --git a/instrumentation/google-http-client-1.19/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/googlehttpclient/GoogleHttpClientInstrumentationModule.java b/instrumentation/google-http-client-1.19/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/googlehttpclient/GoogleHttpClientInstrumentationModule.java index 45e0b242a8..75c00b4f00 100644 --- a/instrumentation/google-http-client-1.19/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/googlehttpclient/GoogleHttpClientInstrumentationModule.java +++ b/instrumentation/google-http-client-1.19/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/googlehttpclient/GoogleHttpClientInstrumentationModule.java @@ -10,10 +10,12 @@ import static java.util.Collections.singletonList; import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import io.opentelemetry.javaagent.extension.instrumentation.internal.ExperimentalInstrumentationModule; import java.util.List; @AutoService(InstrumentationModule.class) -public class GoogleHttpClientInstrumentationModule extends InstrumentationModule { +public class GoogleHttpClientInstrumentationModule extends InstrumentationModule + implements ExperimentalInstrumentationModule { public GoogleHttpClientInstrumentationModule() { super("google-http-client", "google-http-client-1.19"); } @@ -22,4 +24,9 @@ public class GoogleHttpClientInstrumentationModule extends InstrumentationModule public List typeInstrumentations() { return singletonList(new GoogleHttpRequestInstrumentation()); } + + @Override + public boolean isIndyReady() { + return true; + } } diff --git a/instrumentation/google-http-client-1.19/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/googlehttpclient/GoogleHttpRequestInstrumentation.java b/instrumentation/google-http-client-1.19/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/googlehttpclient/GoogleHttpRequestInstrumentation.java index c356690526..093bc09026 100644 --- a/instrumentation/google-http-client-1.19/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/googlehttpclient/GoogleHttpRequestInstrumentation.java +++ b/instrumentation/google-http-client-1.19/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/googlehttpclient/GoogleHttpRequestInstrumentation.java @@ -21,6 +21,7 @@ import io.opentelemetry.instrumentation.api.util.VirtualField; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; import java.util.concurrent.Executor; +import javax.annotation.Nullable; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; @@ -49,78 +50,108 @@ public class GoogleHttpRequestInstrumentation implements TypeInstrumentation { this.getClass().getName() + "$ExecuteAsyncAdvice"); } + public static class AdviceScope { + + private static final VirtualField HTTP_REQUEST_CONTEXT = + VirtualField.find(HttpRequest.class, Context.class); + private final Context context; + private final Scope scope; + private final HttpRequest request; + + public AdviceScope(Context context, Scope scope, HttpRequest request) { + this.context = context; + this.scope = scope; + this.request = request; + } + + @Nullable + public static AdviceScope start(HttpRequest request) { + Context parentContext = currentContext(); + if (!instrumenter().shouldStart(parentContext, request)) { + return null; + } + + Context context = instrumenter().start(parentContext, request); + return new AdviceScope(context, context.makeCurrent(), request); + } + + public void end(HttpResponse response, Throwable throwable) { + scope.close(); + instrumenter().end(context, request, response, throwable); + } + + public void endWhenThrown(HttpRequest request, Throwable throwable) { + scope.close(); + if (throwable != null) { + instrumenter().end(context, request, null, throwable); + } + } + + public static AdviceScope fromVirtualFieldContext(HttpRequest request) { + Context context = HTTP_REQUEST_CONTEXT.get(request); + if (context == null) { + return null; + } + return new AdviceScope(context, context.makeCurrent(), request); + } + + public void storeContextToVirtualField(HttpRequest request) { + HTTP_REQUEST_CONTEXT.set(request, context); + } + } + @SuppressWarnings("unused") public static class ExecuteAdvice { + @Nullable @Advice.OnMethodEnter(suppress = Throwable.class) - public static void methodEnter( - @Advice.This HttpRequest request, - @Advice.Local("otelContext") Context context, - @Advice.Local("otelScope") Scope scope) { + public static AdviceScope methodEnter(@Advice.This HttpRequest request) { - context = VirtualField.find(HttpRequest.class, Context.class).get(request); - if (context != null) { + AdviceScope scope = AdviceScope.fromVirtualFieldContext(request); + if (scope != null) { // span was created by GoogleHttpClientAsyncAdvice instrumentation below // (executeAsync ends up calling execute from a separate thread) // so make it current and end it in method exit - scope = context.makeCurrent(); - return; + return scope; } - Context parentContext = currentContext(); - if (!instrumenter().shouldStart(parentContext, request)) { - return; - } - context = instrumenter().start(parentContext, request); - scope = context.makeCurrent(); + + return AdviceScope.start(request); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) public static void methodExit( - @Advice.This HttpRequest request, @Advice.Return HttpResponse response, @Advice.Thrown Throwable throwable, - @Advice.Local("otelContext") Context context, - @Advice.Local("otelScope") Scope scope) { - if (scope == null) { - return; - } + @Advice.Enter @Nullable AdviceScope scope) { - scope.close(); - instrumenter().end(context, request, response, throwable); + if (scope != null) { + scope.end(response, throwable); + } } } @SuppressWarnings("unused") public static class ExecuteAsyncAdvice { + @Nullable @Advice.OnMethodEnter(suppress = Throwable.class) - public static void methodEnter( - @Advice.This HttpRequest request, - @Advice.Local("otelContext") Context context, - @Advice.Local("otelScope") Scope scope) { - Context parentContext = currentContext(); - if (!instrumenter().shouldStart(parentContext, request)) { - return; - } - context = instrumenter().start(parentContext, request); - scope = context.makeCurrent(); + public static AdviceScope methodEnter(@Advice.This HttpRequest request) { - VirtualField.find(HttpRequest.class, Context.class).set(request, context); + AdviceScope scope = AdviceScope.start(request); + if (scope != null) { + scope.storeContextToVirtualField(request); + } + return scope; } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) public static void methodExit( @Advice.This HttpRequest request, @Advice.Thrown Throwable throwable, - @Advice.Local("otelContext") Context context, - @Advice.Local("otelScope") Scope scope) { - if (scope == null) { - return; - } + @Advice.Enter @Nullable AdviceScope scope) { - scope.close(); - if (throwable != null) { - instrumenter().end(context, request, null, throwable); + if (scope != null) { + scope.endWhenThrown(request, throwable); } } } diff --git a/instrumentation/java-http-client/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/javahttpclient/HttpClientInstrumentation.java b/instrumentation/java-http-client/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/javahttpclient/HttpClientInstrumentation.java index 1131decf09..4178318197 100644 --- a/instrumentation/java-http-client/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/javahttpclient/HttpClientInstrumentation.java +++ b/instrumentation/java-http-client/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/javahttpclient/HttpClientInstrumentation.java @@ -28,7 +28,9 @@ import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.util.concurrent.CompletableFuture; +import javax.annotation.Nullable; import net.bytebuddy.asm.Advice; +import net.bytebuddy.asm.Advice.AssignReturned; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; @@ -68,84 +70,122 @@ public class HttpClientInstrumentation implements TypeInstrumentation { @SuppressWarnings("unused") public static class SendAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void methodEnter( - @Advice.Argument(value = 0) HttpRequest httpRequest, - @Advice.Local("otelContext") Context context, - @Advice.Local("otelScope") Scope scope) { - Context parentContext = currentContext(); - if (!instrumenter().shouldStart(parentContext, httpRequest)) { - return; + public static class AdviceScope { + private final Context context; + private final Scope scope; + private final HttpRequest request; + + private AdviceScope(Context context, Scope scope, HttpRequest request) { + this.context = context; + this.scope = scope; + this.request = request; } - context = instrumenter().start(parentContext, httpRequest); - scope = context.makeCurrent(); + @Nullable + public static AdviceScope start(HttpRequest request) { + Context parentContext = currentContext(); + if (!instrumenter().shouldStart(parentContext, request)) { + return null; + } + + Context context = instrumenter().start(parentContext, request); + return new AdviceScope(context, context.makeCurrent(), request); + } + + public void end(@Nullable HttpResponse response, @Nullable Throwable throwable) { + scope.close(); + instrumenter().end(context, request, response, throwable); + } + } + + @Nullable + @Advice.OnMethodEnter(suppress = Throwable.class) + public static AdviceScope methodEnter(@Advice.Argument(value = 0) HttpRequest httpRequest) { + return AdviceScope.start(httpRequest); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) public static void methodExit( @Advice.Argument(0) HttpRequest httpRequest, - @Advice.Return HttpResponse httpResponse, - @Advice.Thrown Throwable throwable, - @Advice.Local("otelContext") Context context, - @Advice.Local("otelScope") Scope scope) { - if (scope == null) { - return; - } + @Advice.Return @Nullable HttpResponse httpResponse, + @Advice.Thrown @Nullable Throwable throwable, + @Advice.Enter @Nullable AdviceScope scope) { - scope.close(); - instrumenter().end(context, httpRequest, httpResponse, throwable); + if (scope != null) { + scope.end(httpResponse, throwable); + } } } @SuppressWarnings("unused") public static class SendAsyncAdvice { - @Advice.OnMethodEnter(suppress = Throwable.class) - public static void methodEnter( - @Advice.Argument(value = 0) HttpRequest httpRequest, - @Advice.Local("otelCallDepth") CallDepth callDepth, - @Advice.Local("otelContext") Context context, - @Advice.Local("otelParentContext") Context parentContext, - @Advice.Local("otelScope") Scope scope) { - callDepth = CallDepth.forClass(HttpClient.class); - if (callDepth.getAndIncrement() > 0) { - return; + public static class AsyncAdviceScope { + private final Context parentContext; + private final Context context; + private final Scope scope; + private final CallDepth callDepth; + private final HttpRequest request; + + public AsyncAdviceScope( + Context parentContext, + Context context, + Scope scope, + CallDepth callDepth, + HttpRequest request) { + this.parentContext = parentContext; + this.context = context; + this.scope = scope; + this.callDepth = callDepth; + this.request = request; } - parentContext = currentContext(); - if (!instrumenter().shouldStart(parentContext, httpRequest)) { - return; + @Nullable + public static AsyncAdviceScope start(HttpRequest request) { + CallDepth callDepth = CallDepth.forClass(HttpClient.class); + if (callDepth.getAndIncrement() > 0) { + return new AsyncAdviceScope(null, null, null, callDepth, request); + } + Context parentContext = currentContext(); + if (!instrumenter().shouldStart(parentContext, request)) { + return null; + } + Context context = instrumenter().start(parentContext, request); + return new AsyncAdviceScope( + parentContext, context, context.makeCurrent(), callDepth, request); } - context = instrumenter().start(parentContext, httpRequest); - scope = context.makeCurrent(); + public CompletableFuture> end( + @Nullable Throwable throwable, @Nullable CompletableFuture> future) { + if (callDepth.decrementAndGet() > 0 || scope == null) { + // async end nested call + return future; + } + scope.close(); + if (throwable != null) { + // async end with exception: ending span and no wrapping needed + instrumenter().end(context, request, null, throwable); + return future; + } + future = future.whenComplete(new ResponseConsumer(instrumenter(), context, request)); + return CompletableFutureWrapper.wrap(future, parentContext); + } } + @Nullable + @Advice.OnMethodEnter(suppress = Throwable.class) + public static AsyncAdviceScope methodEnter( + @Advice.Argument(value = 0) HttpRequest httpRequest) { + return AsyncAdviceScope.start(httpRequest); + } + + @AssignReturned.ToReturned @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void methodExit( - @Advice.Argument(value = 0) HttpRequest httpRequest, - @Advice.Return(readOnly = false) CompletableFuture> future, - @Advice.Thrown Throwable throwable, - @Advice.Local("otelCallDepth") CallDepth callDepth, - @Advice.Local("otelContext") Context context, - @Advice.Local("otelParentContext") Context parentContext, - @Advice.Local("otelScope") Scope scope) { - if (callDepth.decrementAndGet() > 0) { - return; - } - - if (scope == null) { - return; - } - - scope.close(); - if (throwable != null) { - instrumenter().end(context, httpRequest, null, throwable); - } else { - future = future.whenComplete(new ResponseConsumer(instrumenter(), context, httpRequest)); - future = CompletableFutureWrapper.wrap(future, parentContext); - } + public static CompletableFuture> methodExit( + @Advice.Return @Nullable CompletableFuture> future, + @Advice.Thrown @Nullable Throwable throwable, + @Advice.Enter @Nullable AsyncAdviceScope scope) { + return scope == null ? future : scope.end(throwable, future); } } } diff --git a/instrumentation/java-http-client/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/javahttpclient/HttpClientInstrumentationModule.java b/instrumentation/java-http-client/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/javahttpclient/HttpClientInstrumentationModule.java index 0735a73f55..f400404591 100644 --- a/instrumentation/java-http-client/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/javahttpclient/HttpClientInstrumentationModule.java +++ b/instrumentation/java-http-client/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/javahttpclient/HttpClientInstrumentationModule.java @@ -10,10 +10,12 @@ import static java.util.Arrays.asList; import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import io.opentelemetry.javaagent.extension.instrumentation.internal.ExperimentalInstrumentationModule; import java.util.List; @AutoService(InstrumentationModule.class) -public class HttpClientInstrumentationModule extends InstrumentationModule { +public class HttpClientInstrumentationModule extends InstrumentationModule + implements ExperimentalInstrumentationModule { public HttpClientInstrumentationModule() { super("java-http-client"); } @@ -22,4 +24,9 @@ public class HttpClientInstrumentationModule extends InstrumentationModule { public List typeInstrumentations() { return asList(new HttpClientInstrumentation(), new HttpHeadersInstrumentation()); } + + @Override + public boolean isIndyReady() { + return true; + } } diff --git a/instrumentation/java-http-client/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/javahttpclient/HttpHeadersInstrumentation.java b/instrumentation/java-http-client/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/javahttpclient/HttpHeadersInstrumentation.java index 3f72cdf76b..e52b84979f 100644 --- a/instrumentation/java-http-client/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/javahttpclient/HttpHeadersInstrumentation.java +++ b/instrumentation/java-http-client/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/javahttpclient/HttpHeadersInstrumentation.java @@ -16,6 +16,7 @@ import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; import java.net.http.HttpHeaders; import net.bytebuddy.asm.Advice; +import net.bytebuddy.asm.Advice.AssignReturned; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; @@ -38,9 +39,10 @@ public class HttpHeadersInstrumentation implements TypeInstrumentation { @SuppressWarnings("unused") public static class HeadersAdvice { + @AssignReturned.ToReturned @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) - public static void methodExit(@Advice.Return(readOnly = false) HttpHeaders headers) { - headers = setter().inject(headers, Context.current()); + public static HttpHeaders methodExit(@Advice.Return HttpHeaders headers) { + return setter().inject(headers, Context.current()); } } } diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyClient12ResponseListenersInstrumentation.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyClient12ResponseListenersInstrumentation.java index 940ede1b69..bf88259963 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyClient12ResponseListenersInstrumentation.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyClient12ResponseListenersInstrumentation.java @@ -16,6 +16,7 @@ import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; +import javax.annotation.Nullable; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; @@ -54,55 +55,46 @@ public class JettyClient12ResponseListenersInstrumentation implements TypeInstru @SuppressWarnings("unused") public static class JettyHttpClient12RespListenersNotifyAdvice { + + @Nullable @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnterNotify( - @Advice.Argument(0) Response response, - @Advice.Local("otelContext") Context context, - @Advice.Local("otelScope") Scope scope) { - context = (Context) response.getRequest().getAttributes().get(JETTY_CLIENT_CONTEXT_KEY); - if (context != null) { - scope = context.makeCurrent(); - } + public static Scope onEnterNotify(@Advice.Argument(0) Response response) { + + Context context = + (Context) response.getRequest().getAttributes().get(JETTY_CLIENT_CONTEXT_KEY); + return context == null ? null : context.makeCurrent(); } @Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class) public static void onExitNotify( @Advice.Argument(0) Response response, @Advice.Thrown Throwable throwable, - @Advice.Local("otelContext") Context context, - @Advice.Local("otelScope") Scope scope) { - if (scope == null) { - return; - } + @Advice.Enter @Nullable Scope scope) { - scope.close(); + if (scope != null) { + scope.close(); + } } } @SuppressWarnings("unused") public static class JettyHttpClient12CompleteListenersNotifyAdvice { + @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnterComplete( - @Advice.Argument(0) Result result, - @Advice.Local("otelContext") Context context, - @Advice.Local("otelScope") Scope scope) { - context = (Context) result.getRequest().getAttributes().get(JETTY_CLIENT_CONTEXT_KEY); - if (context != null) { - scope = context.makeCurrent(); - } + public static Scope onEnterComplete(@Advice.Argument(0) Result result) { + + Context context = (Context) result.getRequest().getAttributes().get(JETTY_CLIENT_CONTEXT_KEY); + return context == null ? null : context.makeCurrent(); } @Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class) public static void onExitComplete( @Advice.Argument(0) Result result, @Advice.Thrown Throwable throwable, - @Advice.Local("otelContext") Context context, - @Advice.Local("otelScope") Scope scope) { - if (scope == null) { - return; + @Advice.Enter @Nullable Scope scope) { + if (scope != null) { + scope.close(); } - - scope.close(); } } } diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12Instrumentation.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12Instrumentation.java index 9ba900164b..2fce5882fa 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12Instrumentation.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12Instrumentation.java @@ -17,6 +17,7 @@ import io.opentelemetry.context.Scope; import io.opentelemetry.instrumentation.jetty.httpclient.v12_0.internal.JettyClientTracingListener; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; +import javax.annotation.Nullable; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; @@ -45,63 +46,68 @@ public class JettyHttpClient12Instrumentation implements TypeInstrumentation { @SuppressWarnings("unused") public static class JettyHttpClient12SendAdvice { + public static class AdviceLocals { + public final Context context; + public final Scope scope; + + public AdviceLocals(Context context, Scope scope) { + this.context = context; + this.scope = scope; + } + } + + @Nullable @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnterSend( - @Advice.This HttpRequest request, - @Advice.Local("otelContext") Context context, - @Advice.Local("otelScope") Scope scope) { + public static AdviceLocals onEnterSend(@Advice.This HttpRequest request) { // start span Context parentContext = Context.current(); - context = JettyClientTracingListener.handleRequest(parentContext, request, instrumenter()); + Context context = + JettyClientTracingListener.handleRequest(parentContext, request, instrumenter()); if (context == null) { - return; + return null; } // set context for responseListeners request.attribute(JETTY_CLIENT_CONTEXT_KEY, parentContext); - scope = context.makeCurrent(); + return new AdviceLocals(context, context.makeCurrent()); } @Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class) public static void onExitSend( @Advice.This HttpRequest request, @Advice.Thrown Throwable throwable, - @Advice.Local("otelContext") Context context, - @Advice.Local("otelScope") Scope scope) { - if (scope == null) { + @Advice.Enter @Nullable AdviceLocals locals) { + + if (locals == null) { return; } // not ending span here unless error, span ended in the interceptor - scope.close(); + locals.scope.close(); if (throwable != null) { - instrumenter().end(context, request, null, throwable); + instrumenter().end(locals.context, request, null, throwable); } } } @SuppressWarnings("unused") public static class JettyHttpClient12NotifyAdvice { + + @Nullable @Advice.OnMethodEnter(suppress = Throwable.class) - public static void onEnterNotify( - @Advice.This HttpRequest request, - @Advice.Local("otelContext") Context context, - @Advice.Local("otelScope") Scope scope) { - context = (Context) request.getAttributes().get(JETTY_CLIENT_CONTEXT_KEY); + public static Scope onEnterNotify(@Advice.This HttpRequest request) { + Context context = (Context) request.getAttributes().get(JETTY_CLIENT_CONTEXT_KEY); if (context == null) { - return; + return null; } - scope = context.makeCurrent(); + return context.makeCurrent(); } @Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class) - public static void onExitNotify( - @Advice.Local("otelContext") Context context, @Advice.Local("otelScope") Scope scope) { - if (scope == null) { - return; + public static void onExitNotify(@Advice.Enter Scope scope) { + if (scope != null) { + scope.close(); } - - scope.close(); } } } diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12InstrumentationModule.java b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12InstrumentationModule.java index 5d9690dbc7..b6b6235c73 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12InstrumentationModule.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-12.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v12_0/JettyHttpClient12InstrumentationModule.java @@ -10,10 +10,12 @@ import static java.util.Arrays.asList; import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import io.opentelemetry.javaagent.extension.instrumentation.internal.ExperimentalInstrumentationModule; import java.util.List; @AutoService(InstrumentationModule.class) -public class JettyHttpClient12InstrumentationModule extends InstrumentationModule { +public class JettyHttpClient12InstrumentationModule extends InstrumentationModule + implements ExperimentalInstrumentationModule { public JettyHttpClient12InstrumentationModule() { super("jetty-httpclient", "jetty-httpclient-12.0"); } @@ -24,4 +26,9 @@ public class JettyHttpClient12InstrumentationModule extends InstrumentationModul new JettyHttpClient12Instrumentation(), new JettyClient12ResponseListenersInstrumentation()); } + + @Override + public boolean isIndyReady() { + return true; + } } diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v9_2/JettyHttpClient9Instrumentation.java b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v9_2/JettyHttpClient9Instrumentation.java index 4215289766..2554c50d1c 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v9_2/JettyHttpClient9Instrumentation.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v9_2/JettyHttpClient9Instrumentation.java @@ -19,6 +19,8 @@ import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer; import java.util.List; import net.bytebuddy.asm.Advice; +import net.bytebuddy.asm.Advice.AssignReturned; +import net.bytebuddy.asm.Advice.AssignReturned.ToArguments.ToArgument; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; import org.eclipse.jetty.client.HttpRequest; @@ -43,38 +45,48 @@ public class JettyHttpClient9Instrumentation implements TypeInstrumentation { @SuppressWarnings("unused") public static class JettyHttpClient9Advice { + public static class AdviceLocals { + public final Context context; + public final Scope scope; + + public AdviceLocals(Context context, Scope scope) { + this.context = context; + this.scope = scope; + } + } + + @AssignReturned.ToArguments(@ToArgument(value = 1, index = 1)) @Advice.OnMethodEnter(suppress = Throwable.class) - public static void addTracingEnter( + public static Object[] addTracingEnter( @Advice.Argument(value = 0) HttpRequest httpRequest, - @Advice.Argument(value = 1, readOnly = false) List listeners, - @Advice.Local("otelContext") Context context, - @Advice.Local("otelScope") Scope scope) { + @Advice.Argument(1) List listeners) { Context parentContext = currentContext(); - context = + Context context = JettyClientTracingListener.handleRequest(parentContext, httpRequest, instrumenter()); if (context == null) { - return; + return new Object[] {null, listeners}; } - listeners = wrapResponseListeners(parentContext, listeners); - scope = context.makeCurrent(); + List wrappedListeners = + wrapResponseListeners(parentContext, listeners); + return new Object[] {new AdviceLocals(context, context.makeCurrent()), wrappedListeners}; } @Advice.OnMethodExit(suppress = Throwable.class, onThrowable = Throwable.class) public static void exitTracingInterceptor( @Advice.Argument(value = 0) HttpRequest httpRequest, @Advice.Thrown Throwable throwable, - @Advice.Local("otelContext") Context context, - @Advice.Local("otelScope") Scope scope) { + @Advice.Enter Object[] enterResult) { + AdviceLocals locals = (AdviceLocals) enterResult[0]; - if (scope == null) { + if (locals == null) { return; } // not ending span here unless error, span ended in the interceptor - scope.close(); + locals.scope.close(); if (throwable != null) { - instrumenter().end(context, httpRequest, null, throwable); + instrumenter().end(locals.context, httpRequest, null, throwable); } } } diff --git a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v9_2/JettyHttpClient9InstrumentationModule.java b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v9_2/JettyHttpClient9InstrumentationModule.java index 1715f9133d..8a30279e81 100644 --- a/instrumentation/jetty-httpclient/jetty-httpclient-9.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v9_2/JettyHttpClient9InstrumentationModule.java +++ b/instrumentation/jetty-httpclient/jetty-httpclient-9.2/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jetty/httpclient/v9_2/JettyHttpClient9InstrumentationModule.java @@ -11,11 +11,13 @@ import static java.util.Collections.singletonList; import com.google.auto.service.AutoService; import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule; import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation; +import io.opentelemetry.javaagent.extension.instrumentation.internal.ExperimentalInstrumentationModule; import java.util.List; import net.bytebuddy.matcher.ElementMatcher; @AutoService(InstrumentationModule.class) -public class JettyHttpClient9InstrumentationModule extends InstrumentationModule { +public class JettyHttpClient9InstrumentationModule extends InstrumentationModule + implements ExperimentalInstrumentationModule { public JettyHttpClient9InstrumentationModule() { super("jetty-httpclient", "jetty-httpclient-9.2"); @@ -31,4 +33,9 @@ public class JettyHttpClient9InstrumentationModule extends InstrumentationModule // AbstractTypedContentProvider showed up in version Jetty Client 9.2 on to 10.x return hasClassesNamed("org.eclipse.jetty.client.util.AbstractTypedContentProvider"); } + + @Override + public boolean isIndyReady() { + return true; + } }