Add instrumentation for vert.x sql client withTransaction method (#9462)

This commit is contained in:
Lauri Tulmin 2023-09-14 14:59:07 +03:00 committed by GitHub
parent 97e32cd719
commit 776e2ec4a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 114 additions and 1 deletions

View File

@ -0,0 +1,35 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.vertx.v4_0.sql;
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);
}
}
}

View File

@ -0,0 +1,39 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.vertx.v4_0.sql;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.returns;
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;
public class TransactionImplInstrumentation implements TypeInstrumentation {
@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return named("io.vertx.sqlclient.impl.TransactionImpl");
}
@Override
public void transform(TypeTransformer transformer) {
transformer.applyAdviceToMethod(
named("wrap").and(returns(named("io.vertx.core.Handler"))),
TransactionImplInstrumentation.class.getName() + "$WrapHandlerAdvice");
}
@SuppressWarnings("unused")
public static class WrapHandlerAdvice {
@Advice.OnMethodExit(suppress = Throwable.class)
public static void wrapHandler(@Advice.Return(readOnly = false) Handler<?> handler) {
handler = HandlerWrapper.wrap(handler);
}
}
}

View File

@ -30,6 +30,7 @@ public class VertxSqlClientInstrumentationModule extends InstrumentationModule {
new PoolInstrumentation(),
new SqlClientBaseInstrumentation(),
new QueryExecutorInstrumentation(),
new QueryResultBuilderInstrumentation());
new QueryResultBuilderInstrumentation(),
new TransactionImplInstrumentation());
}
}

View File

@ -203,6 +203,10 @@ class VertxSqlClientTest {
.toCompletableFuture()
.get(30, TimeUnit.SECONDS);
assertPreparedSelect();
}
private static void assertPreparedSelect() {
testing.waitAndAssertTraces(
trace ->
trace.hasSpansSatisfyingExactly(
@ -250,4 +254,38 @@ class VertxSqlClientTest {
equalTo(NET_PEER_NAME, "localhost"),
equalTo(NET_PEER_PORT, port))));
}
@Test
void testWithTransaction() throws Exception {
testing
.runWithSpan(
"parent",
() ->
pool.withTransaction(
conn ->
conn.preparedQuery("select * from test where id = $1")
.execute(Tuple.of(1))))
.toCompletionStage()
.toCompletableFuture()
.get(30, TimeUnit.SECONDS);
assertPreparedSelect();
}
@Test
void testWithConnection() throws Exception {
testing
.runWithSpan(
"parent",
() ->
pool.withConnection(
conn ->
conn.preparedQuery("select * from test where id = $1")
.execute(Tuple.of(1))))
.toCompletionStage()
.toCompletableFuture()
.get(30, TimeUnit.SECONDS);
assertPreparedSelect();
}
}