Skip to content

Commit af3af48

Browse files
committed
Add unit and integration tests for DB exception event extractor
1 parent fcbda86 commit af3af48

25 files changed

Lines changed: 437 additions & 254 deletions

File tree

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.instrumentation.api.incubator.semconv.db.internal;
7+
8+
import static io.opentelemetry.instrumentation.api.internal.SemconvExceptionSignal.emitExceptionAsLogs;
9+
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
10+
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
11+
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies;
12+
import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_MESSAGE;
13+
import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_STACKTRACE;
14+
import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_TYPE;
15+
16+
import io.opentelemetry.api.logs.Severity;
17+
import io.opentelemetry.context.Context;
18+
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
19+
import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder;
20+
import io.opentelemetry.sdk.logs.data.LogRecordData;
21+
import io.opentelemetry.sdk.testing.junit5.OpenTelemetryExtension;
22+
import java.util.List;
23+
import org.assertj.core.api.AbstractAssert;
24+
import org.junit.jupiter.api.Test;
25+
import org.junit.jupiter.api.extension.RegisterExtension;
26+
27+
class DbExceptionEventExtractorsTest {
28+
29+
@RegisterExtension
30+
static final OpenTelemetryExtension otelTesting = OpenTelemetryExtension.create();
31+
32+
@Test
33+
void dbClientExceptionLog() {
34+
InstrumenterBuilder<String, String> builder =
35+
Instrumenter.builder(otelTesting.getOpenTelemetry(), "test", unused -> "span");
36+
DbExceptionEventExtractors.setDbClientExceptionEventExtractor(builder);
37+
Instrumenter<String, String> instrumenter = builder.buildInstrumenter();
38+
39+
Context context = instrumenter.start(Context.root(), "request");
40+
IllegalStateException error = new IllegalStateException("test");
41+
instrumenter.end(context, "request", "response", error);
42+
43+
List<LogRecordData> logs = otelTesting.getLogRecords();
44+
if (emitExceptionAsLogs()) {
45+
assertThat(logs).hasSize(1);
46+
assertThat(logs.get(0))
47+
.hasSeverity(Severity.WARN)
48+
.hasEventName("db.client.operation.exception")
49+
.hasAttributesSatisfyingExactly(
50+
equalTo(EXCEPTION_TYPE, "java.lang.IllegalStateException"),
51+
equalTo(EXCEPTION_MESSAGE, "test"),
52+
satisfies(EXCEPTION_STACKTRACE, AbstractAssert::isNotNull));
53+
} else {
54+
assertThat(logs).isEmpty();
55+
}
56+
}
57+
}

instrumentation/cassandra/cassandra-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/CassandraSingletons.java

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientSpanNameExtractor;
1616
import io.opentelemetry.instrumentation.api.incubator.semconv.db.SqlClientAttributesExtractor;
1717
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
18+
import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder;
1819
import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor;
1920

