diff --git a/instrumentation/hibernate/hibernate-6.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v6_0/HibernateInstrumentationModule.java b/instrumentation/hibernate/hibernate-6.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v6_0/HibernateInstrumentationModule.java index 3758ac451c..9e0f21e06f 100644 --- a/instrumentation/hibernate/hibernate-6.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v6_0/HibernateInstrumentationModule.java +++ b/instrumentation/hibernate/hibernate-6.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/hibernate/v6_0/HibernateInstrumentationModule.java @@ -25,7 +25,7 @@ public class HibernateInstrumentationModule extends InstrumentationModule { public ElementMatcher.Junction classLoaderMatcher() { return hasClassesNamed( // not present before 6.0 - "org.hibernate.query.Query"); + "org.hibernate.query.spi.SqmQuery"); } @Override diff --git a/instrumentation/vertx/vertx-sql-client-4.0/javaagent/build.gradle.kts b/instrumentation/vertx/vertx-sql-client-4.0/javaagent/build.gradle.kts index 977f1c605c..fea055e861 100644 --- a/instrumentation/vertx/vertx-sql-client-4.0/javaagent/build.gradle.kts +++ b/instrumentation/vertx/vertx-sql-client-4.0/javaagent/build.gradle.kts @@ -15,10 +15,67 @@ dependencies { library("io.vertx:vertx-sql-client:4.0.0") compileOnly("io.vertx:vertx-codegen:4.0.0") + // for hibernateReactive2Test + testInstrumentation(project(":instrumentation:hibernate:hibernate-6.0:javaagent")) + testLibrary("io.vertx:vertx-pg-client:4.0.0") testLibrary("io.vertx:vertx-codegen:4.0.0") } -tasks.withType().configureEach { - usesService(gradle.sharedServices.registrations["testcontainersBuildService"].service) +val latestDepTest = findProperty("testLatestDeps") as Boolean + +testing { + suites { + val hibernateReactive1Test by registering(JvmTestSuite::class) { + dependencies { + implementation("org.testcontainers:testcontainers") + if (latestDepTest) { + implementation("org.hibernate.reactive:hibernate-reactive-core:1.+") + implementation("io.vertx:vertx-pg-client:+") + } else { + implementation("org.hibernate.reactive:hibernate-reactive-core:1.0.0.Final") + implementation("io.vertx:vertx-pg-client:4.1.5") + } + } + } + + val hibernateReactive2Test by registering(JvmTestSuite::class) { + dependencies { + implementation("org.testcontainers:testcontainers") + if (latestDepTest) { + implementation("org.hibernate.reactive:hibernate-reactive-core:2.+") + implementation("io.vertx:vertx-pg-client:+") + } else { + implementation("org.hibernate.reactive:hibernate-reactive-core:2.0.0.Final") + implementation("io.vertx:vertx-pg-client:4.4.2") + } + } + } + } +} + +tasks { + withType().configureEach { + usesService(gradle.sharedServices.registrations["testcontainersBuildService"].service) + } + named("compileHibernateReactive2TestJava", JavaCompile::class).configure { + options.release.set(11) + } + val testJavaVersion = + gradle.startParameter.projectProperties.get("testJavaVersion")?.let(JavaVersion::toVersion) + ?: JavaVersion.current() + if (testJavaVersion.isJava8) { + named("hibernateReactive2Test", Test::class).configure { + enabled = false + } + if (latestDepTest) { + named("hibernateReactive1Test", Test::class).configure { + enabled = false + } + } + } + + check { + dependsOn(testing.suites) + } } diff --git a/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/hibernateReactive1Test/java/io/opentelemetry/javaagent/instrumentation/hibernate/reactive/v1_0/HibernateReactiveTest.java b/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/hibernateReactive1Test/java/io/opentelemetry/javaagent/instrumentation/hibernate/reactive/v1_0/HibernateReactiveTest.java new file mode 100644 index 0000000000..54419f78d3 --- /dev/null +++ b/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/hibernateReactive1Test/java/io/opentelemetry/javaagent/instrumentation/hibernate/reactive/v1_0/HibernateReactiveTest.java @@ -0,0 +1,160 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.hibernate.reactive.v1_0; + +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.DB_NAME; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.DB_OPERATION; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.DB_SQL_TABLE; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.DB_STATEMENT; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.DB_USER; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NET_PEER_NAME; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NET_PEER_PORT; + +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import java.time.Duration; +import java.util.concurrent.TimeUnit; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; +import org.hibernate.reactive.mutiny.Mutiny; +import org.hibernate.reactive.stage.Stage; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.output.Slf4jLogConsumer; + +class HibernateReactiveTest { + private static final Logger logger = LoggerFactory.getLogger(HibernateReactiveTest.class); + + private static final String USER_DB = "SA"; + private static final String PW_DB = "password123"; + private static final String DB = "tempdb"; + + @RegisterExtension + protected static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); + + private static GenericContainer container; + private static int port; + private static EntityManagerFactory entityManagerFactory; + private static Mutiny.SessionFactory mutinySessionFactory; + private static Stage.SessionFactory stageSessionFactory; + + @BeforeAll + static void setUp() { + container = + new GenericContainer<>("postgres:9.6.8") + .withEnv("POSTGRES_USER", USER_DB) + .withEnv("POSTGRES_PASSWORD", PW_DB) + .withEnv("POSTGRES_DB", DB) + .withExposedPorts(5432) + .withLogConsumer(new Slf4jLogConsumer(logger)) + .withStartupTimeout(Duration.ofMinutes(2)); + container.start(); + + port = container.getMappedPort(5432); + System.setProperty("db.port", String.valueOf(port)); + + entityManagerFactory = Persistence.createEntityManagerFactory("test-pu"); + + Value value = new Value("name"); + value.setId(1L); + + mutinySessionFactory = entityManagerFactory.unwrap(Mutiny.SessionFactory.class); + stageSessionFactory = entityManagerFactory.unwrap(Stage.SessionFactory.class); + + mutinySessionFactory + .withTransaction((session, tx) -> session.merge(value)) + .await() + .atMost(Duration.ofSeconds(30)); + } + + @AfterAll + static void cleanUp() { + if (entityManagerFactory != null) { + entityManagerFactory.close(); + } + if (mutinySessionFactory != null) { + mutinySessionFactory.close(); + } + if (stageSessionFactory != null) { + stageSessionFactory.close(); + } + container.stop(); + } + + @Test + void testMutiny() { + testing.runWithSpan( + "parent", + () -> { + mutinySessionFactory + .withSession( + session -> + session + .find(Value.class, 1L) + .invoke( + value -> { + testing.runWithSpan("callback", () -> {}); + })) + .await() + .atMost(Duration.ofSeconds(30)); + }); + + assertTrace(); + } + + @Test + void testStage() throws Exception { + testing + .runWithSpan( + "parent", + () -> + stageSessionFactory + .withSession( + session -> + session + .find(Value.class, 1L) + .thenAccept( + value -> { + testing.runWithSpan("callback", () -> {}); + })) + .toCompletableFuture()) + .get(30, TimeUnit.SECONDS); + + assertTrace(); + } + + private static void assertTrace() { + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("parent").hasKind(SpanKind.INTERNAL), + span -> + span.hasName("SELECT tempdb.Value") + .hasKind(SpanKind.CLIENT) + .hasParent(trace.getSpan(0)) + .hasAttributesSatisfyingExactly( + equalTo(DB_NAME, DB), + equalTo(DB_USER, USER_DB), + equalTo( + DB_STATEMENT, + "select value0_.id as id1_0_0_, value0_.name as name2_0_0_ from Value value0_ where value0_.id=$?"), + equalTo(DB_OPERATION, "SELECT"), + equalTo(DB_SQL_TABLE, "Value"), + equalTo(NET_PEER_NAME, "localhost"), + equalTo(NET_PEER_PORT, port)), + span -> + span.hasName("callback") + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)))); + } +} diff --git a/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/hibernateReactive1Test/java/io/opentelemetry/javaagent/instrumentation/hibernate/reactive/v1_0/Value.java b/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/hibernateReactive1Test/java/io/opentelemetry/javaagent/instrumentation/hibernate/reactive/v1_0/Value.java new file mode 100644 index 0000000000..50b0d1bdc1 --- /dev/null +++ b/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/hibernateReactive1Test/java/io/opentelemetry/javaagent/instrumentation/hibernate/reactive/v1_0/Value.java @@ -0,0 +1,43 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.hibernate.reactive.v1_0; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table +public class Value { + + private Long id; + private String name; + + public Value() {} + + public Value(String name) { + this.name = name; + } + + @Id + @GeneratedValue + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String title) { + name = title; + } +} diff --git a/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/hibernateReactive1Test/resources/META-INF/persistence.xml b/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/hibernateReactive1Test/resources/META-INF/persistence.xml new file mode 100644 index 0000000000..c2b26d0fce --- /dev/null +++ b/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/hibernateReactive1Test/resources/META-INF/persistence.xml @@ -0,0 +1,20 @@ + + + + org.hibernate.reactive.provider.ReactivePersistenceProvider + io.opentelemetry.javaagent.instrumentation.hibernate.reactive.v1_0.Value + true + + + + + + + + + + + diff --git a/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/hibernateReactive2Test/java/io/opentelemetry/javaagent/instrumentation/hibernate/reactive/v2_0/HibernateReactiveTest.java b/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/hibernateReactive2Test/java/io/opentelemetry/javaagent/instrumentation/hibernate/reactive/v2_0/HibernateReactiveTest.java new file mode 100644 index 0000000000..066247898d --- /dev/null +++ b/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/hibernateReactive2Test/java/io/opentelemetry/javaagent/instrumentation/hibernate/reactive/v2_0/HibernateReactiveTest.java @@ -0,0 +1,160 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.hibernate.reactive.v2_0; + +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.DB_NAME; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.DB_OPERATION; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.DB_SQL_TABLE; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.DB_STATEMENT; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.DB_USER; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NET_PEER_NAME; +import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NET_PEER_PORT; + +import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; +import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import jakarta.persistence.EntityManagerFactory; +import jakarta.persistence.Persistence; +import java.time.Duration; +import java.util.concurrent.TimeUnit; +import org.hibernate.reactive.mutiny.Mutiny; +import org.hibernate.reactive.stage.Stage; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.output.Slf4jLogConsumer; + +class HibernateReactiveTest { + private static final Logger logger = LoggerFactory.getLogger(HibernateReactiveTest.class); + + private static final String USER_DB = "SA"; + private static final String PW_DB = "password123"; + private static final String DB = "tempdb"; + + @RegisterExtension + protected static final InstrumentationExtension testing = AgentInstrumentationExtension.create(); + + private static GenericContainer container; + private static int port; + private static EntityManagerFactory entityManagerFactory; + private static Mutiny.SessionFactory mutinySessionFactory; + private static Stage.SessionFactory stageSessionFactory; + + @BeforeAll + static void setUp() { + container = + new GenericContainer<>("postgres:9.6.8") + .withEnv("POSTGRES_USER", USER_DB) + .withEnv("POSTGRES_PASSWORD", PW_DB) + .withEnv("POSTGRES_DB", DB) + .withExposedPorts(5432) + .withLogConsumer(new Slf4jLogConsumer(logger)) + .withStartupTimeout(Duration.ofMinutes(2)); + container.start(); + + port = container.getMappedPort(5432); + System.setProperty("db.port", String.valueOf(port)); + + entityManagerFactory = Persistence.createEntityManagerFactory("test-pu"); + + Value value = new Value("name"); + value.setId(1L); + + mutinySessionFactory = entityManagerFactory.unwrap(Mutiny.SessionFactory.class); + stageSessionFactory = entityManagerFactory.unwrap(Stage.SessionFactory.class); + + mutinySessionFactory + .withTransaction((session, tx) -> session.merge(value)) + .await() + .atMost(Duration.ofSeconds(30)); + } + + @AfterAll + static void cleanUp() { + if (entityManagerFactory != null) { + entityManagerFactory.close(); + } + if (mutinySessionFactory != null) { + mutinySessionFactory.close(); + } + if (stageSessionFactory != null) { + stageSessionFactory.close(); + } + container.stop(); + } + + @Test + void testMutiny() { + testing.runWithSpan( + "parent", + () -> { + mutinySessionFactory + .withSession( + session -> + session + .find(Value.class, 1L) + .invoke( + value -> { + testing.runWithSpan("callback", () -> {}); + })) + .await() + .atMost(Duration.ofSeconds(30)); + }); + + assertTrace(); + } + + @Test + void testStage() throws Exception { + testing + .runWithSpan( + "parent", + () -> + stageSessionFactory + .withSession( + session -> + session + .find(Value.class, 1L) + .thenAccept( + value -> { + testing.runWithSpan("callback", () -> {}); + })) + .toCompletableFuture()) + .get(30, TimeUnit.SECONDS); + + assertTrace(); + } + + private static void assertTrace() { + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("parent").hasKind(SpanKind.INTERNAL), + span -> + span.hasName("SELECT tempdb.Value") + .hasKind(SpanKind.CLIENT) + .hasParent(trace.getSpan(0)) + .hasAttributesSatisfyingExactly( + equalTo(DB_NAME, DB), + equalTo(DB_USER, USER_DB), + equalTo( + DB_STATEMENT, + "select v1_0.id,v1_0.name from Value v1_0 where v1_0.id=$?"), + equalTo(DB_OPERATION, "SELECT"), + equalTo(DB_SQL_TABLE, "Value"), + equalTo(NET_PEER_NAME, "localhost"), + equalTo(NET_PEER_PORT, port)), + span -> + span.hasName("callback") + .hasKind(SpanKind.INTERNAL) + .hasParent(trace.getSpan(0)))); + } +} diff --git a/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/hibernateReactive2Test/java/io/opentelemetry/javaagent/instrumentation/hibernate/reactive/v2_0/Value.java b/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/hibernateReactive2Test/java/io/opentelemetry/javaagent/instrumentation/hibernate/reactive/v2_0/Value.java new file mode 100644 index 0000000000..df243fdda4 --- /dev/null +++ b/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/hibernateReactive2Test/java/io/opentelemetry/javaagent/instrumentation/hibernate/reactive/v2_0/Value.java @@ -0,0 +1,43 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.hibernate.reactive.v2_0; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.Table; + +@Entity +@Table +public class Value { + + private Long id; + private String name; + + public Value() {} + + public Value(String name) { + this.name = name; + } + + @Id + @GeneratedValue + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String title) { + name = title; + } +} diff --git a/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/hibernateReactive2Test/resources/META-INF/persistence.xml b/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/hibernateReactive2Test/resources/META-INF/persistence.xml new file mode 100644 index 0000000000..f543bd5ba5 --- /dev/null +++ b/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/hibernateReactive2Test/resources/META-INF/persistence.xml @@ -0,0 +1,20 @@ + + + + org.hibernate.reactive.provider.ReactivePersistenceProvider + io.opentelemetry.javaagent.instrumentation.hibernate.reactive.v2_0.Value + true + + + + + + + + + + + diff --git a/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/sql/PoolInstrumentation.java b/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/sql/PoolInstrumentation.java index bccb0d94fd..f9ff3ee0de 100644 --- a/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/sql/PoolInstrumentation.java +++ b/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/sql/PoolInstrumentation.java @@ -5,36 +5,53 @@ package io.opentelemetry.javaagent.instrumentation.vertx.v4_0.sql; +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.sql.VertxSqlClientSingletons.setSqlConnectOptions; +import static net.bytebuddy.matcher.ElementMatchers.isStatic; import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.returns; 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; +import io.vertx.core.Future; import io.vertx.sqlclient.Pool; import io.vertx.sqlclient.SqlConnectOptions; +import io.vertx.sqlclient.SqlConnection; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.matcher.ElementMatcher; public class PoolInstrumentation implements TypeInstrumentation { + @Override + public ElementMatcher classLoaderOptimization() { + return hasClassesNamed("io.vertx.sqlclient.Pool"); + } + @Override public ElementMatcher typeMatcher() { - return named("io.vertx.sqlclient.Pool"); + return implementsInterface(named("io.vertx.sqlclient.Pool")); } @Override public void transform(TypeTransformer transformer) { transformer.applyAdviceToMethod( named("pool") + .and(isStatic()) .and(takesArguments(3)) .and(takesArgument(1, named("io.vertx.sqlclient.SqlConnectOptions"))) .and(returns(named("io.vertx.sqlclient.Pool"))), PoolInstrumentation.class.getName() + "$PoolAdvice"); + + transformer.applyAdviceToMethod( + named("getConnection").and(takesNoArguments()).and(returns(named("io.vertx.core.Future"))), + PoolInstrumentation.class.getName() + "$GetConnectionAdvice"); } @SuppressWarnings("unused") @@ -53,12 +70,33 @@ public class PoolInstrumentation implements TypeInstrumentation { } @Advice.OnMethodExit(suppress = Throwable.class) - public static void onExit(@Advice.Local("otelCallDepth") CallDepth callDepth) { + public static void onExit( + @Advice.Return Pool pool, + @Advice.Argument(1) SqlConnectOptions sqlConnectOptions, + @Advice.Local("otelCallDepth") CallDepth callDepth) { if (callDepth.decrementAndGet() > 0) { return; } + VirtualField virtualField = + VirtualField.find(Pool.class, SqlConnectOptions.class); + virtualField.set(pool, sqlConnectOptions); + setSqlConnectOptions(null); } } + + @SuppressWarnings("unused") + public static class GetConnectionAdvice { + @Advice.OnMethodExit(suppress = Throwable.class) + public static void onExit( + @Advice.This Pool pool, @Advice.Return(readOnly = false) Future future) { + // copy connect options stored on pool to new connection + VirtualField virtualField = + VirtualField.find(Pool.class, SqlConnectOptions.class); + SqlConnectOptions sqlConnectOptions = virtualField.get(pool); + + future = VertxSqlClientSingletons.attachConnectOptions(future, sqlConnectOptions); + } + } } diff --git a/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/sql/SqlClientBaseInstrumentation.java b/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/sql/SqlClientBaseInstrumentation.java index 8c8b18ad03..07cfb16bb5 100644 --- a/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/sql/SqlClientBaseInstrumentation.java +++ b/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/sql/SqlClientBaseInstrumentation.java @@ -42,6 +42,7 @@ public class SqlClientBaseInstrumentation implements TypeInstrumentation { @Advice.OnMethodExit(suppress = Throwable.class) public static void onExit(@Advice.This SqlClientBase sqlClientBase) { // copy connection options from ThreadLocal to VirtualField + // this virtual field is also set in VertxSqlClientSingletons.attachConnectOptions VirtualField, SqlConnectOptions> virtualField = VirtualField.find(SqlClientBase.class, SqlConnectOptions.class); virtualField.set(sqlClientBase, getSqlConnectOptions()); diff --git a/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/sql/VertxSqlClientSingletons.java b/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/sql/VertxSqlClientSingletons.java index 2861962e21..fd9bcd91d0 100644 --- a/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/sql/VertxSqlClientSingletons.java +++ b/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/sql/VertxSqlClientSingletons.java @@ -16,8 +16,12 @@ import io.opentelemetry.instrumentation.api.instrumenter.db.DbClientSpanNameExtr import io.opentelemetry.instrumentation.api.instrumenter.db.SqlClientAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.net.PeerServiceAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.network.ServerAttributesExtractor; +import io.opentelemetry.instrumentation.api.util.VirtualField; import io.opentelemetry.javaagent.bootstrap.internal.CommonConfig; +import io.vertx.core.Future; import io.vertx.sqlclient.SqlConnectOptions; +import io.vertx.sqlclient.SqlConnection; +import io.vertx.sqlclient.impl.SqlClientBase; import java.util.Map; public final class VertxSqlClientSingletons { @@ -74,5 +78,20 @@ public final class VertxSqlClientSingletons { return otelParentContext.makeCurrent(); } + // this virtual field is also used in SqlClientBase instrumentation + private static final VirtualField, SqlConnectOptions> connectOptionsField = + VirtualField.find(SqlClientBase.class, SqlConnectOptions.class); + + public static Future attachConnectOptions( + Future future, SqlConnectOptions connectOptions) { + return future.map( + sqlConnection -> { + if (sqlConnection instanceof SqlClientBase) { + connectOptionsField.set((SqlClientBase) sqlConnection, connectOptions); + } + return sqlConnection; + }); + } + private VertxSqlClientSingletons() {} }