Skip to content

Commit

Permalink
Vertx http client 4 instrumentation (#3665)
Browse files Browse the repository at this point in the history
* Vertx http client 4 instrumentation

* remove debugging

* rebase
  • Loading branch information
laurit authored Jul 28, 2021
1 parent e4fcbb8 commit 441609a
Show file tree
Hide file tree
Showing 21 changed files with 686 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ muzzle {
dependencies {
library("io.vertx:vertx-core:3.0.0")

implementation(project(":instrumentation:vertx-http-client:vertx-http-client-common:javaagent"))

//We need both version as different versions of Vert.x use different versions of Netty
testInstrumentation(project(":instrumentation:netty:netty-4.0:javaagent"))
testInstrumentation(project(":instrumentation:netty:netty-4.1:javaagent"))
testInstrumentation(project(":instrumentation:jdbc:javaagent"))

// Vert.x 4.0 is incompatible with our tests.
// 3.9.7 Requires Netty 4.1.60, no other version works with it.
Expand All @@ -29,4 +30,4 @@ tasks {
named<Test>("test") {
systemProperty("testLatestDeps", findProperty("testLatestDeps"))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.vertx.client;
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.client.VertxClientTracer.tracer;
import static io.opentelemetry.javaagent.instrumentation.vertx.v3_0.client.VertxClientTracer.tracer;
import static net.bytebuddy.matcher.ElementMatchers.isMethod;
import static net.bytebuddy.matcher.ElementMatchers.isPrivate;
import static net.bytebuddy.matcher.ElementMatchers.nameStartsWith;
Expand All @@ -21,6 +21,8 @@
import io.opentelemetry.javaagent.instrumentation.api.ContextStore;
import io.opentelemetry.javaagent.instrumentation.api.InstrumentationContext;
import io.opentelemetry.javaagent.instrumentation.api.Java8BytecodeBridge;
import io.opentelemetry.javaagent.instrumentation.vertx.client.Contexts;
import io.opentelemetry.javaagent.instrumentation.vertx.client.ExceptionHandlerWrapper;
import io.vertx.core.Handler;
import io.vertx.core.http.HttpClientRequest;
import io.vertx.core.http.HttpClientResponse;
Expand Down Expand Up @@ -205,7 +207,7 @@ public static void wrapExceptionHandler(
if (handler != null) {
ContextStore<HttpClientRequest, Contexts> contextStore =
InstrumentationContext.get(HttpClientRequest.class, Contexts.class);
handler = new ExceptionHandlerWrapper(request, contextStore, handler);
handler = new ExceptionHandlerWrapper(tracer(), request, contextStore, handler);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,28 @@
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.vertx.client;
package io.opentelemetry.javaagent.instrumentation.vertx.v3_0.client;

import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
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 java.util.List;
import net.bytebuddy.matcher.ElementMatcher;

@AutoService(InstrumentationModule.class)
public class VertxClientInstrumentationModule extends InstrumentationModule {

public VertxClientInstrumentationModule() {
super("vertx-client", "vertx");
super("vertx-client", "vertx-client-3.0", "vertx");
}

@Override
public ElementMatcher.Junction<ClassLoader> classLoaderMatcher() {
// class removed in 4.0
return hasClassesNamed("io.vertx.core.Starter");
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.vertx.v3_0.client;

import io.opentelemetry.javaagent.instrumentation.vertx.client.AbstractVertxClientTracer;
import io.vertx.core.http.HttpClientRequest;
import java.net.URI;
import java.net.URISyntaxException;
import org.checkerframework.checker.nullness.qual.Nullable;

public class VertxClientTracer extends AbstractVertxClientTracer {
private static final VertxClientTracer TRACER = new VertxClientTracer();

public static VertxClientTracer tracer() {
return TRACER;
}

@Override
protected String getInstrumentationName() {
return "io.opentelemetry.vertx-http-client-3.0";
}

@Override
protected String method(HttpClientRequest request) {
return request.method().name();
}

@Override
@Nullable
protected URI url(HttpClientRequest request) throws URISyntaxException {
return new URI(request.uri());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
plugins {
id("otel.javaagent-instrumentation")
}

muzzle {
pass {
group.set("io.vertx")
module.set("vertx-core")
versions.set("[4.0.0,)")
assertInverse.set(true)
}
}

dependencies {
library("io.vertx:vertx-core:4.0.0")

implementation(project(":instrumentation:vertx-http-client:vertx-http-client-common:javaagent"))

testInstrumentation(project(":instrumentation:netty:netty-4.1:javaagent"))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.vertx.v4_0.client;

import static net.bytebuddy.matcher.ElementMatchers.named;
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 net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;

/** Propagate context to connection established callback. */
public class ConnectionManagerInstrumentation implements TypeInstrumentation {

@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return named("io.vertx.core.net.impl.clientconnection.ConnectionManager") // 4.0.0
.or(named("io.vertx.core.net.impl.pool.ConnectionManager")); // 4.1.0
}

@Override
public void transform(TypeTransformer transformer) {
transformer.applyAdviceToMethod(
named("getConnection").and(takesArgument(2, named("io.vertx.core.Handler"))),
ConnectionManagerInstrumentation.class.getName() + "$GetConnectionArg2Advice");
transformer.applyAdviceToMethod(
named("getConnection").and(takesArgument(3, named("io.vertx.core.Handler"))),
ConnectionManagerInstrumentation.class.getName() + "$GetConnectionArg3Advice");
}

@SuppressWarnings("unused")
public static class GetConnectionArg2Advice {
@Advice.OnMethodEnter(suppress = Throwable.class)
public static void wrapHandler(
@Advice.Argument(value = 2, readOnly = false) Handler<?> handler) {
handler = HandlerWrapper.wrap(handler);
}
}

@SuppressWarnings("unused")
public static class GetConnectionArg3Advice {
@Advice.OnMethodEnter(suppress = Throwable.class)
public static void wrapHandler(
@Advice.Argument(value = 3, readOnly = false) Handler<?> handler) {
handler = HandlerWrapper.wrap(handler);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.vertx.v4_0.client;

import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.vertx.core.Handler;

public class HandlerWrapper<T> implements Handler<T> {
private final Handler<T> delegate;
private final Context context;

private HandlerWrapper(Handler<T> delegate, Context context) {
this.delegate = delegate;
this.context = context;
}

public static <T> Handler<T> wrap(Handler<T> handler) {
Context current = Context.current();
if (handler != null && !(handler instanceof HandlerWrapper) && current != Context.root()) {
handler = new HandlerWrapper<>(handler, current);
}
return handler;
}

@Override
public void handle(T t) {
try (Scope ignore = context.makeCurrent()) {
delegate.handle(t);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

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 net.bytebuddy.matcher.ElementMatchers.named;
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 net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;

/** Propagate context to stream opened callback. */
public class HttpClientConnectionInstrumentation implements TypeInstrumentation {

@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return implementsInterface(named("io.vertx.core.http.impl.HttpClientConnection"));
}

@Override
public ElementMatcher<ClassLoader> classLoaderOptimization() {
return hasClassesNamed("io.vertx.core.http.impl.HttpClientConnection");
}

@Override
public void transform(TypeTransformer transformer) {
transformer.applyAdviceToMethod(
named("createStream").and(takesArgument(1, named("io.vertx.core.Handler"))),
HttpClientConnectionInstrumentation.class.getName() + "$CreateStreamAdvice");
}

@SuppressWarnings("unused")
public static class CreateStreamAdvice {
@Advice.OnMethodEnter(suppress = Throwable.class)
public static void wrapHandler(
@Advice.Argument(value = 1, readOnly = false) Handler<?> handler) {
handler = HandlerWrapper.wrap(handler);
}
}
}
Loading

0 comments on commit 441609a

Please sign in to comment.