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