make vertx indy-ready (#14567)

This commit is contained in:
SylvainJuge 2025-09-05 14:44:46 +02:00 committed by GitHub
parent d84b144cad
commit 1961f62b95
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
33 changed files with 604 additions and 404 deletions

View File

@ -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);
}
}
}

View File

@ -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,10 +54,8 @@ 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(
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));
}
}
}

View File

@ -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 {
@Advice.OnMethodEnter(suppress = Throwable.class)
public static void attachContext(
@Advice.This HttpClientRequest request,
@Advice.Local("otelContext") Context context,
@Advice.Local("otelScope") Scope scope) {
public static class AdviceScope {
private final Context context;
private final Scope scope;
VertxRequestInfo requestInfo =
VirtualField.find(HttpClientRequest.class, VertxRequestInfo.class).get(request);
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;
return null;
}
Context parentContext = Java8BytecodeBridge.currentContext();
Context parentContext = Context.current();
if (!instrumenter().shouldStart(parentContext, request)) {
return;
return null;
}
Context context = instrumenter().start(parentContext, request);
CONTEXTS.set(request, new Contexts(parentContext, context));
return new AdviceScope(context, context.makeCurrent());
}
context = instrumenter().start(parentContext, request);
Contexts contexts = new Contexts(parentContext, context);
VirtualField.find(HttpClientRequest.class, Contexts.class).set(request, contexts);
public void end(@Nullable Throwable throwable, HttpClientRequest request) {
scope.close();
if (throwable != null) {
instrumenter().end(context, request, null, throwable);
}
}
}
scope = context.makeCurrent();
@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(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);
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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);
}
}
}

View File

@ -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);

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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,45 +41,47 @@ 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) {
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;
}
@Nullable
public static AdviceScope start(
RedisStandaloneConnection connection, @Nullable Request request, NetSocket netSocket) {
if (request == null) {
return;
return null;
}
String commandName = VertxRedisClientSingletons.getCommandName(request.command());
RedisURI redisUri = VertxRedisClientSingletons.getRedisUri(connection);
if (commandName == null || redisUri == null) {
return;
return null;
}
otelRequest =
VertxRedisClientRequest otelRequest =
new VertxRedisClientRequest(
commandName, RequestUtil.getArgs(request), redisUri, netSocket);
Context parentContext = currentContext();
Context parentContext = Context.current();
if (!instrumenter().shouldStart(parentContext, otelRequest)) {
return;
return null;
}
Context context = instrumenter().start(parentContext, otelRequest);
return new AdviceScope(otelRequest, context, context.makeCurrent());
}
context = instrumenter().start(parentContext, otelRequest);
scope = context.makeCurrent();
}
@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void 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) {
@Nullable
public Future<Response> end(
@Nullable Future<Response> responseFuture, @Nullable Throwable throwable) {
if (scope == null) {
return;
return responseFuture;
}
scope.close();
@ -88,6 +91,33 @@ public class RedisStandaloneConnectionInstrumentation implements TypeInstrumenta
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 Future<Response> onExit(
@Advice.Thrown Throwable throwable,
@Advice.Return @Nullable Future<Response> responseFuture,
@Advice.Enter @Nullable AdviceScope adviceScope) {
if (adviceScope != null) {
return adviceScope.end(responseFuture, throwable);
}
return responseFuture;
}
}

View File

@ -39,4 +39,9 @@ public class VertxRedisClientInstrumentationModule extends InstrumentationModule
new RedisConnectionProviderInstrumentation(),
new CommandImplInstrumentation());
}
@Override
public boolean isIndyReady() {
return true;
}
}

View File

@ -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());
}
}
}

View File

@ -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;
}
}

View File

@ -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));
}
}
}

View File

