Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions instrumentation/jdbc/javaagent/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ dependencies {
testLibrary("org.apache.tomcat:tomcat-juli:7.0.19")
testLibrary("com.zaxxer:HikariCP:2.4.0")
testLibrary("com.mchange:c3p0:0.9.5")
testLibrary("com.alibaba:druid:1.2.20")

// some classes in earlier versions of derby were split out into derbytools in later versions
latestDepTestLibrary("org.apache.derby:derbytools:latest.release")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.instrumentation.jdbc.internal.JdbcUtils;
import io.opentelemetry.javaagent.bootstrap.CallDepth;
import io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge;
import io.opentelemetry.javaagent.bootstrap.jdbc.DbInfo;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
Expand All @@ -33,7 +34,7 @@ public ElementMatcher<TypeDescription> typeMatcher() {
@Override
public void transform(TypeTransformer transformer) {
transformer.applyAdviceToMethod(
named("getConnection").and(returns(named("java.sql.Connection"))),
named("getConnection").and(returns(implementsInterface(named("java.sql.Connection")))),
DataSourceInstrumentation.class.getName() + "$GetConnectionAdvice");
}

Expand All @@ -44,7 +45,13 @@ public static class GetConnectionAdvice {
public static void start(
@Advice.This DataSource ds,
@Advice.Local("otelContext") Context context,
@Advice.Local("otelScope") Scope scope) {
@Advice.Local("otelScope") Scope scope,
@Advice.Local("otelCallDepth") CallDepth callDepth) {
callDepth = CallDepth.forClass(DataSource.class);
if (callDepth.getAndIncrement() > 0) {
return;
}

Context parentContext = Java8BytecodeBridge.currentContext();
if (!Java8BytecodeBridge.spanFromContext(parentContext).getSpanContext().isValid()) {
// this instrumentation is already very noisy, and calls to getConnection outside of an
Expand All @@ -64,7 +71,12 @@ public static void stopSpan(
@Advice.Return Connection connection,
@Advice.Thrown Throwable throwable,
@Advice.Local("otelContext") Context context,
@Advice.Local("otelScope") Scope scope) {
@Advice.Local("otelScope") Scope scope,
@Advice.Local("otelCallDepth") CallDepth callDepth) {
if (callDepth.decrementAndGet() > 0) {
return;
}

if (scope == null) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

package io.opentelemetry.javaagent.instrumentation.jdbc.test;

import static io.opentelemetry.api.trace.SpanKind.INTERNAL;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_FUNCTION;
import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_NAMESPACE;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_NAME;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_SYSTEM;
import static org.assertj.core.api.Assertions.assertThat;

import com.alibaba.druid.pool.DruidDataSource;
import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
import io.opentelemetry.sdk.trace.data.SpanData;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.stream.Collectors;
import javax.sql.DataSource;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

@SuppressWarnings("deprecation") // using deprecated semconv
class DataSourceInstrumentationTest {

@RegisterExtension
static final InstrumentationExtension testing = AgentInstrumentationExtension.create();

private DataSource dataSource;

@BeforeEach
void setUp() {
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setUrl("jdbc:h2:mem:test");
druidDataSource.setDriverClassName("org.h2.Driver");
druidDataSource.setUsername("sa");
druidDataSource.setPassword("");
druidDataSource.setMaxActive(1);
this.dataSource = druidDataSource;
}

@AfterEach
void tearDown() {
if (dataSource instanceof DruidDataSource) {
((DruidDataSource) dataSource).close();
}
}

@Test
void testDruidDataSourceGetConnection() throws SQLException {
testing.runWithSpan(
"parent",
() -> {
try (Connection connection = dataSource.getConnection()) {
return null;
} catch (SQLException e) {
throw new RuntimeException(e);
}
});

testing.waitAndAssertTraces(
trace ->
trace.hasSpansSatisfyingExactly(
span -> span.hasName("parent").hasKind(INTERNAL).hasNoParent(),
span ->
span.hasName("DruidDataSource.getConnection")
.hasKind(INTERNAL)
.hasParent(trace.getSpan(0))
.hasAttributesSatisfying(
equalTo(CODE_NAMESPACE, "com.alibaba.druid.pool.DruidDataSource"),
equalTo(CODE_FUNCTION, "getConnection"),
equalTo(DB_SYSTEM, "h2"),
equalTo(DB_NAME, "test"))));

List<SpanData> spans = testing.spans();
List<SpanData> dataSourceSpans =
spans.stream()
.filter(span -> span.getName().equals("DruidDataSource.getConnection"))
.collect(Collectors.toList());

assertThat(dataSourceSpans)
.as("Should have exactly one DruidDataSource.getConnection span, not duplicates")
.hasSize(1);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1041,7 +1041,6 @@ void testGetConnection(
throws SQLException {
// Tomcat's pool doesn't work because the getConnection method is
// implemented in a parent class that doesn't implement DataSource
boolean recursive = datasource instanceof EmbeddedDataSource;

if (init != null) {
init.accept(datasource);
Expand Down Expand Up @@ -1073,14 +1072,6 @@ void testGetConnection(
.hasKind(SpanKind.INTERNAL)
.hasParent(trace.getSpan(0))
.hasAttributesSatisfyingExactly(attributesAssertions)));
if (recursive) {
assertions.add(
span ->
span.hasName(datasource.getClass().getSimpleName() + ".getConnection")
.hasKind(SpanKind.INTERNAL)
.hasParent(trace.getSpan(1))
.hasAttributesSatisfyingExactly(attributesAssertions));
}
trace.hasSpansSatisfyingExactly(assertions);
});
}
Expand Down
Loading