diff --git a/instrumentation/jdbc/javaagent/build.gradle.kts b/instrumentation/jdbc/javaagent/build.gradle.kts index 213dc1718f55..894616e9cf9e 100644 --- a/instrumentation/jdbc/javaagent/build.gradle.kts +++ b/instrumentation/jdbc/javaagent/build.gradle.kts @@ -104,6 +104,7 @@ tasks { tasks { withType().configureEach { + systemProperty("testLatestDeps", findProperty("testLatestDeps") as Boolean) jvmArgs("-Dotel.instrumentation.jdbc.experimental.transaction.enabled=true") } } diff --git a/instrumentation/jdbc/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/PreparedStatementInstrumentation.java b/instrumentation/jdbc/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/PreparedStatementInstrumentation.java index 38fad89aa090..ea0ec5302c23 100644 --- a/instrumentation/jdbc/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/PreparedStatementInstrumentation.java +++ b/instrumentation/jdbc/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/PreparedStatementInstrumentation.java @@ -77,7 +77,8 @@ public void transform(TypeTransformer transformer) { "setTimestamp", "setURL", "setRowId", - "setNString") + "setNString", + "setObject") .and(takesArgument(0, int.class)) .and(takesArguments(2)) .and(isPublic()), @@ -89,6 +90,13 @@ public void transform(TypeTransformer transformer) { .and(takesArguments(3)) .and(isPublic()), PreparedStatementInstrumentation.class.getName() + "$SetTimeParameter3Advice"); + transformer.applyAdviceToMethod( + namedOneOf("setObject") + .and(takesArgument(0, int.class)) + .and(takesArgument(2, int.class)) + .and(takesArguments(3)) + .and(isPublic()), + PreparedStatementInstrumentation.class.getName() + "$SetParameter3Advice"); transformer.applyAdviceToMethod( named("clearParameters").and(takesNoArguments()).and(isPublic()), PreparedStatementInstrumentation.class.getName() + "$ClearParametersAdvice"); @@ -192,6 +200,38 @@ public static void onExit( } } + @SuppressWarnings("unused") + public static class SetParameter3Advice { + @Advice.OnMethodExit(suppress = Throwable.class) + public static void onExit( + @Advice.This PreparedStatement statement, + @Advice.Argument(0) int index, + @Advice.Argument(1) Object value, + @Advice.Argument(2) int targetSqlType) { + if (!CAPTURE_QUERY_PARAMETERS) { + return; + } + + String str = null; + + if (value instanceof Boolean + // Short, Int, Long, Float, Double, BigDecimal + || value instanceof Number + || value instanceof String + || value instanceof Date + || value instanceof Time + || value instanceof Timestamp + || value instanceof URL + || value instanceof RowId) { + str = value.toString(); + } + + if (str != null) { + JdbcData.addParameter(statement, Integer.toString(index - 1), str); + } + } + } + @SuppressWarnings("unused") public static class SetTimeParameter3Advice { @Advice.OnMethodExit(suppress = Throwable.class) diff --git a/instrumentation/jdbc/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jdbc/test/PreparedStatementParametersTest.java b/instrumentation/jdbc/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jdbc/test/PreparedStatementParametersTest.java index fc5db502d82d..6af380167147 100644 --- a/instrumentation/jdbc/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jdbc/test/PreparedStatementParametersTest.java +++ b/instrumentation/jdbc/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/jdbc/test/PreparedStatementParametersTest.java @@ -33,6 +33,7 @@ import java.sql.SQLException; import java.sql.Time; import java.sql.Timestamp; +import java.sql.Types; import java.util.Calendar; import java.util.Locale; import java.util.Map; @@ -306,6 +307,59 @@ void testStringPreparedStatementParameter( "S"); } + @ParameterizedTest + @MethodSource("preparedStatementStream") + void testObjectPreparedStatementParameter( + String system, + Connection connection, + String username, + String query, + String sanitizedQuery, + String spanName, + String url, + String table) + throws SQLException { + test( + system, + connection, + username, + query, + sanitizedQuery, + spanName, + url, + table, + statement -> statement.setObject(1, "S"), + "S"); + } + + @ParameterizedTest + @MethodSource("preparedStatementStream") + void testObjectWithTypePreparedStatementParameter( + String system, + Connection connection, + String username, + String query, + String sanitizedQuery, + String spanName, + String url, + String table) + throws SQLException { + // we are using old database drivers that don't support the tested setObject method + Assumptions.assumeTrue(Boolean.getBoolean("testLatestDeps")); + + test( + system, + connection, + username, + query, + sanitizedQuery, + spanName, + url, + table, + statement -> statement.setObject(1, "S", Types.CHAR), + "S"); + } + @ParameterizedTest @MethodSource("preparedStatementStream") void testDate2PreparedStatementParameter(