diff --git a/dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/jdbc/JDBCInstrumentationTest.groovy b/dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/jdbc/JDBCInstrumentationTest.groovy index d4ba98466f..f64752bbb0 100644 --- a/dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/jdbc/JDBCInstrumentationTest.groovy +++ b/dd-java-agent-ittests/src/test/groovy/datadog/trace/agent/integration/jdbc/JDBCInstrumentationTest.groovy @@ -273,7 +273,7 @@ class JDBCInstrumentationTest extends Specification { where: driver | connection | username | query "h2" | connections.get("h2") | null | "CREATE TABLE PS_H2 (id INTEGER not NULL, PRIMARY KEY ( id ))" - // Derby calls executeLargeUpdate from executeUpdate thus generating a nested span breaking this test. + "derby" | connections.get("derby") | "APP" | "CREATE TABLE PS_DERBY (id INTEGER not NULL, PRIMARY KEY ( id ))" "hsqldb" | connections.get("hsqldb") | "SA" | "CREATE TABLE PUBLIC.PS_HSQLDB (id INTEGER not NULL, PRIMARY KEY ( id ))" } } diff --git a/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/PreparedStatementInstrumentation.java b/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/PreparedStatementInstrumentation.java index 35a51628c5..429e8cc13b 100644 --- a/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/PreparedStatementInstrumentation.java +++ b/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/PreparedStatementInstrumentation.java @@ -14,10 +14,10 @@ import datadog.trace.agent.tooling.DDAdvice; import datadog.trace.agent.tooling.DDTransformers; import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.api.DDTags; +import datadog.trace.bootstrap.CallDepthThreadLocalMap; import datadog.trace.bootstrap.JDBCMaps; import io.opentracing.Scope; import io.opentracing.Span; -import io.opentracing.noop.NoopScopeManager; import io.opentracing.tag.Tags; import io.opentracing.util.GlobalTracer; import java.sql.Connection; @@ -50,13 +50,18 @@ public final class PreparedStatementInstrumentation extends Instrumenter.Configu @Advice.OnMethodEnter(suppress = Throwable.class) public static Scope startSpan(@Advice.This final PreparedStatement statement) { + final int callDepth = + CallDepthThreadLocalMap.get(PreparedStatement.class).incrementCallDepth(); + if (callDepth > 0) { + return null; + } final String sql = JDBCMaps.preparedStatements.get(statement); final Connection connection; try { connection = statement.getConnection(); } catch (final Throwable e) { // Had some problem getting the connection. - return NoopScopeManager.NoopScope.INSTANCE; + return null; } JDBCMaps.DBInfo dbInfo = JDBCMaps.connectionInfo.get(connection); @@ -86,12 +91,15 @@ public final class PreparedStatementInstrumentation extends Instrumenter.Configu @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) public static void stopSpan( @Advice.Enter final Scope scope, @Advice.Thrown final Throwable throwable) { - if (throwable != null) { - final Span span = scope.span(); - Tags.ERROR.set(span, true); - span.log(Collections.singletonMap(ERROR_OBJECT, throwable)); + if (scope != null) { + if (throwable != null) { + final Span span = scope.span(); + Tags.ERROR.set(span, true); + span.log(Collections.singletonMap(ERROR_OBJECT, throwable)); + } + scope.close(); + CallDepthThreadLocalMap.get(PreparedStatement.class).reset(); } - scope.close(); } } } diff --git a/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/StatementInstrumentation.java b/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/StatementInstrumentation.java index cdcda46d64..f877afc541 100644 --- a/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/StatementInstrumentation.java +++ b/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/StatementInstrumentation.java @@ -14,10 +14,10 @@ import datadog.trace.agent.tooling.DDAdvice; import datadog.trace.agent.tooling.DDTransformers; import datadog.trace.agent.tooling.Instrumenter; import datadog.trace.api.DDTags; +import datadog.trace.bootstrap.CallDepthThreadLocalMap; import datadog.trace.bootstrap.JDBCMaps; import io.opentracing.Scope; import io.opentracing.Span; -import io.opentracing.noop.NoopScopeManager; import io.opentracing.tag.Tags; import io.opentracing.util.GlobalTracer; import java.sql.Connection; @@ -51,12 +51,16 @@ public final class StatementInstrumentation extends Instrumenter.Configurable { @Advice.OnMethodEnter(suppress = Throwable.class) public static Scope startSpan( @Advice.Argument(0) final String sql, @Advice.This final Statement statement) { + final int callDepth = CallDepthThreadLocalMap.get(Statement.class).incrementCallDepth(); + if (callDepth > 0) { + return null; + } final Connection connection; try { connection = statement.getConnection(); } catch (final Throwable e) { // Had some problem getting the connection. - return NoopScopeManager.NoopScope.INSTANCE; + return null; } JDBCMaps.DBInfo dbInfo = JDBCMaps.connectionInfo.get(connection); @@ -88,12 +92,15 @@ public final class StatementInstrumentation extends Instrumenter.Configurable { @Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class) public static void stopSpan( @Advice.Enter final Scope scope, @Advice.Thrown final Throwable throwable) { - if (throwable != null) { - final Span span = scope.span(); - Tags.ERROR.set(span, true); - span.log(Collections.singletonMap(ERROR_OBJECT, throwable)); + if (scope != null) { + if (throwable != null) { + final Span span = scope.span(); + Tags.ERROR.set(span, true); + span.log(Collections.singletonMap(ERROR_OBJECT, throwable)); + } + scope.close(); + CallDepthThreadLocalMap.get(Statement.class).reset(); } - scope.close(); } } }