@ -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,17 +54,29 @@ 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());
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);
}
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;
return new AdviceScope(callDepth);
}
// The parameter we need are in different positions, we are not going to have separate
@ -81,36 +93,30 @@ public class QueryExecutorInstrumentation implements TypeInstrumentation {
sql = ((PreparedStatement) argument).sql();
}
} else if (argument instanceof PromiseInternal) {
promiseInternal = (PromiseInternal) argument;
promiseInternal = (PromiseInternal<?>) argument;
}
}
if (sql == null || promiseInternal == null) {
return;
return new AdviceScope(callDepth);
}
otelRequest =
VertxSqlClientRequest otelRequest =
new VertxSqlClientRequest(sql, QueryExecutorUtil.getConnectOptions(queryExecutor));
Context parentContext = currentContext();
Context parentContext = Context.current();
if (!instrumenter().shouldStart(parentContext, otelRequest)) {
return;
return new AdviceScope(callDepth, null, null, null);
}
context = instrumenter().start(parentContext, otelRequest);
scope = context.makeCurrent();
Context context = instrumenter().start(parentContext, otelRequest);
VertxSqlClientUtil.attachRequest(promiseInternal, otelRequest, context, parentContext);
return new AdviceScope(callDepth, otelRequest, context, context.makeCurrent());
}
@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) {
public void end(@Nullable Throwable throwable) {
if (callDepth.decrementAndGet() > 0) {
return;
}
if (scope == null) {
if (scope == null || context == null || otelRequest == null) {
return;
}
@ -121,4 +127,21 @@ public class QueryExecutorInstrumentation implements TypeInstrumentation {
// 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 @Nullable Throwable throwable,
@Advice.Enter @Nullable AdviceScope adviceScope) {
if (adviceScope != null) {
adviceScope.end(throwable);
}
}
}
}

View File

@ -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;
}

View File

@ -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);
}
}
}

View File

@ -49,4 +49,9 @@ public class VertxSqlClientInstrumentationModule extends InstrumentationModule
new QueryResultBuilderInstrumentation(),
new TransactionImplInstrumentation());
}
@Override
public boolean isIndyReady() {
return true;
}
}

View File

@ -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));
}
}
}

View File

@ -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,17 +54,28 @@ 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());
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);
}
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;
return new AdviceScope(callDepth);
}
// The parameter we need are in different positions, we are not going to have separate
@ -81,36 +92,30 @@ public class QueryExecutorInstrumentation implements TypeInstrumentation {
sql = ((PreparedStatement) argument).sql();
}
} else if (argument instanceof PromiseInternal) {
promiseInternal = (PromiseInternal) argument;
promiseInternal = (PromiseInternal<?>) argument;
}
}
if (sql == null || promiseInternal == null) {
return;
return new AdviceScope(callDepth);
}
otelRequest =
VertxSqlClientRequest otelRequest =
new VertxSqlClientRequest(sql, QueryExecutorUtil.getConnectOptions(queryExecutor));
Context parentContext = currentContext();
Context parentContext = Context.current();
if (!instrumenter().shouldStart(parentContext, otelRequest)) {
return;
return new AdviceScope(callDepth);
}
context = instrumenter().start(parentContext, otelRequest);
scope = context.makeCurrent();
Context context = instrumenter().start(parentContext, otelRequest);
VertxSqlClientUtil.attachRequest(promiseInternal, otelRequest, context, parentContext);
return new AdviceScope(callDepth, otelRequest, context, context.makeCurrent());
}
@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) {
public void end(Throwable throwable) {
if (callDepth.decrementAndGet() > 0) {
return;
}
if (scope == null) {
if (scope == null || context == null || otelRequest == null) {
return;
}
@ -121,4 +126,17 @@ public class QueryExecutorInstrumentation implements TypeInstrumentation {
// 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 @Nullable Throwable throwable, @Advice.Enter AdviceScope adviceScope) {
adviceScope.end(throwable);
}
}
}

View File

@ -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;
}

View File

@ -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);
}
}
}

View File

@ -49,4 +49,9 @@ public class VertxSqlClientInstrumentationModule extends InstrumentationModule
new QueryResultBuilderInstrumentation(),
new TransactionImplInstrumentation());
}
@Override
public boolean isIndyReady() {
return true;
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}