Skip to content

Commit 2c304a5

Browse files
committed
fix covariant return type
1 parent f737744 commit 2c304a5

File tree

3 files changed

+107
-2
lines changed

3 files changed

+107
-2
lines changed

instrumentation/jdbc/javaagent/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ dependencies {
3131
testLibrary("org.apache.tomcat:tomcat-juli:7.0.19")
3232
testLibrary("com.zaxxer:HikariCP:2.4.0")
3333
testLibrary("com.mchange:c3p0:0.9.5")
34+
testLibrary("com.alibaba:druid:1.2.20")
3435

3536
// some classes in earlier versions of derby were split out into derbytools in later versions
3637
latestDepTestLibrary("org.apache.derby:derbytools:latest.release")

instrumentation/jdbc/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jdbc/datasource/DataSourceInstrumentation.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import io.opentelemetry.context.Context;
1414
import io.opentelemetry.context.Scope;
1515
import io.opentelemetry.instrumentation.jdbc.internal.JdbcUtils;
16+
import io.opentelemetry.javaagent.bootstrap.CallDepth;
1617
import io.opentelemetry.javaagent.bootstrap.Java8BytecodeBridge;
1718
import io.opentelemetry.javaagent.bootstrap.jdbc.DbInfo;
1819
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
@@ -44,7 +45,13 @@ public static class GetConnectionAdvice {
4445
public static void start(
4546
@Advice.This DataSource ds,
4647
@Advice.Local("otelContext") Context context,
47-
@Advice.Local("otelScope") Scope scope) {
48+
@Advice.Local("otelScope") Scope scope,
49+
@Advice.Local("otelCallDepth") CallDepth callDepth) {
50+
callDepth = CallDepth.forClass(DataSource.class);
51+
if (callDepth.getAndIncrement() > 0) {
52+
return;
53+
}
54+
4855
Context parentContext = Java8BytecodeBridge.currentContext();
4956
if (!Java8BytecodeBridge.spanFromContext(parentContext).getSpanContext().isValid()) {
5057
// this instrumentation is already very noisy, and calls to getConnection outside of an
@@ -64,7 +71,12 @@ public static void stopSpan(
6471
@Advice.Return Connection connection,
6572
@Advice.Thrown Throwable throwable,
6673
@Advice.Local("otelContext") Context context,
67-
@Advice.Local("otelScope") Scope scope) {
74+
@Advice.Local("otelScope") Scope scope,
75+
@Advice.Local("otelCallDepth") CallDepth callDepth) {
76+
if (callDepth.decrementAndGet() > 0) {
77+
return;
78+
}
79+
6880
if (scope == null) {
6981
return;
7082
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.javaagent.instrumentation.jdbc.test;
7+
8+
import static io.opentelemetry.api.trace.SpanKind.INTERNAL;
9+
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
10+
import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_FUNCTION;
11+
import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_NAMESPACE;
12+
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_NAME;
13+
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_SYSTEM;
14+
import static org.assertj.core.api.Assertions.assertThat;
15+
16+
import com.alibaba.druid.pool.DruidDataSource;
17+
import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
18+
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
19+
import io.opentelemetry.sdk.trace.data.SpanData;
20+
import java.sql.Connection;
21+
import java.sql.SQLException;
22+
import java.util.List;
23+
import java.util.stream.Collectors;
24+
import javax.sql.DataSource;
25+
import org.junit.jupiter.api.AfterEach;
26+
import org.junit.jupiter.api.BeforeEach;
27+
import org.junit.jupiter.api.Test;
28+
import org.junit.jupiter.api.extension.RegisterExtension;
29+
30+
@SuppressWarnings("deprecation") // using deprecated semconv
31+
class DataSourceInstrumentationTest {
32+
33+
@RegisterExtension
34+
static final InstrumentationExtension testing = AgentInstrumentationExtension.create();
35+
36+
private DataSource dataSource;
37+
38+
@BeforeEach
39+
void setUp() {
40+
DruidDataSource druidDataSource = new DruidDataSource();
41+
druidDataSource.setUrl("jdbc:h2:mem:test");
42+
druidDataSource.setDriverClassName("org.h2.Driver");
43+
druidDataSource.setUsername("sa");
44+
druidDataSource.setPassword("");
45+
druidDataSource.setMaxActive(1);
46+
this.dataSource = druidDataSource;
47+
}
48+
49+
@AfterEach
50+
void tearDown() {
51+
if (dataSource instanceof DruidDataSource) {
52+
((DruidDataSource) dataSource).close();
53+
}
54+
}
55+
56+
@Test
57+
void testDruidDataSourceGetConnection() throws SQLException {
58+
testing.runWithSpan(
59+
"parent",
60+
() -> {
61+
try (Connection connection = dataSource.getConnection()) {
62+
return null;
63+
} catch (SQLException e) {
64+
throw new RuntimeException(e);
65+
}
66+
});
67+
68+
testing.waitAndAssertTraces(
69+
trace ->
70+
trace.hasSpansSatisfyingExactly(
71+
span -> span.hasName("parent").hasKind(INTERNAL).hasNoParent(),
72+
span ->
73+
span.hasName("DruidDataSource.getConnection")
74+
.hasKind(INTERNAL)
75+
.hasParent(trace.getSpan(0))
76+
.hasAttributesSatisfying(
77+
equalTo(CODE_NAMESPACE, "com.alibaba.druid.pool.DruidDataSource"),
78+
equalTo(CODE_FUNCTION, "getConnection"),
79+
equalTo(DB_SYSTEM, "h2"),
80+
equalTo(DB_NAME, "test"))));
81+
82+
List<SpanData> spans = testing.spans();
83+
List<SpanData> dataSourceSpans =
84+
spans.stream()
85+
.filter(span -> span.getName().equals("DruidDataSource.getConnection"))
86+
.collect(Collectors.toList());
87+
88+
assertThat(dataSourceSpans)
89+
.as("Should have exactly one DruidDataSource.getConnection span, not duplicates")
90+
.hasSize(1);
91+
}
92+
}

0 commit comments

Comments
 (0)