From 75d33c41d3c4c33db891034a38e8bff5d2e72407 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Mon, 15 Jun 2026 13:24:24 -0700 Subject: [PATCH] Add Vert.x SQL batch size attribute --- .../v4_0/QueryExecutorInstrumentation.java | 16 ++++++++++++---- .../vertx/sqlclient/v4_0/VertxSqlClientTest.java | 10 ++++++++-- .../v5_0/QueryExecutorInstrumentation.java | 16 ++++++++++++---- .../vertx/sqlclient/v5_0/VertxSqlClientTest.java | 10 ++++++++-- .../v4_0/VertxSqlClientAttributesGetter.java | 6 ++++++ .../common/v4_0/VertxSqlClientRequest.java | 10 +++++++++- 6 files changed, 55 insertions(+), 13 deletions(-) diff --git a/instrumentation/vertx/vertx-sql-client/vertx-sql-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/sqlclient/v4_0/QueryExecutorInstrumentation.java b/instrumentation/vertx/vertx-sql-client/vertx-sql-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/sqlclient/v4_0/QueryExecutorInstrumentation.java index cb0649368ff8..5b75e7972880 100644 --- a/instrumentation/vertx/vertx-sql-client/vertx-sql-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/sqlclient/v4_0/QueryExecutorInstrumentation.java +++ b/instrumentation/vertx/vertx-sql-client/vertx-sql-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/sqlclient/v4_0/QueryExecutorInstrumentation.java @@ -22,6 +22,7 @@ import io.vertx.sqlclient.SqlConnectOptions; import io.vertx.sqlclient.impl.PreparedStatement; import io.vertx.sqlclient.impl.QueryExecutorUtil; +import java.util.Collection; import javax.annotation.Nullable; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; @@ -73,7 +74,7 @@ private AdviceScope( this.scope = scope; } - public static AdviceScope start(Object queryExecutor, Object[] arguments) { + public static AdviceScope start(Object queryExecutor, String methodName, Object[] arguments) { CallDepth callDepth = CallDepth.forClass(queryExecutor.getClass()); if (callDepth.getAndIncrement() > 0) { return new AdviceScope(callDepth); @@ -86,6 +87,7 @@ public static AdviceScope start(Object queryExecutor, Object[] arguments) { String sql = null; boolean preparedStatement = false; PromiseInternal promiseInternal = null; + Long batchSize = null; for (Object argument : arguments) { if (sql == null) { if (argument instanceof String) { @@ -97,6 +99,10 @@ public static AdviceScope start(Object queryExecutor, Object[] arguments) { } else if (argument instanceof PromiseInternal) { promiseInternal = (PromiseInternal) argument; } + if (methodName.equals("executeBatchQuery") && argument instanceof Collection) { + int size = ((Collection) argument).size(); + batchSize = size > 1 ? (long) size : null; + } } if (sql == null || promiseInternal == null) { return new AdviceScope(callDepth); @@ -116,7 +122,7 @@ public static AdviceScope start(Object queryExecutor, Object[] arguments) { dbSystem = VertxSqlClientUtil.getDbSystemNameFromClassName(connectOptions); } VertxSqlClientRequest otelRequest = - new VertxSqlClientRequest(sql, connectOptions, preparedStatement, dbSystem); + new VertxSqlClientRequest(sql, connectOptions, preparedStatement, dbSystem, batchSize); Context parentContext = Context.current(); if (!instrumenter().shouldStart(parentContext, otelRequest)) { return new AdviceScope(callDepth); @@ -145,8 +151,10 @@ public void end(@Nullable Throwable throwable) { @Advice.OnMethodEnter(suppress = Throwable.class, inline = false) public static AdviceScope onEnter( - @Advice.This Object queryExecutor, @Advice.AllArguments Object[] arguments) { - return AdviceScope.start(queryExecutor, arguments); + @Advice.This Object queryExecutor, + @Advice.Origin("#m") String methodName, + @Advice.AllArguments Object[] arguments) { + return AdviceScope.start(queryExecutor, methodName, arguments); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class, inline = false) diff --git a/instrumentation/vertx/vertx-sql-client/vertx-sql-client-4.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/vertx/sqlclient/v4_0/VertxSqlClientTest.java b/instrumentation/vertx/vertx-sql-client/vertx-sql-client-4.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/vertx/sqlclient/v4_0/VertxSqlClientTest.java index 9d74ab1b9a5f..57e02529e399 100644 --- a/instrumentation/vertx/vertx-sql-client/vertx-sql-client-4.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/vertx/sqlclient/v4_0/VertxSqlClientTest.java +++ b/instrumentation/vertx/vertx-sql-client/vertx-sql-client-4.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/vertx/sqlclient/v4_0/VertxSqlClientTest.java @@ -10,6 +10,7 @@ import static io.opentelemetry.instrumentation.testing.junit.service.SemconvServiceStabilityUtil.maybeStablePeerService; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies; +import static io.opentelemetry.semconv.DbAttributes.DB_OPERATION_BATCH_SIZE; import static io.opentelemetry.semconv.DbAttributes.DB_QUERY_SUMMARY; import static io.opentelemetry.semconv.ErrorAttributes.ERROR_TYPE; import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_MESSAGE; @@ -290,7 +291,10 @@ void testBatch() throws Exception { trace.hasSpansSatisfyingExactly( span -> span.hasName("parent").hasKind(SpanKind.INTERNAL), span -> - span.hasName(emitStableDatabaseSemconv() ? "insert test" : "INSERT tempdb.test") + span.hasName( + emitStableDatabaseSemconv() + ? "BATCH insert test" + : "INSERT tempdb.test") .hasKind(SpanKind.CLIENT) .hasParent(trace.getSpan(0)) .hasAttributesSatisfyingExactly( @@ -304,7 +308,9 @@ void testBatch() throws Exception { "insert into test values ($1, $2) returning *"), equalTo( DB_QUERY_SUMMARY, - emitStableDatabaseSemconv() ? "insert test" : null), + emitStableDatabaseSemconv() ? "BATCH insert test" : null), + equalTo( + DB_OPERATION_BATCH_SIZE, emitStableDatabaseSemconv() ? 2L : null), equalTo( maybeStable(DB_OPERATION), emitStableDatabaseSemconv() ? null : "INSERT"), diff --git a/instrumentation/vertx/vertx-sql-client/vertx-sql-client-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/sqlclient/v5_0/QueryExecutorInstrumentation.java b/instrumentation/vertx/vertx-sql-client/vertx-sql-client-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/sqlclient/v5_0/QueryExecutorInstrumentation.java index 8584c48a038e..62983148f3fa 100644 --- a/instrumentation/vertx/vertx-sql-client/vertx-sql-client-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/sqlclient/v5_0/QueryExecutorInstrumentation.java +++ b/instrumentation/vertx/vertx-sql-client/vertx-sql-client-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/sqlclient/v5_0/QueryExecutorInstrumentation.java @@ -22,6 +22,7 @@ import io.vertx.sqlclient.SqlConnectOptions; import io.vertx.sqlclient.impl.QueryExecutorUtil; import io.vertx.sqlclient.internal.PreparedStatement; +import java.util.Collection; import javax.annotation.Nullable; import net.bytebuddy.asm.Advice; import net.bytebuddy.description.type.TypeDescription; @@ -72,7 +73,7 @@ private AdviceScope( this.scope = scope; } - public static AdviceScope start(Object queryExecutor, Object[] arguments) { + public static AdviceScope start(Object queryExecutor, String methodName, Object[] arguments) { CallDepth callDepth = CallDepth.forClass(queryExecutor.getClass()); if (callDepth.getAndIncrement() > 0) { return new AdviceScope(callDepth); @@ -85,6 +86,7 @@ public static AdviceScope start(Object queryExecutor, Object[] arguments) { String sql = null; boolean preparedStatement = false; PromiseInternal promiseInternal = null; + Long batchSize = null; for (Object argument : arguments) { if (sql == null) { if (argument instanceof String) { @@ -96,6 +98,10 @@ public static AdviceScope start(Object queryExecutor, Object[] arguments) { } else if (argument instanceof PromiseInternal) { promiseInternal = (PromiseInternal) argument; } + if (methodName.equals("executeBatchQuery") && argument instanceof Collection) { + int size = ((Collection) argument).size(); + batchSize = size > 1 ? (long) size : null; + } } if (sql == null || promiseInternal == null) { return new AdviceScope(callDepth); @@ -110,7 +116,7 @@ public static AdviceScope start(Object queryExecutor, Object[] arguments) { } String dbSystem = VertxSqlClientSingletons.getConnectOptionsDbSystem(connectOptions); VertxSqlClientRequest otelRequest = - new VertxSqlClientRequest(sql, connectOptions, preparedStatement, dbSystem); + new VertxSqlClientRequest(sql, connectOptions, preparedStatement, dbSystem, batchSize); Context parentContext = Context.current(); if (!instrumenter().shouldStart(parentContext, otelRequest)) { return new AdviceScope(callDepth); @@ -139,8 +145,10 @@ public void end(@Nullable Throwable throwable) { @Advice.OnMethodEnter(suppress = Throwable.class, inline = false) public static AdviceScope onEnter( - @Advice.This Object queryExecutor, @Advice.AllArguments Object[] arguments) { - return AdviceScope.start(queryExecutor, arguments); + @Advice.This Object queryExecutor, + @Advice.Origin("#m") String methodName, + @Advice.AllArguments Object[] arguments) { + return AdviceScope.start(queryExecutor, methodName, arguments); } @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class, inline = false) diff --git a/instrumentation/vertx/vertx-sql-client/vertx-sql-client-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/vertx/sqlclient/v5_0/VertxSqlClientTest.java b/instrumentation/vertx/vertx-sql-client/vertx-sql-client-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/vertx/sqlclient/v5_0/VertxSqlClientTest.java index 235b520e7576..c2aa7868d215 100644 --- a/instrumentation/vertx/vertx-sql-client/vertx-sql-client-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/vertx/sqlclient/v5_0/VertxSqlClientTest.java +++ b/instrumentation/vertx/vertx-sql-client/vertx-sql-client-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/vertx/sqlclient/v5_0/VertxSqlClientTest.java @@ -10,6 +10,7 @@ import static io.opentelemetry.instrumentation.testing.junit.service.SemconvServiceStabilityUtil.maybeStablePeerService; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies; +import static io.opentelemetry.semconv.DbAttributes.DB_OPERATION_BATCH_SIZE; import static io.opentelemetry.semconv.DbAttributes.DB_QUERY_SUMMARY; import static io.opentelemetry.semconv.ErrorAttributes.ERROR_TYPE; import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_MESSAGE; @@ -291,7 +292,10 @@ void testBatch() throws Exception { trace.hasSpansSatisfyingExactly( span -> span.hasName("parent").hasKind(SpanKind.INTERNAL), span -> - span.hasName(emitStableDatabaseSemconv() ? "insert test" : "INSERT tempdb.test") + span.hasName( + emitStableDatabaseSemconv() + ? "BATCH insert test" + : "INSERT tempdb.test") .hasKind(SpanKind.CLIENT) .hasParent(trace.getSpan(0)) .hasAttributesSatisfyingExactly( @@ -305,7 +309,9 @@ void testBatch() throws Exception { "insert into test values ($1, $2) returning *"), equalTo( DB_QUERY_SUMMARY, - emitStableDatabaseSemconv() ? "insert test" : null), + emitStableDatabaseSemconv() ? "BATCH insert test" : null), + equalTo( + DB_OPERATION_BATCH_SIZE, emitStableDatabaseSemconv() ? 2L : null), equalTo( maybeStable(DB_OPERATION), emitStableDatabaseSemconv() ? null : "INSERT"), diff --git a/instrumentation/vertx/vertx-sql-client/vertx-sql-client-common-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/sqlclient/common/v4_0/VertxSqlClientAttributesGetter.java b/instrumentation/vertx/vertx-sql-client/vertx-sql-client-common-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/sqlclient/common/v4_0/VertxSqlClientAttributesGetter.java index 37e1479eb3b3..acdaf30c9534 100644 --- a/instrumentation/vertx/vertx-sql-client/vertx-sql-client-common-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/sqlclient/common/v4_0/VertxSqlClientAttributesGetter.java +++ b/instrumentation/vertx/vertx-sql-client/vertx-sql-client-common-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/sqlclient/common/v4_0/VertxSqlClientAttributesGetter.java @@ -90,6 +90,12 @@ public Collection getRawQueryTexts(VertxSqlClientRequest request) { return singleton(request.getQueryText()); } + @Nullable + @Override + public Long getDbOperationBatchSize(VertxSqlClientRequest request) { + return request.getOperationBatchSize(); + } + @Nullable @Override public String getErrorType( diff --git a/instrumentation/vertx/vertx-sql-client/vertx-sql-client-common-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/sqlclient/common/v4_0/VertxSqlClientRequest.java b/instrumentation/vertx/vertx-sql-client/vertx-sql-client-common-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/sqlclient/common/v4_0/VertxSqlClientRequest.java index bb7749a52c9e..666597516729 100644 --- a/instrumentation/vertx/vertx-sql-client/vertx-sql-client-common-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/sqlclient/common/v4_0/VertxSqlClientRequest.java +++ b/instrumentation/vertx/vertx-sql-client/vertx-sql-client-common-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/sqlclient/common/v4_0/VertxSqlClientRequest.java @@ -14,16 +14,19 @@ public class VertxSqlClientRequest { @Nullable private final SqlConnectOptions sqlConnectOptions; private final boolean parameterizedQuery; private final String dbSystemName; + @Nullable private final Long operationBatchSize; public VertxSqlClientRequest( String queryText, @Nullable SqlConnectOptions sqlConnectOptions, boolean parameterizedQuery, - String dbSystemName) { + String dbSystemName, + @Nullable Long operationBatchSize) { this.queryText = queryText; this.sqlConnectOptions = sqlConnectOptions; this.parameterizedQuery = parameterizedQuery; this.dbSystemName = dbSystemName; + this.operationBatchSize = operationBatchSize; } public String getQueryText() { @@ -57,4 +60,9 @@ public boolean isParameterizedQuery() { public String getDbSystemName() { return dbSystemName; } + + @Nullable + public Long getOperationBatchSize() { + return operationBatchSize; + } }