make vertx indy-ready (#14567)
This commit is contained in:
		
							parent
							
								
									d84b144cad
								
							
						
					
					
						commit
						1961f62b95
					
				| 
						 | 
				
			
			@ -5,10 +5,10 @@
 | 
			
		|||
 | 
			
		||||
package io.opentelemetry.javaagent.instrumentation.vertx.v3_0.client;
 | 
			
		||||
 | 
			
		||||
import static io.opentelemetry.javaagent.instrumentation.vertx.v3_0.client.VertxClientSingletons.HTTP_CLIENT_OPTIONS;
 | 
			
		||||
import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
 | 
			
		||||
import static net.bytebuddy.matcher.ElementMatchers.named;
 | 
			
		||||
 | 
			
		||||
import io.opentelemetry.instrumentation.api.util.VirtualField;
 | 
			
		||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
 | 
			
		||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
 | 
			
		||||
import io.vertx.core.http.HttpClientOptions;
 | 
			
		||||
| 
						 | 
				
			
			@ -36,7 +36,7 @@ public class HttpClientImplInstrumentation implements TypeInstrumentation {
 | 
			
		|||
    public static void attachHttpClientOptions(
 | 
			
		||||
        @Advice.This HttpClientImpl client,
 | 
			
		||||
        @Advice.FieldValue("options") HttpClientOptions options) {
 | 
			
		||||
      VirtualField.find(HttpClientImpl.class, HttpClientOptions.class).set(client, options);
 | 
			
		||||
      HTTP_CLIENT_OPTIONS.set(client, options);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,11 +5,12 @@
 | 
			
		|||
 | 
			
		||||
package io.opentelemetry.javaagent.instrumentation.vertx.v3_0.client;
 | 
			
		||||
 | 
			
		||||
import static io.opentelemetry.javaagent.instrumentation.vertx.v3_0.client.VertxClientSingletons.HTTP_CLIENT_OPTIONS;
 | 
			
		||||
import static io.opentelemetry.javaagent.instrumentation.vertx.v3_0.client.VertxClientSingletons.REQUEST_INFO;
 | 
			
		||||
import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
 | 
			
		||||
import static net.bytebuddy.matcher.ElementMatchers.named;
 | 
			
		||||
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
 | 
			
		||||
 | 
			
		||||
import io.opentelemetry.instrumentation.api.util.VirtualField;
 | 
			
		||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
 | 
			
		||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
 | 
			
		||||
import io.vertx.core.http.HttpClientOptions;
 | 
			
		||||
| 
						 | 
				
			
			@ -53,13 +54,11 @@ public class HttpRequestImplInstrumentation implements TypeInstrumentation {
 | 
			
		|||
        @Advice.Argument(0) HttpClientImpl client,
 | 
			
		||||
        @Advice.Argument(2) String host,
 | 
			
		||||
        @Advice.Argument(3) int port) {
 | 
			
		||||
      HttpClientOptions httpClientOptions =
 | 
			
		||||
          VirtualField.find(HttpClientImpl.class, HttpClientOptions.class).get(client);
 | 
			
		||||
      VirtualField.find(HttpClientRequest.class, VertxRequestInfo.class)
 | 
			
		||||
          .set(
 | 
			
		||||
              request,
 | 
			
		||||
              VertxRequestInfo.create(
 | 
			
		||||
                  httpClientOptions != null && httpClientOptions.isSsl(), host, port));
 | 
			
		||||
      HttpClientOptions httpClientOptions = HTTP_CLIENT_OPTIONS.get(client);
 | 
			
		||||
      REQUEST_INFO.set(
 | 
			
		||||
          request,
 | 
			
		||||
          VertxRequestInfo.create(
 | 
			
		||||
              httpClientOptions != null && httpClientOptions.isSsl(), host, port));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -71,8 +70,7 @@ public class HttpRequestImplInstrumentation implements TypeInstrumentation {
 | 
			
		|||
        @Advice.Argument(1) boolean ssl,
 | 
			
		||||
        @Advice.Argument(3) String host,
 | 
			
		||||
        @Advice.Argument(4) int port) {
 | 
			
		||||
      VirtualField.find(HttpClientRequest.class, VertxRequestInfo.class)
 | 
			
		||||
          .set(request, VertxRequestInfo.create(ssl, host, port));
 | 
			
		||||
      REQUEST_INFO.set(request, VertxRequestInfo.create(ssl, host, port));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -84,8 +82,7 @@ public class HttpRequestImplInstrumentation implements TypeInstrumentation {
 | 
			
		|||
        @Advice.Argument(1) boolean ssl,
 | 
			
		||||
        @Advice.Argument(4) String host,
 | 
			
		||||
        @Advice.Argument(5) int port) {
 | 
			
		||||
      VirtualField.find(HttpClientRequest.class, VertxRequestInfo.class)
 | 
			
		||||
          .set(request, VertxRequestInfo.create(ssl, host, port));
 | 
			
		||||
      REQUEST_INFO.set(request, VertxRequestInfo.create(ssl, host, port));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,8 @@ package io.opentelemetry.javaagent.instrumentation.vertx.v3_0.client;
 | 
			
		|||
 | 
			
		||||
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
 | 
			
		||||
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.implementsInterface;
 | 
			
		||||
import static io.opentelemetry.javaagent.instrumentation.vertx.v3_0.client.VertxClientSingletons.CONTEXTS;
 | 
			
		||||
import static io.opentelemetry.javaagent.instrumentation.vertx.v3_0.client.VertxClientSingletons.REQUEST_INFO;
 | 
			
		||||
import static io.opentelemetry.javaagent.instrumentation.vertx.v3_0.client.VertxClientSingletons.instrumenter;
 | 
			
		||||
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
 | 
			
		||||
import static net.bytebuddy.matcher.ElementMatchers.isPrivate;
 | 
			
		||||
| 
						 | 
				
			
			@ -16,8 +18,6 @@ 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 io.opentelemetry.javaagent.instrumentation.vertx.client.Contexts;
 | 
			
		||||
| 
						 | 
				
			
			@ -25,7 +25,10 @@ import io.opentelemetry.javaagent.instrumentation.vertx.client.ExceptionHandlerW
 | 
			
		|||
import io.vertx.core.Handler;
 | 
			
		||||
import io.vertx.core.http.HttpClientRequest;
 | 
			
		||||
import io.vertx.core.http.HttpClientResponse;
 | 
			
		||||
import javax.annotation.Nullable;
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -83,41 +86,52 @@ public class HttpRequestInstrumentation implements TypeInstrumentation {
 | 
			
		|||
  @SuppressWarnings("unused")
 | 
			
		||||
  public static class EndRequestAdvice {
 | 
			
		||||
 | 
			
		||||
    public static class AdviceScope {
 | 
			
		||||
      private final Context context;
 | 
			
		||||
      private final Scope scope;
 | 
			
		||||
 | 
			
		||||
      private AdviceScope(Context context, Scope scope) {
 | 
			
		||||
        this.context = context;
 | 
			
		||||
        this.scope = scope;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      @Nullable
 | 
			
		||||
      public static AdviceScope startAndAttachContext(HttpClientRequest request) {
 | 
			
		||||
        VertxRequestInfo requestInfo = REQUEST_INFO.get(request);
 | 
			
		||||
        if (requestInfo == null) {
 | 
			
		||||
          return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Context parentContext = Context.current();
 | 
			
		||||
        if (!instrumenter().shouldStart(parentContext, request)) {
 | 
			
		||||
          return null;
 | 
			
		||||
        }
 | 
			
		||||
        Context context = instrumenter().start(parentContext, request);
 | 
			
		||||
        CONTEXTS.set(request, new Contexts(parentContext, context));
 | 
			
		||||
        return new AdviceScope(context, context.makeCurrent());
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      public void end(@Nullable Throwable throwable, HttpClientRequest request) {
 | 
			
		||||
        scope.close();
 | 
			
		||||
        if (throwable != null) {
 | 
			
		||||
          instrumenter().end(context, request, null, throwable);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nullable
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static void attachContext(
 | 
			
		||||
        @Advice.This HttpClientRequest request,
 | 
			
		||||
        @Advice.Local("otelContext") Context context,
 | 
			
		||||
        @Advice.Local("otelScope") Scope scope) {
 | 
			
		||||
 | 
			
		||||
      VertxRequestInfo requestInfo =
 | 
			
		||||
          VirtualField.find(HttpClientRequest.class, VertxRequestInfo.class).get(request);
 | 
			
		||||
      if (requestInfo == null) {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      Context parentContext = Java8BytecodeBridge.currentContext();
 | 
			
		||||
      if (!instrumenter().shouldStart(parentContext, request)) {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      context = instrumenter().start(parentContext, request);
 | 
			
		||||
      Contexts contexts = new Contexts(parentContext, context);
 | 
			
		||||
      VirtualField.find(HttpClientRequest.class, Contexts.class).set(request, contexts);
 | 
			
		||||
 | 
			
		||||
      scope = context.makeCurrent();
 | 
			
		||||
    public static AdviceScope attachContext(@Advice.This HttpClientRequest request) {
 | 
			
		||||
      return AdviceScope.startAndAttachContext(request);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
 | 
			
		||||
    public static void endScope(
 | 
			
		||||
        @Advice.This HttpClientRequest request,
 | 
			
		||||
        @Advice.Local("otelContext") Context context,
 | 
			
		||||
        @Advice.Local("otelScope") Scope scope,
 | 
			
		||||
        @Advice.Thrown Throwable throwable) {
 | 
			
		||||
      if (scope != null) {
 | 
			
		||||
        scope.close();
 | 
			
		||||
      }
 | 
			
		||||
      if (throwable != null) {
 | 
			
		||||
        instrumenter().end(context, request, null, throwable);
 | 
			
		||||
        @Advice.Thrown @Nullable Throwable throwable,
 | 
			
		||||
        @Advice.Enter @Nullable AdviceScope adviceScope) {
 | 
			
		||||
      if (adviceScope != null) {
 | 
			
		||||
        adviceScope.end(throwable, request);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -125,25 +139,23 @@ public class HttpRequestInstrumentation implements TypeInstrumentation {
 | 
			
		|||
  @SuppressWarnings("unused")
 | 
			
		||||
  public static class HandleExceptionAdvice {
 | 
			
		||||
 | 
			
		||||
    @Nullable
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static void handleException(
 | 
			
		||||
        @Advice.This HttpClientRequest request,
 | 
			
		||||
        @Advice.Argument(0) Throwable t,
 | 
			
		||||
        @Advice.Local("otelScope") Scope scope) {
 | 
			
		||||
      Contexts contexts = VirtualField.find(HttpClientRequest.class, Contexts.class).get(request);
 | 
			
		||||
    public static Scope handleException(
 | 
			
		||||
        @Advice.This HttpClientRequest request, @Advice.Argument(0) Throwable t) {
 | 
			
		||||
 | 
			
		||||
      Contexts contexts = CONTEXTS.get(request);
 | 
			
		||||
      if (contexts == null) {
 | 
			
		||||
        return;
 | 
			
		||||
        return null;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      instrumenter().end(contexts.context, request, null, t);
 | 
			
		||||
 | 
			
		||||
      // Scoping all potential callbacks etc to the parent context
 | 
			
		||||
      scope = contexts.parentContext.makeCurrent();
 | 
			
		||||
      return contexts.parentContext.makeCurrent();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
 | 
			
		||||
    public static void handleResponseExit(@Advice.Local("otelScope") Scope scope) {
 | 
			
		||||
    public static void handleResponseExit(@Advice.Enter @Nullable Scope scope) {
 | 
			
		||||
      if (scope != null) {
 | 
			
		||||
        scope.close();
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			@ -153,25 +165,23 @@ public class HttpRequestInstrumentation implements TypeInstrumentation {
 | 
			
		|||
  @SuppressWarnings("unused")
 | 
			
		||||
  public static class HandleResponseAdvice {
 | 
			
		||||
 | 
			
		||||
    @Nullable
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static void handleResponseEnter(
 | 
			
		||||
        @Advice.This HttpClientRequest request,
 | 
			
		||||
        @Advice.Argument(0) HttpClientResponse response,
 | 
			
		||||
        @Advice.Local("otelScope") Scope scope) {
 | 
			
		||||
      Contexts contexts = VirtualField.find(HttpClientRequest.class, Contexts.class).get(request);
 | 
			
		||||
    public static Scope handleResponseEnter(
 | 
			
		||||
        @Advice.This HttpClientRequest request, @Advice.Argument(0) HttpClientResponse response) {
 | 
			
		||||
 | 
			
		||||
      Contexts contexts = CONTEXTS.get(request);
 | 
			
		||||
      if (contexts == null) {
 | 
			
		||||
        return;
 | 
			
		||||
        return null;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      instrumenter().end(contexts.context, request, response, null);
 | 
			
		||||
 | 
			
		||||
      // Scoping all potential callbacks etc to the parent context
 | 
			
		||||
      scope = contexts.parentContext.makeCurrent();
 | 
			
		||||
      return contexts.parentContext.makeCurrent();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
 | 
			
		||||
    public static void handleResponseExit(@Advice.Local("otelScope") Scope scope) {
 | 
			
		||||
    public static void handleResponseExit(@Advice.Enter @Nullable Scope scope) {
 | 
			
		||||
      if (scope != null) {
 | 
			
		||||
        scope.close();
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			@ -181,19 +191,18 @@ public class HttpRequestInstrumentation implements TypeInstrumentation {
 | 
			
		|||
  @SuppressWarnings("unused")
 | 
			
		||||
  public static class MountContextAdvice {
 | 
			
		||||
 | 
			
		||||
    @Nullable
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static void mountContext(
 | 
			
		||||
        @Advice.This HttpClientRequest request, @Advice.Local("otelScope") Scope scope) {
 | 
			
		||||
      Contexts contexts = VirtualField.find(HttpClientRequest.class, Contexts.class).get(request);
 | 
			
		||||
    public static Scope mountContext(@Advice.This HttpClientRequest request) {
 | 
			
		||||
      Contexts contexts = CONTEXTS.get(request);
 | 
			
		||||
      if (contexts == null) {
 | 
			
		||||
        return;
 | 
			
		||||
        return null;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      scope = contexts.context.makeCurrent();
 | 
			
		||||
      return contexts.context.makeCurrent();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
 | 
			
		||||
    public static void unmountContext(@Advice.Local("otelScope") Scope scope) {
 | 
			
		||||
    public static void unmountContext(@Advice.Enter @Nullable Scope scope) {
 | 
			
		||||
      if (scope != null) {
 | 
			
		||||
        scope.close();
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			@ -203,15 +212,16 @@ public class HttpRequestInstrumentation implements TypeInstrumentation {
 | 
			
		|||
  @SuppressWarnings("unused")
 | 
			
		||||
  public static class ExceptionHandlerAdvice {
 | 
			
		||||
 | 
			
		||||
    @Nullable
 | 
			
		||||
    @AssignReturned.ToArguments(@ToArgument(0))
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static void wrapExceptionHandler(
 | 
			
		||||
    public static Handler<Throwable> wrapExceptionHandler(
 | 
			
		||||
        @Advice.This HttpClientRequest request,
 | 
			
		||||
        @Advice.Argument(value = 0, readOnly = false) Handler<Throwable> handler) {
 | 
			
		||||
      if (handler != null) {
 | 
			
		||||
        VirtualField<HttpClientRequest, Contexts> virtualField =
 | 
			
		||||
            VirtualField.find(HttpClientRequest.class, Contexts.class);
 | 
			
		||||
        handler = ExceptionHandlerWrapper.wrap(instrumenter(), request, virtualField, handler);
 | 
			
		||||
        @Advice.Argument(0) @Nullable Handler<Throwable> handler) {
 | 
			
		||||
      if (handler == null) {
 | 
			
		||||
        return null;
 | 
			
		||||
      }
 | 
			
		||||
      return ExceptionHandlerWrapper.wrap(instrumenter(), request, CONTEXTS, handler);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,11 +11,13 @@ 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;
 | 
			
		||||
import net.bytebuddy.matcher.ElementMatcher;
 | 
			
		||||
 | 
			
		||||
@AutoService(InstrumentationModule.class)
 | 
			
		||||
public class VertxClientInstrumentationModule extends InstrumentationModule {
 | 
			
		||||
public class VertxClientInstrumentationModule extends InstrumentationModule
 | 
			
		||||
    implements ExperimentalInstrumentationModule {
 | 
			
		||||
 | 
			
		||||
  public VertxClientInstrumentationModule() {
 | 
			
		||||
    super("vertx-http-client", "vertx-http-client-3.0", "vertx");
 | 
			
		||||
| 
						 | 
				
			
			@ -34,4 +36,9 @@ public class VertxClientInstrumentationModule extends InstrumentationModule {
 | 
			
		|||
        new HttpRequestImplInstrumentation(),
 | 
			
		||||
        new HttpRequestInstrumentation());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public boolean isIndyReady() {
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,9 +6,13 @@
 | 
			
		|||
package io.opentelemetry.javaagent.instrumentation.vertx.v3_0.client;
 | 
			
		||||
 | 
			
		||||
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
 | 
			
		||||
import io.opentelemetry.instrumentation.api.util.VirtualField;
 | 
			
		||||
import io.opentelemetry.javaagent.instrumentation.vertx.client.Contexts;
 | 
			
		||||
import io.opentelemetry.javaagent.instrumentation.vertx.client.VertxClientInstrumenterFactory;
 | 
			
		||||
import io.vertx.core.http.HttpClientOptions;
 | 
			
		||||
import io.vertx.core.http.HttpClientRequest;
 | 
			
		||||
import io.vertx.core.http.HttpClientResponse;
 | 
			
		||||
import io.vertx.core.http.impl.HttpClientImpl;
 | 
			
		||||
 | 
			
		||||
public final class VertxClientSingletons {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -16,6 +20,15 @@ public final class VertxClientSingletons {
 | 
			
		|||
      VertxClientInstrumenterFactory.create(
 | 
			
		||||
          "io.opentelemetry.vertx-http-client-3.0", new Vertx3HttpAttributesGetter());
 | 
			
		||||
 | 
			
		||||
  public static final VirtualField<HttpClientRequest, Contexts> CONTEXTS =
 | 
			
		||||
      VirtualField.find(HttpClientRequest.class, Contexts.class);
 | 
			
		||||
 | 
			
		||||
  public static final VirtualField<HttpClientRequest, VertxRequestInfo> REQUEST_INFO =
 | 
			
		||||
      VirtualField.find(HttpClientRequest.class, VertxRequestInfo.class);
 | 
			
		||||
 | 
			
		||||
  public static final VirtualField<HttpClientImpl, HttpClientOptions> HTTP_CLIENT_OPTIONS =
 | 
			
		||||
      VirtualField.find(HttpClientImpl.class, HttpClientOptions.class);
 | 
			
		||||
 | 
			
		||||
  public static Instrumenter<HttpClientRequest, HttpClientResponse> instrumenter() {
 | 
			
		||||
    return INSTRUMENTER;
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,7 +12,10 @@ import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
 | 
			
		|||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
 | 
			
		||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
 | 
			
		||||
import io.vertx.core.Handler;
 | 
			
		||||
import javax.annotation.Nullable;
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -42,28 +45,31 @@ public class ConnectionManagerInstrumentation implements TypeInstrumentation {
 | 
			
		|||
 | 
			
		||||
  @SuppressWarnings("unused")
 | 
			
		||||
  public static class GetConnectionArg2Advice {
 | 
			
		||||
    @Nullable
 | 
			
		||||
    @AssignReturned.ToArguments(@ToArgument(2))
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static void wrapHandler(
 | 
			
		||||
        @Advice.Argument(value = 2, readOnly = false) Handler<?> handler) {
 | 
			
		||||
      handler = HandlerWrapper.wrap(handler);
 | 
			
		||||
    public static Handler<?> wrapHandler(@Advice.Argument(2) @Nullable Handler<?> handler) {
 | 
			
		||||
      return HandlerWrapper.wrap(handler);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @SuppressWarnings("unused")
 | 
			
		||||
  public static class GetConnectionArg3Advice {
 | 
			
		||||
    @Nullable
 | 
			
		||||
    @AssignReturned.ToArguments(@ToArgument(3))
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static void wrapHandler(
 | 
			
		||||
        @Advice.Argument(value = 3, readOnly = false) Handler<?> handler) {
 | 
			
		||||
      handler = HandlerWrapper.wrap(handler);
 | 
			
		||||
    public static Handler<?> wrapHandler(@Advice.Argument(3) @Nullable Handler<?> handler) {
 | 
			
		||||
      return HandlerWrapper.wrap(handler);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @SuppressWarnings("unused")
 | 
			
		||||
  public static class GetConnectionArg4Advice {
 | 
			
		||||
    @Nullable
 | 
			
		||||
    @AssignReturned.ToArguments(@ToArgument(4))
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static void wrapHandler(
 | 
			
		||||
        @Advice.Argument(value = 4, readOnly = false) Handler<?> handler) {
 | 
			
		||||
      handler = HandlerWrapper.wrap(handler);
 | 
			
		||||
    public static Handler<?> wrapHandler(@Advice.Argument(4) @Nullable Handler<?> handler) {
 | 
			
		||||
      return HandlerWrapper.wrap(handler);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,6 +8,7 @@ package io.opentelemetry.javaagent.instrumentation.vertx.v4_0.client;
 | 
			
		|||
import io.opentelemetry.context.Context;
 | 
			
		||||
import io.opentelemetry.context.Scope;
 | 
			
		||||
import io.vertx.core.Handler;
 | 
			
		||||
import javax.annotation.Nullable;
 | 
			
		||||
 | 
			
		||||
public class HandlerWrapper<T> implements Handler<T> {
 | 
			
		||||
  private final Handler<T> delegate;
 | 
			
		||||
| 
						 | 
				
			
			@ -18,7 +19,8 @@ public class HandlerWrapper<T> implements Handler<T> {
 | 
			
		|||
    this.context = context;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public static <T> Handler<T> wrap(Handler<T> handler) {
 | 
			
		||||
  @Nullable
 | 
			
		||||
  public static <T> Handler<T> wrap(@Nullable Handler<T> handler) {
 | 
			
		||||
    Context current = Context.current();
 | 
			
		||||
    if (handler != null && !(handler instanceof HandlerWrapper) && current != Context.root()) {
 | 
			
		||||
      handler = new HandlerWrapper<>(handler, current);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,6 +14,8 @@ import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
 | 
			
		|||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
 | 
			
		||||
import io.vertx.core.Handler;
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -39,10 +41,10 @@ public class HttpClientConnectionInstrumentation implements TypeInstrumentation
 | 
			
		|||
 | 
			
		||||
  @SuppressWarnings("unused")
 | 
			
		||||
  public static class CreateStreamAdvice {
 | 
			
		||||
    @AssignReturned.ToArguments(@ToArgument(1))
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static void wrapHandler(
 | 
			
		||||
        @Advice.Argument(value = 1, readOnly = false) Handler<?> handler) {
 | 
			
		||||
      handler = HandlerWrapper.wrap(handler);
 | 
			
		||||
    public static Handler<?> wrapHandler(@Advice.Argument(1) Handler<?> handler) {
 | 
			
		||||
      return HandlerWrapper.wrap(handler);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,7 @@ package io.opentelemetry.javaagent.instrumentation.vertx.v4_0.client;
 | 
			
		|||
 | 
			
		||||
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
 | 
			
		||||
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.implementsInterface;
 | 
			
		||||
import static io.opentelemetry.javaagent.instrumentation.vertx.v4_0.client.VertxClientSingletons.CONTEXTS;
 | 
			
		||||
import static io.opentelemetry.javaagent.instrumentation.vertx.v4_0.client.VertxClientSingletons.instrumenter;
 | 
			
		||||
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
 | 
			
		||||
import static net.bytebuddy.matcher.ElementMatchers.isPrivate;
 | 
			
		||||
| 
						 | 
				
			
			@ -16,8 +17,6 @@ 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 io.opentelemetry.javaagent.instrumentation.vertx.client.Contexts;
 | 
			
		||||
| 
						 | 
				
			
			@ -25,7 +24,10 @@ import io.opentelemetry.javaagent.instrumentation.vertx.client.ExceptionHandlerW
 | 
			
		|||
import io.vertx.core.Handler;
 | 
			
		||||
import io.vertx.core.http.HttpClientRequest;
 | 
			
		||||
import io.vertx.core.http.HttpClientResponse;
 | 
			
		||||
import javax.annotation.Nullable;
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -85,35 +87,50 @@ public class HttpRequestInstrumentation implements TypeInstrumentation {
 | 
			
		|||
  @SuppressWarnings("unused")
 | 
			
		||||
  public static class EndRequestAdvice {
 | 
			
		||||
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static void attachContext(
 | 
			
		||||
        @Advice.This HttpClientRequest request,
 | 
			
		||||
        @Advice.Local("otelContext") Context context,
 | 
			
		||||
        @Advice.Local("otelScope") Scope scope) {
 | 
			
		||||
      Context parentContext = Java8BytecodeBridge.currentContext();
 | 
			
		||||
    public static class AdviceScope {
 | 
			
		||||
      private final Context context;
 | 
			
		||||
      private final Scope scope;
 | 
			
		||||
 | 
			
		||||
      if (!instrumenter().shouldStart(parentContext, request)) {
 | 
			
		||||
        return;
 | 
			
		||||
      private AdviceScope(Context context, Scope scope) {
 | 
			
		||||
        this.context = context;
 | 
			
		||||
        this.scope = scope;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      context = instrumenter().start(parentContext, request);
 | 
			
		||||
      Contexts contexts = new Contexts(parentContext, context);
 | 
			
		||||
      VirtualField.find(HttpClientRequest.class, Contexts.class).set(request, contexts);
 | 
			
		||||
      @Nullable
 | 
			
		||||
      public static AdviceScope startAndAttachContext(HttpClientRequest request) {
 | 
			
		||||
        Context parentContext = Context.current();
 | 
			
		||||
        if (!instrumenter().shouldStart(parentContext, request)) {
 | 
			
		||||
          return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      scope = context.makeCurrent();
 | 
			
		||||
        Context context = instrumenter().start(parentContext, request);
 | 
			
		||||
        Contexts contexts = new Contexts(parentContext, context);
 | 
			
		||||
        CONTEXTS.set(request, contexts);
 | 
			
		||||
 | 
			
		||||
        return new AdviceScope(context, context.makeCurrent());
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      public void end(HttpClientRequest request, Throwable throwable) {
 | 
			
		||||
        scope.close();
 | 
			
		||||
        if (throwable != null) {
 | 
			
		||||
          instrumenter().end(context, request, null, throwable);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nullable
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static AdviceScope attachContext(@Advice.This HttpClientRequest request) {
 | 
			
		||||
      return AdviceScope.startAndAttachContext(request);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
 | 
			
		||||
    public static void endScope(
 | 
			
		||||
        @Advice.This HttpClientRequest request,
 | 
			
		||||
        @Advice.Local("otelContext") Context context,
 | 
			
		||||
        @Advice.Local("otelScope") Scope scope,
 | 
			
		||||
        @Advice.Thrown Throwable throwable) {
 | 
			
		||||
      if (scope != null) {
 | 
			
		||||
        scope.close();
 | 
			
		||||
      }
 | 
			
		||||
      if (throwable != null) {
 | 
			
		||||
        instrumenter().end(context, request, null, throwable);
 | 
			
		||||
        @Advice.Thrown Throwable throwable,
 | 
			
		||||
        @Advice.Enter @Nullable AdviceScope adviceScope) {
 | 
			
		||||
      if (adviceScope != null) {
 | 
			
		||||
        adviceScope.end(request, throwable);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -121,25 +138,24 @@ public class HttpRequestInstrumentation implements TypeInstrumentation {
 | 
			
		|||
  @SuppressWarnings("unused")
 | 
			
		||||
  public static class HandleExceptionAdvice {
 | 
			
		||||
 | 
			
		||||
    @Nullable
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static void handleException(
 | 
			
		||||
        @Advice.This HttpClientRequest request,
 | 
			
		||||
        @Advice.Argument(0) Throwable t,
 | 
			
		||||
        @Advice.Local("otelScope") Scope scope) {
 | 
			
		||||
      Contexts contexts = VirtualField.find(HttpClientRequest.class, Contexts.class).get(request);
 | 
			
		||||
    public static Scope handleException(
 | 
			
		||||
        @Advice.This HttpClientRequest request, @Advice.Argument(0) Throwable t) {
 | 
			
		||||
      Contexts contexts = CONTEXTS.get(request);
 | 
			
		||||
 | 
			
		||||
      if (contexts == null) {
 | 
			
		||||
        return;
 | 
			
		||||
        return null;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      instrumenter().end(contexts.context, request, null, t);
 | 
			
		||||
 | 
			
		||||
      // Scoping all potential callbacks etc to the parent context
 | 
			
		||||
      scope = contexts.parentContext.makeCurrent();
 | 
			
		||||
      return contexts.parentContext.makeCurrent();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
 | 
			
		||||
    public static void handleResponseExit(@Advice.Local("otelScope") Scope scope) {
 | 
			
		||||
    public static void handleResponseExit(@Advice.Enter @Nullable Scope scope) {
 | 
			
		||||
      if (scope != null) {
 | 
			
		||||
        scope.close();
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			@ -149,25 +165,24 @@ public class HttpRequestInstrumentation implements TypeInstrumentation {
 | 
			
		|||
  @SuppressWarnings("unused")
 | 
			
		||||
  public static class HandleResponseAdvice {
 | 
			
		||||
 | 
			
		||||
    @Nullable
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static void handleResponseEnter(
 | 
			
		||||
        @Advice.This HttpClientRequest request,
 | 
			
		||||
        @Advice.Argument(1) HttpClientResponse response,
 | 
			
		||||
        @Advice.Local("otelScope") Scope scope) {
 | 
			
		||||
      Contexts contexts = VirtualField.find(HttpClientRequest.class, Contexts.class).get(request);
 | 
			
		||||
    public static Scope handleResponseEnter(
 | 
			
		||||
        @Advice.This HttpClientRequest request, @Advice.Argument(1) HttpClientResponse response) {
 | 
			
		||||
      Contexts contexts = CONTEXTS.get(request);
 | 
			
		||||
 | 
			
		||||
      if (contexts == null) {
 | 
			
		||||
        return;
 | 
			
		||||
        return null;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      instrumenter().end(contexts.context, request, response, null);
 | 
			
		||||
 | 
			
		||||
      // Scoping all potential callbacks etc to the parent context
 | 
			
		||||
      scope = contexts.parentContext.makeCurrent();
 | 
			
		||||
      return contexts.parentContext.makeCurrent();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
 | 
			
		||||
    public static void handleResponseExit(@Advice.Local("otelScope") Scope scope) {
 | 
			
		||||
    public static void handleResponseExit(@Advice.Enter @Nullable Scope scope) {
 | 
			
		||||
      if (scope != null) {
 | 
			
		||||
        scope.close();
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			@ -177,19 +192,19 @@ public class HttpRequestInstrumentation implements TypeInstrumentation {
 | 
			
		|||
  @SuppressWarnings("unused")
 | 
			
		||||
  public static class MountContextAdvice {
 | 
			
		||||
 | 
			
		||||
    @Nullable
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static void mountContext(
 | 
			
		||||
        @Advice.This HttpClientRequest request, @Advice.Local("otelScope") Scope scope) {
 | 
			
		||||
      Contexts contexts = VirtualField.find(HttpClientRequest.class, Contexts.class).get(request);
 | 
			
		||||
    public static Scope mountContext(@Advice.This HttpClientRequest request) {
 | 
			
		||||
      Contexts contexts = CONTEXTS.get(request);
 | 
			
		||||
      if (contexts == null) {
 | 
			
		||||
        return;
 | 
			
		||||
        return null;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      scope = contexts.context.makeCurrent();
 | 
			
		||||
      return contexts.context.makeCurrent();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
 | 
			
		||||
    public static void unmountContext(@Advice.Local("otelScope") Scope scope) {
 | 
			
		||||
    public static void unmountContext(@Advice.Enter @Nullable Scope scope) {
 | 
			
		||||
      if (scope != null) {
 | 
			
		||||
        scope.close();
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			@ -199,15 +214,16 @@ public class HttpRequestInstrumentation implements TypeInstrumentation {
 | 
			
		|||
  @SuppressWarnings("unused")
 | 
			
		||||
  public static class ExceptionHandlerAdvice {
 | 
			
		||||
 | 
			
		||||
    @Nullable
 | 
			
		||||
    @AssignReturned.ToArguments(@ToArgument(0))
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static void wrapExceptionHandler(
 | 
			
		||||
    public static Handler<Throwable> wrapExceptionHandler(
 | 
			
		||||
        @Advice.This HttpClientRequest request,
 | 
			
		||||
        @Advice.Argument(value = 0, readOnly = false) Handler<Throwable> handler) {
 | 
			
		||||
      if (handler != null) {
 | 
			
		||||
        VirtualField<HttpClientRequest, Contexts> virtualField =
 | 
			
		||||
            VirtualField.find(HttpClientRequest.class, Contexts.class);
 | 
			
		||||
        handler = ExceptionHandlerWrapper.wrap(instrumenter(), request, virtualField, handler);
 | 
			
		||||
        @Advice.Argument(0) @Nullable Handler<Throwable> handler) {
 | 
			
		||||
      if (handler == null) {
 | 
			
		||||
        return null;
 | 
			
		||||
      }
 | 
			
		||||
      return ExceptionHandlerWrapper.wrap(instrumenter(), request, CONTEXTS, handler);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,11 +12,13 @@ import static net.bytebuddy.matcher.ElementMatchers.not;
 | 
			
		|||
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 VertxClientInstrumentationModule extends InstrumentationModule {
 | 
			
		||||
public class VertxClientInstrumentationModule extends InstrumentationModule
 | 
			
		||||
    implements ExperimentalInstrumentationModule {
 | 
			
		||||
 | 
			
		||||
  public VertxClientInstrumentationModule() {
 | 
			
		||||
    super("vertx-http-client", "vertx-http-client-4.0", "vertx");
 | 
			
		||||
| 
						 | 
				
			
			@ -37,4 +39,9 @@ public class VertxClientInstrumentationModule extends InstrumentationModule {
 | 
			
		|||
        new HttpClientConnectionInstrumentation(),
 | 
			
		||||
        new HttpRequestInstrumentation());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public boolean isIndyReady() {
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,6 +6,8 @@
 | 
			
		|||
package io.opentelemetry.javaagent.instrumentation.vertx.v4_0.client;
 | 
			
		||||
 | 
			
		||||
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
 | 
			
		||||
import io.opentelemetry.instrumentation.api.util.VirtualField;
 | 
			
		||||
import io.opentelemetry.javaagent.instrumentation.vertx.client.Contexts;
 | 
			
		||||
import io.opentelemetry.javaagent.instrumentation.vertx.client.VertxClientInstrumenterFactory;
 | 
			
		||||
import io.vertx.core.http.HttpClientRequest;
 | 
			
		||||
import io.vertx.core.http.HttpClientResponse;
 | 
			
		||||
| 
						 | 
				
			
			@ -16,6 +18,9 @@ public final class VertxClientSingletons {
 | 
			
		|||
      VertxClientInstrumenterFactory.create(
 | 
			
		||||
          "io.opentelemetry.vertx-http-client-4.0", new Vertx4HttpAttributesGetter());
 | 
			
		||||
 | 
			
		||||
  public static final VirtualField<HttpClientRequest, Contexts> CONTEXTS =
 | 
			
		||||
      VirtualField.find(HttpClientRequest.class, Contexts.class);
 | 
			
		||||
 | 
			
		||||
  public static Instrumenter<HttpClientRequest, HttpClientResponse> instrumenter() {
 | 
			
		||||
    return INSTRUMENTER;
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,7 @@ package io.opentelemetry.javaagent.instrumentation.vertx.v5_0.client;
 | 
			
		|||
 | 
			
		||||
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
 | 
			
		||||
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.implementsInterface;
 | 
			
		||||
import static io.opentelemetry.javaagent.instrumentation.vertx.v5_0.client.VertxClientSingletons.CONTEXTS;
 | 
			
		||||
import static io.opentelemetry.javaagent.instrumentation.vertx.v5_0.client.VertxClientSingletons.instrumenter;
 | 
			
		||||
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
 | 
			
		||||
import static net.bytebuddy.matcher.ElementMatchers.isPrivate;
 | 
			
		||||
| 
						 | 
				
			
			@ -16,8 +17,6 @@ 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 io.opentelemetry.javaagent.instrumentation.vertx.client.Contexts;
 | 
			
		||||
| 
						 | 
				
			
			@ -25,7 +24,10 @@ import io.opentelemetry.javaagent.instrumentation.vertx.client.ExceptionHandlerW
 | 
			
		|||
import io.vertx.core.Handler;
 | 
			
		||||
import io.vertx.core.http.HttpClientRequest;
 | 
			
		||||
import io.vertx.core.http.HttpClientResponse;
 | 
			
		||||
import javax.annotation.Nullable;
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -85,35 +87,47 @@ public class HttpRequestInstrumentation implements TypeInstrumentation {
 | 
			
		|||
  @SuppressWarnings("unused")
 | 
			
		||||
  public static class EndRequestAdvice {
 | 
			
		||||
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static void attachContext(
 | 
			
		||||
        @Advice.This HttpClientRequest request,
 | 
			
		||||
        @Advice.Local("otelContext") Context context,
 | 
			
		||||
        @Advice.Local("otelScope") Scope scope) {
 | 
			
		||||
      Context parentContext = Java8BytecodeBridge.currentContext();
 | 
			
		||||
    public static class AdviceScope {
 | 
			
		||||
      private final Context context;
 | 
			
		||||
      private final Scope scope;
 | 
			
		||||
 | 
			
		||||
      if (!instrumenter().shouldStart(parentContext, request)) {
 | 
			
		||||
        return;
 | 
			
		||||
      private AdviceScope(Context context, Scope scope) {
 | 
			
		||||
        this.context = context;
 | 
			
		||||
        this.scope = scope;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      context = instrumenter().start(parentContext, request);
 | 
			
		||||
      Contexts contexts = new Contexts(parentContext, context);
 | 
			
		||||
      VirtualField.find(HttpClientRequest.class, Contexts.class).set(request, contexts);
 | 
			
		||||
      @Nullable
 | 
			
		||||
      public static AdviceScope startAndAttachContext(HttpClientRequest request) {
 | 
			
		||||
        Context parentContext = Context.current();
 | 
			
		||||
        if (!instrumenter().shouldStart(parentContext, request)) {
 | 
			
		||||
          return null;
 | 
			
		||||
        }
 | 
			
		||||
        Context context = instrumenter().start(parentContext, request);
 | 
			
		||||
        CONTEXTS.set(request, new Contexts(parentContext, context));
 | 
			
		||||
        return new AdviceScope(context, context.makeCurrent());
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      scope = context.makeCurrent();
 | 
			
		||||
      public void end(HttpClientRequest request, @Nullable Throwable throwable) {
 | 
			
		||||
        scope.close();
 | 
			
		||||
        if (throwable != null) {
 | 
			
		||||
          instrumenter().end(context, request, null, throwable);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nullable
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static AdviceScope attachContext(@Advice.This HttpClientRequest request) {
 | 
			
		||||
      return AdviceScope.startAndAttachContext(request);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
 | 
			
		||||
    public static void endScope(
 | 
			
		||||
        @Advice.This HttpClientRequest request,
 | 
			
		||||
        @Advice.Local("otelContext") Context context,
 | 
			
		||||
        @Advice.Local("otelScope") Scope scope,
 | 
			
		||||
        @Advice.Thrown Throwable throwable) {
 | 
			
		||||
      if (scope != null) {
 | 
			
		||||
        scope.close();
 | 
			
		||||
      }
 | 
			
		||||
      if (throwable != null) {
 | 
			
		||||
        instrumenter().end(context, request, null, throwable);
 | 
			
		||||
        @Advice.Thrown @Nullable Throwable throwable,
 | 
			
		||||
        @Advice.Enter @Nullable AdviceScope adviceScope) {
 | 
			
		||||
      if (adviceScope != null) {
 | 
			
		||||
        adviceScope.end(request, throwable);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			@ -122,24 +136,21 @@ public class HttpRequestInstrumentation implements TypeInstrumentation {
 | 
			
		|||
  public static class HandleExceptionAdvice {
 | 
			
		||||
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static void handleException(
 | 
			
		||||
        @Advice.This HttpClientRequest request,
 | 
			
		||||
        @Advice.Argument(0) Throwable t,
 | 
			
		||||
        @Advice.Local("otelScope") Scope scope) {
 | 
			
		||||
      Contexts contexts = VirtualField.find(HttpClientRequest.class, Contexts.class).get(request);
 | 
			
		||||
 | 
			
		||||
    public static Scope handleException(
 | 
			
		||||
        @Advice.This HttpClientRequest request, @Advice.Argument(0) Throwable t) {
 | 
			
		||||
      Contexts contexts = CONTEXTS.get(request);
 | 
			
		||||
      if (contexts == null) {
 | 
			
		||||
        return;
 | 
			
		||||
        return null;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      instrumenter().end(contexts.context, request, null, t);
 | 
			
		||||
 | 
			
		||||
      // Scoping all potential callbacks etc to the parent context
 | 
			
		||||
      scope = contexts.parentContext.makeCurrent();
 | 
			
		||||
      return contexts.parentContext.makeCurrent();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
 | 
			
		||||
    public static void handleResponseExit(@Advice.Local("otelScope") Scope scope) {
 | 
			
		||||
    public static void handleResponseExit(@Advice.Enter Scope scope) {
 | 
			
		||||
      if (scope != null) {
 | 
			
		||||
        scope.close();
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			@ -150,24 +161,22 @@ public class HttpRequestInstrumentation implements TypeInstrumentation {
 | 
			
		|||
  public static class HandleResponseAdvice {
 | 
			
		||||
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static void handleResponseEnter(
 | 
			
		||||
        @Advice.This HttpClientRequest request,
 | 
			
		||||
        @Advice.Argument(1) HttpClientResponse response,
 | 
			
		||||
        @Advice.Local("otelScope") Scope scope) {
 | 
			
		||||
      Contexts contexts = VirtualField.find(HttpClientRequest.class, Contexts.class).get(request);
 | 
			
		||||
    public static Scope handleResponseEnter(
 | 
			
		||||
        @Advice.This HttpClientRequest request, @Advice.Argument(1) HttpClientResponse response) {
 | 
			
		||||
      Contexts contexts = CONTEXTS.get(request);
 | 
			
		||||
 | 
			
		||||
      if (contexts == null) {
 | 
			
		||||
        return;
 | 
			
		||||
        return null;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      instrumenter().end(contexts.context, request, response, null);
 | 
			
		||||
 | 
			
		||||
      // Scoping all potential callbacks etc to the parent context
 | 
			
		||||
      scope = contexts.parentContext.makeCurrent();
 | 
			
		||||
      return contexts.parentContext.makeCurrent();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
 | 
			
		||||
    public static void handleResponseExit(@Advice.Local("otelScope") Scope scope) {
 | 
			
		||||
    public static void handleResponseExit(@Advice.Enter Scope scope) {
 | 
			
		||||
      if (scope != null) {
 | 
			
		||||
        scope.close();
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			@ -178,18 +187,17 @@ public class HttpRequestInstrumentation implements TypeInstrumentation {
 | 
			
		|||
  public static class MountContextAdvice {
 | 
			
		||||
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static void mountContext(
 | 
			
		||||
        @Advice.This HttpClientRequest request, @Advice.Local("otelScope") Scope scope) {
 | 
			
		||||
      Contexts contexts = VirtualField.find(HttpClientRequest.class, Contexts.class).get(request);
 | 
			
		||||
    public static Scope mountContext(@Advice.This HttpClientRequest request) {
 | 
			
		||||
      Contexts contexts = CONTEXTS.get(request);
 | 
			
		||||
      if (contexts == null) {
 | 
			
		||||
        return;
 | 
			
		||||
        return null;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      scope = contexts.context.makeCurrent();
 | 
			
		||||
      return contexts.context.makeCurrent();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
 | 
			
		||||
    public static void unmountContext(@Advice.Local("otelScope") Scope scope) {
 | 
			
		||||
    public static void unmountContext(@Advice.Enter Scope scope) {
 | 
			
		||||
      if (scope != null) {
 | 
			
		||||
        scope.close();
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			@ -199,15 +207,16 @@ public class HttpRequestInstrumentation implements TypeInstrumentation {
 | 
			
		|||
  @SuppressWarnings("unused")
 | 
			
		||||
  public static class ExceptionHandlerAdvice {
 | 
			
		||||
 | 
			
		||||
    @AssignReturned.ToArguments(@ToArgument(0))
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static void wrapExceptionHandler(
 | 
			
		||||
    public static Handler<Throwable> wrapExceptionHandler(
 | 
			
		||||
        @Advice.This HttpClientRequest request,
 | 
			
		||||
        @Advice.Argument(value = 0, readOnly = false) Handler<Throwable> handler) {
 | 
			
		||||
        @Advice.Argument(0) Handler<Throwable> originalHandler) {
 | 
			
		||||
      Handler<Throwable> handler = originalHandler;
 | 
			
		||||
      if (handler != null) {
 | 
			
		||||
        VirtualField<HttpClientRequest, Contexts> virtualField =
 | 
			
		||||
            VirtualField.find(HttpClientRequest.class, Contexts.class);
 | 
			
		||||
        handler = ExceptionHandlerWrapper.wrap(instrumenter(), request, virtualField, handler);
 | 
			
		||||
        handler = ExceptionHandlerWrapper.wrap(instrumenter(), request, CONTEXTS, handler);
 | 
			
		||||
      }
 | 
			
		||||
      return handler;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,6 +12,7 @@ import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
 | 
			
		|||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
 | 
			
		||||
import io.vertx.core.Future;
 | 
			
		||||
import net.bytebuddy.asm.Advice;
 | 
			
		||||
import net.bytebuddy.asm.Advice.AssignReturned;
 | 
			
		||||
import net.bytebuddy.description.type.TypeDescription;
 | 
			
		||||
import net.bytebuddy.matcher.ElementMatcher;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -32,9 +33,10 @@ public class ResourceManagerInstrumentation implements TypeInstrumentation {
 | 
			
		|||
 | 
			
		||||
  @SuppressWarnings("unused")
 | 
			
		||||
  public static class WithResourceAsyncAdvice {
 | 
			
		||||
    @AssignReturned.ToReturned
 | 
			
		||||
    @Advice.OnMethodExit(suppress = Throwable.class)
 | 
			
		||||
    public static void wrapFuture(@Advice.Return(readOnly = false) Future<?> future) {
 | 
			
		||||
      future = VertxClientSingletons.wrapFuture(future);
 | 
			
		||||
    public static Future<?> wrapFuture(@Advice.Return Future<?> future) {
 | 
			
		||||
      return VertxClientSingletons.wrapFuture(future);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,11 +11,13 @@ 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;
 | 
			
		||||
import net.bytebuddy.matcher.ElementMatcher;
 | 
			
		||||
 | 
			
		||||
@AutoService(InstrumentationModule.class)
 | 
			
		||||
public class VertxClientInstrumentationModule extends InstrumentationModule {
 | 
			
		||||
public class VertxClientInstrumentationModule extends InstrumentationModule
 | 
			
		||||
    implements ExperimentalInstrumentationModule {
 | 
			
		||||
 | 
			
		||||
  public VertxClientInstrumentationModule() {
 | 
			
		||||
    super("vertx-http-client", "vertx-http-client-5.0", "vertx");
 | 
			
		||||
| 
						 | 
				
			
			@ -34,4 +36,9 @@ public class VertxClientInstrumentationModule extends InstrumentationModule {
 | 
			
		|||
        new HttpClientRequestBaseInstrumentation(),
 | 
			
		||||
        new ResourceManagerInstrumentation());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public boolean isIndyReady() {
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,6 +9,7 @@ import io.opentelemetry.context.Context;
 | 
			
		|||
import io.opentelemetry.context.Scope;
 | 
			
		||||
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
 | 
			
		||||
import io.opentelemetry.instrumentation.api.util.VirtualField;
 | 
			
		||||
import io.opentelemetry.javaagent.instrumentation.vertx.client.Contexts;
 | 
			
		||||
import io.opentelemetry.javaagent.instrumentation.vertx.client.VertxClientInstrumenterFactory;
 | 
			
		||||
import io.vertx.core.Future;
 | 
			
		||||
import io.vertx.core.http.HttpClientRequest;
 | 
			
		||||
| 
						 | 
				
			
			@ -29,6 +30,9 @@ public final class VertxClientSingletons {
 | 
			
		|||
  private static final VirtualField<HttpClientRequest, HostAndPort> authorityField =
 | 
			
		||||
      VirtualField.find(HttpClientRequest.class, HostAndPort.class);
 | 
			
		||||
 | 
			
		||||
  public static final VirtualField<HttpClientRequest, Contexts> CONTEXTS =
 | 
			
		||||
      VirtualField.find(HttpClientRequest.class, Contexts.class);
 | 
			
		||||
 | 
			
		||||
  public static void setAuthority(HttpClientRequest request, HostAndPort authority) {
 | 
			
		||||
    authorityField.set(request, authority);
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,6 +16,8 @@ import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
 | 
			
		|||
import io.vertx.core.Handler;
 | 
			
		||||
import io.vertx.kafka.client.consumer.impl.KafkaReadStreamImpl;
 | 
			
		||||
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.apache.kafka.clients.consumer.ConsumerRecord;
 | 
			
		||||
| 
						 | 
				
			
			@ -47,24 +49,26 @@ public class KafkaReadStreamImplInstrumentation implements TypeInstrumentation {
 | 
			
		|||
  @SuppressWarnings("unused")
 | 
			
		||||
  public static class HandlerAdvice {
 | 
			
		||||
 | 
			
		||||
    @AssignReturned.ToArguments(@ToArgument(0))
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static <K, V> void onEnter(
 | 
			
		||||
    public static <K, V> Handler<ConsumerRecord<K, V>> onEnter(
 | 
			
		||||
        @Advice.This KafkaReadStreamImpl<K, V> readStream,
 | 
			
		||||
        @Advice.Argument(value = 0, readOnly = false) Handler<ConsumerRecord<K, V>> handler) {
 | 
			
		||||
        @Advice.Argument(0) Handler<ConsumerRecord<K, V>> handler) {
 | 
			
		||||
 | 
			
		||||
      handler = new InstrumentedSingleRecordHandler<>(handler);
 | 
			
		||||
      return new InstrumentedSingleRecordHandler<>(handler);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @SuppressWarnings("unused")
 | 
			
		||||
  public static class BatchHandlerAdvice {
 | 
			
		||||
 | 
			
		||||
    @AssignReturned.ToArguments(@ToArgument(0))
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static <K, V> void onEnter(
 | 
			
		||||
    public static <K, V> Handler<ConsumerRecords<K, V>> onEnter(
 | 
			
		||||
        @Advice.This KafkaReadStreamImpl<K, V> readStream,
 | 
			
		||||
        @Advice.Argument(value = 0, readOnly = false) Handler<ConsumerRecords<K, V>> handler) {
 | 
			
		||||
        @Advice.Argument(0) Handler<ConsumerRecords<K, V>> handler) {
 | 
			
		||||
 | 
			
		||||
      handler = new InstrumentedBatchRecordsHandler<>(handler);
 | 
			
		||||
      return new InstrumentedBatchRecordsHandler<>(handler);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 VertxKafkaInstrumentationModule extends InstrumentationModule {
 | 
			
		||||
public class VertxKafkaInstrumentationModule extends InstrumentationModule
 | 
			
		||||
    implements ExperimentalInstrumentationModule {
 | 
			
		||||
 | 
			
		||||
  public VertxKafkaInstrumentationModule() {
 | 
			
		||||
    super("vertx-kafka-client", "vertx-kafka-client-3.6", "vertx");
 | 
			
		||||
| 
						 | 
				
			
			@ -24,4 +26,9 @@ public class VertxKafkaInstrumentationModule extends InstrumentationModule {
 | 
			
		|||
    return asList(
 | 
			
		||||
        new KafkaReadStreamImplInstrumentation(), new KafkaConsumerRecordsImplInstrumentation());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public boolean isIndyReady() {
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,7 +5,6 @@
 | 
			
		|||
 | 
			
		||||
package io.opentelemetry.javaagent.instrumentation.vertx.v4_0.redis;
 | 
			
		||||
 | 
			
		||||
import static io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge.currentContext;
 | 
			
		||||
import static io.opentelemetry.javaagent.instrumentation.vertx.v4_0.redis.VertxRedisClientSingletons.instrumenter;
 | 
			
		||||
import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
 | 
			
		||||
import static net.bytebuddy.matcher.ElementMatchers.named;
 | 
			
		||||
| 
						 | 
				
			
			@ -21,7 +20,9 @@ import io.vertx.redis.client.Response;
 | 
			
		|||
import io.vertx.redis.client.impl.RedisStandaloneConnection;
 | 
			
		||||
import io.vertx.redis.client.impl.RedisURI;
 | 
			
		||||
import io.vertx.redis.client.impl.RequestUtil;
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -40,54 +41,83 @@ public class RedisStandaloneConnectionInstrumentation implements TypeInstrumenta
 | 
			
		|||
 | 
			
		||||
  @SuppressWarnings("unused")
 | 
			
		||||
  public static class SendAdvice {
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static void onEnter(
 | 
			
		||||
        @Advice.This RedisStandaloneConnection connection,
 | 
			
		||||
        @Advice.Argument(0) Request request,
 | 
			
		||||
        @Advice.FieldValue("netSocket") NetSocket netSocket,
 | 
			
		||||
        @Advice.Local("otelRequest") VertxRedisClientRequest otelRequest,
 | 
			
		||||
        @Advice.Local("otelContext") Context context,
 | 
			
		||||
        @Advice.Local("otelScope") Scope scope) {
 | 
			
		||||
      if (request == null) {
 | 
			
		||||
        return;
 | 
			
		||||
    public static class AdviceScope {
 | 
			
		||||
      private final VertxRedisClientRequest otelRequest;
 | 
			
		||||
      private final Context context;
 | 
			
		||||
      private final Scope scope;
 | 
			
		||||
 | 
			
		||||
      private AdviceScope(VertxRedisClientRequest otelRequest, Context context, Scope scope) {
 | 
			
		||||
        this.otelRequest = otelRequest;
 | 
			
		||||
        this.context = context;
 | 
			
		||||
        this.scope = scope;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      String commandName = VertxRedisClientSingletons.getCommandName(request.command());
 | 
			
		||||
      RedisURI redisUri = VertxRedisClientSingletons.getRedisUri(connection);
 | 
			
		||||
      if (commandName == null || redisUri == null) {
 | 
			
		||||
        return;
 | 
			
		||||
      @Nullable
 | 
			
		||||
      public static AdviceScope start(
 | 
			
		||||
          RedisStandaloneConnection connection, @Nullable Request request, NetSocket netSocket) {
 | 
			
		||||
 | 
			
		||||
        if (request == null) {
 | 
			
		||||
          return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        String commandName = VertxRedisClientSingletons.getCommandName(request.command());
 | 
			
		||||
        RedisURI redisUri = VertxRedisClientSingletons.getRedisUri(connection);
 | 
			
		||||
        if (commandName == null || redisUri == null) {
 | 
			
		||||
          return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        VertxRedisClientRequest otelRequest =
 | 
			
		||||
            new VertxRedisClientRequest(
 | 
			
		||||
                commandName, RequestUtil.getArgs(request), redisUri, netSocket);
 | 
			
		||||
        Context parentContext = Context.current();
 | 
			
		||||
        if (!instrumenter().shouldStart(parentContext, otelRequest)) {
 | 
			
		||||
          return null;
 | 
			
		||||
        }
 | 
			
		||||
        Context context = instrumenter().start(parentContext, otelRequest);
 | 
			
		||||
        return new AdviceScope(otelRequest, context, context.makeCurrent());
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      otelRequest =
 | 
			
		||||
          new VertxRedisClientRequest(
 | 
			
		||||
              commandName, RequestUtil.getArgs(request), redisUri, netSocket);
 | 
			
		||||
      Context parentContext = currentContext();
 | 
			
		||||
      if (!instrumenter().shouldStart(parentContext, otelRequest)) {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      @Nullable
 | 
			
		||||
      public Future<Response> end(
 | 
			
		||||
          @Nullable Future<Response> responseFuture, @Nullable Throwable throwable) {
 | 
			
		||||
        if (scope == null) {
 | 
			
		||||
          return responseFuture;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      context = instrumenter().start(parentContext, otelRequest);
 | 
			
		||||
      scope = context.makeCurrent();
 | 
			
		||||
        scope.close();
 | 
			
		||||
        if (throwable != null) {
 | 
			
		||||
          instrumenter().end(context, otelRequest, null, throwable);
 | 
			
		||||
        } else {
 | 
			
		||||
          responseFuture =
 | 
			
		||||
              VertxRedisClientSingletons.wrapEndSpan(responseFuture, context, otelRequest);
 | 
			
		||||
        }
 | 
			
		||||
        return responseFuture;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nullable
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static AdviceScope onEnter(
 | 
			
		||||
        @Advice.This RedisStandaloneConnection connection,
 | 
			
		||||
        @Advice.Argument(0) @Nullable Request request,
 | 
			
		||||
        @Advice.FieldValue("netSocket") NetSocket netSocket) {
 | 
			
		||||
 | 
			
		||||
      return AdviceScope.start(connection, request, netSocket);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nullable
 | 
			
		||||
    @AssignReturned.ToReturned
 | 
			
		||||
    @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
 | 
			
		||||
    public static void onExit(
 | 
			
		||||
    public static Future<Response> onExit(
 | 
			
		||||
        @Advice.Thrown Throwable throwable,
 | 
			
		||||
        @Advice.Return(readOnly = false) Future<Response> responseFuture,
 | 
			
		||||
        @Advice.Local("otelRequest") VertxRedisClientRequest otelRequest,
 | 
			
		||||
        @Advice.Local("otelContext") Context context,
 | 
			
		||||
        @Advice.Local("otelScope") Scope scope) {
 | 
			
		||||
      if (scope == null) {
 | 
			
		||||
        return;
 | 
			
		||||
        @Advice.Return @Nullable Future<Response> responseFuture,
 | 
			
		||||
        @Advice.Enter @Nullable AdviceScope adviceScope) {
 | 
			
		||||
 | 
			
		||||
      if (adviceScope != null) {
 | 
			
		||||
        return adviceScope.end(responseFuture, throwable);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      scope.close();
 | 
			
		||||
      if (throwable != null) {
 | 
			
		||||
        instrumenter().end(context, otelRequest, null, throwable);
 | 
			
		||||
      } else {
 | 
			
		||||
        responseFuture =
 | 
			
		||||
            VertxRedisClientSingletons.wrapEndSpan(responseFuture, context, otelRequest);
 | 
			
		||||
      }
 | 
			
		||||
      return responseFuture;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -39,4 +39,9 @@ public class VertxRedisClientInstrumentationModule extends InstrumentationModule
 | 
			
		|||
        new RedisConnectionProviderInstrumentation(),
 | 
			
		||||
        new CommandImplInstrumentation());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public boolean isIndyReady() {
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,6 +18,8 @@ import io.vertx.core.AsyncResult;
 | 
			
		|||
import io.vertx.core.Handler;
 | 
			
		||||
import java.util.function.Consumer;
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -50,22 +52,22 @@ public class AsyncResultSingleInstrumentation implements TypeInstrumentation {
 | 
			
		|||
  @SuppressWarnings("unused")
 | 
			
		||||
  public static class ConstructorWithHandlerAdvice {
 | 
			
		||||
 | 
			
		||||
    @AssignReturned.ToArguments(@ToArgument(0))
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static void wrapHandler(
 | 
			
		||||
        @Advice.Argument(value = 0, readOnly = false) Handler<Handler<AsyncResult<?>>> handler) {
 | 
			
		||||
      handler =
 | 
			
		||||
          AsyncResultHandlerWrapper.wrapIfNeeded(handler, Java8BytecodeBridge.currentContext());
 | 
			
		||||
    public static Handler<Handler<AsyncResult<?>>> wrapHandler(
 | 
			
		||||
        @Advice.Argument(0) Handler<Handler<AsyncResult<?>>> handler) {
 | 
			
		||||
      return AsyncResultHandlerWrapper.wrapIfNeeded(handler, Java8BytecodeBridge.currentContext());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @SuppressWarnings("unused")
 | 
			
		||||
  public static class ConstructorWithConsumerAdvice {
 | 
			
		||||
 | 
			
		||||
    @AssignReturned.ToArguments(@ToArgument(0))
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static void wrapHandler(
 | 
			
		||||
        @Advice.Argument(value = 0, readOnly = false) Consumer<Handler<AsyncResult<?>>> handler) {
 | 
			
		||||
      handler =
 | 
			
		||||
          AsyncResultConsumerWrapper.wrapIfNeeded(handler, Java8BytecodeBridge.currentContext());
 | 
			
		||||
    public static Consumer<Handler<AsyncResult<?>>> wrapHandler(
 | 
			
		||||
        @Advice.Argument(0) Consumer<Handler<AsyncResult<?>>> handler) {
 | 
			
		||||
      return AsyncResultConsumerWrapper.wrapIfNeeded(handler, Java8BytecodeBridge.currentContext());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 VertxRxInstrumentationModule extends InstrumentationModule {
 | 
			
		||||
public class VertxRxInstrumentationModule extends InstrumentationModule
 | 
			
		||||
    implements ExperimentalInstrumentationModule {
 | 
			
		||||
 | 
			
		||||
  public VertxRxInstrumentationModule() {
 | 
			
		||||
    super("vertx-rx-java", "vertx-rx-java-3.5", "vertx");
 | 
			
		||||
| 
						 | 
				
			
			@ -23,4 +25,9 @@ public class VertxRxInstrumentationModule extends InstrumentationModule {
 | 
			
		|||
  public List<TypeInstrumentation> typeInstrumentations() {
 | 
			
		||||
    return singletonList(new AsyncResultSingleInstrumentation());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public boolean isIndyReady() {
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,6 +27,7 @@ import io.vertx.sqlclient.Pool;
 | 
			
		|||
import io.vertx.sqlclient.SqlConnectOptions;
 | 
			
		||||
import io.vertx.sqlclient.SqlConnection;
 | 
			
		||||
import net.bytebuddy.asm.Advice;
 | 
			
		||||
import net.bytebuddy.asm.Advice.AssignReturned;
 | 
			
		||||
import net.bytebuddy.description.type.TypeDescription;
 | 
			
		||||
import net.bytebuddy.matcher.ElementMatcher;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -60,23 +61,22 @@ public class PoolInstrumentation implements TypeInstrumentation {
 | 
			
		|||
  @SuppressWarnings("unused")
 | 
			
		||||
  public static class PoolAdvice {
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static void onEnter(
 | 
			
		||||
        @Advice.Argument(1) SqlConnectOptions sqlConnectOptions,
 | 
			
		||||
        @Advice.Local("otelCallDepth") CallDepth callDepth) {
 | 
			
		||||
      callDepth = CallDepth.forClass(Pool.class);
 | 
			
		||||
    public static CallDepth onEnter(@Advice.Argument(1) SqlConnectOptions sqlConnectOptions) {
 | 
			
		||||
      CallDepth callDepth = CallDepth.forClass(Pool.class);
 | 
			
		||||
      if (callDepth.getAndIncrement() > 0) {
 | 
			
		||||
        return;
 | 
			
		||||
        return callDepth;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // set connection options to ThreadLocal, they will be read in SqlClientBase constructor
 | 
			
		||||
      setSqlConnectOptions(sqlConnectOptions);
 | 
			
		||||
      return callDepth;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Advice.OnMethodExit(suppress = Throwable.class)
 | 
			
		||||
    public static void onExit(
 | 
			
		||||
        @Advice.Return Pool pool,
 | 
			
		||||
        @Advice.Argument(1) SqlConnectOptions sqlConnectOptions,
 | 
			
		||||
        @Advice.Local("otelCallDepth") CallDepth callDepth) {
 | 
			
		||||
        @Advice.Enter CallDepth callDepth) {
 | 
			
		||||
      if (callDepth.decrementAndGet() > 0) {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			@ -88,14 +88,13 @@ public class PoolInstrumentation implements TypeInstrumentation {
 | 
			
		|||
 | 
			
		||||
  @SuppressWarnings("unused")
 | 
			
		||||
  public static class GetConnectionAdvice {
 | 
			
		||||
    @AssignReturned.ToReturned
 | 
			
		||||
    @Advice.OnMethodExit(suppress = Throwable.class)
 | 
			
		||||
    public static void onExit(
 | 
			
		||||
        @Advice.This Pool pool, @Advice.Return(readOnly = false) Future<SqlConnection> future) {
 | 
			
		||||
    public static Future<SqlConnection> onExit(
 | 
			
		||||
        @Advice.This Pool pool, @Advice.Return Future<SqlConnection> future) {
 | 
			
		||||
      // copy connect options stored on pool to new connection
 | 
			
		||||
      SqlConnectOptions sqlConnectOptions = getPoolSqlConnectOptions(pool);
 | 
			
		||||
 | 
			
		||||
      future = attachConnectOptions(future, sqlConnectOptions);
 | 
			
		||||
      future = wrapContext(future);
 | 
			
		||||
      return wrapContext(attachConnectOptions(future, sqlConnectOptions));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,7 +5,6 @@
 | 
			
		|||
 | 
			
		||||
package io.opentelemetry.javaagent.instrumentation.vertx.v4_0.sql;
 | 
			
		||||
 | 
			
		||||
import static io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge.currentContext;
 | 
			
		||||
import static io.opentelemetry.javaagent.instrumentation.vertx.sql.VertxSqlClientUtil.getSqlConnectOptions;
 | 
			
		||||
import static io.opentelemetry.javaagent.instrumentation.vertx.v4_0.sql.VertxSqlClientSingletons.instrumenter;
 | 
			
		||||
import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
 | 
			
		||||
| 
						 | 
				
			
			@ -22,6 +21,7 @@ import io.opentelemetry.javaagent.instrumentation.vertx.sql.VertxSqlClientUtil;
 | 
			
		|||
import io.vertx.core.impl.future.PromiseInternal;
 | 
			
		||||
import io.vertx.sqlclient.impl.PreparedStatement;
 | 
			
		||||
import io.vertx.sqlclient.impl.QueryExecutorUtil;
 | 
			
		||||
import javax.annotation.Nullable;
 | 
			
		||||
import net.bytebuddy.asm.Advice;
 | 
			
		||||
import net.bytebuddy.description.type.TypeDescription;
 | 
			
		||||
import net.bytebuddy.matcher.ElementMatcher;
 | 
			
		||||
| 
						 | 
				
			
			@ -54,71 +54,94 @@ public class QueryExecutorInstrumentation implements TypeInstrumentation {
 | 
			
		|||
 | 
			
		||||
  @SuppressWarnings("unused")
 | 
			
		||||
  public static class QueryAdvice {
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static void onEnter(
 | 
			
		||||
        @Advice.This Object queryExecutor,
 | 
			
		||||
        @Advice.AllArguments Object[] arguments,
 | 
			
		||||
        @Advice.Local("otelCallDepth") CallDepth callDepth,
 | 
			
		||||
        @Advice.Local("otelRequest") VertxSqlClientRequest otelRequest,
 | 
			
		||||
        @Advice.Local("otelContext") Context context,
 | 
			
		||||
        @Advice.Local("otelScope") Scope scope) {
 | 
			
		||||
      callDepth = CallDepth.forClass(queryExecutor.getClass());
 | 
			
		||||
      if (callDepth.getAndIncrement() > 0) {
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    public static class AdviceScope {
 | 
			
		||||
      private final CallDepth callDepth;
 | 
			
		||||
      @Nullable private final VertxSqlClientRequest otelRequest;
 | 
			
		||||
      @Nullable private final Context context;
 | 
			
		||||
      @Nullable private final Scope scope;
 | 
			
		||||
 | 
			
		||||
      private AdviceScope(CallDepth callDepth) {
 | 
			
		||||
        this(callDepth, null, null, null);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // The parameter we need are in different positions, we are not going to have separate
 | 
			
		||||
      // advices for all of them. The method gets the statement either as String or
 | 
			
		||||
      // PreparedStatement, use the first argument that is either of these. PromiseInternal is
 | 
			
		||||
      // always at the end of the argument list.
 | 
			
		||||
      String sql = null;
 | 
			
		||||
      PromiseInternal<?> promiseInternal = null;
 | 
			
		||||
      for (Object argument : arguments) {
 | 
			
		||||
        if (sql == null) {
 | 
			
		||||
          if (argument instanceof String) {
 | 
			
		||||
            sql = (String) argument;
 | 
			
		||||
          } else if (argument instanceof PreparedStatement) {
 | 
			
		||||
            sql = ((PreparedStatement) argument).sql();
 | 
			
		||||
          }
 | 
			
		||||
        } else if (argument instanceof PromiseInternal) {
 | 
			
		||||
          promiseInternal = (PromiseInternal) argument;
 | 
			
		||||
      private AdviceScope(
 | 
			
		||||
          CallDepth callDepth, VertxSqlClientRequest otelRequest, Context context, Scope scope) {
 | 
			
		||||
        this.callDepth = callDepth;
 | 
			
		||||
        this.otelRequest = otelRequest;
 | 
			
		||||
        this.context = context;
 | 
			
		||||
        this.scope = scope;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      public static AdviceScope start(Object queryExecutor, Object[] arguments) {
 | 
			
		||||
        CallDepth callDepth = CallDepth.forClass(queryExecutor.getClass());
 | 
			
		||||
        if (callDepth.getAndIncrement() > 0) {
 | 
			
		||||
          return new AdviceScope(callDepth);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      if (sql == null || promiseInternal == null) {
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
        // The parameter we need are in different positions, we are not going to have separate
 | 
			
		||||
        // advices for all of them. The method gets the statement either as String or
 | 
			
		||||
        // PreparedStatement, use the first argument that is either of these. PromiseInternal is
 | 
			
		||||
        // always at the end of the argument list.
 | 
			
		||||
        String sql = null;
 | 
			
		||||
        PromiseInternal<?> promiseInternal = null;
 | 
			
		||||
        for (Object argument : arguments) {
 | 
			
		||||
          if (sql == null) {
 | 
			
		||||
            if (argument instanceof String) {
 | 
			
		||||
              sql = (String) argument;
 | 
			
		||||
            } else if (argument instanceof PreparedStatement) {
 | 
			
		||||
              sql = ((PreparedStatement) argument).sql();
 | 
			
		||||
            }
 | 
			
		||||
          } else if (argument instanceof PromiseInternal) {
 | 
			
		||||
            promiseInternal = (PromiseInternal<?>) argument;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        if (sql == null || promiseInternal == null) {
 | 
			
		||||
          return new AdviceScope(callDepth);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        VertxSqlClientRequest otelRequest =
 | 
			
		||||
            new VertxSqlClientRequest(sql, QueryExecutorUtil.getConnectOptions(queryExecutor));
 | 
			
		||||
        Context parentContext = Context.current();
 | 
			
		||||
        if (!instrumenter().shouldStart(parentContext, otelRequest)) {
 | 
			
		||||
          return new AdviceScope(callDepth, null, null, null);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Context context = instrumenter().start(parentContext, otelRequest);
 | 
			
		||||
        VertxSqlClientUtil.attachRequest(promiseInternal, otelRequest, context, parentContext);
 | 
			
		||||
        return new AdviceScope(callDepth, otelRequest, context, context.makeCurrent());
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      otelRequest =
 | 
			
		||||
          new VertxSqlClientRequest(sql, QueryExecutorUtil.getConnectOptions(queryExecutor));
 | 
			
		||||
      Context parentContext = currentContext();
 | 
			
		||||
      if (!instrumenter().shouldStart(parentContext, otelRequest)) {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      public void end(@Nullable Throwable throwable) {
 | 
			
		||||
        if (callDepth.decrementAndGet() > 0) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        if (scope == null || context == null || otelRequest == null) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      context = instrumenter().start(parentContext, otelRequest);
 | 
			
		||||
      scope = context.makeCurrent();
 | 
			
		||||
      VertxSqlClientUtil.attachRequest(promiseInternal, otelRequest, context, parentContext);
 | 
			
		||||
        scope.close();
 | 
			
		||||
        if (throwable != null) {
 | 
			
		||||
          instrumenter().end(context, otelRequest, null, throwable);
 | 
			
		||||
        }
 | 
			
		||||
        // span will be ended in QueryResultBuilderInstrumentation
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static AdviceScope onEnter(
 | 
			
		||||
        @Advice.This Object queryExecutor, @Advice.AllArguments Object[] arguments) {
 | 
			
		||||
      return AdviceScope.start(queryExecutor, arguments);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
 | 
			
		||||
    public static void onExit(
 | 
			
		||||
        @Advice.Thrown Throwable throwable,
 | 
			
		||||
        @Advice.Local("otelCallDepth") CallDepth callDepth,
 | 
			
		||||
        @Advice.Local("otelRequest") VertxSqlClientRequest otelRequest,
 | 
			
		||||
        @Advice.Local("otelContext") Context context,
 | 
			
		||||
        @Advice.Local("otelScope") Scope scope) {
 | 
			
		||||
      if (callDepth.decrementAndGet() > 0) {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      if (scope == null) {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
        @Advice.Thrown @Nullable Throwable throwable,
 | 
			
		||||
        @Advice.Enter @Nullable AdviceScope adviceScope) {
 | 
			
		||||
 | 
			
		||||
      scope.close();
 | 
			
		||||
      if (throwable != null) {
 | 
			
		||||
        instrumenter().end(context, otelRequest, null, throwable);
 | 
			
		||||
      if (adviceScope != null) {
 | 
			
		||||
        adviceScope.end(throwable);
 | 
			
		||||
      }
 | 
			
		||||
      // span will be ended in QueryResultBuilderInstrumentation
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -50,22 +50,21 @@ public class SqlClientBaseInstrumentation implements TypeInstrumentation {
 | 
			
		|||
  @SuppressWarnings("unused")
 | 
			
		||||
  public static class QueryAdvice {
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static void onEnter(
 | 
			
		||||
        @Advice.This SqlClientBase<?> sqlClientBase,
 | 
			
		||||
        @Advice.Local("otelCallDepth") CallDepth callDepth) {
 | 
			
		||||
      callDepth = CallDepth.forClass(SqlClientBase.class);
 | 
			
		||||
    public static CallDepth onEnter(@Advice.This SqlClientBase<?> sqlClientBase) {
 | 
			
		||||
      CallDepth callDepth = CallDepth.forClass(SqlClientBase.class);
 | 
			
		||||
      if (callDepth.getAndIncrement() > 0) {
 | 
			
		||||
        return;
 | 
			
		||||
        return callDepth;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // set connection options to ThreadLocal, they will be read in QueryExecutor constructor
 | 
			
		||||
      SqlConnectOptions sqlConnectOptions = getSqlConnectOptions(sqlClientBase);
 | 
			
		||||
      setSqlConnectOptions(sqlConnectOptions);
 | 
			
		||||
      return callDepth;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
 | 
			
		||||
    public static void onExit(
 | 
			
		||||
        @Advice.Thrown Throwable throwable, @Advice.Local("otelCallDepth") CallDepth callDepth) {
 | 
			
		||||
        @Advice.Thrown Throwable throwable, @Advice.Enter CallDepth callDepth) {
 | 
			
		||||
      if (callDepth.decrementAndGet() > 0) {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,6 +12,7 @@ import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
 | 
			
		|||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
 | 
			
		||||
import io.vertx.core.Handler;
 | 
			
		||||
import net.bytebuddy.asm.Advice;
 | 
			
		||||
import net.bytebuddy.asm.Advice.AssignReturned;
 | 
			
		||||
import net.bytebuddy.description.type.TypeDescription;
 | 
			
		||||
import net.bytebuddy.matcher.ElementMatcher;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -31,9 +32,10 @@ public class TransactionImplInstrumentation implements TypeInstrumentation {
 | 
			
		|||
 | 
			
		||||
  @SuppressWarnings("unused")
 | 
			
		||||
  public static class WrapHandlerAdvice {
 | 
			
		||||
    @AssignReturned.ToReturned
 | 
			
		||||
    @Advice.OnMethodExit(suppress = Throwable.class)
 | 
			
		||||
    public static void wrapHandler(@Advice.Return(readOnly = false) Handler<?> handler) {
 | 
			
		||||
      handler = HandlerWrapper.wrap(handler);
 | 
			
		||||
    public static Handler<?> wrapHandler(@Advice.Return Handler<?> handler) {
 | 
			
		||||
      return HandlerWrapper.wrap(handler);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -49,4 +49,9 @@ public class VertxSqlClientInstrumentationModule extends InstrumentationModule
 | 
			
		|||
        new QueryResultBuilderInstrumentation(),
 | 
			
		||||
        new TransactionImplInstrumentation());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public boolean isIndyReady() {
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,6 @@ import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
 | 
			
		|||
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
 | 
			
		||||
import static net.bytebuddy.matcher.ElementMatchers.takesNoArguments;
 | 
			
		||||
 | 
			
		||||
import io.opentelemetry.instrumentation.api.util.VirtualField;
 | 
			
		||||
import io.opentelemetry.javaagent.bootstrap.CallDepth;
 | 
			
		||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
 | 
			
		||||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
 | 
			
		||||
| 
						 | 
				
			
			@ -28,6 +27,7 @@ import io.vertx.sqlclient.Pool;
 | 
			
		|||
import io.vertx.sqlclient.SqlConnectOptions;
 | 
			
		||||
import io.vertx.sqlclient.SqlConnection;
 | 
			
		||||
import net.bytebuddy.asm.Advice;
 | 
			
		||||
import net.bytebuddy.asm.Advice.AssignReturned;
 | 
			
		||||
import net.bytebuddy.description.type.TypeDescription;
 | 
			
		||||
import net.bytebuddy.matcher.ElementMatcher;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -60,32 +60,28 @@ public class PoolInstrumentation implements TypeInstrumentation {
 | 
			
		|||
 | 
			
		||||
  @SuppressWarnings("unused")
 | 
			
		||||
  public static class PoolAdvice {
 | 
			
		||||
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static void onEnter(
 | 
			
		||||
        @Advice.Argument(1) SqlConnectOptions sqlConnectOptions,
 | 
			
		||||
        @Advice.Local("otelCallDepth") CallDepth callDepth) {
 | 
			
		||||
      callDepth = CallDepth.forClass(Pool.class);
 | 
			
		||||
    public static CallDepth onEnter(@Advice.Argument(1) SqlConnectOptions sqlConnectOptions) {
 | 
			
		||||
      CallDepth callDepth = CallDepth.forClass(Pool.class);
 | 
			
		||||
      if (callDepth.getAndIncrement() > 0) {
 | 
			
		||||
        return;
 | 
			
		||||
        return callDepth;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // set connection options to ThreadLocal, they will be read in SqlClientBase constructor
 | 
			
		||||
      setSqlConnectOptions(sqlConnectOptions);
 | 
			
		||||
      return callDepth;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Advice.OnMethodExit(suppress = Throwable.class)
 | 
			
		||||
    public static void onExit(
 | 
			
		||||
        @Advice.Return Pool pool,
 | 
			
		||||
        @Advice.Argument(1) SqlConnectOptions sqlConnectOptions,
 | 
			
		||||
        @Advice.Local("otelCallDepth") CallDepth callDepth) {
 | 
			
		||||
        @Advice.Enter CallDepth callDepth) {
 | 
			
		||||
      if (callDepth.decrementAndGet() > 0) {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      VirtualField<Pool, SqlConnectOptions> virtualField =
 | 
			
		||||
          VirtualField.find(Pool.class, SqlConnectOptions.class);
 | 
			
		||||
      virtualField.set(pool, sqlConnectOptions);
 | 
			
		||||
 | 
			
		||||
      setPoolConnectOptions(pool, sqlConnectOptions);
 | 
			
		||||
      setSqlConnectOptions(null);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -93,14 +89,14 @@ public class PoolInstrumentation implements TypeInstrumentation {
 | 
			
		|||
 | 
			
		||||
  @SuppressWarnings("unused")
 | 
			
		||||
  public static class GetConnectionAdvice {
 | 
			
		||||
    @AssignReturned.ToReturned
 | 
			
		||||
    @Advice.OnMethodExit(suppress = Throwable.class)
 | 
			
		||||
    public static void onExit(
 | 
			
		||||
        @Advice.This Pool pool, @Advice.Return(readOnly = false) Future<SqlConnection> future) {
 | 
			
		||||
    public static Future<SqlConnection> onExit(
 | 
			
		||||
        @Advice.This Pool pool, @Advice.Return Future<SqlConnection> future) {
 | 
			
		||||
      // copy connect options stored on pool to new connection
 | 
			
		||||
      SqlConnectOptions sqlConnectOptions = getPoolSqlConnectOptions(pool);
 | 
			
		||||
 | 
			
		||||
      future = attachConnectOptions(future, sqlConnectOptions);
 | 
			
		||||
      future = wrapContext(future);
 | 
			
		||||
      return wrapContext(attachConnectOptions(future, sqlConnectOptions));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,7 +5,6 @@
 | 
			
		|||
 | 
			
		||||
package io.opentelemetry.javaagent.instrumentation.vertx.v5_0.sql;
 | 
			
		||||
 | 
			
		||||
import static io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge.currentContext;
 | 
			
		||||
import static io.opentelemetry.javaagent.instrumentation.vertx.sql.VertxSqlClientUtil.getSqlConnectOptions;
 | 
			
		||||
import static io.opentelemetry.javaagent.instrumentation.vertx.v5_0.sql.VertxSqlClientSingletons.instrumenter;
 | 
			
		||||
import static net.bytebuddy.matcher.ElementMatchers.isConstructor;
 | 
			
		||||
| 
						 | 
				
			
			@ -22,6 +21,7 @@ import io.opentelemetry.javaagent.instrumentation.vertx.sql.VertxSqlClientUtil;
 | 
			
		|||
import io.vertx.core.internal.PromiseInternal;
 | 
			
		||||
import io.vertx.sqlclient.impl.QueryExecutorUtil;
 | 
			
		||||
import io.vertx.sqlclient.internal.PreparedStatement;
 | 
			
		||||
import javax.annotation.Nullable;
 | 
			
		||||
import net.bytebuddy.asm.Advice;
 | 
			
		||||
import net.bytebuddy.description.type.TypeDescription;
 | 
			
		||||
import net.bytebuddy.matcher.ElementMatcher;
 | 
			
		||||
| 
						 | 
				
			
			@ -54,71 +54,89 @@ public class QueryExecutorInstrumentation implements TypeInstrumentation {
 | 
			
		|||
 | 
			
		||||
  @SuppressWarnings("unused")
 | 
			
		||||
  public static class QueryAdvice {
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static void onEnter(
 | 
			
		||||
        @Advice.This Object queryExecutor,
 | 
			
		||||
        @Advice.AllArguments Object[] arguments,
 | 
			
		||||
        @Advice.Local("otelCallDepth") CallDepth callDepth,
 | 
			
		||||
        @Advice.Local("otelRequest") VertxSqlClientRequest otelRequest,
 | 
			
		||||
        @Advice.Local("otelContext") Context context,
 | 
			
		||||
        @Advice.Local("otelScope") Scope scope) {
 | 
			
		||||
      callDepth = CallDepth.forClass(queryExecutor.getClass());
 | 
			
		||||
      if (callDepth.getAndIncrement() > 0) {
 | 
			
		||||
        return;
 | 
			
		||||
    public static class AdviceScope {
 | 
			
		||||
      private final CallDepth callDepth;
 | 
			
		||||
      @Nullable private final VertxSqlClientRequest otelRequest;
 | 
			
		||||
      @Nullable private final Context context;
 | 
			
		||||
      @Nullable private final Scope scope;
 | 
			
		||||
 | 
			
		||||
      private AdviceScope(CallDepth callDepth) {
 | 
			
		||||
        this(callDepth, null, null, null);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // The parameter we need are in different positions, we are not going to have separate
 | 
			
		||||
      // advices for all of them. The method gets the statement either as String or
 | 
			
		||||
      // PreparedStatement, use the first argument that is either of these. PromiseInternal is
 | 
			
		||||
      // always at the end of the argument list.
 | 
			
		||||
      String sql = null;
 | 
			
		||||
      PromiseInternal<?> promiseInternal = null;
 | 
			
		||||
      for (Object argument : arguments) {
 | 
			
		||||
        if (sql == null) {
 | 
			
		||||
          if (argument instanceof String) {
 | 
			
		||||
            sql = (String) argument;
 | 
			
		||||
          } else if (argument instanceof PreparedStatement) {
 | 
			
		||||
            sql = ((PreparedStatement) argument).sql();
 | 
			
		||||
          }
 | 
			
		||||
        } else if (argument instanceof PromiseInternal) {
 | 
			
		||||
          promiseInternal = (PromiseInternal) argument;
 | 
			
		||||
      private AdviceScope(
 | 
			
		||||
          CallDepth callDepth, VertxSqlClientRequest otelRequest, Context context, Scope scope) {
 | 
			
		||||
        this.callDepth = callDepth;
 | 
			
		||||
        this.otelRequest = otelRequest;
 | 
			
		||||
        this.context = context;
 | 
			
		||||
        this.scope = scope;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      public static AdviceScope start(Object queryExecutor, Object[] arguments) {
 | 
			
		||||
        CallDepth callDepth = CallDepth.forClass(queryExecutor.getClass());
 | 
			
		||||
        if (callDepth.getAndIncrement() > 0) {
 | 
			
		||||
          return new AdviceScope(callDepth);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      if (sql == null || promiseInternal == null) {
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
        // The parameter we need are in different positions, we are not going to have separate
 | 
			
		||||
        // advices for all of them. The method gets the statement either as String or
 | 
			
		||||
        // PreparedStatement, use the first argument that is either of these. PromiseInternal is
 | 
			
		||||
        // always at the end of the argument list.
 | 
			
		||||
        String sql = null;
 | 
			
		||||
        PromiseInternal<?> promiseInternal = null;
 | 
			
		||||
        for (Object argument : arguments) {
 | 
			
		||||
          if (sql == null) {
 | 
			
		||||
            if (argument instanceof String) {
 | 
			
		||||
              sql = (String) argument;
 | 
			
		||||
            } else if (argument instanceof PreparedStatement) {
 | 
			
		||||
              sql = ((PreparedStatement) argument).sql();
 | 
			
		||||
            }
 | 
			
		||||
          } else if (argument instanceof PromiseInternal) {
 | 
			
		||||
            promiseInternal = (PromiseInternal<?>) argument;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        if (sql == null || promiseInternal == null) {
 | 
			
		||||
          return new AdviceScope(callDepth);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        VertxSqlClientRequest otelRequest =
 | 
			
		||||
            new VertxSqlClientRequest(sql, QueryExecutorUtil.getConnectOptions(queryExecutor));
 | 
			
		||||
        Context parentContext = Context.current();
 | 
			
		||||
        if (!instrumenter().shouldStart(parentContext, otelRequest)) {
 | 
			
		||||
          return new AdviceScope(callDepth);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Context context = instrumenter().start(parentContext, otelRequest);
 | 
			
		||||
        VertxSqlClientUtil.attachRequest(promiseInternal, otelRequest, context, parentContext);
 | 
			
		||||
        return new AdviceScope(callDepth, otelRequest, context, context.makeCurrent());
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      otelRequest =
 | 
			
		||||
          new VertxSqlClientRequest(sql, QueryExecutorUtil.getConnectOptions(queryExecutor));
 | 
			
		||||
      Context parentContext = currentContext();
 | 
			
		||||
      if (!instrumenter().shouldStart(parentContext, otelRequest)) {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      public void end(Throwable throwable) {
 | 
			
		||||
        if (callDepth.decrementAndGet() > 0) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
        if (scope == null || context == null || otelRequest == null) {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      context = instrumenter().start(parentContext, otelRequest);
 | 
			
		||||
      scope = context.makeCurrent();
 | 
			
		||||
      VertxSqlClientUtil.attachRequest(promiseInternal, otelRequest, context, parentContext);
 | 
			
		||||
        scope.close();
 | 
			
		||||
        if (throwable != null) {
 | 
			
		||||
          instrumenter().end(context, otelRequest, null, throwable);
 | 
			
		||||
        }
 | 
			
		||||
        // span will be ended in QueryResultBuilderInstrumentation
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static AdviceScope onEnter(
 | 
			
		||||
        @Advice.This Object queryExecutor, @Advice.AllArguments Object[] arguments) {
 | 
			
		||||
      return AdviceScope.start(queryExecutor, arguments);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
 | 
			
		||||
    public static void onExit(
 | 
			
		||||
        @Advice.Thrown Throwable throwable,
 | 
			
		||||
        @Advice.Local("otelCallDepth") CallDepth callDepth,
 | 
			
		||||
        @Advice.Local("otelRequest") VertxSqlClientRequest otelRequest,
 | 
			
		||||
        @Advice.Local("otelContext") Context context,
 | 
			
		||||
        @Advice.Local("otelScope") Scope scope) {
 | 
			
		||||
      if (callDepth.decrementAndGet() > 0) {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      if (scope == null) {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      scope.close();
 | 
			
		||||
      if (throwable != null) {
 | 
			
		||||
        instrumenter().end(context, otelRequest, null, throwable);
 | 
			
		||||
      }
 | 
			
		||||
      // span will be ended in QueryResultBuilderInstrumentation
 | 
			
		||||
        @Advice.Thrown @Nullable Throwable throwable, @Advice.Enter AdviceScope adviceScope) {
 | 
			
		||||
      adviceScope.end(throwable);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -50,22 +50,21 @@ public class SqlClientBaseInstrumentation implements TypeInstrumentation {
 | 
			
		|||
  @SuppressWarnings("unused")
 | 
			
		||||
  public static class QueryAdvice {
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static void onEnter(
 | 
			
		||||
        @Advice.This SqlClientBase sqlClientBase,
 | 
			
		||||
        @Advice.Local("otelCallDepth") CallDepth callDepth) {
 | 
			
		||||
      callDepth = CallDepth.forClass(SqlClientBase.class);
 | 
			
		||||
    public static CallDepth onEnter(@Advice.This SqlClientBase sqlClientBase) {
 | 
			
		||||
      CallDepth callDepth = CallDepth.forClass(SqlClientBase.class);
 | 
			
		||||
      if (callDepth.getAndIncrement() > 0) {
 | 
			
		||||
        return;
 | 
			
		||||
        return callDepth;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // set connection options to ThreadLocal, they will be read in QueryExecutor constructor
 | 
			
		||||
      SqlConnectOptions sqlConnectOptions = getSqlConnectOptions(sqlClientBase);
 | 
			
		||||
      setSqlConnectOptions(sqlConnectOptions);
 | 
			
		||||
      return callDepth;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
 | 
			
		||||
    public static void onExit(
 | 
			
		||||
        @Advice.Thrown Throwable throwable, @Advice.Local("otelCallDepth") CallDepth callDepth) {
 | 
			
		||||
        @Advice.Thrown Throwable throwable, @Advice.Enter CallDepth callDepth) {
 | 
			
		||||
      if (callDepth.decrementAndGet() > 0) {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,6 +12,7 @@ import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
 | 
			
		|||
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
 | 
			
		||||
import io.vertx.core.Completable;
 | 
			
		||||
import net.bytebuddy.asm.Advice;
 | 
			
		||||
import net.bytebuddy.asm.Advice.AssignReturned;
 | 
			
		||||
import net.bytebuddy.description.type.TypeDescription;
 | 
			
		||||
import net.bytebuddy.matcher.ElementMatcher;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -31,9 +32,10 @@ public class TransactionImplInstrumentation implements TypeInstrumentation {
 | 
			
		|||
 | 
			
		||||
  @SuppressWarnings("unused")
 | 
			
		||||
  public static class WrapHandlerAdvice {
 | 
			
		||||
    @AssignReturned.ToReturned
 | 
			
		||||
    @Advice.OnMethodExit(suppress = Throwable.class)
 | 
			
		||||
    public static void wrapHandler(@Advice.Return(readOnly = false) Completable<?> handler) {
 | 
			
		||||
      handler = CompletableWrapper.wrap(handler);
 | 
			
		||||
    public static Completable<?> wrapHandler(@Advice.Return Completable<?> handler) {
 | 
			
		||||
      return CompletableWrapper.wrap(handler);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -49,4 +49,9 @@ public class VertxSqlClientInstrumentationModule extends InstrumentationModule
 | 
			
		|||
        new QueryResultBuilderInstrumentation(),
 | 
			
		||||
        new TransactionImplInstrumentation());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public boolean isIndyReady() {
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,6 +16,8 @@ import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
 | 
			
		|||
import io.vertx.core.Handler;
 | 
			
		||||
import io.vertx.ext.web.RoutingContext;
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -40,10 +42,11 @@ public class RouteInstrumentation implements TypeInstrumentation {
 | 
			
		|||
  @SuppressWarnings("unused")
 | 
			
		||||
  public static class HandlerAdvice {
 | 
			
		||||
 | 
			
		||||
    @AssignReturned.ToArguments(@ToArgument(0))
 | 
			
		||||
    @Advice.OnMethodEnter(suppress = Throwable.class)
 | 
			
		||||
    public static void wrapHandler(
 | 
			
		||||
        @Advice.Argument(value = 0, readOnly = false) Handler<RoutingContext> handler) {
 | 
			
		||||
      handler = new RoutingContextHandlerWrapper(handler);
 | 
			
		||||
    public static Handler<RoutingContext> wrapHandler(
 | 
			
		||||
        @Advice.Argument(0) Handler<RoutingContext> handler) {
 | 
			
		||||
      return new RoutingContextHandlerWrapper(handler);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 VertxWebInstrumentationModule extends InstrumentationModule {
 | 
			
		||||
public class VertxWebInstrumentationModule extends InstrumentationModule
 | 
			
		||||
    implements ExperimentalInstrumentationModule {
 | 
			
		||||
 | 
			
		||||
  public VertxWebInstrumentationModule() {
 | 
			
		||||
    super("vertx-web", "vertx-web-3.0", "vertx");
 | 
			
		||||
| 
						 | 
				
			
			@ -23,4 +25,9 @@ public class VertxWebInstrumentationModule extends InstrumentationModule {
 | 
			
		|||
  public List<TypeInstrumentation> typeInstrumentations() {
 | 
			
		||||
    return asList(new RouteInstrumentation(), new RoutingContextInstrumentation());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public boolean isIndyReady() {
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue