From ab9aecc537e44327effffb10dbcf58e33ad27535 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Wed, 3 Jun 2026 11:28:33 -0700 Subject: [PATCH 1/9] Add DB exception event extractor helper --- .../internal/DbExceptionEventExtractors.java | 38 +++++++++++++ .../cassandra/v3_0/CassandraSingletons.java | 27 +++++---- .../cassandra/v4_0/CassandraSingletons.java | 27 +++++---- .../v4_4/CassandraTelemetryBuilder.java | 23 +++++--- .../v0_5/ClickHouseInstrumenterFactory.java | 26 +++++---- .../couchbase/v2_0/CouchbaseSingletons.java | 3 + .../ElasticsearchRestInstrumenterFactory.java | 16 ++++-- ...ticsearchTransportInstrumenterFactory.java | 3 + .../geode/v1_4/GeodeSingletons.java | 16 ++++-- .../influxdb/v2_4/InfluxDbSingletons.java | 21 ++++--- .../internal/JdbcInstrumenterFactory.java | 22 ++++---- .../jedis/v1_4/JedisSingletons.java | 21 ++++--- .../jedis/v3_0/JedisSingletons.java | 21 ++++--- .../jedis/v4_0/JedisSingletons.java | 15 +++-- .../lettuce/v4_0/LettuceSingletons.java | 15 +++-- .../lettuce/v5_0/LettuceSingletons.java | 15 +++-- .../lettuce/v5_1/LettuceTelemetryBuilder.java | 32 ++++++----- .../internal/MongoInstrumenterFactory.java | 13 +++-- .../opensearch/v3_0/OpenSearchSingletons.java | 16 ++++-- .../OpenSearchRestInstrumenterFactory.java | 16 ++++-- .../internal/R2dbcInstrumenterBuilder.java | 19 ++++--- .../rediscala/v1_8/RediscalaSingletons.java | 15 +++-- .../v3_0/RedissonInstrumenterFactory.java | 15 +++-- .../v2_12/SpymemcachedSingletons.java | 56 ++++++++++--------- .../v4_0/VertxRedisClientSingletons.java | 3 + .../v4_0/VertxSqlInstrumenterFactory.java | 3 + 26 files changed, 309 insertions(+), 188 deletions(-) create mode 100644 instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/internal/DbExceptionEventExtractors.java diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/internal/DbExceptionEventExtractors.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/internal/DbExceptionEventExtractors.java new file mode 100644 index 000000000000..1afb5a41db2c --- /dev/null +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/internal/DbExceptionEventExtractors.java @@ -0,0 +1,38 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.api.incubator.semconv.db.internal; + +import com.google.errorprone.annotations.CanIgnoreReturnValue; +import io.opentelemetry.api.logs.Severity; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; +import io.opentelemetry.instrumentation.api.internal.Experimental; + +/** + * This class is internal and is hence not for public use. Its APIs are unstable and can change at + * any time. + */ +public final class DbExceptionEventExtractors { + + /** + * Configures the database client exception event name and severity. Only takes effect when + * emitting exceptions as logs is enabled via the {@code otel.semconv.exception.signal.preview} + * flag. + */ + @CanIgnoreReturnValue + public static + InstrumenterBuilder setDbClientExceptionEventExtractor( + InstrumenterBuilder builder) { + Experimental.setExceptionEventExtractor( + builder, + (logRecordBuilder, context, request) -> { + logRecordBuilder.setEventName("db.client.operation.exception"); + logRecordBuilder.setSeverity(Severity.WARN); + }); + return builder; + } + + private DbExceptionEventExtractors() {} +} diff --git a/instrumentation/cassandra/cassandra-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/CassandraSingletons.java b/instrumentation/cassandra/cassandra-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/CassandraSingletons.java index 79003ff1ae59..460bac5bb79c 100644 --- a/instrumentation/cassandra/cassandra-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/CassandraSingletons.java +++ b/instrumentation/cassandra/cassandra-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/CassandraSingletons.java @@ -5,6 +5,7 @@ package io.opentelemetry.javaagent.instrumentation.cassandra.v3_0; +import static io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.DbExceptionEventExtractors.setDbClientExceptionEventExtractor; import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_CASSANDRA_TABLE; import com.datastax.driver.core.ExecutionInfo; @@ -28,18 +29,20 @@ class CassandraSingletons { CassandraSqlAttributesGetter attributesGetter = new CassandraSqlAttributesGetter(); instrumenter = - Instrumenter.builder( - GlobalOpenTelemetry.get(), - INSTRUMENTATION_NAME, - DbClientSpanNameExtractor.create(attributesGetter)) - .addAttributesExtractor( - SqlClientAttributesExtractor.builder(attributesGetter) - .setTableAttribute(DB_CASSANDRA_TABLE) - .setQuerySanitizationEnabled( - DbConfig.isQuerySanitizationEnabled(GlobalOpenTelemetry.get(), "cassandra")) - .build()) - .addAttributesExtractor(new CassandraAttributesExtractor()) - .addOperationMetrics(DbClientMetrics.get()) + setDbClientExceptionEventExtractor( + Instrumenter.builder( + GlobalOpenTelemetry.get(), + INSTRUMENTATION_NAME, + DbClientSpanNameExtractor.create(attributesGetter)) + .addAttributesExtractor( + SqlClientAttributesExtractor.builder(attributesGetter) + .setTableAttribute(DB_CASSANDRA_TABLE) + .setQuerySanitizationEnabled( + DbConfig.isQuerySanitizationEnabled( + GlobalOpenTelemetry.get(), "cassandra")) + .build()) + .addAttributesExtractor(new CassandraAttributesExtractor()) + .addOperationMetrics(DbClientMetrics.get())) .buildInstrumenter(SpanKindExtractor.alwaysClient()); } diff --git a/instrumentation/cassandra/cassandra-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CassandraSingletons.java b/instrumentation/cassandra/cassandra-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CassandraSingletons.java index 7da20c9df516..71ec59baf9fa 100644 --- a/instrumentation/cassandra/cassandra-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CassandraSingletons.java +++ b/instrumentation/cassandra/cassandra-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CassandraSingletons.java @@ -5,6 +5,7 @@ package io.opentelemetry.javaagent.instrumentation.cassandra.v4_0; +import static io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.DbExceptionEventExtractors.setDbClientExceptionEventExtractor; import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_CASSANDRA_TABLE; import com.datastax.oss.driver.api.core.cql.ExecutionInfo; @@ -27,18 +28,20 @@ class CassandraSingletons { CassandraSqlAttributesGetter attributesGetter = new CassandraSqlAttributesGetter(); instrumenter = - Instrumenter.builder( - GlobalOpenTelemetry.get(), - INSTRUMENTATION_NAME, - DbClientSpanNameExtractor.create(attributesGetter)) - .addAttributesExtractor( - SqlClientAttributesExtractor.builder(attributesGetter) - .setTableAttribute(DB_CASSANDRA_TABLE) - .setQuerySanitizationEnabled( - DbConfig.isQuerySanitizationEnabled(GlobalOpenTelemetry.get(), "cassandra")) - .build()) - .addAttributesExtractor(new CassandraAttributesExtractor()) - .addOperationMetrics(DbClientMetrics.get()) + setDbClientExceptionEventExtractor( + Instrumenter.builder( + GlobalOpenTelemetry.get(), + INSTRUMENTATION_NAME, + DbClientSpanNameExtractor.create(attributesGetter)) + .addAttributesExtractor( + SqlClientAttributesExtractor.builder(attributesGetter) + .setTableAttribute(DB_CASSANDRA_TABLE) + .setQuerySanitizationEnabled( + DbConfig.isQuerySanitizationEnabled( + GlobalOpenTelemetry.get(), "cassandra")) + .build()) + .addAttributesExtractor(new CassandraAttributesExtractor()) + .addOperationMetrics(DbClientMetrics.get())) .buildInstrumenter(SpanKindExtractor.alwaysClient()); } diff --git a/instrumentation/cassandra/cassandra-4.4/library/src/main/java/io/opentelemetry/instrumentation/cassandra/v4_4/CassandraTelemetryBuilder.java b/instrumentation/cassandra/cassandra-4.4/library/src/main/java/io/opentelemetry/instrumentation/cassandra/v4_4/CassandraTelemetryBuilder.java index 0ff155074333..89eeb6141bb7 100644 --- a/instrumentation/cassandra/cassandra-4.4/library/src/main/java/io/opentelemetry/instrumentation/cassandra/v4_4/CassandraTelemetryBuilder.java +++ b/instrumentation/cassandra/cassandra-4.4/library/src/main/java/io/opentelemetry/instrumentation/cassandra/v4_4/CassandraTelemetryBuilder.java @@ -5,6 +5,8 @@ package io.opentelemetry.instrumentation.cassandra.v4_4; +import static io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.DbExceptionEventExtractors.setDbClientExceptionEventExtractor; + import com.datastax.oss.driver.api.core.cql.ExecutionInfo; import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.opentelemetry.api.OpenTelemetry; @@ -56,15 +58,18 @@ private static Instrumenter createInstrumenter( OpenTelemetry openTelemetry, boolean querySanitizationEnabled) { CassandraSqlAttributesGetter attributesGetter = new CassandraSqlAttributesGetter(); - return Instrumenter.builder( - openTelemetry, INSTRUMENTATION_NAME, DbClientSpanNameExtractor.create(attributesGetter)) - .addAttributesExtractor( - SqlClientAttributesExtractor.builder(attributesGetter) - .setTableAttribute(DB_CASSANDRA_TABLE) - .setQuerySanitizationEnabled(querySanitizationEnabled) - .build()) - .addAttributesExtractor(new CassandraAttributesExtractor()) - .addOperationMetrics(DbClientMetrics.get()) + return setDbClientExceptionEventExtractor( + Instrumenter.builder( + openTelemetry, + INSTRUMENTATION_NAME, + DbClientSpanNameExtractor.create(attributesGetter)) + .addAttributesExtractor( + SqlClientAttributesExtractor.builder(attributesGetter) + .setTableAttribute(DB_CASSANDRA_TABLE) + .setQuerySanitizationEnabled(querySanitizationEnabled) + .build()) + .addAttributesExtractor(new CassandraAttributesExtractor()) + .addOperationMetrics(DbClientMetrics.get())) .buildInstrumenter(SpanKindExtractor.alwaysClient()); } } diff --git a/instrumentation/clickhouse/clickhouse-client-common-0.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/clickhouse/client/common/v0_5/ClickHouseInstrumenterFactory.java b/instrumentation/clickhouse/clickhouse-client-common-0.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/clickhouse/client/common/v0_5/ClickHouseInstrumenterFactory.java index 2c733386380b..d6588e563164 100644 --- a/instrumentation/clickhouse/clickhouse-client-common-0.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/clickhouse/client/common/v0_5/ClickHouseInstrumenterFactory.java +++ b/instrumentation/clickhouse/clickhouse-client-common-0.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/clickhouse/client/common/v0_5/ClickHouseInstrumenterFactory.java @@ -5,6 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.clickhouse.client.common.v0_5; +import static io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.DbExceptionEventExtractors.setDbClientExceptionEventExtractor; + import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.api.incubator.config.internal.DbConfig; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientMetrics; @@ -22,17 +24,19 @@ public static Instrumenter createInstrumenter( ClickHouseAttributesGetter dbAttributesGetter = new ClickHouseAttributesGetter(errorCodeExtractor); - return Instrumenter.builder( - GlobalOpenTelemetry.get(), - instrumenterName, - DbClientSpanNameExtractor.createWithGenericOldSpanName(dbAttributesGetter)) - .addAttributesExtractor( - SqlClientAttributesExtractor.builder(dbAttributesGetter) - .setTableAttribute(null) - .setQuerySanitizationEnabled( - DbConfig.isQuerySanitizationEnabled(GlobalOpenTelemetry.get(), "clickhouse")) - .build()) - .addOperationMetrics(DbClientMetrics.get()) + return setDbClientExceptionEventExtractor( + Instrumenter.builder( + GlobalOpenTelemetry.get(), + instrumenterName, + DbClientSpanNameExtractor.createWithGenericOldSpanName(dbAttributesGetter)) + .addAttributesExtractor( + SqlClientAttributesExtractor.builder(dbAttributesGetter) + .setTableAttribute(null) + .setQuerySanitizationEnabled( + DbConfig.isQuerySanitizationEnabled( + GlobalOpenTelemetry.get(), "clickhouse")) + .build()) + .addOperationMetrics(DbClientMetrics.get())) .buildInstrumenter(SpanKindExtractor.alwaysClient()); } diff --git a/instrumentation/couchbase/couchbase-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseSingletons.java b/instrumentation/couchbase/couchbase-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseSingletons.java index f259ae27b43f..f45d52c557bd 100644 --- a/instrumentation/couchbase/couchbase-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseSingletons.java +++ b/instrumentation/couchbase/couchbase-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseSingletons.java @@ -5,6 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.couchbase.v2_0; +import static io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.DbExceptionEventExtractors.setDbClientExceptionEventExtractor; + import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientAttributesExtractor; @@ -35,6 +37,7 @@ public class CouchbaseSingletons { (context, couchbaseRequest, startAttributes) -> CouchbaseRequestInfo.init(context, couchbaseRequest)) .addOperationMetrics(DbClientMetrics.get()); + setDbClientExceptionEventExtractor(builder); if (DeclarativeConfigUtil.getInstrumentationConfig(GlobalOpenTelemetry.get(), "couchbase") .getBoolean("experimental_span_attributes/development", false)) { diff --git a/instrumentation/elasticsearch/elasticsearch-rest-common-5.0/library/src/main/java/io/opentelemetry/instrumentation/elasticsearch/rest/common/v5_0/internal/ElasticsearchRestInstrumenterFactory.java b/instrumentation/elasticsearch/elasticsearch-rest-common-5.0/library/src/main/java/io/opentelemetry/instrumentation/elasticsearch/rest/common/v5_0/internal/ElasticsearchRestInstrumenterFactory.java index 47472b9625d1..9d3071312307 100644 --- a/instrumentation/elasticsearch/elasticsearch-rest-common-5.0/library/src/main/java/io/opentelemetry/instrumentation/elasticsearch/rest/common/v5_0/internal/ElasticsearchRestInstrumenterFactory.java +++ b/instrumentation/elasticsearch/elasticsearch-rest-common-5.0/library/src/main/java/io/opentelemetry/instrumentation/elasticsearch/rest/common/v5_0/internal/ElasticsearchRestInstrumenterFactory.java @@ -5,6 +5,8 @@ package io.opentelemetry.instrumentation.elasticsearch.rest.common.v5_0.internal; +import static io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.DbExceptionEventExtractors.setDbClientExceptionEventExtractor; + import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientAttributesExtractor; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientMetrics; @@ -41,12 +43,14 @@ public static Instrumenter create( spanNameExtractorTransformer.apply( new ElasticsearchSpanNameExtractor(dbClientAttributesGetter)); - return Instrumenter.builder( - openTelemetry, instrumentationName, spanNameExtractor) - .addAttributesExtractor(DbClientAttributesExtractor.create(dbClientAttributesGetter)) - .addAttributesExtractor(esClientAttributesExtractor) - .addAttributesExtractors(attributesExtractors) - .addOperationMetrics(DbClientMetrics.get()) + return setDbClientExceptionEventExtractor( + Instrumenter.builder( + openTelemetry, instrumentationName, spanNameExtractor) + .addAttributesExtractor( + DbClientAttributesExtractor.create(dbClientAttributesGetter)) + .addAttributesExtractor(esClientAttributesExtractor) + .addAttributesExtractors(attributesExtractors) + .addOperationMetrics(DbClientMetrics.get())) .buildInstrumenter(SpanKindExtractor.alwaysClient()); } diff --git a/instrumentation/elasticsearch/elasticsearch-transport-common-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/common/v5_0/ElasticsearchTransportInstrumenterFactory.java b/instrumentation/elasticsearch/elasticsearch-transport-common-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/common/v5_0/ElasticsearchTransportInstrumenterFactory.java index 80af6012b450..b5ffc9bf0d72 100644 --- a/instrumentation/elasticsearch/elasticsearch-transport-common-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/common/v5_0/ElasticsearchTransportInstrumenterFactory.java +++ b/instrumentation/elasticsearch/elasticsearch-transport-common-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/common/v5_0/ElasticsearchTransportInstrumenterFactory.java @@ -5,6 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.elasticsearch.transport.common.v5_0; +import static io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.DbExceptionEventExtractors.setDbClientExceptionEventExtractor; + import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientAttributesExtractor; @@ -33,6 +35,7 @@ public static Instrumenter create( DbClientSpanNameExtractor.create(dbClientAttributesGetter)) .addAttributesExtractor(DbClientAttributesExtractor.create(dbClientAttributesGetter)) .addOperationMetrics(DbClientMetrics.get()); + setDbClientExceptionEventExtractor(instrumenterBuilder); if (CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES) { instrumenterBuilder.addAttributesExtractor(experimentalAttributesExtractor); diff --git a/instrumentation/geode-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/v1_4/GeodeSingletons.java b/instrumentation/geode-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/v1_4/GeodeSingletons.java index 3ac3cb9f3514..c9f01e6352be 100644 --- a/instrumentation/geode-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/v1_4/GeodeSingletons.java +++ b/instrumentation/geode-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/v1_4/GeodeSingletons.java @@ -5,6 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.geode.v1_4; +import static io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.DbExceptionEventExtractors.setDbClientExceptionEventExtractor; + import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientAttributesExtractor; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientMetrics; @@ -21,12 +23,14 @@ class GeodeSingletons { GeodeDbAttributesGetter dbClientAttributesGetter = new GeodeDbAttributesGetter(); instrumenter = - Instrumenter.builder( - GlobalOpenTelemetry.get(), - INSTRUMENTATION_NAME, - DbClientSpanNameExtractor.create(dbClientAttributesGetter)) - .addAttributesExtractor(DbClientAttributesExtractor.create(dbClientAttributesGetter)) - .addOperationMetrics(DbClientMetrics.get()) + setDbClientExceptionEventExtractor( + Instrumenter.builder( + GlobalOpenTelemetry.get(), + INSTRUMENTATION_NAME, + DbClientSpanNameExtractor.create(dbClientAttributesGetter)) + .addAttributesExtractor( + DbClientAttributesExtractor.create(dbClientAttributesGetter)) + .addOperationMetrics(DbClientMetrics.get())) .buildInstrumenter(SpanKindExtractor.alwaysClient()); } diff --git a/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbSingletons.java b/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbSingletons.java index ad808080c725..8d039cce6d22 100644 --- a/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbSingletons.java +++ b/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbSingletons.java @@ -5,6 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.influxdb.v2_4; +import static io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.DbExceptionEventExtractors.setDbClientExceptionEventExtractor; + import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientMetrics; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientSpanNameExtractor; @@ -21,15 +23,16 @@ public class InfluxDbSingletons { InfluxDbAttributesGetter dbAttributesGetter = new InfluxDbAttributesGetter(); instrumenter = - Instrumenter.builder( - GlobalOpenTelemetry.get(), - "io.opentelemetry.influxdb-2.4", - DbClientSpanNameExtractor.createWithGenericOldSpanName(dbAttributesGetter)) - .addAttributesExtractor( - SqlClientAttributesExtractor.builder(dbAttributesGetter) - .setTableAttribute(null) - .build()) - .addOperationMetrics(DbClientMetrics.get()) + setDbClientExceptionEventExtractor( + Instrumenter.builder( + GlobalOpenTelemetry.get(), + "io.opentelemetry.influxdb-2.4", + DbClientSpanNameExtractor.createWithGenericOldSpanName(dbAttributesGetter)) + .addAttributesExtractor( + SqlClientAttributesExtractor.builder(dbAttributesGetter) + .setTableAttribute(null) + .build()) + .addOperationMetrics(DbClientMetrics.get())) .buildInstrumenter(SpanKindExtractor.alwaysClient()); } diff --git a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcInstrumenterFactory.java b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcInstrumenterFactory.java index 4be6d9265775..2236e8b28540 100644 --- a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcInstrumenterFactory.java +++ b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcInstrumenterFactory.java @@ -5,6 +5,7 @@ package io.opentelemetry.instrumentation.jdbc.internal; +import static io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.DbExceptionEventExtractors.setDbClientExceptionEventExtractor; import static java.util.Collections.emptyList; import io.opentelemetry.api.OpenTelemetry; @@ -74,16 +75,17 @@ public static Instrumenter createStatementInstrumenter( boolean querySanitizationEnabled, boolean captureQueryParameters) { JdbcAttributesGetter getter = new JdbcAttributesGetter(); - return Instrumenter.builder( - openTelemetry, INSTRUMENTATION_NAME, DbClientSpanNameExtractor.create(getter)) - .addAttributesExtractor( - SqlClientAttributesExtractor.builder(getter) - .setQuerySanitizationEnabled(querySanitizationEnabled) - .setCaptureQueryParameters(captureQueryParameters) - .build()) - .addAttributesExtractors(extractors) - .addOperationMetrics(DbClientMetrics.get()) - .setEnabled(enabled) + return setDbClientExceptionEventExtractor( + Instrumenter.builder( + openTelemetry, INSTRUMENTATION_NAME, DbClientSpanNameExtractor.create(getter)) + .addAttributesExtractor( + SqlClientAttributesExtractor.builder(getter) + .setQuerySanitizationEnabled(querySanitizationEnabled) + .setCaptureQueryParameters(captureQueryParameters) + .build()) + .addAttributesExtractors(extractors) + .addOperationMetrics(DbClientMetrics.get()) + .setEnabled(enabled)) .buildInstrumenter(SpanKindExtractor.alwaysClient()); } diff --git a/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisSingletons.java b/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisSingletons.java index bc2f19485b71..f35def02ff16 100644 --- a/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisSingletons.java +++ b/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisSingletons.java @@ -5,6 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.jedis.v1_4; +import static io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.DbExceptionEventExtractors.setDbClientExceptionEventExtractor; + import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientAttributesExtractor; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientMetrics; @@ -22,15 +24,16 @@ class JedisSingletons { JedisDbAttributesGetter dbAttributesGetter = new JedisDbAttributesGetter(); instrumenter = - Instrumenter.builder( - GlobalOpenTelemetry.get(), - INSTRUMENTATION_NAME, - DbClientSpanNameExtractor.create(dbAttributesGetter)) - .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) - .addAttributesExtractor( - ServicePeerAttributesExtractor.create( - dbAttributesGetter, GlobalOpenTelemetry.get())) - .addOperationMetrics(DbClientMetrics.get()) + setDbClientExceptionEventExtractor( + Instrumenter.builder( + GlobalOpenTelemetry.get(), + INSTRUMENTATION_NAME, + DbClientSpanNameExtractor.create(dbAttributesGetter)) + .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) + .addAttributesExtractor( + ServicePeerAttributesExtractor.create( + dbAttributesGetter, GlobalOpenTelemetry.get())) + .addOperationMetrics(DbClientMetrics.get())) .buildInstrumenter(SpanKindExtractor.alwaysClient()); } diff --git a/instrumentation/jedis/jedis-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v3_0/JedisSingletons.java b/instrumentation/jedis/jedis-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v3_0/JedisSingletons.java index 9eecfbdcbbfe..4167c755c317 100644 --- a/instrumentation/jedis/jedis-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v3_0/JedisSingletons.java +++ b/instrumentation/jedis/jedis-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v3_0/JedisSingletons.java @@ -5,6 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.jedis.v3_0; +import static io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.DbExceptionEventExtractors.setDbClientExceptionEventExtractor; + import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientAttributesExtractor; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientMetrics; @@ -22,15 +24,16 @@ public class JedisSingletons { JedisDbAttributesGetter dbAttributesGetter = new JedisDbAttributesGetter(); instrumenter = - Instrumenter.builder( - GlobalOpenTelemetry.get(), - INSTRUMENTATION_NAME, - DbClientSpanNameExtractor.create(dbAttributesGetter)) - .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) - .addAttributesExtractor( - ServicePeerAttributesExtractor.create( - dbAttributesGetter, GlobalOpenTelemetry.get())) - .addOperationMetrics(DbClientMetrics.get()) + setDbClientExceptionEventExtractor( + Instrumenter.builder( + GlobalOpenTelemetry.get(), + INSTRUMENTATION_NAME, + DbClientSpanNameExtractor.create(dbAttributesGetter)) + .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) + .addAttributesExtractor( + ServicePeerAttributesExtractor.create( + dbAttributesGetter, GlobalOpenTelemetry.get())) + .addOperationMetrics(DbClientMetrics.get())) .buildInstrumenter(SpanKindExtractor.alwaysClient()); } diff --git a/instrumentation/jedis/jedis-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v4_0/JedisSingletons.java b/instrumentation/jedis/jedis-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v4_0/JedisSingletons.java index 6c8b68ee78d2..82332557e7c2 100644 --- a/instrumentation/jedis/jedis-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v4_0/JedisSingletons.java +++ b/instrumentation/jedis/jedis-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v4_0/JedisSingletons.java @@ -5,6 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.jedis.v4_0; +import static io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.DbExceptionEventExtractors.setDbClientExceptionEventExtractor; + import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientAttributesExtractor; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientMetrics; @@ -21,12 +23,13 @@ public class JedisSingletons { JedisDbAttributesGetter dbAttributesGetter = new JedisDbAttributesGetter(); instrumenter = - Instrumenter.builder( - GlobalOpenTelemetry.get(), - INSTRUMENTATION_NAME, - DbClientSpanNameExtractor.create(dbAttributesGetter)) - .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) - .addOperationMetrics(DbClientMetrics.get()) + setDbClientExceptionEventExtractor( + Instrumenter.builder( + GlobalOpenTelemetry.get(), + INSTRUMENTATION_NAME, + DbClientSpanNameExtractor.create(dbAttributesGetter)) + .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) + .addOperationMetrics(DbClientMetrics.get())) .buildInstrumenter(SpanKindExtractor.alwaysClient()); } diff --git a/instrumentation/lettuce/lettuce-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceSingletons.java b/instrumentation/lettuce/lettuce-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceSingletons.java index fe9e70dc6ae1..04b6dc823ce2 100644 --- a/instrumentation/lettuce/lettuce-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceSingletons.java +++ b/instrumentation/lettuce/lettuce-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceSingletons.java @@ -5,6 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.lettuce.v4_0; +import static io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.DbExceptionEventExtractors.setDbClientExceptionEventExtractor; + import com.lambdaworks.redis.RedisURI; import com.lambdaworks.redis.protocol.AsyncCommand; import com.lambdaworks.redis.protocol.RedisCommand; @@ -37,12 +39,13 @@ public class LettuceSingletons { LettuceDbAttributesGetter dbAttributesGetter = new LettuceDbAttributesGetter(); instrumenter = - Instrumenter., Void>builder( - GlobalOpenTelemetry.get(), - INSTRUMENTATION_NAME, - DbClientSpanNameExtractor.create(dbAttributesGetter)) - .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) - .addOperationMetrics(DbClientMetrics.get()) + setDbClientExceptionEventExtractor( + Instrumenter., Void>builder( + GlobalOpenTelemetry.get(), + INSTRUMENTATION_NAME, + DbClientSpanNameExtractor.create(dbAttributesGetter)) + .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) + .addOperationMetrics(DbClientMetrics.get())) .buildInstrumenter(SpanKindExtractor.alwaysClient()); LettuceConnectNetworkAttributesGetter netAttributesGetter = diff --git a/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceSingletons.java b/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceSingletons.java index bd95b9a73c96..7d26171f0d39 100644 --- a/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceSingletons.java +++ b/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceSingletons.java @@ -5,6 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.lettuce.v5_0; +import static io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.DbExceptionEventExtractors.setDbClientExceptionEventExtractor; + import io.lettuce.core.RedisURI; import io.lettuce.core.protocol.AsyncCommand; import io.lettuce.core.protocol.RedisCommand; @@ -37,12 +39,13 @@ public class LettuceSingletons { LettuceDbAttributesGetter dbAttributesGetter = new LettuceDbAttributesGetter(); instrumenter = - Instrumenter., Void>builder( - GlobalOpenTelemetry.get(), - INSTRUMENTATION_NAME, - DbClientSpanNameExtractor.create(dbAttributesGetter)) - .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) - .addOperationMetrics(DbClientMetrics.get()) + setDbClientExceptionEventExtractor( + Instrumenter., Void>builder( + GlobalOpenTelemetry.get(), + INSTRUMENTATION_NAME, + DbClientSpanNameExtractor.create(dbAttributesGetter)) + .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) + .addOperationMetrics(DbClientMetrics.get())) .buildInstrumenter(SpanKindExtractor.alwaysClient()); LettuceConnectNetworkAttributesGetter connectNetworkAttributesGetter = diff --git a/instrumentation/lettuce/lettuce-5.1/library/src/main/java/io/opentelemetry/instrumentation/lettuce/v5_1/LettuceTelemetryBuilder.java b/instrumentation/lettuce/lettuce-5.1/library/src/main/java/io/opentelemetry/instrumentation/lettuce/v5_1/LettuceTelemetryBuilder.java index 201b1d227f8d..22d6d5218940 100644 --- a/instrumentation/lettuce/lettuce-5.1/library/src/main/java/io/opentelemetry/instrumentation/lettuce/v5_1/LettuceTelemetryBuilder.java +++ b/instrumentation/lettuce/lettuce-5.1/library/src/main/java/io/opentelemetry/instrumentation/lettuce/v5_1/LettuceTelemetryBuilder.java @@ -5,6 +5,7 @@ package io.opentelemetry.instrumentation.lettuce.v5_1; +import static io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.DbExceptionEventExtractors.setDbClientExceptionEventExtractor; import static io.opentelemetry.instrumentation.lettuce.v5_1.LettuceTelemetry.INSTRUMENTATION_NAME; import com.google.errorprone.annotations.CanIgnoreReturnValue; @@ -59,21 +60,22 @@ public LettuceTelemetry build() { LettuceDbAttributesGetter dbAttributesGetter = new LettuceDbAttributesGetter(); Instrumenter instrumenter = - Instrumenter.builder( - openTelemetry, - INSTRUMENTATION_NAME, - DbClientSpanNameExtractor.create(dbAttributesGetter)) - .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) - .addOperationMetrics(DbClientMetrics.get()) - .setSpanStatusExtractor( - (spanStatusBuilder, request, response, error) -> { - if (response != null && response.getErrorMessage() != null) { - spanStatusBuilder.setStatus(StatusCode.ERROR); - } else { - SpanStatusExtractor.getDefault() - .extract(spanStatusBuilder, request, response, error); - } - }) + setDbClientExceptionEventExtractor( + Instrumenter.builder( + openTelemetry, + INSTRUMENTATION_NAME, + DbClientSpanNameExtractor.create(dbAttributesGetter)) + .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) + .addOperationMetrics(DbClientMetrics.get()) + .setSpanStatusExtractor( + (spanStatusBuilder, request, response, error) -> { + if (response != null && response.getErrorMessage() != null) { + spanStatusBuilder.setStatus(StatusCode.ERROR); + } else { + SpanStatusExtractor.getDefault() + .extract(spanStatusBuilder, request, response, error); + } + })) .buildInstrumenter(SpanKindExtractor.alwaysClient()); return new LettuceTelemetry(instrumenter, querySanitizationEnabled, encodingEventsEnabled); diff --git a/instrumentation/mongo/mongo-3.1/library/src/main/java/io/opentelemetry/instrumentation/mongo/v3_1/internal/MongoInstrumenterFactory.java b/instrumentation/mongo/mongo-3.1/library/src/main/java/io/opentelemetry/instrumentation/mongo/v3_1/internal/MongoInstrumenterFactory.java index dce872517880..2643b507c4ab 100644 --- a/instrumentation/mongo/mongo-3.1/library/src/main/java/io/opentelemetry/instrumentation/mongo/v3_1/internal/MongoInstrumenterFactory.java +++ b/instrumentation/mongo/mongo-3.1/library/src/main/java/io/opentelemetry/instrumentation/mongo/v3_1/internal/MongoInstrumenterFactory.java @@ -5,6 +5,8 @@ package io.opentelemetry.instrumentation.mongo.v3_1.internal; +import static io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.DbExceptionEventExtractors.setDbClientExceptionEventExtractor; + import com.mongodb.event.CommandStartedEvent; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientAttributesExtractor; @@ -42,11 +44,12 @@ public static Instrumenter createInstrumenter( SpanNameExtractor spanNameExtractor = new MongoSpanNameExtractor(dbAttributesGetter, attributesExtractor); - return Instrumenter.builder( - openTelemetry, instrumentationName, spanNameExtractor) - .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) - .addAttributesExtractor(attributesExtractor) - .addOperationMetrics(DbClientMetrics.get()) + return setDbClientExceptionEventExtractor( + Instrumenter.builder( + openTelemetry, instrumentationName, spanNameExtractor) + .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) + .addAttributesExtractor(attributesExtractor) + .addOperationMetrics(DbClientMetrics.get())) .buildInstrumenter(SpanKindExtractor.alwaysClient()); } diff --git a/instrumentation/opensearch/opensearch-java-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opensearch/v3_0/OpenSearchSingletons.java b/instrumentation/opensearch/opensearch-java-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opensearch/v3_0/OpenSearchSingletons.java index 2aa437c2dd54..29d2286fe5cc 100644 --- a/instrumentation/opensearch/opensearch-java-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opensearch/v3_0/OpenSearchSingletons.java +++ b/instrumentation/opensearch/opensearch-java-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opensearch/v3_0/OpenSearchSingletons.java @@ -5,6 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.opensearch.v3_0; +import static io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.DbExceptionEventExtractors.setDbClientExceptionEventExtractor; + import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.api.incubator.config.internal.DeclarativeConfigUtil; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientAttributesExtractor; @@ -27,12 +29,14 @@ public static Instrumenter instrumenter() { private static Instrumenter createInstrumenter() { OpenSearchAttributesGetter dbClientAttributesGetter = new OpenSearchAttributesGetter(); - return Instrumenter.builder( - GlobalOpenTelemetry.get(), - "io.opentelemetry.opensearch-java-3.0", - DbClientSpanNameExtractor.create(dbClientAttributesGetter)) - .addAttributesExtractor(DbClientAttributesExtractor.create(dbClientAttributesGetter)) - .addOperationMetrics(DbClientMetrics.get()) + return setDbClientExceptionEventExtractor( + Instrumenter.builder( + GlobalOpenTelemetry.get(), + "io.opentelemetry.opensearch-java-3.0", + DbClientSpanNameExtractor.create(dbClientAttributesGetter)) + .addAttributesExtractor( + DbClientAttributesExtractor.create(dbClientAttributesGetter)) + .addOperationMetrics(DbClientMetrics.get())) .buildInstrumenter(SpanKindExtractor.alwaysClient()); } diff --git a/instrumentation/opensearch/opensearch-rest-common-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opensearch/rest/common/v1_0/OpenSearchRestInstrumenterFactory.java b/instrumentation/opensearch/opensearch-rest-common-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opensearch/rest/common/v1_0/OpenSearchRestInstrumenterFactory.java index 6ec6988ce061..3f81990d833a 100644 --- a/instrumentation/opensearch/opensearch-rest-common-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opensearch/rest/common/v1_0/OpenSearchRestInstrumenterFactory.java +++ b/instrumentation/opensearch/opensearch-rest-common-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opensearch/rest/common/v1_0/OpenSearchRestInstrumenterFactory.java @@ -5,6 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.opensearch.rest.common.v1_0; +import static io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.DbExceptionEventExtractors.setDbClientExceptionEventExtractor; + import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientAttributesExtractor; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientMetrics; @@ -18,12 +20,14 @@ public static Instrumenter create String instrumentationName) { OpenSearchRestAttributesGetter dbClientAttributesGetter = new OpenSearchRestAttributesGetter(); - return Instrumenter.builder( - GlobalOpenTelemetry.get(), - instrumentationName, - DbClientSpanNameExtractor.create(dbClientAttributesGetter)) - .addAttributesExtractor(DbClientAttributesExtractor.create(dbClientAttributesGetter)) - .addOperationMetrics(DbClientMetrics.get()) + return setDbClientExceptionEventExtractor( + Instrumenter.builder( + GlobalOpenTelemetry.get(), + instrumentationName, + DbClientSpanNameExtractor.create(dbClientAttributesGetter)) + .addAttributesExtractor( + DbClientAttributesExtractor.create(dbClientAttributesGetter)) + .addOperationMetrics(DbClientMetrics.get())) .buildInstrumenter(SpanKindExtractor.alwaysClient()); } diff --git a/instrumentation/r2dbc-1.0/library/src/main/java/io/opentelemetry/instrumentation/r2dbc/v1_0/internal/R2dbcInstrumenterBuilder.java b/instrumentation/r2dbc-1.0/library/src/main/java/io/opentelemetry/instrumentation/r2dbc/v1_0/internal/R2dbcInstrumenterBuilder.java index d1c0049d5b85..7246c445a777 100644 --- a/instrumentation/r2dbc-1.0/library/src/main/java/io/opentelemetry/instrumentation/r2dbc/v1_0/internal/R2dbcInstrumenterBuilder.java +++ b/instrumentation/r2dbc-1.0/library/src/main/java/io/opentelemetry/instrumentation/r2dbc/v1_0/internal/R2dbcInstrumenterBuilder.java @@ -5,6 +5,8 @@ package io.opentelemetry.instrumentation.r2dbc.v1_0.internal; +import static io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.DbExceptionEventExtractors.setDbClientExceptionEventExtractor; + import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientMetrics; @@ -49,14 +51,15 @@ public Instrumenter build( spanNameExtractorTransformer.apply( DbClientSpanNameExtractor.create(new R2dbcSqlAttributesGetter())); - return Instrumenter.builder( - openTelemetry, INSTRUMENTATION_NAME, spanNameExtractor) - .addAttributesExtractor( - SqlClientAttributesExtractor.builder(new R2dbcSqlAttributesGetter()) - .setQuerySanitizationEnabled(querySanitizationEnabled) - .build()) - .addAttributesExtractors(additionalExtractors) - .addOperationMetrics(DbClientMetrics.get()) + return setDbClientExceptionEventExtractor( + Instrumenter.builder( + openTelemetry, INSTRUMENTATION_NAME, spanNameExtractor) + .addAttributesExtractor( + SqlClientAttributesExtractor.builder(new R2dbcSqlAttributesGetter()) + .setQuerySanitizationEnabled(querySanitizationEnabled) + .build()) + .addAttributesExtractors(additionalExtractors) + .addOperationMetrics(DbClientMetrics.get())) .buildInstrumenter(SpanKindExtractor.alwaysClient()); } } diff --git a/instrumentation/rediscala-1.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/v1_8/RediscalaSingletons.java b/instrumentation/rediscala-1.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/v1_8/RediscalaSingletons.java index 5c768068180d..b0bc3b655fd4 100644 --- a/instrumentation/rediscala-1.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/v1_8/RediscalaSingletons.java +++ b/instrumentation/rediscala-1.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/v1_8/RediscalaSingletons.java @@ -5,6 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.rediscala.v1_8; +import static io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.DbExceptionEventExtractors.setDbClientExceptionEventExtractor; + import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientAttributesExtractor; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientMetrics; @@ -23,12 +25,13 @@ public class RediscalaSingletons { RediscalaAttributesGetter dbAttributesGetter = new RediscalaAttributesGetter(); instrumenter = - Instrumenter., Void>builder( - GlobalOpenTelemetry.get(), - INSTRUMENTATION_NAME, - DbClientSpanNameExtractor.create(dbAttributesGetter)) - .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) - .addOperationMetrics(DbClientMetrics.get()) + setDbClientExceptionEventExtractor( + Instrumenter., Void>builder( + GlobalOpenTelemetry.get(), + INSTRUMENTATION_NAME, + DbClientSpanNameExtractor.create(dbAttributesGetter)) + .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) + .addOperationMetrics(DbClientMetrics.get())) .buildInstrumenter(SpanKindExtractor.alwaysClient()); } diff --git a/instrumentation/redisson/redisson-common-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/common/v3_0/RedissonInstrumenterFactory.java b/instrumentation/redisson/redisson-common-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/common/v3_0/RedissonInstrumenterFactory.java index 9847150f96c3..16197ffa97eb 100644 --- a/instrumentation/redisson/redisson-common-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/common/v3_0/RedissonInstrumenterFactory.java +++ b/instrumentation/redisson/redisson-common-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/common/v3_0/RedissonInstrumenterFactory.java @@ -5,6 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.redisson.common.v3_0; +import static io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.DbExceptionEventExtractors.setDbClientExceptionEventExtractor; + import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientAttributesExtractor; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientMetrics; @@ -17,12 +19,13 @@ public class RedissonInstrumenterFactory { public static Instrumenter createInstrumenter(String instrumentationName) { RedissonDbAttributesGetter dbAttributesGetter = new RedissonDbAttributesGetter(); - return Instrumenter.builder( - GlobalOpenTelemetry.get(), - instrumentationName, - DbClientSpanNameExtractor.create(dbAttributesGetter)) - .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) - .addOperationMetrics(DbClientMetrics.get()) + return setDbClientExceptionEventExtractor( + Instrumenter.builder( + GlobalOpenTelemetry.get(), + instrumentationName, + DbClientSpanNameExtractor.create(dbAttributesGetter)) + .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) + .addOperationMetrics(DbClientMetrics.get())) .buildInstrumenter(SpanKindExtractor.alwaysClient()); } diff --git a/instrumentation/spymemcached-2.12/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/v2_12/SpymemcachedSingletons.java b/instrumentation/spymemcached-2.12/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/v2_12/SpymemcachedSingletons.java index 8f2fa2327d02..0b03c5a1bce2 100644 --- a/instrumentation/spymemcached-2.12/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/v2_12/SpymemcachedSingletons.java +++ b/instrumentation/spymemcached-2.12/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/v2_12/SpymemcachedSingletons.java @@ -5,6 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.spymemcached.v2_12; +import static io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.DbExceptionEventExtractors.setDbClientExceptionEventExtractor; + import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.common.AttributesBuilder; import io.opentelemetry.context.Context; @@ -30,32 +32,36 @@ public class SpymemcachedSingletons { ServerAttributesExtractor.create(serverAttributesGetter); instrumenter = - Instrumenter.builder( - GlobalOpenTelemetry.get(), - INSTRUMENTATION_NAME, - DbClientSpanNameExtractor.create(dbAttributesGetter)) - .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) - .addAttributesExtractor( - new AttributesExtractor() { - @Override - public void onStart( - AttributesBuilder attributes, Context context, SpymemcachedRequest request) {} + setDbClientExceptionEventExtractor( + Instrumenter.builder( + GlobalOpenTelemetry.get(), + INSTRUMENTATION_NAME, + DbClientSpanNameExtractor.create(dbAttributesGetter)) + .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) + .addAttributesExtractor( + new AttributesExtractor() { + @Override + public void onStart( + AttributesBuilder attributes, + Context context, + SpymemcachedRequest request) {} - @Override - public void onEnd( - AttributesBuilder attributes, - Context context, - SpymemcachedRequest request, - @Nullable Object object, - @Nullable Throwable error) { - // For spymemcached, we can only extract server attributes at the end of the - // request because they are not available at the start. - serverAttributesExtractor.onStart(attributes, context, request); - } - }) - .addContextCustomizer( - (context, request, attributes) -> SpymemcachedRequestHolder.init(context, request)) - .addOperationMetrics(DbClientMetrics.get()) + @Override + public void onEnd( + AttributesBuilder attributes, + Context context, + SpymemcachedRequest request, + @Nullable Object object, + @Nullable Throwable error) { + // For spymemcached, we can only extract server attributes at the + // end of the request because they are not available at the start. + serverAttributesExtractor.onStart(attributes, context, request); + } + }) + .addContextCustomizer( + (context, request, attributes) -> + SpymemcachedRequestHolder.init(context, request)) + .addOperationMetrics(DbClientMetrics.get())) .buildInstrumenter(SpanKindExtractor.alwaysClient()); } diff --git a/instrumentation/vertx/vertx-redis-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/redisclient/v4_0/VertxRedisClientSingletons.java b/instrumentation/vertx/vertx-redis-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/redisclient/v4_0/VertxRedisClientSingletons.java index 24458daa1627..a04611854b68 100644 --- a/instrumentation/vertx/vertx-redis-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/redisclient/v4_0/VertxRedisClientSingletons.java +++ b/instrumentation/vertx/vertx-redis-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/redisclient/v4_0/VertxRedisClientSingletons.java @@ -5,6 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.vertx.redisclient.v4_0; +import static io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.DbExceptionEventExtractors.setDbClientExceptionEventExtractor; + import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; @@ -48,6 +50,7 @@ public class VertxRedisClientSingletons { .addAttributesExtractor( ServicePeerAttributesExtractor.create(getter, GlobalOpenTelemetry.get())) .addOperationMetrics(DbClientMetrics.get()); + setDbClientExceptionEventExtractor(builder); instrumenter = builder.buildInstrumenter(SpanKindExtractor.alwaysClient()); } diff --git a/instrumentation/vertx/vertx-sql-client/vertx-sql-client-common-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/sqlclient/common/v4_0/VertxSqlInstrumenterFactory.java b/instrumentation/vertx/vertx-sql-client/vertx-sql-client-common-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/sqlclient/common/v4_0/VertxSqlInstrumenterFactory.java index e469979b359b..92d2c7462803 100644 --- a/instrumentation/vertx/vertx-sql-client/vertx-sql-client-common-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/sqlclient/common/v4_0/VertxSqlInstrumenterFactory.java +++ b/instrumentation/vertx/vertx-sql-client/vertx-sql-client-common-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/sqlclient/common/v4_0/VertxSqlInstrumenterFactory.java @@ -5,6 +5,8 @@ package io.opentelemetry.javaagent.instrumentation.vertx.sqlclient.common.v4_0; +import static io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.DbExceptionEventExtractors.setDbClientExceptionEventExtractor; + import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.instrumentation.api.incubator.config.internal.DbConfig; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientMetrics; @@ -36,6 +38,7 @@ public static Instrumenter createInstrumenter( .addAttributesExtractor( ServicePeerAttributesExtractor.create(attributesGetter, GlobalOpenTelemetry.get())) .addOperationMetrics(DbClientMetrics.get()); + setDbClientExceptionEventExtractor(builder); return builder.buildInstrumenter(SpanKindExtractor.alwaysClient()); } From d6fbc1f608308f863124c4c5279e67eaaf41eac2 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Wed, 3 Jun 2026 17:22:46 -0700 Subject: [PATCH 2/9] Add unit and integration tests for DB exception event extractor --- .../DbExceptionEventExtractorsTest.java | 57 +++++++++++++++ .../cassandra/v3_0/CassandraSingletons.java | 33 ++++----- .../cassandra/v4_0/CassandraSingletons.java | 33 ++++----- .../v4_4/CassandraTelemetryBuilder.java | 28 ++++---- .../v0_5/ClickHouseInstrumenterFactory.java | 30 ++++---- .../ElasticsearchRestInstrumenterFactory.java | 19 ++--- .../geode/v1_4/GeodeSingletons.java | 21 +++--- .../influxdb/v2_4/InfluxDbSingletons.java | 26 +++---- .../jdbc/javaagent/build.gradle.kts | 15 ++++ instrumentation/jdbc/library/build.gradle.kts | 9 ++- .../internal/JdbcInstrumenterFactory.java | 26 +++---- .../AbstractJdbcInstrumentationTest.java | 70 +++++++++++++++++++ .../jedis/v1_4/JedisSingletons.java | 26 +++---- .../jedis/v3_0/JedisSingletons.java | 26 +++---- .../jedis/v4_0/JedisSingletons.java | 20 +++--- .../lettuce/v4_0/LettuceSingletons.java | 20 +++--- .../lettuce/v5_0/LettuceSingletons.java | 20 +++--- .../lettuce/v5_1/LettuceTelemetryBuilder.java | 37 +++++----- .../internal/MongoInstrumenterFactory.java | 16 +++-- .../opensearch/v3_0/OpenSearchSingletons.java | 19 ++--- .../OpenSearchRestInstrumenterFactory.java | 19 ++--- .../internal/R2dbcInstrumenterBuilder.java | 22 +++--- .../rediscala/v1_8/RediscalaSingletons.java | 20 +++--- .../v3_0/RedissonInstrumenterFactory.java | 18 ++--- .../v2_12/SpymemcachedSingletons.java | 61 ++++++++-------- 25 files changed, 437 insertions(+), 254 deletions(-) create mode 100644 instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/internal/DbExceptionEventExtractorsTest.java diff --git a/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/internal/DbExceptionEventExtractorsTest.java b/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/internal/DbExceptionEventExtractorsTest.java new file mode 100644 index 000000000000..24cab96d2648 --- /dev/null +++ b/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/internal/DbExceptionEventExtractorsTest.java @@ -0,0 +1,57 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.instrumentation.api.incubator.semconv.db.internal; + +import static io.opentelemetry.instrumentation.api.internal.SemconvExceptionSignal.emitExceptionAsLogs; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies; +import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_MESSAGE; +import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_STACKTRACE; +import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_TYPE; + +import io.opentelemetry.api.logs.Severity; +import io.opentelemetry.context.Context; +import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; +import io.opentelemetry.sdk.logs.data.LogRecordData; +import io.opentelemetry.sdk.testing.junit5.OpenTelemetryExtension; +import java.util.List; +import org.assertj.core.api.AbstractAssert; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +class DbExceptionEventExtractorsTest { + + @RegisterExtension + static final OpenTelemetryExtension otelTesting = OpenTelemetryExtension.create(); + + @Test + void dbClientExceptionLog() { + InstrumenterBuilder builder = + Instrumenter.builder(otelTesting.getOpenTelemetry(), "test", unused -> "span"); + DbExceptionEventExtractors.setDbClientExceptionEventExtractor(builder); + Instrumenter instrumenter = builder.buildInstrumenter(); + + Context context = instrumenter.start(Context.root(), "request"); + IllegalStateException error = new IllegalStateException("test"); + instrumenter.end(context, "request", "response", error); + + List logs = otelTesting.getLogRecords(); + if (emitExceptionAsLogs()) { + assertThat(logs).hasSize(1); + assertThat(logs.get(0)) + .hasSeverity(Severity.WARN) + .hasEventName("db.client.operation.exception") + .hasAttributesSatisfyingExactly( + equalTo(EXCEPTION_TYPE, "java.lang.IllegalStateException"), + equalTo(EXCEPTION_MESSAGE, "test"), + satisfies(EXCEPTION_STACKTRACE, AbstractAssert::isNotNull)); + } else { + assertThat(logs).isEmpty(); + } + } +} diff --git a/instrumentation/cassandra/cassandra-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/CassandraSingletons.java b/instrumentation/cassandra/cassandra-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/CassandraSingletons.java index 460bac5bb79c..0afbd9bf76a7 100644 --- a/instrumentation/cassandra/cassandra-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/CassandraSingletons.java +++ b/instrumentation/cassandra/cassandra-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/CassandraSingletons.java @@ -15,6 +15,7 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientSpanNameExtractor; import io.opentelemetry.instrumentation.api.incubator.semconv.db.SqlClientAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; @SuppressWarnings("deprecation") // using deprecated semconv @@ -28,22 +29,22 @@ class CassandraSingletons { static { CassandraSqlAttributesGetter attributesGetter = new CassandraSqlAttributesGetter(); - instrumenter = - setDbClientExceptionEventExtractor( - Instrumenter.builder( - GlobalOpenTelemetry.get(), - INSTRUMENTATION_NAME, - DbClientSpanNameExtractor.create(attributesGetter)) - .addAttributesExtractor( - SqlClientAttributesExtractor.builder(attributesGetter) - .setTableAttribute(DB_CASSANDRA_TABLE) - .setQuerySanitizationEnabled( - DbConfig.isQuerySanitizationEnabled( - GlobalOpenTelemetry.get(), "cassandra")) - .build()) - .addAttributesExtractor(new CassandraAttributesExtractor()) - .addOperationMetrics(DbClientMetrics.get())) - .buildInstrumenter(SpanKindExtractor.alwaysClient()); + InstrumenterBuilder builder = + Instrumenter.builder( + GlobalOpenTelemetry.get(), + INSTRUMENTATION_NAME, + DbClientSpanNameExtractor.create(attributesGetter)) + .addAttributesExtractor( + SqlClientAttributesExtractor.builder(attributesGetter) + .setTableAttribute(DB_CASSANDRA_TABLE) + .setQuerySanitizationEnabled( + DbConfig.isQuerySanitizationEnabled(GlobalOpenTelemetry.get(), "cassandra")) + .build()) + .addAttributesExtractor(new CassandraAttributesExtractor()) + .addOperationMetrics(DbClientMetrics.get()); + setDbClientExceptionEventExtractor(builder); + + instrumenter = builder.buildInstrumenter(SpanKindExtractor.alwaysClient()); } static Instrumenter instrumenter() { diff --git a/instrumentation/cassandra/cassandra-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CassandraSingletons.java b/instrumentation/cassandra/cassandra-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CassandraSingletons.java index 71ec59baf9fa..4cdf830b72b2 100644 --- a/instrumentation/cassandra/cassandra-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CassandraSingletons.java +++ b/instrumentation/cassandra/cassandra-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CassandraSingletons.java @@ -15,6 +15,7 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientSpanNameExtractor; import io.opentelemetry.instrumentation.api.incubator.semconv.db.SqlClientAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; @SuppressWarnings("deprecation") // using deprecated semconv @@ -27,22 +28,22 @@ class CassandraSingletons { static { CassandraSqlAttributesGetter attributesGetter = new CassandraSqlAttributesGetter(); - instrumenter = - setDbClientExceptionEventExtractor( - Instrumenter.builder( - GlobalOpenTelemetry.get(), - INSTRUMENTATION_NAME, - DbClientSpanNameExtractor.create(attributesGetter)) - .addAttributesExtractor( - SqlClientAttributesExtractor.builder(attributesGetter) - .setTableAttribute(DB_CASSANDRA_TABLE) - .setQuerySanitizationEnabled( - DbConfig.isQuerySanitizationEnabled( - GlobalOpenTelemetry.get(), "cassandra")) - .build()) - .addAttributesExtractor(new CassandraAttributesExtractor()) - .addOperationMetrics(DbClientMetrics.get())) - .buildInstrumenter(SpanKindExtractor.alwaysClient()); + InstrumenterBuilder builder = + Instrumenter.builder( + GlobalOpenTelemetry.get(), + INSTRUMENTATION_NAME, + DbClientSpanNameExtractor.create(attributesGetter)) + .addAttributesExtractor( + SqlClientAttributesExtractor.builder(attributesGetter) + .setTableAttribute(DB_CASSANDRA_TABLE) + .setQuerySanitizationEnabled( + DbConfig.isQuerySanitizationEnabled(GlobalOpenTelemetry.get(), "cassandra")) + .build()) + .addAttributesExtractor(new CassandraAttributesExtractor()) + .addOperationMetrics(DbClientMetrics.get()); + setDbClientExceptionEventExtractor(builder); + + instrumenter = builder.buildInstrumenter(SpanKindExtractor.alwaysClient()); } static Instrumenter instrumenter() { diff --git a/instrumentation/cassandra/cassandra-4.4/library/src/main/java/io/opentelemetry/instrumentation/cassandra/v4_4/CassandraTelemetryBuilder.java b/instrumentation/cassandra/cassandra-4.4/library/src/main/java/io/opentelemetry/instrumentation/cassandra/v4_4/CassandraTelemetryBuilder.java index 89eeb6141bb7..202dbef03845 100644 --- a/instrumentation/cassandra/cassandra-4.4/library/src/main/java/io/opentelemetry/instrumentation/cassandra/v4_4/CassandraTelemetryBuilder.java +++ b/instrumentation/cassandra/cassandra-4.4/library/src/main/java/io/opentelemetry/instrumentation/cassandra/v4_4/CassandraTelemetryBuilder.java @@ -15,6 +15,7 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientSpanNameExtractor; import io.opentelemetry.instrumentation.api.incubator.semconv.db.SqlClientAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; /** A builder of {@link CassandraTelemetry}. */ @@ -58,18 +59,19 @@ private static Instrumenter createInstrumenter( OpenTelemetry openTelemetry, boolean querySanitizationEnabled) { CassandraSqlAttributesGetter attributesGetter = new CassandraSqlAttributesGetter(); - return setDbClientExceptionEventExtractor( - Instrumenter.builder( - openTelemetry, - INSTRUMENTATION_NAME, - DbClientSpanNameExtractor.create(attributesGetter)) - .addAttributesExtractor( - SqlClientAttributesExtractor.builder(attributesGetter) - .setTableAttribute(DB_CASSANDRA_TABLE) - .setQuerySanitizationEnabled(querySanitizationEnabled) - .build()) - .addAttributesExtractor(new CassandraAttributesExtractor()) - .addOperationMetrics(DbClientMetrics.get())) - .buildInstrumenter(SpanKindExtractor.alwaysClient()); + InstrumenterBuilder builder = + Instrumenter.builder( + openTelemetry, + INSTRUMENTATION_NAME, + DbClientSpanNameExtractor.create(attributesGetter)) + .addAttributesExtractor( + SqlClientAttributesExtractor.builder(attributesGetter) + .setTableAttribute(DB_CASSANDRA_TABLE) + .setQuerySanitizationEnabled(querySanitizationEnabled) + .build()) + .addAttributesExtractor(new CassandraAttributesExtractor()) + .addOperationMetrics(DbClientMetrics.get()); + setDbClientExceptionEventExtractor(builder); + return builder.buildInstrumenter(SpanKindExtractor.alwaysClient()); } } diff --git a/instrumentation/clickhouse/clickhouse-client-common-0.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/clickhouse/client/common/v0_5/ClickHouseInstrumenterFactory.java b/instrumentation/clickhouse/clickhouse-client-common-0.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/clickhouse/client/common/v0_5/ClickHouseInstrumenterFactory.java index d6588e563164..33715f6c00e7 100644 --- a/instrumentation/clickhouse/clickhouse-client-common-0.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/clickhouse/client/common/v0_5/ClickHouseInstrumenterFactory.java +++ b/instrumentation/clickhouse/clickhouse-client-common-0.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/clickhouse/client/common/v0_5/ClickHouseInstrumenterFactory.java @@ -13,6 +13,7 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientSpanNameExtractor; import io.opentelemetry.instrumentation.api.incubator.semconv.db.SqlClientAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; import java.util.function.Function; @@ -24,20 +25,21 @@ public static Instrumenter createInstrumenter( ClickHouseAttributesGetter dbAttributesGetter = new ClickHouseAttributesGetter(errorCodeExtractor); - return setDbClientExceptionEventExtractor( - Instrumenter.builder( - GlobalOpenTelemetry.get(), - instrumenterName, - DbClientSpanNameExtractor.createWithGenericOldSpanName(dbAttributesGetter)) - .addAttributesExtractor( - SqlClientAttributesExtractor.builder(dbAttributesGetter) - .setTableAttribute(null) - .setQuerySanitizationEnabled( - DbConfig.isQuerySanitizationEnabled( - GlobalOpenTelemetry.get(), "clickhouse")) - .build()) - .addOperationMetrics(DbClientMetrics.get())) - .buildInstrumenter(SpanKindExtractor.alwaysClient()); + InstrumenterBuilder builder = + Instrumenter.builder( + GlobalOpenTelemetry.get(), + instrumenterName, + DbClientSpanNameExtractor.createWithGenericOldSpanName(dbAttributesGetter)) + .addAttributesExtractor( + SqlClientAttributesExtractor.builder(dbAttributesGetter) + .setTableAttribute(null) + .setQuerySanitizationEnabled( + DbConfig.isQuerySanitizationEnabled( + GlobalOpenTelemetry.get(), "clickhouse")) + .build()) + .addOperationMetrics(DbClientMetrics.get()); + setDbClientExceptionEventExtractor(builder); + return builder.buildInstrumenter(SpanKindExtractor.alwaysClient()); } private ClickHouseInstrumenterFactory() {} diff --git a/instrumentation/elasticsearch/elasticsearch-rest-common-5.0/library/src/main/java/io/opentelemetry/instrumentation/elasticsearch/rest/common/v5_0/internal/ElasticsearchRestInstrumenterFactory.java b/instrumentation/elasticsearch/elasticsearch-rest-common-5.0/library/src/main/java/io/opentelemetry/instrumentation/elasticsearch/rest/common/v5_0/internal/ElasticsearchRestInstrumenterFactory.java index 9d3071312307..57debc63fbc7 100644 --- a/instrumentation/elasticsearch/elasticsearch-rest-common-5.0/library/src/main/java/io/opentelemetry/instrumentation/elasticsearch/rest/common/v5_0/internal/ElasticsearchRestInstrumenterFactory.java +++ b/instrumentation/elasticsearch/elasticsearch-rest-common-5.0/library/src/main/java/io/opentelemetry/instrumentation/elasticsearch/rest/common/v5_0/internal/ElasticsearchRestInstrumenterFactory.java @@ -12,6 +12,7 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientMetrics; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; import java.util.List; @@ -43,15 +44,15 @@ public static Instrumenter create( spanNameExtractorTransformer.apply( new ElasticsearchSpanNameExtractor(dbClientAttributesGetter)); - return setDbClientExceptionEventExtractor( - Instrumenter.builder( - openTelemetry, instrumentationName, spanNameExtractor) - .addAttributesExtractor( - DbClientAttributesExtractor.create(dbClientAttributesGetter)) - .addAttributesExtractor(esClientAttributesExtractor) - .addAttributesExtractors(attributesExtractors) - .addOperationMetrics(DbClientMetrics.get())) - .buildInstrumenter(SpanKindExtractor.alwaysClient()); + InstrumenterBuilder builder = + Instrumenter.builder( + openTelemetry, instrumentationName, spanNameExtractor) + .addAttributesExtractor(DbClientAttributesExtractor.create(dbClientAttributesGetter)) + .addAttributesExtractor(esClientAttributesExtractor) + .addAttributesExtractors(attributesExtractors) + .addOperationMetrics(DbClientMetrics.get()); + setDbClientExceptionEventExtractor(builder); + return builder.buildInstrumenter(SpanKindExtractor.alwaysClient()); } private ElasticsearchRestInstrumenterFactory() {} diff --git a/instrumentation/geode-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/v1_4/GeodeSingletons.java b/instrumentation/geode-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/v1_4/GeodeSingletons.java index c9f01e6352be..60b6aadf4435 100644 --- a/instrumentation/geode-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/v1_4/GeodeSingletons.java +++ b/instrumentation/geode-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/v1_4/GeodeSingletons.java @@ -12,6 +12,7 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientMetrics; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientSpanNameExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; class GeodeSingletons { @@ -22,16 +23,16 @@ class GeodeSingletons { static { GeodeDbAttributesGetter dbClientAttributesGetter = new GeodeDbAttributesGetter(); - instrumenter = - setDbClientExceptionEventExtractor( - Instrumenter.builder( - GlobalOpenTelemetry.get(), - INSTRUMENTATION_NAME, - DbClientSpanNameExtractor.create(dbClientAttributesGetter)) - .addAttributesExtractor( - DbClientAttributesExtractor.create(dbClientAttributesGetter)) - .addOperationMetrics(DbClientMetrics.get())) - .buildInstrumenter(SpanKindExtractor.alwaysClient()); + InstrumenterBuilder builder = + Instrumenter.builder( + GlobalOpenTelemetry.get(), + INSTRUMENTATION_NAME, + DbClientSpanNameExtractor.create(dbClientAttributesGetter)) + .addAttributesExtractor(DbClientAttributesExtractor.create(dbClientAttributesGetter)) + .addOperationMetrics(DbClientMetrics.get()); + setDbClientExceptionEventExtractor(builder); + + instrumenter = builder.buildInstrumenter(SpanKindExtractor.alwaysClient()); } static Instrumenter instrumenter() { diff --git a/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbSingletons.java b/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbSingletons.java index 8d039cce6d22..0110c8f0eb6a 100644 --- a/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbSingletons.java +++ b/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbSingletons.java @@ -12,6 +12,7 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientSpanNameExtractor; import io.opentelemetry.instrumentation.api.incubator.semconv.db.SqlClientAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; @SuppressWarnings("deprecation") // to support old semconv @@ -22,18 +23,19 @@ public class InfluxDbSingletons { static { InfluxDbAttributesGetter dbAttributesGetter = new InfluxDbAttributesGetter(); - instrumenter = - setDbClientExceptionEventExtractor( - Instrumenter.builder( - GlobalOpenTelemetry.get(), - "io.opentelemetry.influxdb-2.4", - DbClientSpanNameExtractor.createWithGenericOldSpanName(dbAttributesGetter)) - .addAttributesExtractor( - SqlClientAttributesExtractor.builder(dbAttributesGetter) - .setTableAttribute(null) - .build()) - .addOperationMetrics(DbClientMetrics.get())) - .buildInstrumenter(SpanKindExtractor.alwaysClient()); + InstrumenterBuilder builder = + Instrumenter.builder( + GlobalOpenTelemetry.get(), + "io.opentelemetry.influxdb-2.4", + DbClientSpanNameExtractor.createWithGenericOldSpanName(dbAttributesGetter)) + .addAttributesExtractor( + SqlClientAttributesExtractor.builder(dbAttributesGetter) + .setTableAttribute(null) + .build()) + .addOperationMetrics(DbClientMetrics.get()); + setDbClientExceptionEventExtractor(builder); + + instrumenter = builder.buildInstrumenter(SpanKindExtractor.alwaysClient()); } public static Instrumenter instrumenter() { diff --git a/instrumentation/jdbc/javaagent/build.gradle.kts b/instrumentation/jdbc/javaagent/build.gradle.kts index c911c070ecce..855e753ce466 100644 --- a/instrumentation/jdbc/javaagent/build.gradle.kts +++ b/instrumentation/jdbc/javaagent/build.gradle.kts @@ -111,6 +111,20 @@ tasks { jvmArgs("-Dotel.instrumentation.jdbc.experimental.capture-query-parameters=true") } + val testExceptionSignalLogs by registering(Test::class) { + testClassesDirs = sourceSets.test.get().output.classesDirs + classpath = sourceSets.test.get().runtimeClasspath + + filter { + excludeTestsMatching("SlickTest") + excludeTestsMatching("SqlCommenterTest") + excludeTestsMatching("PreparedStatementParametersTest") + } + jvmArgs("-Dotel.instrumentation.jdbc-datasource.enabled=true") + jvmArgs("-Dotel.semconv.exception.signal.preview=logs") + systemProperty("metadataConfig", "otel.semconv.exception.signal.preview=logs") + } + test { filter { excludeTestsMatching("SlickTest") @@ -126,6 +140,7 @@ tasks { dependsOn(testStableSemconv) dependsOn(testSlickStableSemconv) dependsOn(testCaptureParameters) + dependsOn(testExceptionSignalLogs) } } diff --git a/instrumentation/jdbc/library/build.gradle.kts b/instrumentation/jdbc/library/build.gradle.kts index 4531a2f11823..af109aeee190 100644 --- a/instrumentation/jdbc/library/build.gradle.kts +++ b/instrumentation/jdbc/library/build.gradle.kts @@ -70,8 +70,15 @@ tasks { jvmArgs("-Dotel.semconv-stability.opt-in=database") } + val testExceptionSignalLogs by registering(Test::class) { + testClassesDirs = sourceSets.test.get().output.classesDirs + classpath = sourceSets.test.get().runtimeClasspath + + jvmArgs("-Dotel.semconv.exception.signal.preview=logs") + } + check { - dependsOn(testStableSemconv) + dependsOn(testStableSemconv, testExceptionSignalLogs) } } diff --git a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcInstrumenterFactory.java b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcInstrumenterFactory.java index 2236e8b28540..9a77521db4a1 100644 --- a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcInstrumenterFactory.java +++ b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcInstrumenterFactory.java @@ -18,6 +18,7 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.db.SqlClientAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil; import io.opentelemetry.instrumentation.jdbc.internal.dbinfo.DbInfo; @@ -75,18 +76,19 @@ public static Instrumenter createStatementInstrumenter( boolean querySanitizationEnabled, boolean captureQueryParameters) { JdbcAttributesGetter getter = new JdbcAttributesGetter(); - return setDbClientExceptionEventExtractor( - Instrumenter.builder( - openTelemetry, INSTRUMENTATION_NAME, DbClientSpanNameExtractor.create(getter)) - .addAttributesExtractor( - SqlClientAttributesExtractor.builder(getter) - .setQuerySanitizationEnabled(querySanitizationEnabled) - .setCaptureQueryParameters(captureQueryParameters) - .build()) - .addAttributesExtractors(extractors) - .addOperationMetrics(DbClientMetrics.get()) - .setEnabled(enabled)) - .buildInstrumenter(SpanKindExtractor.alwaysClient()); + InstrumenterBuilder builder = + Instrumenter.builder( + openTelemetry, INSTRUMENTATION_NAME, DbClientSpanNameExtractor.create(getter)) + .addAttributesExtractor( + SqlClientAttributesExtractor.builder(getter) + .setQuerySanitizationEnabled(querySanitizationEnabled) + .setCaptureQueryParameters(captureQueryParameters) + .build()) + .addAttributesExtractors(extractors) + .addOperationMetrics(DbClientMetrics.get()) + .setEnabled(enabled); + setDbClientExceptionEventExtractor(builder); + return builder.buildInstrumenter(SpanKindExtractor.alwaysClient()); } public static Instrumenter createDataSourceInstrumenter( diff --git a/instrumentation/jdbc/testing/src/main/java/io/opentelemetry/instrumentation/jdbc/testing/AbstractJdbcInstrumentationTest.java b/instrumentation/jdbc/testing/src/main/java/io/opentelemetry/instrumentation/jdbc/testing/AbstractJdbcInstrumentationTest.java index f90d44fae4d8..be14e4bf891a 100644 --- a/instrumentation/jdbc/testing/src/main/java/io/opentelemetry/instrumentation/jdbc/testing/AbstractJdbcInstrumentationTest.java +++ b/instrumentation/jdbc/testing/src/main/java/io/opentelemetry/instrumentation/jdbc/testing/AbstractJdbcInstrumentationTest.java @@ -5,6 +5,8 @@ package io.opentelemetry.instrumentation.jdbc.testing; +import static io.opentelemetry.instrumentation.api.internal.SemconvExceptionSignal.emitExceptionAsLogs; +import static io.opentelemetry.instrumentation.api.internal.SemconvExceptionSignal.emitExceptionAsSpanEvents; import static io.opentelemetry.instrumentation.api.internal.SemconvStability.emitStableDatabaseSemconv; import static io.opentelemetry.instrumentation.testing.junit.code.SemconvCodeStabilityUtil.codeFunctionAssertions; import static io.opentelemetry.instrumentation.testing.junit.db.DbClientMetricsTestUtil.assertDurationMetric; @@ -14,11 +16,15 @@ import static io.opentelemetry.instrumentation.testing.util.TestLatestDeps.testLatestDeps; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies; import static io.opentelemetry.semconv.DbAttributes.DB_NAMESPACE; import static io.opentelemetry.semconv.DbAttributes.DB_OPERATION_BATCH_SIZE; import static io.opentelemetry.semconv.DbAttributes.DB_QUERY_SUMMARY; import static io.opentelemetry.semconv.DbAttributes.DB_STORED_PROCEDURE_NAME; import static io.opentelemetry.semconv.DbAttributes.DB_SYSTEM_NAME; +import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_MESSAGE; +import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_STACKTRACE; +import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_TYPE; import static io.opentelemetry.semconv.ServerAttributes.SERVER_ADDRESS; import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_CONNECTION_STRING; import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_NAME; @@ -30,6 +36,7 @@ import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DbSystemNameIncubatingValues.HSQLDB; import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DbSystemNameIncubatingValues.OTHER_SQL; import static java.util.Arrays.asList; +import static java.util.stream.Collectors.toList; import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.google.common.collect.ImmutableMap; @@ -37,14 +44,17 @@ import com.mchange.v2.c3p0.ComboPooledDataSource; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; +import io.opentelemetry.api.logs.Severity; import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.instrumentation.jdbc.TestConnection; import io.opentelemetry.instrumentation.jdbc.TestDriver; import io.opentelemetry.instrumentation.testing.internal.AutoCleanupExtension; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.sdk.logs.data.LogRecordData; import io.opentelemetry.sdk.testing.assertj.AttributeAssertion; import io.opentelemetry.sdk.testing.assertj.SpanDataAssert; import io.opentelemetry.sdk.testing.assertj.TraceAssert; +import io.opentelemetry.sdk.trace.data.StatusData; import java.beans.PropertyVetoException; import java.io.Closeable; import java.sql.CallableStatement; @@ -66,6 +76,7 @@ import org.apache.derby.jdbc.EmbeddedDataSource; import org.apache.derby.jdbc.EmbeddedDriver; import org.assertj.core.api.ThrowingConsumer; +import org.awaitility.Awaitility; import org.h2.jdbcx.JdbcDataSource; import org.hsqldb.jdbc.JDBCDriver; import org.junit.jupiter.api.BeforeAll; @@ -418,6 +429,65 @@ isCallStatement && emitStableDatabaseSemconv() testing(), "io.opentelemetry.jdbc", DB_SYSTEM_NAME, DB_NAMESPACE, DB_QUERY_SUMMARY); } + @Test + void testFailedStatement() throws SQLException { + Connection connection = wrap(new org.h2.Driver().connect(JDBC_URLS.get("h2"), null)); + Statement statement = connection.createStatement(); + cleanup.deferCleanup(statement); + + assertThatThrownBy( + () -> + testing() + .runWithSpan( + "parent", + () -> statement.executeQuery("SELECT * FROM table_does_not_exist"))) + .isInstanceOf(SQLException.class); + + testing() + .waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("parent").hasKind(SpanKind.INTERNAL).hasNoParent(), + span -> + span.hasKind(SpanKind.CLIENT) + .hasParent(trace.getSpan(0)) + .hasStatus(StatusData.error()) + .satisfies( + spanData -> { + if (emitExceptionAsSpanEvents()) { + assertThat(spanData.getEvents()).hasSize(1); + assertThat(spanData.getEvents().get(0).getName()) + .isEqualTo("exception"); + } else { + assertThat(spanData.getEvents()).isEmpty(); + } + }))); + + if (emitExceptionAsLogs()) { + assertExceptionLog(); + } + } + + private void assertExceptionLog() { + Awaitility.await() + .untilAsserted( + () -> { + List logs = + testing().logRecords().stream() + .filter(log -> "db.client.operation.exception".equals(log.getEventName())) + .collect(toList()); + + assertThat(logs).hasSize(1); + assertThat(logs.get(0)) + .hasSeverity(Severity.WARN) + .hasEventName("db.client.operation.exception") + .hasAttributesSatisfyingExactly( + satisfies(EXCEPTION_TYPE, val -> val.isNotNull()), + satisfies(EXCEPTION_MESSAGE, val -> val.isNotNull()), + satisfies(EXCEPTION_STACKTRACE, val -> val.isNotNull())); + }); + } + static Stream preparedStatementStream() throws SQLException { return Stream.of( Arguments.of( diff --git a/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisSingletons.java b/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisSingletons.java index f35def02ff16..4c3e1a251664 100644 --- a/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisSingletons.java +++ b/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisSingletons.java @@ -13,6 +13,7 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientSpanNameExtractor; import io.opentelemetry.instrumentation.api.incubator.semconv.service.peer.ServicePeerAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; class JedisSingletons { @@ -23,18 +24,19 @@ class JedisSingletons { static { JedisDbAttributesGetter dbAttributesGetter = new JedisDbAttributesGetter(); - instrumenter = - setDbClientExceptionEventExtractor( - Instrumenter.builder( - GlobalOpenTelemetry.get(), - INSTRUMENTATION_NAME, - DbClientSpanNameExtractor.create(dbAttributesGetter)) - .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) - .addAttributesExtractor( - ServicePeerAttributesExtractor.create( - dbAttributesGetter, GlobalOpenTelemetry.get())) - .addOperationMetrics(DbClientMetrics.get())) - .buildInstrumenter(SpanKindExtractor.alwaysClient()); + InstrumenterBuilder builder = + Instrumenter.builder( + GlobalOpenTelemetry.get(), + INSTRUMENTATION_NAME, + DbClientSpanNameExtractor.create(dbAttributesGetter)) + .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) + .addAttributesExtractor( + ServicePeerAttributesExtractor.create( + dbAttributesGetter, GlobalOpenTelemetry.get())) + .addOperationMetrics(DbClientMetrics.get()); + setDbClientExceptionEventExtractor(builder); + + instrumenter = builder.buildInstrumenter(SpanKindExtractor.alwaysClient()); } static Instrumenter instrumenter() { diff --git a/instrumentation/jedis/jedis-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v3_0/JedisSingletons.java b/instrumentation/jedis/jedis-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v3_0/JedisSingletons.java index 4167c755c317..879900f3c2d0 100644 --- a/instrumentation/jedis/jedis-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v3_0/JedisSingletons.java +++ b/instrumentation/jedis/jedis-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v3_0/JedisSingletons.java @@ -13,6 +13,7 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientSpanNameExtractor; import io.opentelemetry.instrumentation.api.incubator.semconv.service.peer.ServicePeerAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; public class JedisSingletons { @@ -23,18 +24,19 @@ public class JedisSingletons { static { JedisDbAttributesGetter dbAttributesGetter = new JedisDbAttributesGetter(); - instrumenter = - setDbClientExceptionEventExtractor( - Instrumenter.builder( - GlobalOpenTelemetry.get(), - INSTRUMENTATION_NAME, - DbClientSpanNameExtractor.create(dbAttributesGetter)) - .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) - .addAttributesExtractor( - ServicePeerAttributesExtractor.create( - dbAttributesGetter, GlobalOpenTelemetry.get())) - .addOperationMetrics(DbClientMetrics.get())) - .buildInstrumenter(SpanKindExtractor.alwaysClient()); + InstrumenterBuilder builder = + Instrumenter.builder( + GlobalOpenTelemetry.get(), + INSTRUMENTATION_NAME, + DbClientSpanNameExtractor.create(dbAttributesGetter)) + .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) + .addAttributesExtractor( + ServicePeerAttributesExtractor.create( + dbAttributesGetter, GlobalOpenTelemetry.get())) + .addOperationMetrics(DbClientMetrics.get()); + setDbClientExceptionEventExtractor(builder); + + instrumenter = builder.buildInstrumenter(SpanKindExtractor.alwaysClient()); } public static Instrumenter instrumenter() { diff --git a/instrumentation/jedis/jedis-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v4_0/JedisSingletons.java b/instrumentation/jedis/jedis-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v4_0/JedisSingletons.java index 82332557e7c2..7aa09ebabfeb 100644 --- a/instrumentation/jedis/jedis-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v4_0/JedisSingletons.java +++ b/instrumentation/jedis/jedis-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v4_0/JedisSingletons.java @@ -12,6 +12,7 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientMetrics; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientSpanNameExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; public class JedisSingletons { @@ -22,15 +23,16 @@ public class JedisSingletons { static { JedisDbAttributesGetter dbAttributesGetter = new JedisDbAttributesGetter(); - instrumenter = - setDbClientExceptionEventExtractor( - Instrumenter.builder( - GlobalOpenTelemetry.get(), - INSTRUMENTATION_NAME, - DbClientSpanNameExtractor.create(dbAttributesGetter)) - .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) - .addOperationMetrics(DbClientMetrics.get())) - .buildInstrumenter(SpanKindExtractor.alwaysClient()); + InstrumenterBuilder builder = + Instrumenter.builder( + GlobalOpenTelemetry.get(), + INSTRUMENTATION_NAME, + DbClientSpanNameExtractor.create(dbAttributesGetter)) + .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) + .addOperationMetrics(DbClientMetrics.get()); + setDbClientExceptionEventExtractor(builder); + + instrumenter = builder.buildInstrumenter(SpanKindExtractor.alwaysClient()); } public static Instrumenter instrumenter() { diff --git a/instrumentation/lettuce/lettuce-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceSingletons.java b/instrumentation/lettuce/lettuce-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceSingletons.java index 04b6dc823ce2..13683c5aab13 100644 --- a/instrumentation/lettuce/lettuce-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceSingletons.java +++ b/instrumentation/lettuce/lettuce-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceSingletons.java @@ -19,6 +19,7 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientSpanNameExtractor; import io.opentelemetry.instrumentation.api.incubator.semconv.service.peer.ServicePeerAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; import io.opentelemetry.instrumentation.api.semconv.network.ServerAttributesExtractor; import io.opentelemetry.instrumentation.api.util.VirtualField; @@ -38,15 +39,16 @@ public class LettuceSingletons { static { LettuceDbAttributesGetter dbAttributesGetter = new LettuceDbAttributesGetter(); - instrumenter = - setDbClientExceptionEventExtractor( - Instrumenter., Void>builder( - GlobalOpenTelemetry.get(), - INSTRUMENTATION_NAME, - DbClientSpanNameExtractor.create(dbAttributesGetter)) - .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) - .addOperationMetrics(DbClientMetrics.get())) - .buildInstrumenter(SpanKindExtractor.alwaysClient()); + InstrumenterBuilder, Void> builder = + Instrumenter., Void>builder( + GlobalOpenTelemetry.get(), + INSTRUMENTATION_NAME, + DbClientSpanNameExtractor.create(dbAttributesGetter)) + .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) + .addOperationMetrics(DbClientMetrics.get()); + setDbClientExceptionEventExtractor(builder); + + instrumenter = builder.buildInstrumenter(SpanKindExtractor.alwaysClient()); LettuceConnectNetworkAttributesGetter netAttributesGetter = new LettuceConnectNetworkAttributesGetter(); diff --git a/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceSingletons.java b/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceSingletons.java index 7d26171f0d39..23c7981d27f4 100644 --- a/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceSingletons.java +++ b/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceSingletons.java @@ -19,6 +19,7 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientSpanNameExtractor; import io.opentelemetry.instrumentation.api.incubator.semconv.service.peer.ServicePeerAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; import io.opentelemetry.instrumentation.api.semconv.network.ServerAttributesExtractor; import io.opentelemetry.instrumentation.api.util.VirtualField; @@ -38,15 +39,16 @@ public class LettuceSingletons { static { LettuceDbAttributesGetter dbAttributesGetter = new LettuceDbAttributesGetter(); - instrumenter = - setDbClientExceptionEventExtractor( - Instrumenter., Void>builder( - GlobalOpenTelemetry.get(), - INSTRUMENTATION_NAME, - DbClientSpanNameExtractor.create(dbAttributesGetter)) - .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) - .addOperationMetrics(DbClientMetrics.get())) - .buildInstrumenter(SpanKindExtractor.alwaysClient()); + InstrumenterBuilder, Void> builder = + Instrumenter., Void>builder( + GlobalOpenTelemetry.get(), + INSTRUMENTATION_NAME, + DbClientSpanNameExtractor.create(dbAttributesGetter)) + .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) + .addOperationMetrics(DbClientMetrics.get()); + setDbClientExceptionEventExtractor(builder); + + instrumenter = builder.buildInstrumenter(SpanKindExtractor.alwaysClient()); LettuceConnectNetworkAttributesGetter connectNetworkAttributesGetter = new LettuceConnectNetworkAttributesGetter(); diff --git a/instrumentation/lettuce/lettuce-5.1/library/src/main/java/io/opentelemetry/instrumentation/lettuce/v5_1/LettuceTelemetryBuilder.java b/instrumentation/lettuce/lettuce-5.1/library/src/main/java/io/opentelemetry/instrumentation/lettuce/v5_1/LettuceTelemetryBuilder.java index 22d6d5218940..123acf2b4b07 100644 --- a/instrumentation/lettuce/lettuce-5.1/library/src/main/java/io/opentelemetry/instrumentation/lettuce/v5_1/LettuceTelemetryBuilder.java +++ b/instrumentation/lettuce/lettuce-5.1/library/src/main/java/io/opentelemetry/instrumentation/lettuce/v5_1/LettuceTelemetryBuilder.java @@ -15,6 +15,7 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientMetrics; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientSpanNameExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; import io.opentelemetry.instrumentation.api.instrumenter.SpanStatusExtractor; @@ -59,24 +60,26 @@ public LettuceTelemetryBuilder setEncodingSpanEventsEnabled(boolean encodingEven public LettuceTelemetry build() { LettuceDbAttributesGetter dbAttributesGetter = new LettuceDbAttributesGetter(); + InstrumenterBuilder builder = + Instrumenter.builder( + openTelemetry, + INSTRUMENTATION_NAME, + DbClientSpanNameExtractor.create(dbAttributesGetter)) + .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) + .addOperationMetrics(DbClientMetrics.get()) + .setSpanStatusExtractor( + (spanStatusBuilder, request, response, error) -> { + if (response != null && response.getErrorMessage() != null) { + spanStatusBuilder.setStatus(StatusCode.ERROR); + } else { + SpanStatusExtractor.getDefault() + .extract(spanStatusBuilder, request, response, error); + } + }); + setDbClientExceptionEventExtractor(builder); + Instrumenter instrumenter = - setDbClientExceptionEventExtractor( - Instrumenter.builder( - openTelemetry, - INSTRUMENTATION_NAME, - DbClientSpanNameExtractor.create(dbAttributesGetter)) - .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) - .addOperationMetrics(DbClientMetrics.get()) - .setSpanStatusExtractor( - (spanStatusBuilder, request, response, error) -> { - if (response != null && response.getErrorMessage() != null) { - spanStatusBuilder.setStatus(StatusCode.ERROR); - } else { - SpanStatusExtractor.getDefault() - .extract(spanStatusBuilder, request, response, error); - } - })) - .buildInstrumenter(SpanKindExtractor.alwaysClient()); + builder.buildInstrumenter(SpanKindExtractor.alwaysClient()); return new LettuceTelemetry(instrumenter, querySanitizationEnabled, encodingEventsEnabled); } diff --git a/instrumentation/mongo/mongo-3.1/library/src/main/java/io/opentelemetry/instrumentation/mongo/v3_1/internal/MongoInstrumenterFactory.java b/instrumentation/mongo/mongo-3.1/library/src/main/java/io/opentelemetry/instrumentation/mongo/v3_1/internal/MongoInstrumenterFactory.java index 2643b507c4ab..439cce33f170 100644 --- a/instrumentation/mongo/mongo-3.1/library/src/main/java/io/opentelemetry/instrumentation/mongo/v3_1/internal/MongoInstrumenterFactory.java +++ b/instrumentation/mongo/mongo-3.1/library/src/main/java/io/opentelemetry/instrumentation/mongo/v3_1/internal/MongoInstrumenterFactory.java @@ -12,6 +12,7 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientAttributesExtractor; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientMetrics; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; @@ -44,13 +45,14 @@ public static Instrumenter createInstrumenter( SpanNameExtractor spanNameExtractor = new MongoSpanNameExtractor(dbAttributesGetter, attributesExtractor); - return setDbClientExceptionEventExtractor( - Instrumenter.builder( - openTelemetry, instrumentationName, spanNameExtractor) - .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) - .addAttributesExtractor(attributesExtractor) - .addOperationMetrics(DbClientMetrics.get())) - .buildInstrumenter(SpanKindExtractor.alwaysClient()); + InstrumenterBuilder builder = + Instrumenter.builder( + openTelemetry, instrumentationName, spanNameExtractor) + .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) + .addAttributesExtractor(attributesExtractor) + .addOperationMetrics(DbClientMetrics.get()); + setDbClientExceptionEventExtractor(builder); + return builder.buildInstrumenter(SpanKindExtractor.alwaysClient()); } private MongoInstrumenterFactory() {} diff --git a/instrumentation/opensearch/opensearch-java-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opensearch/v3_0/OpenSearchSingletons.java b/instrumentation/opensearch/opensearch-java-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opensearch/v3_0/OpenSearchSingletons.java index 29d2286fe5cc..904e7bd11757 100644 --- a/instrumentation/opensearch/opensearch-java-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opensearch/v3_0/OpenSearchSingletons.java +++ b/instrumentation/opensearch/opensearch-java-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opensearch/v3_0/OpenSearchSingletons.java @@ -13,6 +13,7 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientMetrics; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientSpanNameExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; class OpenSearchSingletons { @@ -29,15 +30,15 @@ public static Instrumenter instrumenter() { private static Instrumenter createInstrumenter() { OpenSearchAttributesGetter dbClientAttributesGetter = new OpenSearchAttributesGetter(); - return setDbClientExceptionEventExtractor( - Instrumenter.builder( - GlobalOpenTelemetry.get(), - "io.opentelemetry.opensearch-java-3.0", - DbClientSpanNameExtractor.create(dbClientAttributesGetter)) - .addAttributesExtractor( - DbClientAttributesExtractor.create(dbClientAttributesGetter)) - .addOperationMetrics(DbClientMetrics.get())) - .buildInstrumenter(SpanKindExtractor.alwaysClient()); + InstrumenterBuilder builder = + Instrumenter.builder( + GlobalOpenTelemetry.get(), + "io.opentelemetry.opensearch-java-3.0", + DbClientSpanNameExtractor.create(dbClientAttributesGetter)) + .addAttributesExtractor(DbClientAttributesExtractor.create(dbClientAttributesGetter)) + .addOperationMetrics(DbClientMetrics.get()); + setDbClientExceptionEventExtractor(builder); + return builder.buildInstrumenter(SpanKindExtractor.alwaysClient()); } private OpenSearchSingletons() {} diff --git a/instrumentation/opensearch/opensearch-rest-common-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opensearch/rest/common/v1_0/OpenSearchRestInstrumenterFactory.java b/instrumentation/opensearch/opensearch-rest-common-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opensearch/rest/common/v1_0/OpenSearchRestInstrumenterFactory.java index 3f81990d833a..3d2e6bc1a393 100644 --- a/instrumentation/opensearch/opensearch-rest-common-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opensearch/rest/common/v1_0/OpenSearchRestInstrumenterFactory.java +++ b/instrumentation/opensearch/opensearch-rest-common-1.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opensearch/rest/common/v1_0/OpenSearchRestInstrumenterFactory.java @@ -12,6 +12,7 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientMetrics; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientSpanNameExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; public class OpenSearchRestInstrumenterFactory { @@ -20,15 +21,15 @@ public static Instrumenter create String instrumentationName) { OpenSearchRestAttributesGetter dbClientAttributesGetter = new OpenSearchRestAttributesGetter(); - return setDbClientExceptionEventExtractor( - Instrumenter.builder( - GlobalOpenTelemetry.get(), - instrumentationName, - DbClientSpanNameExtractor.create(dbClientAttributesGetter)) - .addAttributesExtractor( - DbClientAttributesExtractor.create(dbClientAttributesGetter)) - .addOperationMetrics(DbClientMetrics.get())) - .buildInstrumenter(SpanKindExtractor.alwaysClient()); + InstrumenterBuilder builder = + Instrumenter.builder( + GlobalOpenTelemetry.get(), + instrumentationName, + DbClientSpanNameExtractor.create(dbClientAttributesGetter)) + .addAttributesExtractor(DbClientAttributesExtractor.create(dbClientAttributesGetter)) + .addOperationMetrics(DbClientMetrics.get()); + setDbClientExceptionEventExtractor(builder); + return builder.buildInstrumenter(SpanKindExtractor.alwaysClient()); } private OpenSearchRestInstrumenterFactory() {} diff --git a/instrumentation/r2dbc-1.0/library/src/main/java/io/opentelemetry/instrumentation/r2dbc/v1_0/internal/R2dbcInstrumenterBuilder.java b/instrumentation/r2dbc-1.0/library/src/main/java/io/opentelemetry/instrumentation/r2dbc/v1_0/internal/R2dbcInstrumenterBuilder.java index 7246c445a777..de8c3b770936 100644 --- a/instrumentation/r2dbc-1.0/library/src/main/java/io/opentelemetry/instrumentation/r2dbc/v1_0/internal/R2dbcInstrumenterBuilder.java +++ b/instrumentation/r2dbc-1.0/library/src/main/java/io/opentelemetry/instrumentation/r2dbc/v1_0/internal/R2dbcInstrumenterBuilder.java @@ -14,6 +14,7 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.db.SqlClientAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; import io.opentelemetry.instrumentation.api.instrumenter.SpanNameExtractor; import java.util.ArrayList; @@ -51,15 +52,16 @@ public Instrumenter build( spanNameExtractorTransformer.apply( DbClientSpanNameExtractor.create(new R2dbcSqlAttributesGetter())); - return setDbClientExceptionEventExtractor( - Instrumenter.builder( - openTelemetry, INSTRUMENTATION_NAME, spanNameExtractor) - .addAttributesExtractor( - SqlClientAttributesExtractor.builder(new R2dbcSqlAttributesGetter()) - .setQuerySanitizationEnabled(querySanitizationEnabled) - .build()) - .addAttributesExtractors(additionalExtractors) - .addOperationMetrics(DbClientMetrics.get())) - .buildInstrumenter(SpanKindExtractor.alwaysClient()); + InstrumenterBuilder builder = + Instrumenter.builder( + openTelemetry, INSTRUMENTATION_NAME, spanNameExtractor) + .addAttributesExtractor( + SqlClientAttributesExtractor.builder(new R2dbcSqlAttributesGetter()) + .setQuerySanitizationEnabled(querySanitizationEnabled) + .build()) + .addAttributesExtractors(additionalExtractors) + .addOperationMetrics(DbClientMetrics.get()); + setDbClientExceptionEventExtractor(builder); + return builder.buildInstrumenter(SpanKindExtractor.alwaysClient()); } } diff --git a/instrumentation/rediscala-1.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/v1_8/RediscalaSingletons.java b/instrumentation/rediscala-1.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/v1_8/RediscalaSingletons.java index b0bc3b655fd4..67c5ec815e21 100644 --- a/instrumentation/rediscala-1.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/v1_8/RediscalaSingletons.java +++ b/instrumentation/rediscala-1.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/v1_8/RediscalaSingletons.java @@ -12,6 +12,7 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientMetrics; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientSpanNameExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; import redis.RedisCommand; @@ -24,15 +25,16 @@ public class RediscalaSingletons { static { RediscalaAttributesGetter dbAttributesGetter = new RediscalaAttributesGetter(); - instrumenter = - setDbClientExceptionEventExtractor( - Instrumenter., Void>builder( - GlobalOpenTelemetry.get(), - INSTRUMENTATION_NAME, - DbClientSpanNameExtractor.create(dbAttributesGetter)) - .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) - .addOperationMetrics(DbClientMetrics.get())) - .buildInstrumenter(SpanKindExtractor.alwaysClient()); + InstrumenterBuilder, Void> builder = + Instrumenter., Void>builder( + GlobalOpenTelemetry.get(), + INSTRUMENTATION_NAME, + DbClientSpanNameExtractor.create(dbAttributesGetter)) + .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) + .addOperationMetrics(DbClientMetrics.get()); + setDbClientExceptionEventExtractor(builder); + + instrumenter = builder.buildInstrumenter(SpanKindExtractor.alwaysClient()); } public static Instrumenter, Void> instrumenter() { diff --git a/instrumentation/redisson/redisson-common-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/common/v3_0/RedissonInstrumenterFactory.java b/instrumentation/redisson/redisson-common-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/common/v3_0/RedissonInstrumenterFactory.java index 16197ffa97eb..16018f2f0568 100644 --- a/instrumentation/redisson/redisson-common-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/common/v3_0/RedissonInstrumenterFactory.java +++ b/instrumentation/redisson/redisson-common-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/common/v3_0/RedissonInstrumenterFactory.java @@ -12,6 +12,7 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientMetrics; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientSpanNameExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; public class RedissonInstrumenterFactory { @@ -19,14 +20,15 @@ public class RedissonInstrumenterFactory { public static Instrumenter createInstrumenter(String instrumentationName) { RedissonDbAttributesGetter dbAttributesGetter = new RedissonDbAttributesGetter(); - return setDbClientExceptionEventExtractor( - Instrumenter.builder( - GlobalOpenTelemetry.get(), - instrumentationName, - DbClientSpanNameExtractor.create(dbAttributesGetter)) - .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) - .addOperationMetrics(DbClientMetrics.get())) - .buildInstrumenter(SpanKindExtractor.alwaysClient()); + InstrumenterBuilder builder = + Instrumenter.builder( + GlobalOpenTelemetry.get(), + instrumentationName, + DbClientSpanNameExtractor.create(dbAttributesGetter)) + .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) + .addOperationMetrics(DbClientMetrics.get()); + setDbClientExceptionEventExtractor(builder); + return builder.buildInstrumenter(SpanKindExtractor.alwaysClient()); } private RedissonInstrumenterFactory() {} diff --git a/instrumentation/spymemcached-2.12/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/v2_12/SpymemcachedSingletons.java b/instrumentation/spymemcached-2.12/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/v2_12/SpymemcachedSingletons.java index 0b03c5a1bce2..06f11d5a4176 100644 --- a/instrumentation/spymemcached-2.12/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/v2_12/SpymemcachedSingletons.java +++ b/instrumentation/spymemcached-2.12/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/v2_12/SpymemcachedSingletons.java @@ -15,6 +15,7 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientSpanNameExtractor; import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; +import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.instrumenter.SpanKindExtractor; import io.opentelemetry.instrumentation.api.semconv.network.ServerAttributesExtractor; import javax.annotation.Nullable; @@ -31,38 +32,36 @@ public class SpymemcachedSingletons { ServerAttributesExtractor serverAttributesExtractor = ServerAttributesExtractor.create(serverAttributesGetter); - instrumenter = - setDbClientExceptionEventExtractor( - Instrumenter.builder( - GlobalOpenTelemetry.get(), - INSTRUMENTATION_NAME, - DbClientSpanNameExtractor.create(dbAttributesGetter)) - .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) - .addAttributesExtractor( - new AttributesExtractor() { - @Override - public void onStart( - AttributesBuilder attributes, - Context context, - SpymemcachedRequest request) {} + InstrumenterBuilder builder = + Instrumenter.builder( + GlobalOpenTelemetry.get(), + INSTRUMENTATION_NAME, + DbClientSpanNameExtractor.create(dbAttributesGetter)) + .addAttributesExtractor(DbClientAttributesExtractor.create(dbAttributesGetter)) + .addAttributesExtractor( + new AttributesExtractor() { + @Override + public void onStart( + AttributesBuilder attributes, Context context, SpymemcachedRequest request) {} - @Override - public void onEnd( - AttributesBuilder attributes, - Context context, - SpymemcachedRequest request, - @Nullable Object object, - @Nullable Throwable error) { - // For spymemcached, we can only extract server attributes at the - // end of the request because they are not available at the start. - serverAttributesExtractor.onStart(attributes, context, request); - } - }) - .addContextCustomizer( - (context, request, attributes) -> - SpymemcachedRequestHolder.init(context, request)) - .addOperationMetrics(DbClientMetrics.get())) - .buildInstrumenter(SpanKindExtractor.alwaysClient()); + @Override + public void onEnd( + AttributesBuilder attributes, + Context context, + SpymemcachedRequest request, + @Nullable Object object, + @Nullable Throwable error) { + // For spymemcached, we can only extract server attributes at the + // end of the request because they are not available at the start. + serverAttributesExtractor.onStart(attributes, context, request); + } + }) + .addContextCustomizer( + (context, request, attributes) -> SpymemcachedRequestHolder.init(context, request)) + .addOperationMetrics(DbClientMetrics.get()); + setDbClientExceptionEventExtractor(builder); + + instrumenter = builder.buildInstrumenter(SpanKindExtractor.alwaysClient()); } public static Instrumenter instrumenter() { From 50dc81eadfb976304043245d351b59f8f702afb3 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Fri, 5 Jun 2026 11:04:17 -0700 Subject: [PATCH 3/9] Apply suggestion from @trask --- .../spymemcached/v2_12/SpymemcachedSingletons.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/instrumentation/spymemcached-2.12/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/v2_12/SpymemcachedSingletons.java b/instrumentation/spymemcached-2.12/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/v2_12/SpymemcachedSingletons.java index 06f11d5a4176..8f22d4ec1028 100644 --- a/instrumentation/spymemcached-2.12/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/v2_12/SpymemcachedSingletons.java +++ b/instrumentation/spymemcached-2.12/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/v2_12/SpymemcachedSingletons.java @@ -51,8 +51,8 @@ public void onEnd( SpymemcachedRequest request, @Nullable Object object, @Nullable Throwable error) { - // For spymemcached, we can only extract server attributes at the - // end of the request because they are not available at the start. + // For spymemcached, we can only extract server attributes at the end of the + // request because they are not available at the start. serverAttributesExtractor.onStart(attributes, context, request); } }) From 031e78832b2a012b129fc6c89de055918b383062 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Fri, 5 Jun 2026 11:35:02 -0700 Subject: [PATCH 4/9] simplify --- .../AbstractJdbcInstrumentationTest.java | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/instrumentation/jdbc/testing/src/main/java/io/opentelemetry/instrumentation/jdbc/testing/AbstractJdbcInstrumentationTest.java b/instrumentation/jdbc/testing/src/main/java/io/opentelemetry/instrumentation/jdbc/testing/AbstractJdbcInstrumentationTest.java index be14e4bf891a..3400c2cb13b9 100644 --- a/instrumentation/jdbc/testing/src/main/java/io/opentelemetry/instrumentation/jdbc/testing/AbstractJdbcInstrumentationTest.java +++ b/instrumentation/jdbc/testing/src/main/java/io/opentelemetry/instrumentation/jdbc/testing/AbstractJdbcInstrumentationTest.java @@ -37,7 +37,9 @@ import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DbSystemNameIncubatingValues.OTHER_SQL; import static java.util.Arrays.asList; import static java.util.stream.Collectors.toList; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.Assertions.catchThrowable; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; @@ -435,13 +437,15 @@ void testFailedStatement() throws SQLException { Statement statement = connection.createStatement(); cleanup.deferCleanup(statement); - assertThatThrownBy( + Throwable error = + catchThrowable( () -> testing() .runWithSpan( "parent", - () -> statement.executeQuery("SELECT * FROM table_does_not_exist"))) - .isInstanceOf(SQLException.class); + () -> statement.executeQuery("SELECT * FROM table_does_not_exist"))); + + assertThat(error).isInstanceOf(SQLException.class); testing() .waitAndAssertTraces( @@ -452,16 +456,7 @@ void testFailedStatement() throws SQLException { span.hasKind(SpanKind.CLIENT) .hasParent(trace.getSpan(0)) .hasStatus(StatusData.error()) - .satisfies( - spanData -> { - if (emitExceptionAsSpanEvents()) { - assertThat(spanData.getEvents()).hasSize(1); - assertThat(spanData.getEvents().get(0).getName()) - .isEqualTo("exception"); - } else { - assertThat(spanData.getEvents()).isEmpty(); - } - }))); + .hasException(emitExceptionAsSpanEvents() ? error : null))); if (emitExceptionAsLogs()) { assertExceptionLog(); From 48a969b27903826590a0b0c0d41d56f0d782a753 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Fri, 5 Jun 2026 11:45:11 -0700 Subject: [PATCH 5/9] Inline JDBC exception log assertion --- .../AbstractJdbcInstrumentationTest.java | 34 ++++++------------- 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/instrumentation/jdbc/testing/src/main/java/io/opentelemetry/instrumentation/jdbc/testing/AbstractJdbcInstrumentationTest.java b/instrumentation/jdbc/testing/src/main/java/io/opentelemetry/instrumentation/jdbc/testing/AbstractJdbcInstrumentationTest.java index 3400c2cb13b9..db805eb26b22 100644 --- a/instrumentation/jdbc/testing/src/main/java/io/opentelemetry/instrumentation/jdbc/testing/AbstractJdbcInstrumentationTest.java +++ b/instrumentation/jdbc/testing/src/main/java/io/opentelemetry/instrumentation/jdbc/testing/AbstractJdbcInstrumentationTest.java @@ -36,7 +36,6 @@ import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DbSystemNameIncubatingValues.HSQLDB; import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DbSystemNameIncubatingValues.OTHER_SQL; import static java.util.Arrays.asList; -import static java.util.stream.Collectors.toList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.catchThrowable; @@ -52,7 +51,6 @@ import io.opentelemetry.instrumentation.jdbc.TestDriver; import io.opentelemetry.instrumentation.testing.internal.AutoCleanupExtension; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; -import io.opentelemetry.sdk.logs.data.LogRecordData; import io.opentelemetry.sdk.testing.assertj.AttributeAssertion; import io.opentelemetry.sdk.testing.assertj.SpanDataAssert; import io.opentelemetry.sdk.testing.assertj.TraceAssert; @@ -78,7 +76,6 @@ import org.apache.derby.jdbc.EmbeddedDataSource; import org.apache.derby.jdbc.EmbeddedDriver; import org.assertj.core.api.ThrowingConsumer; -import org.awaitility.Awaitility; import org.h2.jdbcx.JdbcDataSource; import org.hsqldb.jdbc.JDBCDriver; import org.junit.jupiter.api.BeforeAll; @@ -459,30 +456,19 @@ void testFailedStatement() throws SQLException { .hasException(emitExceptionAsSpanEvents() ? error : null))); if (emitExceptionAsLogs()) { - assertExceptionLog(); + testing() + .waitAndAssertLogRecords( + logRecord -> + logRecord + .hasSeverity(Severity.WARN) + .hasEventName("db.client.operation.exception") + .hasAttributesSatisfyingExactly( + equalTo(EXCEPTION_TYPE, error.getClass().getName()), + equalTo(EXCEPTION_MESSAGE, error.getMessage()), + satisfies(EXCEPTION_STACKTRACE, val -> val.isNotNull()))); } } - private void assertExceptionLog() { - Awaitility.await() - .untilAsserted( - () -> { - List logs = - testing().logRecords().stream() - .filter(log -> "db.client.operation.exception".equals(log.getEventName())) - .collect(toList()); - - assertThat(logs).hasSize(1); - assertThat(logs.get(0)) - .hasSeverity(Severity.WARN) - .hasEventName("db.client.operation.exception") - .hasAttributesSatisfyingExactly( - satisfies(EXCEPTION_TYPE, val -> val.isNotNull()), - satisfies(EXCEPTION_MESSAGE, val -> val.isNotNull()), - satisfies(EXCEPTION_STACKTRACE, val -> val.isNotNull())); - }); - } - static Stream preparedStatementStream() throws SQLException { return Stream.of( Arguments.of( From 2c442bd2fd61d4363fd69227d312b12e1237698b Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Fri, 5 Jun 2026 13:41:10 -0700 Subject: [PATCH 6/9] Fix JDBC exception log test filtering The JDBC exception signal log test used waitAndAssertLogRecords(), which expects the captured log list to contain only the asserted records. In these test runs, unrelated JDBC driver or pool logs can be captured first, and the logged exception class/message can be normalized differently from the thrown SQLException subtype. Restore filtering to the db.client.operation.exception log record and assert that the exception attributes are present instead of matching the exact thrown exception values. Validation: .\gradlew.bat :instrumentation:jdbc:library:testExceptionSignalLogs :instrumentation:jdbc:javaagent:testExceptionSignalLogs --no-build-cache --- .../AbstractJdbcInstrumentationTest.java | 34 +++++++++++++------ 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/instrumentation/jdbc/testing/src/main/java/io/opentelemetry/instrumentation/jdbc/testing/AbstractJdbcInstrumentationTest.java b/instrumentation/jdbc/testing/src/main/java/io/opentelemetry/instrumentation/jdbc/testing/AbstractJdbcInstrumentationTest.java index db805eb26b22..3400c2cb13b9 100644 --- a/instrumentation/jdbc/testing/src/main/java/io/opentelemetry/instrumentation/jdbc/testing/AbstractJdbcInstrumentationTest.java +++ b/instrumentation/jdbc/testing/src/main/java/io/opentelemetry/instrumentation/jdbc/testing/AbstractJdbcInstrumentationTest.java @@ -36,6 +36,7 @@ import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DbSystemNameIncubatingValues.HSQLDB; import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DbSystemNameIncubatingValues.OTHER_SQL; import static java.util.Arrays.asList; +import static java.util.stream.Collectors.toList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.catchThrowable; @@ -51,6 +52,7 @@ import io.opentelemetry.instrumentation.jdbc.TestDriver; import io.opentelemetry.instrumentation.testing.internal.AutoCleanupExtension; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.sdk.logs.data.LogRecordData; import io.opentelemetry.sdk.testing.assertj.AttributeAssertion; import io.opentelemetry.sdk.testing.assertj.SpanDataAssert; import io.opentelemetry.sdk.testing.assertj.TraceAssert; @@ -76,6 +78,7 @@ import org.apache.derby.jdbc.EmbeddedDataSource; import org.apache.derby.jdbc.EmbeddedDriver; import org.assertj.core.api.ThrowingConsumer; +import org.awaitility.Awaitility; import org.h2.jdbcx.JdbcDataSource; import org.hsqldb.jdbc.JDBCDriver; import org.junit.jupiter.api.BeforeAll; @@ -456,19 +459,30 @@ void testFailedStatement() throws SQLException { .hasException(emitExceptionAsSpanEvents() ? error : null))); if (emitExceptionAsLogs()) { - testing() - .waitAndAssertLogRecords( - logRecord -> - logRecord - .hasSeverity(Severity.WARN) - .hasEventName("db.client.operation.exception") - .hasAttributesSatisfyingExactly( - equalTo(EXCEPTION_TYPE, error.getClass().getName()), - equalTo(EXCEPTION_MESSAGE, error.getMessage()), - satisfies(EXCEPTION_STACKTRACE, val -> val.isNotNull()))); + assertExceptionLog(); } } + private void assertExceptionLog() { + Awaitility.await() + .untilAsserted( + () -> { + List logs = + testing().logRecords().stream() + .filter(log -> "db.client.operation.exception".equals(log.getEventName())) + .collect(toList()); + + assertThat(logs).hasSize(1); + assertThat(logs.get(0)) + .hasSeverity(Severity.WARN) + .hasEventName("db.client.operation.exception") + .hasAttributesSatisfyingExactly( + satisfies(EXCEPTION_TYPE, val -> val.isNotNull()), + satisfies(EXCEPTION_MESSAGE, val -> val.isNotNull()), + satisfies(EXCEPTION_STACKTRACE, val -> val.isNotNull())); + }); + } + static Stream preparedStatementStream() throws SQLException { return Stream.of( Arguments.of( From 9d22c5dc1a3aa5ccef7786e8e28984926f7f1f43 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Fri, 5 Jun 2026 15:14:12 -0700 Subject: [PATCH 7/9] Assert JDBC exception log records --- .../AbstractJdbcInstrumentationTest.java | 42 +++++++------------ 1 file changed, 14 insertions(+), 28 deletions(-) diff --git a/instrumentation/jdbc/testing/src/main/java/io/opentelemetry/instrumentation/jdbc/testing/AbstractJdbcInstrumentationTest.java b/instrumentation/jdbc/testing/src/main/java/io/opentelemetry/instrumentation/jdbc/testing/AbstractJdbcInstrumentationTest.java index 3400c2cb13b9..1e82635f9ca3 100644 --- a/instrumentation/jdbc/testing/src/main/java/io/opentelemetry/instrumentation/jdbc/testing/AbstractJdbcInstrumentationTest.java +++ b/instrumentation/jdbc/testing/src/main/java/io/opentelemetry/instrumentation/jdbc/testing/AbstractJdbcInstrumentationTest.java @@ -16,15 +16,11 @@ import static io.opentelemetry.instrumentation.testing.util.TestLatestDeps.testLatestDeps; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; -import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies; import static io.opentelemetry.semconv.DbAttributes.DB_NAMESPACE; import static io.opentelemetry.semconv.DbAttributes.DB_OPERATION_BATCH_SIZE; import static io.opentelemetry.semconv.DbAttributes.DB_QUERY_SUMMARY; import static io.opentelemetry.semconv.DbAttributes.DB_STORED_PROCEDURE_NAME; import static io.opentelemetry.semconv.DbAttributes.DB_SYSTEM_NAME; -import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_MESSAGE; -import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_STACKTRACE; -import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_TYPE; import static io.opentelemetry.semconv.ServerAttributes.SERVER_ADDRESS; import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_CONNECTION_STRING; import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_NAME; @@ -36,7 +32,6 @@ import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DbSystemNameIncubatingValues.HSQLDB; import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DbSystemNameIncubatingValues.OTHER_SQL; import static java.util.Arrays.asList; -import static java.util.stream.Collectors.toList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.catchThrowable; @@ -52,7 +47,6 @@ import io.opentelemetry.instrumentation.jdbc.TestDriver; import io.opentelemetry.instrumentation.testing.internal.AutoCleanupExtension; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; -import io.opentelemetry.sdk.logs.data.LogRecordData; import io.opentelemetry.sdk.testing.assertj.AttributeAssertion; import io.opentelemetry.sdk.testing.assertj.SpanDataAssert; import io.opentelemetry.sdk.testing.assertj.TraceAssert; @@ -78,7 +72,6 @@ import org.apache.derby.jdbc.EmbeddedDataSource; import org.apache.derby.jdbc.EmbeddedDriver; import org.assertj.core.api.ThrowingConsumer; -import org.awaitility.Awaitility; import org.h2.jdbcx.JdbcDataSource; import org.hsqldb.jdbc.JDBCDriver; import org.junit.jupiter.api.BeforeAll; @@ -459,30 +452,23 @@ void testFailedStatement() throws SQLException { .hasException(emitExceptionAsSpanEvents() ? error : null))); if (emitExceptionAsLogs()) { - assertExceptionLog(); + testing() + .waitAndAssertLogRecords( + logRecord -> + logRecord + .hasSeverity(Severity.WARN) + .hasEventName("db.client.operation.exception") + .hasException(error) + .hasTotalAttributeCount(3), + logRecord -> + logRecord + .hasSeverity(Severity.WARN) + .hasEventName("exception") + .hasException(error) + .hasTotalAttributeCount(3)); } } - private void assertExceptionLog() { - Awaitility.await() - .untilAsserted( - () -> { - List logs = - testing().logRecords().stream() - .filter(log -> "db.client.operation.exception".equals(log.getEventName())) - .collect(toList()); - - assertThat(logs).hasSize(1); - assertThat(logs.get(0)) - .hasSeverity(Severity.WARN) - .hasEventName("db.client.operation.exception") - .hasAttributesSatisfyingExactly( - satisfies(EXCEPTION_TYPE, val -> val.isNotNull()), - satisfies(EXCEPTION_MESSAGE, val -> val.isNotNull()), - satisfies(EXCEPTION_STACKTRACE, val -> val.isNotNull())); - }); - } - static Stream preparedStatementStream() throws SQLException { return Stream.of( Arguments.of( From f16611e2294ec7c12f13a0f0a974175db2d31cfd Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Sat, 6 Jun 2026 16:06:57 -0700 Subject: [PATCH 8/9] Address review comment: clean up failed JDBC test connection --- .../jdbc/testing/AbstractJdbcInstrumentationTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/instrumentation/jdbc/testing/src/main/java/io/opentelemetry/instrumentation/jdbc/testing/AbstractJdbcInstrumentationTest.java b/instrumentation/jdbc/testing/src/main/java/io/opentelemetry/instrumentation/jdbc/testing/AbstractJdbcInstrumentationTest.java index 1e82635f9ca3..96933a57b976 100644 --- a/instrumentation/jdbc/testing/src/main/java/io/opentelemetry/instrumentation/jdbc/testing/AbstractJdbcInstrumentationTest.java +++ b/instrumentation/jdbc/testing/src/main/java/io/opentelemetry/instrumentation/jdbc/testing/AbstractJdbcInstrumentationTest.java @@ -427,6 +427,7 @@ isCallStatement && emitStableDatabaseSemconv() @Test void testFailedStatement() throws SQLException { Connection connection = wrap(new org.h2.Driver().connect(JDBC_URLS.get("h2"), null)); + cleanup.deferCleanup(connection); Statement statement = connection.createStatement(); cleanup.deferCleanup(statement); From c0fe32d297126586a2b565de8441b9dd1c1d0e61 Mon Sep 17 00:00:00 2001 From: Trask Stalnaker Date: Sat, 6 Jun 2026 16:35:40 -0700 Subject: [PATCH 9/9] Relax DB helper builder type --- .../semconv/db/internal/DbExceptionEventExtractors.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/internal/DbExceptionEventExtractors.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/internal/DbExceptionEventExtractors.java index 1afb5a41db2c..a6e915e62e03 100644 --- a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/internal/DbExceptionEventExtractors.java +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/internal/DbExceptionEventExtractors.java @@ -5,7 +5,6 @@ package io.opentelemetry.instrumentation.api.incubator.semconv.db.internal; -import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.opentelemetry.api.logs.Severity; import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder; import io.opentelemetry.instrumentation.api.internal.Experimental; @@ -21,17 +20,14 @@ public final class DbExceptionEventExtractors { * emitting exceptions as logs is enabled via the {@code otel.semconv.exception.signal.preview} * flag. */ - @CanIgnoreReturnValue - public static - InstrumenterBuilder setDbClientExceptionEventExtractor( - InstrumenterBuilder builder) { + public static void setDbClientExceptionEventExtractor( + InstrumenterBuilder builder) { Experimental.setExceptionEventExtractor( builder, (logRecordBuilder, context, request) -> { logRecordBuilder.setEventName("db.client.operation.exception"); logRecordBuilder.setSeverity(Severity.WARN); }); - return builder; } private DbExceptionEventExtractors() {}