2021
@SuppressWarnings("deprecation") // using deprecated semconv
@@ -28,22 +29,22 @@ class CassandraSingletons {
2829
static {
2930
CassandraSqlAttributesGetter attributesGetter = new CassandraSqlAttributesGetter();
3031

31-
instrumenter =
32-
setDbClientExceptionEventExtractor(
33-
Instrumenter.<CassandraRequest, ExecutionInfo>builder(
34-
GlobalOpenTelemetry.get(),
35-
INSTRUMENTATION_NAME,
36-
DbClientSpanNameExtractor.create(attributesGetter))
37-
.addAttributesExtractor(
38-
SqlClientAttributesExtractor.builder(attributesGetter)
39-
.setTableAttribute(DB_CASSANDRA_TABLE)
40-
.setQuerySanitizationEnabled(
41-
DbConfig.isQuerySanitizationEnabled(
42-
GlobalOpenTelemetry.get(), "cassandra"))
43-
.build())
44-
.addAttributesExtractor(new CassandraAttributesExtractor())
45-
.addOperationMetrics(DbClientMetrics.get()))
46-
.buildInstrumenter(SpanKindExtractor.alwaysClient());
32+
InstrumenterBuilder<CassandraRequest, ExecutionInfo> builder =
33+
Instrumenter.<CassandraRequest, ExecutionInfo>builder(
34+
GlobalOpenTelemetry.get(),
35+
INSTRUMENTATION_NAME,
36+
DbClientSpanNameExtractor.create(attributesGetter))
37+
.addAttributesExtractor(
38+
SqlClientAttributesExtractor.builder(attributesGetter)
39+
.setTableAttribute(DB_CASSANDRA_TABLE)
40+
.setQuerySanitizationEnabled(
41+
DbConfig.isQuerySanitizationEnabled(GlobalOpenTelemetry.get(), "cassandra"))
42+
.build())
43+
.addAttributesExtractor(new CassandraAttributesExtractor())
44+
.addOperationMetrics(DbClientMetrics.get());
45+
setDbClientExceptionEventExtractor(builder);
46+
47+
instrumenter = builder.buildInstrumenter(SpanKindExtractor.alwaysClient());
4748
}
4849

4950
static Instrumenter<CassandraRequest, ExecutionInfo> instrumenter() {

instrumentation/cassandra/cassandra-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CassandraSingletons.java

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientSpanNameExtractor;
1616
import io.opentelemetry.instrumentation.api.incubator.semconv.db.SqlClientAttributesExtractor;
1717
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
18+
import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder;
1819
import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor;
1920

2021
@SuppressWarnings("deprecation") // using deprecated semconv
@@ -27,22 +28,22 @@ class CassandraSingletons {
2728
static {
2829
CassandraSqlAttributesGetter attributesGetter = new CassandraSqlAttributesGetter();
2930

30-
instrumenter =
31-
setDbClientExceptionEventExtractor(
32-
Instrumenter.<CassandraRequest, ExecutionInfo>builder(
33-
GlobalOpenTelemetry.get(),
34-
INSTRUMENTATION_NAME,
35-
DbClientSpanNameExtractor.create(attributesGetter))
36-
.addAttributesExtractor(
37-
SqlClientAttributesExtractor.builder(attributesGetter)
38-
.setTableAttribute(DB_CASSANDRA_TABLE)
39-
.setQuerySanitizationEnabled(
40-
DbConfig.isQuerySanitizationEnabled(
41-
GlobalOpenTelemetry.get(), "cassandra"))
42-
.build())
43-
.addAttributesExtractor(new CassandraAttributesExtractor())
44-
.addOperationMetrics(DbClientMetrics.get()))
45-
.buildInstrumenter(SpanKindExtractor.alwaysClient());
31+
InstrumenterBuilder<CassandraRequest, ExecutionInfo> builder =
32+
Instrumenter.<CassandraRequest, ExecutionInfo>builder(
33+
GlobalOpenTelemetry.get(),
34+
INSTRUMENTATION_NAME,
35+
DbClientSpanNameExtractor.create(attributesGetter))
36+
.addAttributesExtractor(
37+
SqlClientAttributesExtractor.builder(attributesGetter)
38+
.setTableAttribute(DB_CASSANDRA_TABLE)
39+
.setQuerySanitizationEnabled(
40+
DbConfig.isQuerySanitizationEnabled(GlobalOpenTelemetry.get(), "cassandra"))
41+
.build())
42+
.addAttributesExtractor(new CassandraAttributesExtractor())
43+
.addOperationMetrics(DbClientMetrics.get());
44+
setDbClientExceptionEventExtractor(builder);
45+
46+
instrumenter = builder.buildInstrumenter(SpanKindExtractor.alwaysClient());
4647
}
4748

4849
static Instrumenter<CassandraRequest, ExecutionInfo> instrumenter() {

instrumentation/cassandra/cassandra-4.4/library/src/main/java/io/opentelemetry/instrumentation/cassandra/v4_4/CassandraTelemetryBuilder.java

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientSpanNameExtractor;
1616
import io.opentelemetry.instrumentation.api.incubator.semconv.db.SqlClientAttributesExtractor;
1717
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
18+
import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder;
1819
import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor;
1920

2021
/** A builder of {@link CassandraTelemetry}. */
@@ -58,18 +59,19 @@ private static Instrumenter<CassandraRequest, ExecutionInfo> createInstrumenter(
5859
OpenTelemetry openTelemetry, boolean querySanitizationEnabled) {
5960
CassandraSqlAttributesGetter attributesGetter = new CassandraSqlAttributesGetter();
6061

61-
return setDbClientExceptionEventExtractor(
62-
Instrumenter.<CassandraRequest, ExecutionInfo>builder(
63-
openTelemetry,
64-
INSTRUMENTATION_NAME,
65-
DbClientSpanNameExtractor.create(attributesGetter))
66-
.addAttributesExtractor(
67-
SqlClientAttributesExtractor.builder(attributesGetter)
68-
.setTableAttribute(DB_CASSANDRA_TABLE)
69-
.setQuerySanitizationEnabled(querySanitizationEnabled)
70-
.build())
71-
.addAttributesExtractor(new CassandraAttributesExtractor())
72-
.addOperationMetrics(DbClientMetrics.get()))
73-
.buildInstrumenter(SpanKindExtractor.alwaysClient());
62+
InstrumenterBuilder<CassandraRequest, ExecutionInfo> builder =
63+
Instrumenter.<CassandraRequest, ExecutionInfo>builder(
64+
openTelemetry,
65+
INSTRUMENTATION_NAME,
66+
DbClientSpanNameExtractor.create(attributesGetter))
67+
.addAttributesExtractor(
68+
SqlClientAttributesExtractor.builder(attributesGetter)
69+
.setTableAttribute(DB_CASSANDRA_TABLE)
70+
.setQuerySanitizationEnabled(querySanitizationEnabled)
71+
.build())
72+
.addAttributesExtractor(new CassandraAttributesExtractor())
73+
.addOperationMetrics(DbClientMetrics.get());
74+
setDbClientExceptionEventExtractor(builder);
75+
return builder.buildInstrumenter(SpanKindExtractor.alwaysClient());
7476
}
7577
}

instrumentation/clickhouse/clickhouse-client-common-0.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/clickhouse/client/common/v0_5/ClickHouseInstrumenterFactory.java

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientSpanNameExtractor;
1414
import io.opentelemetry.instrumentation.api.incubator.semconv.db.SqlClientAttributesExtractor;
1515
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
16+
import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder;
1617
import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor;
1718
import java.util.function.Function;
1819

@@ -24,20 +25,21 @@ public static Instrumenter<ClickHouseDbRequest, Void> createInstrumenter(
2425
ClickHouseAttributesGetter dbAttributesGetter =
2526
new ClickHouseAttributesGetter(errorCodeExtractor);
2627

27-
return setDbClientExceptionEventExtractor(
28-
Instrumenter.<ClickHouseDbRequest, Void>builder(
29-
GlobalOpenTelemetry.get(),
30-
instrumenterName,
31-
DbClientSpanNameExtractor.createWithGenericOldSpanName(dbAttributesGetter))
32-
.addAttributesExtractor(
33-
SqlClientAttributesExtractor.builder(dbAttributesGetter)
34-
.setTableAttribute(null)
35-
.setQuerySanitizationEnabled(
36-
DbConfig.isQuerySanitizationEnabled(
37-
GlobalOpenTelemetry.get(), "clickhouse"))
38-
.build())
39-
.addOperationMetrics(DbClientMetrics.get()))
40-
.buildInstrumenter(SpanKindExtractor.alwaysClient());
28+
InstrumenterBuilder<ClickHouseDbRequest, Void> builder =
29+
Instrumenter.<ClickHouseDbRequest, Void>builder(
30+
GlobalOpenTelemetry.get(),
31+
instrumenterName,
32+
DbClientSpanNameExtractor.createWithGenericOldSpanName(dbAttributesGetter))
33+
.addAttributesExtractor(
34+
SqlClientAttributesExtractor.builder(dbAttributesGetter)
35+
.setTableAttribute(null)
36+
.setQuerySanitizationEnabled(
37+
DbConfig.isQuerySanitizationEnabled(
38+
GlobalOpenTelemetry.get(), "clickhouse"))
39+
.build())
40+
.addOperationMetrics(DbClientMetrics.get());
41+
setDbClientExceptionEventExtractor(builder);
42+
return builder.buildInstrumenter(SpanKindExtractor.alwaysClient());
4143
}
4244

4345
private ClickHouseInstrumenterFactory() {}

instrumentation/elasticsearch/elasticsearch-rest-common-5.0/library/src/main/java/io/opentelemetry/instrumentation/elasticsearch/rest/common/v5_0/internal/ElasticsearchRestInstrumenterFactory.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientMetrics;
1313
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
1414
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
15+
import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder;
1516
import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor;
1617
import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor;
1718
import java.util.List;
@@ -43,15 +44,15 @@ public static Instrumenter<ElasticsearchRestRequest, Response> create(
4344
spanNameExtractorTransformer.apply(
4445
new ElasticsearchSpanNameExtractor(dbClientAttributesGetter));
4546

46-
return setDbClientExceptionEventExtractor(
47-
Instrumenter.<ElasticsearchRestRequest, Response>builder(
48-
openTelemetry, instrumentationName, spanNameExtractor)
49-
.addAttributesExtractor(
50-
DbClientAttributesExtractor.create(dbClientAttributesGetter))
51-
.addAttributesExtractor(esClientAttributesExtractor)
52-
.addAttributesExtractors(attributesExtractors)
53-
.addOperationMetrics(DbClientMetrics.get()))
54-
.buildInstrumenter(SpanKindExtractor.alwaysClient());
47+
InstrumenterBuilder<ElasticsearchRestRequest, Response> builder =
48+
Instrumenter.<ElasticsearchRestRequest, Response>builder(
49+
openTelemetry, instrumentationName, spanNameExtractor)
50+
.addAttributesExtractor(DbClientAttributesExtractor.create(dbClientAttributesGetter))
51+
.addAttributesExtractor(esClientAttributesExtractor)
52+
.addAttributesExtractors(attributesExtractors)
53+
.addOperationMetrics(DbClientMetrics.get());
54+
setDbClientExceptionEventExtractor(builder);
55+
return builder.buildInstrumenter(SpanKindExtractor.alwaysClient());
5556
}
5657

5758
private ElasticsearchRestInstrumenterFactory() {}

instrumentation/geode-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/v1_4/GeodeSingletons.java

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientMetrics;
1313
import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientSpanNameExtractor;
1414
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
15+
import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder;
1516
import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor;
1617

1718
class GeodeSingletons {
@@ -22,16 +23,16 @@ class GeodeSingletons {
2223
static {
2324
GeodeDbAttributesGetter dbClientAttributesGetter = new GeodeDbAttributesGetter();
2425

25-
instrumenter =
26-
setDbClientExceptionEventExtractor(
27-
Instrumenter.<GeodeRequest, Void>builder(
28-
GlobalOpenTelemetry.get(),
29-
INSTRUMENTATION_NAME,
30-
DbClientSpanNameExtractor.create(dbClientAttributesGetter))
31-
.addAttributesExtractor(
32-
DbClientAttributesExtractor.create(dbClientAttributesGetter))
33-
.addOperationMetrics(DbClientMetrics.get()))
34-
.buildInstrumenter(SpanKindExtractor.alwaysClient());
26+
InstrumenterBuilder<GeodeRequest, Void> builder =
27+
Instrumenter.<GeodeRequest, Void>builder(
28+
GlobalOpenTelemetry.get(),
29+
INSTRUMENTATION_NAME,
30+
DbClientSpanNameExtractor.create(dbClientAttributesGetter))
31+
.addAttributesExtractor(DbClientAttributesExtractor.create(dbClientAttributesGetter))
32+
.addOperationMetrics(DbClientMetrics.get());
33+
setDbClientExceptionEventExtractor(builder);
34+
35+
instrumenter = builder.buildInstrumenter(SpanKindExtractor.alwaysClient());
3536
}
3637

3738
static Instrumenter<GeodeRequest, Void> instrumenter() {

instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbSingletons.java

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientSpanNameExtractor;
1313
import io.opentelemetry.instrumentation.api.incubator.semconv.db.SqlClientAttributesExtractor;
1414
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
15+
import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder;
1516
import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor;
1617

1718
@SuppressWarnings("deprecation") // to support old semconv
@@ -22,18 +23,19 @@ public class InfluxDbSingletons {
2223
static {
2324
InfluxDbAttributesGetter dbAttributesGetter = new InfluxDbAttributesGetter();
2425

25-
instrumenter =
26-
setDbClientExceptionEventExtractor(
27-
Instrumenter.<InfluxDbRequest, Void>builder(
28-
GlobalOpenTelemetry.get(),
29-
"io.opentelemetry.influxdb-2.4",
30-
DbClientSpanNameExtractor.createWithGenericOldSpanName(dbAttributesGetter))
31-
.addAttributesExtractor(
32-
SqlClientAttributesExtractor.builder(dbAttributesGetter)
33-
.setTableAttribute(null)
34-
.build())
35-
.addOperationMetrics(DbClientMetrics.get()))
36-
.buildInstrumenter(SpanKindExtractor.alwaysClient());
26+
InstrumenterBuilder<InfluxDbRequest, Void> builder =
27+
Instrumenter.<InfluxDbRequest, Void>builder(
28+
GlobalOpenTelemetry.get(),
29+
"io.opentelemetry.influxdb-2.4",
30+
DbClientSpanNameExtractor.createWithGenericOldSpanName(dbAttributesGetter))
31+
.addAttributesExtractor(
32+
SqlClientAttributesExtractor.builder(dbAttributesGetter)
33+
.setTableAttribute(null)
34+
.build())
35+
.addOperationMetrics(DbClientMetrics.get());
36+
setDbClientExceptionEventExtractor(builder);
37+
38+
instrumenter = builder.buildInstrumenter(SpanKindExtractor.alwaysClient());
3739
}
3840

3941
public static Instrumenter<InfluxDbRequest, Void> instrumenter() {

instrumentation/jdbc/javaagent/build.gradle.kts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,20 @@ tasks {
111111
jvmArgs("-Dotel.instrumentation.jdbc.experimental.capture-query-parameters=true")
112112
}
113113

114+
val testExceptionSignalLogs by registering(Test::class) {
115+
testClassesDirs = sourceSets.test.get().output.classesDirs
116+
classpath = sourceSets.test.get().runtimeClasspath
117+
118+
filter {
119+
excludeTestsMatching("SlickTest")
120+
excludeTestsMatching("SqlCommenterTest")
121+
excludeTestsMatching("PreparedStatementParametersTest")
122+
}
123+
jvmArgs("-Dotel.instrumentation.jdbc-datasource.enabled=true")
124+
jvmArgs("-Dotel.semconv.exception.signal.preview=logs")
125+
systemProperty("metadataConfig", "otel.semconv.exception.signal.preview=logs")
126+
}
127+
114128
test {
115129
filter {
116130
excludeTestsMatching("SlickTest")
@@ -126,6 +140,7 @@ tasks {
126140
dependsOn(testStableSemconv)
127141
dependsOn(testSlickStableSemconv)
128142
dependsOn(testCaptureParameters)
143+
dependsOn(testExceptionSignalLogs)
129144
}
130145
}
131146

instrumentation/jdbc/library/build.gradle.kts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,15 @@ tasks {
7070
jvmArgs("-Dotel.semconv-stability.opt-in=database")
7171
}
7272

73+
val testExceptionSignalLogs by registering(Test::class) {
74+
testClassesDirs = sourceSets.test.get().output.classesDirs
75+
classpath = sourceSets.test.get().runtimeClasspath
76+
77+
jvmArgs("-Dotel.semconv.exception.signal.preview=logs")
78+
}
79+
7380
check {
74-
dependsOn(testStableSemconv)
81+
dependsOn(testStableSemconv, testExceptionSignalLogs)
7582
}
7683
}
7784

0 commit comments

Comments
 (0)