Skip to content

Commit 3886f3c

Browse files
committed
Fix vertx sql client instumentation for 5.1
1 parent 3bf6aa3 commit 3886f3c

8 files changed

Lines changed: 83 additions & 20 deletions

File tree

.github/config/latest-dep-versions.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@
212212
"io.vertx:vertx-codegen#+": "5.1.0",
213213
"io.vertx:vertx-codegen#3.+": "3.9.16",
214214
"io.vertx:vertx-codegen#4.+": "4.5.27",
215+
"io.vertx:vertx-codegen#5.0.+": "5.0.12",
215216
"io.vertx:vertx-core#+": "5.1.0",
216217
"io.vertx:vertx-core#3.+": "3.9.16",
217218
"io.vertx:vertx-core#4.+": "4.5.27",
@@ -220,18 +221,21 @@
220221
"io.vertx:vertx-jdbc-client#+": "5.1.0",
221222
"io.vertx:vertx-jdbc-client#3.+": "3.9.16",
222223
"io.vertx:vertx-jdbc-client#4.+": "4.5.27",
224+
"io.vertx:vertx-jdbc-client#5.0.+": "5.0.12",
223225
"io.vertx:vertx-kafka-client#+": "5.1.0",
224226
"io.vertx:vertx-kafka-client#3.+": "3.9.16",
225227
"io.vertx:vertx-kafka-client#4.+": "4.5.27",
226228
"io.vertx:vertx-lang-kotlin-coroutines#+": "5.1.0",
227229
"io.vertx:vertx-pg-client#+": "5.1.0",
228230
"io.vertx:vertx-pg-client#4.+": "4.5.27",
231+
"io.vertx:vertx-pg-client#5.0.+": "5.0.12",
229232
"io.vertx:vertx-redis-client#+": "5.1.0",
230233
"io.vertx:vertx-rx-java2#+": "5.1.0",
231234
"io.vertx:vertx-rx-java2#3.+": "3.9.16",
232235
"io.vertx:vertx-rx-java2#4.+": "4.5.27",
233236
"io.vertx:vertx-sql-client#+": "5.1.0",
234237
"io.vertx:vertx-sql-client#4.+": "4.5.27",
238+
"io.vertx:vertx-sql-client#5.0.+": "5.0.12",
235239
"io.vertx:vertx-web#+": "5.1.0",
236240
"io.vertx:vertx-web#3.+": "3.9.16",
237241
"io.vertx:vertx-web#4.+": "4.5.27",

instrumentation/vertx/vertx-sql-client/vertx-sql-client-5.0/javaagent/build.gradle.kts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,16 @@ dependencies {
2020
library("io.vertx:vertx-sql-client:$version")
2121
library("io.vertx:vertx-codegen:$version")
2222

23+
compileOnly(project(":muzzle")) // For @NoMuzzle
24+
2325
implementation(project(":instrumentation:vertx:vertx-sql-client:vertx-sql-client-common-4.0:javaagent"))
2426

2527
testInstrumentation(project(":instrumentation:jdbc:javaagent"))
2628
testInstrumentation(project(":instrumentation:netty:netty-4.1:javaagent"))
2729
testInstrumentation(project(":instrumentation:vertx:vertx-sql-client:vertx-sql-client-4.0:javaagent"))
2830

2931
testLibrary("io.vertx:vertx-pg-client:$version")
30-
testImplementation("io.vertx:vertx-jdbc-client:$version")
32+
testLibrary("io.vertx:vertx-jdbc-client:$version")
3133
testImplementation("io.agroal:agroal-pool:2.5")
3234
testImplementation("org.hsqldb:hsqldb:2.3.4")
3335
}

instrumentation/vertx/vertx-sql-client/vertx-sql-client-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/sqlclient/v5_0/CommandSchedulerInstrumentation.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@
88
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.hasClassesNamed;
99
import static io.opentelemetry.javaagent.extension.matcher.AgentElementMatchers.implementsInterface;
1010
import static net.bytebuddy.matcher.ElementMatchers.named;
11+
import static net.bytebuddy.matcher.ElementMatchers.namedOneOf;
1112
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
1213

1314
import io.opentelemetry.context.Context;
1415
import io.opentelemetry.context.Scope;
1516
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
1617
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
17-
import io.vertx.sqlclient.internal.command.CommandBase;
1818
import javax.annotation.Nullable;
1919
import net.bytebuddy.asm.Advice;
2020
import net.bytebuddy.description.type.TypeDescription;
@@ -49,7 +49,12 @@ public ElementMatcher<TypeDescription> typeMatcher() {
4949
public void transform(TypeTransformer transformer) {
5050
transformer.applyAdviceToMethod(
5151
named("schedule")
52-
.and(takesArgument(0, named("io.vertx.sqlclient.internal.command.CommandBase")))
52+
.and(
53+
takesArgument(
54+
0,
55+
namedOneOf(
56+
"io.vertx.sqlclient.internal.command.CommandBase",
57+
"io.vertx.sqlclient.spi.protocol.CommandBase")))
5358
.and(takesArgument(1, named("io.vertx.core.Completable"))),
5459
getClass().getName() + "$ScheduleAdvice");
5560
}
@@ -59,7 +64,7 @@ public static class ScheduleAdvice {
5964

6065
@Advice.OnMethodEnter(suppress = Throwable.class, inline = false)
6166
@Nullable
62-
public static Scope onEnter(@Advice.Argument(0) CommandBase<?> command) {
67+
public static Scope onEnter(@Advice.Argument(0) Object command) {
6368
Context stored = VertxSqlClientSingletons.getCommandContext(command);
6469
if (stored == null) {
6570
// First schedule call (query executor → pool or direct connection).

instrumentation/vertx/vertx-sql-client/vertx-sql-client-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/sqlclient/v5_0/VertxSqlClientInstrumentationModule.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010
import static java.util.Collections.singletonList;
1111

1212
import com.google.auto.service.AutoService;
13+
import io.opentelemetry.context.Context;
1314
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
1415
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
1516
import io.opentelemetry.javaagent.extension.instrumentation.internal.ExperimentalInstrumentationModule;
1617
import java.util.List;
18+
import java.util.function.BiConsumer;
1719
import net.bytebuddy.matcher.ElementMatcher;
1820

1921
@AutoService(InstrumentationModule.class)
@@ -51,4 +53,16 @@ public List<TypeInstrumentation> typeInstrumentations() {
5153
new QueryResultBuilderInstrumentation(),
5254
new TransactionImplInstrumentation());
5355
}
56+
57+
@Override
58+
public void registerVirtualFields(BiConsumer<String, String> virtualFieldRegistrar) {
59+
// we add the virtual field to CommandBase manually because it is in different package in 5.0
60+
// and 5.1
61+
// used in 5.0
62+
virtualFieldRegistrar.accept(
63+
"io.vertx.sqlclient.internal.command.CommandBase", Context.class.getName());
64+
// used in 5.1
65+
virtualFieldRegistrar.accept(
66+
"io.vertx.sqlclient.spi.protocol.CommandBase", Context.class.getName());
67+
}
5468
}

instrumentation/vertx/vertx-sql-client/vertx-sql-client-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/sqlclient/v5_0/VertxSqlClientSingletons.java

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@
1212
import io.opentelemetry.instrumentation.api.util.VirtualField;
1313
import io.opentelemetry.javaagent.instrumentation.vertx.sqlclient.common.v4_0.VertxSqlClientRequest;
1414
import io.opentelemetry.javaagent.instrumentation.vertx.sqlclient.common.v4_0.VertxSqlInstrumenterFactory;
15+
import io.opentelemetry.javaagent.tooling.muzzle.NoMuzzle;
1516
import io.vertx.core.Future;
1617
import io.vertx.sqlclient.Pool;
1718
import io.vertx.sqlclient.SqlConnectOptions;
1819
import io.vertx.sqlclient.SqlConnection;
1920
import io.vertx.sqlclient.internal.SqlClientBase;
20-
import io.vertx.sqlclient.internal.command.CommandBase;
2121
import javax.annotation.Nullable;
2222

2323
public class VertxSqlClientSingletons {
@@ -34,26 +34,47 @@ public class VertxSqlClientSingletons {
3434
private static final VirtualField<SqlClientBase, SqlConnectOptions> connectOptionsField =
3535
VirtualField.find(SqlClientBase.class, SqlConnectOptions.class);
3636

37-
// CommandBase is a generic type; VirtualField.find requires the raw type
38-
@SuppressWarnings("rawtypes")
39-
private static final VirtualField<CommandBase, Context> commandContextField =
40-
VirtualField.find(CommandBase.class, Context.class);
37+
@Nullable
38+
private static final VirtualField<Object, Context> commandContextField =
39+
getCommandContextVirtualField();
4140

4241
public static Instrumenter<VertxSqlClientRequest, Void> instrumenter() {
4342
return instrumenter;
4443
}
4544

46-
// CommandBase is a generic type used as VirtualField key
47-
@SuppressWarnings("rawtypes")
45+
@NoMuzzle // to skip virtual field detection in this method
46+
@SuppressWarnings("unchecked") // virtual field key type is not known at compile time
47+
private static VirtualField<Object, Context> getCommandContextVirtualField() {
48+
// CommandBase that we want to attach context to is in different packages in 5.0 and 5.1
49+
Class<?> commandClass = null;
50+
try {
51+
// 5.0.0
52+
commandClass = Class.forName("io.vertx.sqlclient.internal.command.CommandBase");
53+
} catch (ClassNotFoundException ignored) {
54+
// ignored
55+
}
56+
if (commandClass == null) {
57+
try {
58+
// 5.1.0
59+
commandClass = Class.forName("io.vertx.sqlclient.spi.protocol.CommandBase");
60+
} catch (ClassNotFoundException ignored) {
61+
// ignored
62+
}
63+
}
64+
return commandClass != null
65+
? (VirtualField<Object, Context>) VirtualField.find(commandClass, Context.class)
66+
: null;
67+
}
68+
4869
@Nullable
49-
public static Context getCommandContext(CommandBase<?> command) {
50-
return commandContextField.get(command);
70+
public static Context getCommandContext(Object command) {
71+
return commandContextField != null ? commandContextField.get(command) : null;
5172
}
5273

53-
// CommandBase is a generic type used as VirtualField key
54-
@SuppressWarnings("rawtypes")
55-
public static void setCommandContext(CommandBase<?> command, Context context) {
56-
commandContextField.set(command, context);
74+
public static void setCommandContext(Object command, Context context) {
75+
if (commandContextField != null) {
76+
commandContextField.set(command, context);
77+
}
5778
}
5879

5980
public static void storePoolDbSystem(Pool pool, String dbSystem) {

javaagent-extension-api/src/main/java/io/opentelemetry/javaagent/extension/instrumentation/internal/ExperimentalInstrumentationModule.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
1212
import java.util.List;
1313
import java.util.Map;
14+
import java.util.function.BiConsumer;
1415
import net.bytebuddy.utility.JavaModule;
1516

1617
/**
@@ -19,6 +20,12 @@
1920
*/
2021
public interface ExperimentalInstrumentationModule {
2122

23+
/**
24+
* Register virtual field. First argument for the consumer is dot class name of the type where the
25+
* field is added and the second argument is the dot class name of the field type.
26+
*/
27+
default void registerVirtualFields(BiConsumer<String, String> virtualFieldRegistrar) {}
28+
2229
/**
2330
* Returns a list of helper classes that will be defined in the class loader of the instrumented
2431
* library.

javaagent-tooling/src/main/java/io/opentelemetry/javaagent/tooling/field/VirtualFieldImplementationInstallerFactory.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import io.opentelemetry.instrumentation.api.internal.RuntimeVirtualFieldSupplier;
1111
import io.opentelemetry.javaagent.extension.instrumentation.InstrumentationModule;
12+
import io.opentelemetry.javaagent.extension.instrumentation.internal.ExperimentalInstrumentationModule;
1213
import io.opentelemetry.javaagent.tooling.TransformSafeLogger;
1314
import io.opentelemetry.javaagent.tooling.muzzle.InstrumentationModuleMuzzle;
1415
import io.opentelemetry.javaagent.tooling.muzzle.VirtualFieldMappings;
@@ -31,6 +32,10 @@ public static VirtualFieldImplementationInstallerFactory getInstance() {
3132

3233
public VirtualFieldImplementationInstaller create(InstrumentationModule instrumentationModule) {
3334
VirtualFieldMappingsBuilderImpl builder = new VirtualFieldMappingsBuilderImpl();
35+
if (instrumentationModule instanceof ExperimentalInstrumentationModule) {
36+
((ExperimentalInstrumentationModule) instrumentationModule)
37+
.registerVirtualFields(builder::register);
38+
}
3439
if (instrumentationModule instanceof InstrumentationModuleMuzzle) {
3540
((InstrumentationModuleMuzzle) instrumentationModule).registerMuzzleVirtualFields(builder);
3641
} else {

muzzle/src/main/java/io/opentelemetry/javaagent/tooling/muzzle/ReferenceCollectingClassVisitor.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -275,16 +275,21 @@ public void visitEnd() {
275275
}
276276
}
277277
}
278-
MethodVisitor target =
279-
skip ? methodVisitor : new AdviceReferenceMethodVisitor(methodVisitor);
278+
MethodVisitor target;
279+
if (skip) {
280+
target = methodVisitor;
281+
} else {
282+
target = new AdviceReferenceMethodVisitor(methodVisitor);
283+
target = new VirtualFieldCollectingMethodVisitor(target);
284+
}
280285
if (target != null) {
281286
accept(target);
282287
}
283288
}
284289
};
285290
// Additional references we could check
286291
// - Classes in signature (return type, params) and visible from this package
287-
return new VirtualFieldCollectingMethodVisitor(methodNode);
292+
return methodNode;
288293
}
289294

290295
private static VisibilityFlag computeVisibilityFlag(int access) {

0 commit comments

Comments
 (0)