Skip to content

Commit 223e6aa

Browse files
authored
Camel: don't emit db spans under stable semconv (#16275)
1 parent e206d87 commit 223e6aa

3 files changed

Lines changed: 92 additions & 23 deletions

File tree

instrumentation/camel-2.20/javaagent/build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ dependencies {
3535
testInstrumentation(project(":instrumentation:servlet:servlet-3.0:javaagent"))
3636
testInstrumentation(project(":instrumentation:aws-sdk:aws-sdk-1.11:javaagent"))
3737

38+
testInstrumentation(project(":instrumentation:cassandra:cassandra-3.0:javaagent"))
39+
3840
testImplementation("org.apache.camel:camel-core:$camelversion")
3941
testImplementation("org.apache.camel:camel-spring-boot-starter:$camelversion")
4042
testImplementation("org.apache.camel:camel-jetty-starter:$camelversion")

instrumentation/camel-2.20/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/DbSpanDecorator.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,14 @@ class DbSpanDecorator extends BaseSpanDecorator {
5757
this.system = system;
5858
}
5959

60+
@Override
61+
public boolean shouldStartNewSpan() {
62+
// Under stable database semconv, don't create Camel DB spans. The underlying database
63+
// instrumentations (JDBC, Cassandra, MongoDB, etc.) produce more accurate spans with correct
64+
// db.system.name, connection attributes, and dialect-aware query sanitization.
65+
return !emitStableDatabaseSemconv();
66+
}
67+
6068
@Override
6169
public String getOperationName(
6270
Exchange exchange, Endpoint endpoint, CamelDirection camelDirection) {

instrumentation/camel-2.20/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/apachecamel/decorators/CassandraTest.java

Lines changed: 82 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,18 @@
77

88
import static io.opentelemetry.api.common.AttributeKey.stringKey;
99
import static io.opentelemetry.instrumentation.api.internal.SemconvStability.emitStableDatabaseSemconv;
10-
import static io.opentelemetry.instrumentation.testing.junit.db.SemconvStabilityUtil.maybeStable;
1110
import static io.opentelemetry.javaagent.instrumentation.apachecamel.ExperimentalTest.experimental;
1211
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
12+
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies;
13+
import static io.opentelemetry.semconv.DbAttributes.DB_NAMESPACE;
1314
import static io.opentelemetry.semconv.DbAttributes.DB_QUERY_SUMMARY;
15+
import static io.opentelemetry.semconv.DbAttributes.DB_QUERY_TEXT;
16+
import static io.opentelemetry.semconv.DbAttributes.DB_SYSTEM_NAME;
17+
import static io.opentelemetry.semconv.NetworkAttributes.NETWORK_PEER_ADDRESS;
18+
import static io.opentelemetry.semconv.NetworkAttributes.NETWORK_PEER_PORT;
19+
import static io.opentelemetry.semconv.NetworkAttributes.NETWORK_TYPE;
20+
import static io.opentelemetry.semconv.ServerAttributes.SERVER_ADDRESS;
21+
import static io.opentelemetry.semconv.ServerAttributes.SERVER_PORT;
1422
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_NAME;
1523
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_STATEMENT;
1624
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_SYSTEM;
@@ -109,27 +117,78 @@ void testCassandra() {
109117

110118
template.requestBody("direct:input", (Object) null);
111119

112-
testing.waitAndAssertTraces(
113-
trace ->
114-
trace.hasSpansSatisfyingExactly(
115-
span ->
116-
span.hasKind(SpanKind.INTERNAL)
117-
.hasNoParent()
118-
.hasAttributesSatisfyingExactly(
119-
equalTo(stringKey("camel.uri"), experimental("direct://input"))),
120-
span ->
121-
span.hasKind(SpanKind.CLIENT)
122-
.hasAttributesSatisfyingExactly(
123-
equalTo(
124-
stringKey("camel.uri"),
125-
experimental("cql://" + host + ":" + cassandraPort + "/test")),
126-
equalTo(maybeStable(DB_NAME), "test"),
127-
equalTo(
128-
maybeStable(DB_STATEMENT),
129-
"select * from test.users where id=? ALLOW FILTERING"),
130-
equalTo(
131-
DB_QUERY_SUMMARY,
132-
emitStableDatabaseSemconv() ? "SELECT test.users" : null),
133-
equalTo(maybeStable(DB_SYSTEM), CASSANDRA))));
120+
if (emitStableDatabaseSemconv()) {
121+
testing.waitAndAssertTraces(
122+
trace ->
123+
trace.hasSpansSatisfyingExactly(
124+
span ->
125+
span.hasKind(SpanKind.INTERNAL)
126+
.hasNoParent()
127+
.hasAttributesSatisfyingExactly(
128+
equalTo(stringKey("camel.uri"), experimental("direct://input"))),
129+
span ->
130+
span.hasName("SELECT test.users")
131+
.hasKind(SpanKind.CLIENT)
132+
.hasParent(trace.getSpan(0))
133+
.hasAttributesSatisfyingExactly(
134+
satisfies(NETWORK_TYPE, val -> val.isInstanceOf(String.class)),
135+
equalTo(SERVER_ADDRESS, host),
136+
equalTo(SERVER_PORT, cassandraPort),
137+
satisfies(
138+
NETWORK_PEER_ADDRESS, val -> val.isInstanceOf(String.class)),
139+
equalTo(NETWORK_PEER_PORT, cassandraPort),
140+
equalTo(DB_SYSTEM_NAME, "cassandra"),
141+
equalTo(DB_NAMESPACE, "test"),
142+
equalTo(
143+
DB_QUERY_TEXT,
144+
"select * from test.users where id=1 ALLOW FILTERING"),
145+
equalTo(DB_QUERY_SUMMARY, "SELECT test.users"))),
146+
trace ->
147+
trace.hasSpansSatisfyingExactly(
148+
span ->
149+
span.hasName("USE test")
150+
.hasKind(SpanKind.CLIENT)
151+
.hasAttributesSatisfyingExactly(
152+
satisfies(NETWORK_TYPE, val -> val.isInstanceOf(String.class)),
153+
equalTo(SERVER_ADDRESS, host),
154+
equalTo(SERVER_PORT, cassandraPort),
155+
satisfies(
156+
NETWORK_PEER_ADDRESS, val -> val.isInstanceOf(String.class)),
157+
equalTo(NETWORK_PEER_PORT, cassandraPort),
158+
equalTo(DB_SYSTEM_NAME, "cassandra"),
159+
equalTo(DB_QUERY_TEXT, "USE test"),
160+
equalTo(DB_QUERY_SUMMARY, "USE test"))));
161+
} else {
162+
testing.waitAndAssertTraces(
163+
trace ->
164+
trace.hasSpansSatisfyingExactly(
165+
span ->
166+
span.hasKind(SpanKind.INTERNAL)
167+
.hasNoParent()
168+
.hasAttributesSatisfyingExactly(
169+
equalTo(stringKey("camel.uri"), experimental("direct://input"))),
170+
// Camel's DB span (less accurate)
171+
span ->
172+
span.hasName("cql")
173+
.hasKind(SpanKind.CLIENT)
174+
.hasParent(trace.getSpan(0))
175+
.hasAttributesSatisfyingExactly(
176+
equalTo(
177+
stringKey("camel.uri"),
178+
experimental("cql://" + host + ":" + cassandraPort + "/test")),
179+
equalTo(DB_NAME, "test"),
180+
equalTo(
181+
DB_STATEMENT,
182+
"select * from test.users where id=? ALLOW FILTERING"),
183+
equalTo(DB_SYSTEM, CASSANDRA)),
184+
// Cassandra instrumentation's DB span (more accurate, with connection info)
185+
span ->
186+
span.hasName("SELECT test.users")
187+
.hasKind(SpanKind.CLIENT)
188+
.hasParent(trace.getSpan(1))),
189+
trace ->
190+
trace.hasSpansSatisfyingExactly(
191+
span -> span.hasName("DB Query").hasKind(SpanKind.CLIENT)));
192+
}
134193
}
135194
}

0 commit comments

Comments
 (0)