From e2cce4cc162c6994420aa66c3c8f4f3c631c52be Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Mon, 31 Mar 2025 14:40:16 +0200 Subject: [PATCH] Db client error type for JDBC (#13331) Co-authored-by: Jay DeLuca --- .../db/DbClientAttributesExtractor.java | 10 ++-- .../semconv/db/DbClientAttributesGetter.java | 3 +- .../db/DbClientCommonAttributesExtractor.java | 16 ++++- .../db/DbClientCommonAttributesGetter.java | 7 ++- .../semconv/db/DbClientMetricsAdvice.java | 4 -- .../semconv/db/DbClientSpanNameExtractor.java | 12 ++-- .../db/SqlClientAttributesExtractor.java | 8 +-- .../SqlClientAttributesExtractorBuilder.java | 4 +- .../semconv/db/SqlClientAttributesGetter.java | 4 +- .../db/DbClientAttributesExtractorTest.java | 3 +- .../semconv/db/DbClientMetricsTest.java | 4 +- .../db/DbClientSpanNameExtractorTest.java | 4 +- .../db/SqlClientAttributesExtractorTest.java | 5 +- .../v3_0/CassandraSqlAttributesGetter.java | 4 +- .../v4_0/CassandraSqlAttributesGetter.java | 4 +- .../v4_4/CassandraSqlAttributesGetter.java | 4 +- .../ClickHouseAttributesGetter.java | 13 ++++- .../clickhouse/ClickHouseClientTest.java | 13 ++++- .../v2_0/CouchbaseAttributesGetter.java | 3 +- .../ElasticsearchDbAttributesGetter.java | 13 ++++- .../Elasticsearch53SpringTemplateTest.java | 28 ++++++--- ...lasticsearchTransportAttributesGetter.java | 3 +- .../AbstractElasticsearchNodeClientTest.java | 26 ++++++--- ...tractElasticsearchTransportClientTest.java | 26 ++++++--- .../geode/GeodeDbAttributesGetter.java | 2 +- .../v2_4/InfluxDbAttributesGetter.java | 2 +- .../jdbc/internal/JdbcAttributesGetter.java | 12 +++- .../jdbc/datasource/JdbcTelemetryTest.java | 58 +++++++++++++++++++ .../jedis/v1_4/JedisDbAttributesGetter.java | 2 +- .../jedis/v3_0/JedisDbAttributesGetter.java | 2 +- .../jedis/v4_0/JedisDbAttributesGetter.java | 2 +- .../v4_0/LettuceDbAttributesGetter.java | 3 +- .../lettuce/v4_0/LettuceAsyncClientTest.java | 19 +++++- .../v5_0/LettuceDbAttributesGetter.java | 3 +- .../lettuce/v5_0/LettuceAsyncClientTest.java | 22 +++++-- .../mongo/v3_1/MongoDbAttributesGetter.java | 12 +++- .../rest/OpenSearchRestAttributesGetter.java | 13 ++++- .../internal/R2dbcSqlAttributesGetter.java | 12 +++- .../rediscala/RediscalaAttributesGetter.java | 3 +- .../redisson/RedissonDbAttributesGetter.java | 2 +- .../SpymemcachedAttributesGetter.java | 3 +- .../spymemcached/SpymemcachedTest.java | 45 ++++++++++---- .../VertxRedisClientAttributesGetter.java | 2 +- .../sql/VertxSqlClientAttributesGetter.java | 21 ++++++- .../vertx/v4_0/sql/VertxSqlClientTest.java | 25 ++++++-- 45 files changed, 378 insertions(+), 108 deletions(-) diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientAttributesExtractor.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientAttributesExtractor.java index 02318b4e34..f7f2231ff1 100644 --- a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientAttributesExtractor.java +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientAttributesExtractor.java @@ -23,23 +23,23 @@ import io.opentelemetry.instrumentation.api.internal.SemconvStability; */ public final class DbClientAttributesExtractor extends DbClientCommonAttributesExtractor< - REQUEST, RESPONSE, DbClientAttributesGetter> { + REQUEST, RESPONSE, DbClientAttributesGetter> { // copied from DbIncubatingAttributes private static final AttributeKey DB_STATEMENT = AttributeKey.stringKey("db.statement"); private static final AttributeKey DB_QUERY_TEXT = AttributeKey.stringKey("db.query.text"); static final AttributeKey DB_OPERATION = AttributeKey.stringKey("db.operation"); static final AttributeKey DB_OPERATION_NAME = AttributeKey.stringKey("db.operation.name"); - static final AttributeKey DB_RESPONSE_STATUS_CODE = - AttributeKey.longKey("db.response.status_code"); + static final AttributeKey DB_RESPONSE_STATUS_CODE = + AttributeKey.stringKey("db.response.status_code"); /** Creates the database client attributes extractor with default configuration. */ public static AttributesExtractor create( - DbClientAttributesGetter getter) { + DbClientAttributesGetter getter) { return new DbClientAttributesExtractor<>(getter); } - DbClientAttributesExtractor(DbClientAttributesGetter getter) { + DbClientAttributesExtractor(DbClientAttributesGetter getter) { super(getter); } diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientAttributesGetter.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientAttributesGetter.java index ddf9f8f07a..be92ad1d0c 100644 --- a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientAttributesGetter.java +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientAttributesGetter.java @@ -18,7 +18,8 @@ import javax.annotation.Nullable; * from the attribute methods, but implement as many as possible for best compliance with the * OpenTelemetry specification. */ -public interface DbClientAttributesGetter extends DbClientCommonAttributesGetter { +public interface DbClientAttributesGetter + extends DbClientCommonAttributesGetter { /** * @deprecated Use {@link #getDbQueryText(REQUEST)} instead. diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientCommonAttributesExtractor.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientCommonAttributesExtractor.java index 226db055b2..fd01cde296 100644 --- a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientCommonAttributesExtractor.java +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientCommonAttributesExtractor.java @@ -6,6 +6,7 @@ package io.opentelemetry.instrumentation.api.incubator.semconv.db; import static io.opentelemetry.instrumentation.api.internal.AttributesExtractorUtil.internalSet; +import static io.opentelemetry.semconv.ErrorAttributes.ERROR_TYPE; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.AttributesBuilder; @@ -17,7 +18,7 @@ import io.opentelemetry.instrumentation.api.internal.SpanKeyProvider; import javax.annotation.Nullable; abstract class DbClientCommonAttributesExtractor< - REQUEST, RESPONSE, GETTER extends DbClientCommonAttributesGetter> + REQUEST, RESPONSE, GETTER extends DbClientCommonAttributesGetter> implements AttributesExtractor, SpanKeyProvider { // copied from DbIncubatingAttributes @@ -29,6 +30,8 @@ abstract class DbClientCommonAttributesExtractor< private static final AttributeKey DB_USER = AttributeKey.stringKey("db.user"); private static final AttributeKey DB_CONNECTION_STRING = AttributeKey.stringKey("db.connection_string"); + private static final AttributeKey DB_RESPONSE_STATUS_CODE = + AttributeKey.stringKey("db.response.status_code"); final GETTER getter; @@ -60,7 +63,16 @@ abstract class DbClientCommonAttributesExtractor< Context context, REQUEST request, @Nullable RESPONSE response, - @Nullable Throwable error) {} + @Nullable Throwable error) { + if (SemconvStability.emitStableDatabaseSemconv()) { + if (error != null) { + internalSet(attributes, ERROR_TYPE, error.getClass().getName()); + } + if (error != null || response != null) { + internalSet(attributes, DB_RESPONSE_STATUS_CODE, getter.getResponseStatus(response, error)); + } + } + } /** * This method is internal and is hence not for public use. Its API is unstable and can change at diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientCommonAttributesGetter.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientCommonAttributesGetter.java index bc9a335f4e..7797b5b9f9 100644 --- a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientCommonAttributesGetter.java +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientCommonAttributesGetter.java @@ -8,7 +8,7 @@ package io.opentelemetry.instrumentation.api.incubator.semconv.db; import javax.annotation.Nullable; /** An interface for getting attributes common to database clients. */ -public interface DbClientCommonAttributesGetter { +public interface DbClientCommonAttributesGetter { @Deprecated @Nullable @@ -44,4 +44,9 @@ public interface DbClientCommonAttributesGetter { @Deprecated @Nullable String getConnectionString(REQUEST request); + + @Nullable + default String getResponseStatus(@Nullable RESPONSE response, @Nullable Throwable error) { + return null; + } } diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientMetricsAdvice.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientMetricsAdvice.java index bce9910964..72f9b0a221 100644 --- a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientMetricsAdvice.java +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientMetricsAdvice.java @@ -32,11 +32,7 @@ final class DbClientMetricsAdvice { SqlClientAttributesExtractor.DB_COLLECTION_NAME, DbClientCommonAttributesExtractor.DB_NAMESPACE, DbClientAttributesExtractor.DB_OPERATION_NAME, - // will be implemented in - // https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/12804 DbClientAttributesExtractor.DB_RESPONSE_STATUS_CODE, - // will be implemented in - // https://github.com/open-telemetry/opentelemetry-java-instrumentation/issues/12804 ErrorAttributes.ERROR_TYPE, NetworkAttributes.NETWORK_PEER_ADDRESS, NetworkAttributes.NETWORK_PEER_PORT, diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientSpanNameExtractor.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientSpanNameExtractor.java index 78f0f65927..0520076855 100644 --- a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientSpanNameExtractor.java +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientSpanNameExtractor.java @@ -20,7 +20,7 @@ public abstract class DbClientSpanNameExtractor implements SpanNameExtr * @see DbClientAttributesGetter#getDbNamespace(Object) used to extract {@code }. */ public static SpanNameExtractor create( - DbClientAttributesGetter getter) { + DbClientAttributesGetter getter) { return new GenericDbClientSpanNameExtractor<>(getter); } @@ -34,7 +34,7 @@ public abstract class DbClientSpanNameExtractor implements SpanNameExtr * procedure name. */ public static SpanNameExtractor create( - SqlClientAttributesGetter getter) { + SqlClientAttributesGetter getter) { return new SqlClientSpanNameExtractor<>(getter); } @@ -67,9 +67,9 @@ public abstract class DbClientSpanNameExtractor implements SpanNameExtr private static final class GenericDbClientSpanNameExtractor extends DbClientSpanNameExtractor { - private final DbClientAttributesGetter getter; + private final DbClientAttributesGetter getter; - private GenericDbClientSpanNameExtractor(DbClientAttributesGetter getter) { + private GenericDbClientSpanNameExtractor(DbClientAttributesGetter getter) { this.getter = getter; } @@ -87,9 +87,9 @@ public abstract class DbClientSpanNameExtractor implements SpanNameExtr // a dedicated sanitizer just for extracting the operation and identifier name private static final SqlStatementSanitizer sanitizer = SqlStatementSanitizer.create(true); - private final SqlClientAttributesGetter getter; + private final SqlClientAttributesGetter getter; - private SqlClientSpanNameExtractor(SqlClientAttributesGetter getter) { + private SqlClientSpanNameExtractor(SqlClientAttributesGetter getter) { this.getter = getter; } diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/SqlClientAttributesExtractor.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/SqlClientAttributesExtractor.java index 50f9bbdba0..c6a3c82656 100644 --- a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/SqlClientAttributesExtractor.java +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/SqlClientAttributesExtractor.java @@ -26,7 +26,7 @@ import java.util.Collection; */ public final class SqlClientAttributesExtractor extends DbClientCommonAttributesExtractor< - REQUEST, RESPONSE, SqlClientAttributesGetter> { + REQUEST, RESPONSE, SqlClientAttributesGetter> { // copied from DbIncubatingAttributes private static final AttributeKey DB_OPERATION = AttributeKey.stringKey("db.operation"); @@ -41,7 +41,7 @@ public final class SqlClientAttributesExtractor /** Creates the SQL client attributes extractor with default configuration. */ public static AttributesExtractor create( - SqlClientAttributesGetter getter) { + SqlClientAttributesGetter getter) { return SqlClientAttributesExtractor.builder(getter).build(); } @@ -50,7 +50,7 @@ public final class SqlClientAttributesExtractor * client attributes extractor. */ public static SqlClientAttributesExtractorBuilder builder( - SqlClientAttributesGetter getter) { + SqlClientAttributesGetter getter) { return new SqlClientAttributesExtractorBuilder<>(getter); } @@ -62,7 +62,7 @@ public final class SqlClientAttributesExtractor private final boolean statementSanitizationEnabled; SqlClientAttributesExtractor( - SqlClientAttributesGetter getter, + SqlClientAttributesGetter getter, AttributeKey oldSemconvTableAttribute, boolean statementSanitizationEnabled) { super(getter); diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/SqlClientAttributesExtractorBuilder.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/SqlClientAttributesExtractorBuilder.java index 4e7672e942..43cbc63062 100644 --- a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/SqlClientAttributesExtractorBuilder.java +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/SqlClientAttributesExtractorBuilder.java @@ -17,11 +17,11 @@ public final class SqlClientAttributesExtractorBuilder { // copied from DbIncubatingAttributes private static final AttributeKey DB_SQL_TABLE = AttributeKey.stringKey("db.sql.table"); - final SqlClientAttributesGetter getter; + final SqlClientAttributesGetter getter; AttributeKey oldSemconvTableAttribute = DB_SQL_TABLE; boolean statementSanitizationEnabled = true; - SqlClientAttributesExtractorBuilder(SqlClientAttributesGetter getter) { + SqlClientAttributesExtractorBuilder(SqlClientAttributesGetter getter) { this.getter = getter; } diff --git a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/SqlClientAttributesGetter.java b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/SqlClientAttributesGetter.java index 693c907de4..1b795363e7 100644 --- a/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/SqlClientAttributesGetter.java +++ b/instrumentation-api-incubator/src/main/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/SqlClientAttributesGetter.java @@ -22,8 +22,8 @@ import javax.annotation.Nullable; * from the attribute methods, but implement as many as possible for best compliance with the * OpenTelemetry specification. */ -public interface SqlClientAttributesGetter - extends DbClientCommonAttributesGetter { +public interface SqlClientAttributesGetter + extends DbClientCommonAttributesGetter { /** * Get the raw SQL statement. The value returned by this method is later sanitized by the {@link diff --git a/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientAttributesExtractorTest.java b/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientAttributesExtractorTest.java index 7ee75a5183..ec8e7fc373 100644 --- a/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientAttributesExtractorTest.java +++ b/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientAttributesExtractorTest.java @@ -21,7 +21,8 @@ import org.junit.jupiter.api.Test; class DbClientAttributesExtractorTest { - static final class TestAttributesGetter implements DbClientAttributesGetter> { + static final class TestAttributesGetter + implements DbClientAttributesGetter, Void> { @Override public String getDbSystem(Map map) { return map.get("db.system"); diff --git a/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientMetricsTest.java b/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientMetricsTest.java index 8ca4ce4997..a3769d68e0 100644 --- a/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientMetricsTest.java +++ b/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientMetricsTest.java @@ -52,7 +52,7 @@ class DbClientMetricsTest { Attributes responseAttributes = Attributes.builder() - .put(DbClientAttributesExtractor.DB_RESPONSE_STATUS_CODE, 200) + .put(DbClientAttributesExtractor.DB_RESPONSE_STATUS_CODE, "200") .put(ErrorAttributes.ERROR_TYPE, "400") .put(NetworkAttributes.NETWORK_PEER_ADDRESS, "1.2.3.4") .put(NetworkAttributes.NETWORK_PEER_PORT, 8080) @@ -104,7 +104,7 @@ class DbClientMetricsTest { equalTo(ServerAttributes.SERVER_PORT, 1234), equalTo( DbClientAttributesExtractor.DB_RESPONSE_STATUS_CODE, - 200), + "200"), equalTo(ErrorAttributes.ERROR_TYPE, "400"), equalTo( NetworkAttributes.NETWORK_PEER_ADDRESS, "1.2.3.4"), diff --git a/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientSpanNameExtractorTest.java b/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientSpanNameExtractorTest.java index 57c446b191..36ec3ff43f 100644 --- a/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientSpanNameExtractorTest.java +++ b/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/DbClientSpanNameExtractorTest.java @@ -19,8 +19,8 @@ import org.mockito.junit.jupiter.MockitoExtension; @ExtendWith(MockitoExtension.class) class DbClientSpanNameExtractorTest { - @Mock DbClientAttributesGetter dbAttributesGetter; - @Mock SqlClientAttributesGetter sqlAttributesGetter; + @Mock DbClientAttributesGetter dbAttributesGetter; + @Mock SqlClientAttributesGetter sqlAttributesGetter; @Test void shouldExtractFullSpanName() { diff --git a/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/SqlClientAttributesExtractorTest.java b/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/SqlClientAttributesExtractorTest.java index b5fffdf08f..d3cd7dc032 100644 --- a/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/SqlClientAttributesExtractorTest.java +++ b/instrumentation-api-incubator/src/test/java/io/opentelemetry/instrumentation/api/incubator/semconv/db/SqlClientAttributesExtractorTest.java @@ -26,7 +26,8 @@ import org.junit.jupiter.api.Test; @SuppressWarnings("deprecation") // using deprecated semconv class SqlClientAttributesExtractorTest { - static class TestAttributesGetter implements SqlClientAttributesGetter> { + static class TestAttributesGetter + implements SqlClientAttributesGetter, Void> { @Override public Collection getRawQueryTexts(Map map) { @@ -71,7 +72,7 @@ class SqlClientAttributesExtractorTest { } static class TestMultiAttributesGetter extends TestAttributesGetter - implements SqlClientAttributesGetter> { + implements SqlClientAttributesGetter, Void> { @SuppressWarnings("unchecked") @Override diff --git a/instrumentation/cassandra/cassandra-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/CassandraSqlAttributesGetter.java b/instrumentation/cassandra/cassandra-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/CassandraSqlAttributesGetter.java index 61b5dd87b7..0645ee598b 100644 --- a/instrumentation/cassandra/cassandra-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/CassandraSqlAttributesGetter.java +++ b/instrumentation/cassandra/cassandra-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v3_0/CassandraSqlAttributesGetter.java @@ -7,12 +7,14 @@ package io.opentelemetry.javaagent.instrumentation.cassandra.v3_0; import static java.util.Collections.singleton; +import com.datastax.driver.core.ExecutionInfo; import io.opentelemetry.instrumentation.api.incubator.semconv.db.SqlClientAttributesGetter; import io.opentelemetry.semconv.incubating.DbIncubatingAttributes; import java.util.Collection; import javax.annotation.Nullable; -final class CassandraSqlAttributesGetter implements SqlClientAttributesGetter { +final class CassandraSqlAttributesGetter + implements SqlClientAttributesGetter { @SuppressWarnings("deprecation") // using deprecated DbSystemIncubatingValues @Override diff --git a/instrumentation/cassandra/cassandra-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CassandraSqlAttributesGetter.java b/instrumentation/cassandra/cassandra-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CassandraSqlAttributesGetter.java index ada9ad70a0..9e4ce39f1d 100644 --- a/instrumentation/cassandra/cassandra-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CassandraSqlAttributesGetter.java +++ b/instrumentation/cassandra/cassandra-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/cassandra/v4_0/CassandraSqlAttributesGetter.java @@ -8,12 +8,14 @@ package io.opentelemetry.javaagent.instrumentation.cassandra.v4_0; import static java.util.Collections.singleton; import com.datastax.oss.driver.api.core.CqlIdentifier; +import com.datastax.oss.driver.api.core.cql.ExecutionInfo; import io.opentelemetry.instrumentation.api.incubator.semconv.db.SqlClientAttributesGetter; import io.opentelemetry.semconv.incubating.DbIncubatingAttributes; import java.util.Collection; import javax.annotation.Nullable; -final class CassandraSqlAttributesGetter implements SqlClientAttributesGetter { +final class CassandraSqlAttributesGetter + implements SqlClientAttributesGetter { @SuppressWarnings("deprecation") // using deprecated DbSystemIncubatingValues @Override diff --git a/instrumentation/cassandra/cassandra-4.4/library/src/main/java/io/opentelemetry/instrumentation/cassandra/v4_4/CassandraSqlAttributesGetter.java b/instrumentation/cassandra/cassandra-4.4/library/src/main/java/io/opentelemetry/instrumentation/cassandra/v4_4/CassandraSqlAttributesGetter.java index d2012e8afc..9e72fba4fa 100644 --- a/instrumentation/cassandra/cassandra-4.4/library/src/main/java/io/opentelemetry/instrumentation/cassandra/v4_4/CassandraSqlAttributesGetter.java +++ b/instrumentation/cassandra/cassandra-4.4/library/src/main/java/io/opentelemetry/instrumentation/cassandra/v4_4/CassandraSqlAttributesGetter.java @@ -8,11 +8,13 @@ package io.opentelemetry.instrumentation.cassandra.v4_4; import static java.util.Collections.singleton; import com.datastax.oss.driver.api.core.CqlIdentifier; +import com.datastax.oss.driver.api.core.cql.ExecutionInfo; import io.opentelemetry.instrumentation.api.incubator.semconv.db.SqlClientAttributesGetter; import java.util.Collection; import javax.annotation.Nullable; -final class CassandraSqlAttributesGetter implements SqlClientAttributesGetter { +final class CassandraSqlAttributesGetter + implements SqlClientAttributesGetter { // copied from DbIncubatingAttributes.DbSystemIncubatingValues private static final String CASSANDRA = "cassandra"; diff --git a/instrumentation/clickhouse-client-0.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/clickhouse/ClickHouseAttributesGetter.java b/instrumentation/clickhouse-client-0.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/clickhouse/ClickHouseAttributesGetter.java index ee4dfc4697..d185e72272 100644 --- a/instrumentation/clickhouse-client-0.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/clickhouse/ClickHouseAttributesGetter.java +++ b/instrumentation/clickhouse-client-0.5/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/clickhouse/ClickHouseAttributesGetter.java @@ -5,11 +5,13 @@ package io.opentelemetry.javaagent.instrumentation.clickhouse; +import com.clickhouse.client.ClickHouseException; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientAttributesGetter; import io.opentelemetry.semconv.incubating.DbIncubatingAttributes; import javax.annotation.Nullable; -final class ClickHouseAttributesGetter implements DbClientAttributesGetter { +final class ClickHouseAttributesGetter + implements DbClientAttributesGetter { @Nullable @Override @@ -58,4 +60,13 @@ final class ClickHouseAttributesGetter implements DbClientAttributesGetter assertions = + new ArrayList<>(attributeAssertions("select * from non_existent_table", "SELECT")); + if (SemconvStability.emitStableDatabaseSemconv()) { + assertions.add(equalTo(DB_RESPONSE_STATUS_CODE, "60")); + assertions.add(equalTo(ERROR_TYPE, "com.clickhouse.client.ClickHouseException")); + } testing.waitAndAssertTraces( trace -> trace.hasSpansSatisfyingExactly( @@ -204,8 +214,7 @@ class ClickHouseClientTest { .hasKind(SpanKind.CLIENT) .hasStatus(StatusData.error()) .hasException(thrown) - .hasAttributesSatisfyingExactly( - attributeAssertions("select * from non_existent_table", "SELECT")))); + .hasAttributesSatisfyingExactly(assertions))); } @Test diff --git a/instrumentation/couchbase/couchbase-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseAttributesGetter.java b/instrumentation/couchbase/couchbase-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseAttributesGetter.java index 0a8a0aabe3..8e9378ece4 100644 --- a/instrumentation/couchbase/couchbase-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseAttributesGetter.java +++ b/instrumentation/couchbase/couchbase-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/couchbase/v2_0/CouchbaseAttributesGetter.java @@ -9,7 +9,8 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientAttribu import io.opentelemetry.semconv.incubating.DbIncubatingAttributes; import javax.annotation.Nullable; -final class CouchbaseAttributesGetter implements DbClientAttributesGetter { +final class CouchbaseAttributesGetter + implements DbClientAttributesGetter { @SuppressWarnings("deprecation") // using deprecated DbSystemIncubatingValues @Override diff --git a/instrumentation/elasticsearch/elasticsearch-rest-common-5.0/library/src/main/java/io/opentelemetry/instrumentation/elasticsearch/rest/common/v5_0/internal/ElasticsearchDbAttributesGetter.java b/instrumentation/elasticsearch/elasticsearch-rest-common-5.0/library/src/main/java/io/opentelemetry/instrumentation/elasticsearch/rest/common/v5_0/internal/ElasticsearchDbAttributesGetter.java index 147fe4cc25..8e8cf35835 100644 --- a/instrumentation/elasticsearch/elasticsearch-rest-common-5.0/library/src/main/java/io/opentelemetry/instrumentation/elasticsearch/rest/common/v5_0/internal/ElasticsearchDbAttributesGetter.java +++ b/instrumentation/elasticsearch/elasticsearch-rest-common-5.0/library/src/main/java/io/opentelemetry/instrumentation/elasticsearch/rest/common/v5_0/internal/ElasticsearchDbAttributesGetter.java @@ -16,13 +16,14 @@ import java.util.logging.Logger; import java.util.stream.Collectors; import javax.annotation.Nullable; import org.apache.http.HttpEntity; +import org.elasticsearch.client.Response; /** * This class is internal and is hence not for public use. Its APIs are unstable and can change at * any time. */ final class ElasticsearchDbAttributesGetter - implements DbClientAttributesGetter { + implements DbClientAttributesGetter { private static final Logger logger = Logger.getLogger(ElasticsearchDbAttributesGetter.class.getName()); @@ -91,4 +92,14 @@ final class ElasticsearchDbAttributesGetter ElasticsearchEndpointDefinition endpointDefinition = request.getEndpointDefinition(); return endpointDefinition != null ? endpointDefinition.getEndpointName() : null; } + + @Nullable + @Override + public String getResponseStatus(@Nullable Response response, @Nullable Throwable error) { + if (response != null) { + int httpStatus = response.getStatusLine().getStatusCode(); + return httpStatus >= 400 && httpStatus < 600 ? Integer.toString(httpStatus) : null; + } + return null; + } } diff --git a/instrumentation/elasticsearch/elasticsearch-transport-5.3/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v5_3/springdata/Elasticsearch53SpringTemplateTest.java b/instrumentation/elasticsearch/elasticsearch-transport-5.3/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v5_3/springdata/Elasticsearch53SpringTemplateTest.java index e92a7b5338..3361fcd1c2 100644 --- a/instrumentation/elasticsearch/elasticsearch-transport-5.3/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v5_3/springdata/Elasticsearch53SpringTemplateTest.java +++ b/instrumentation/elasticsearch/elasticsearch-transport-5.3/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/v5_3/springdata/Elasticsearch53SpringTemplateTest.java @@ -9,6 +9,7 @@ import static io.opentelemetry.api.common.AttributeKey.longKey; import static io.opentelemetry.api.common.AttributeKey.stringKey; import static io.opentelemetry.instrumentation.testing.junit.db.SemconvStabilityUtil.maybeStable; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; +import static io.opentelemetry.semconv.ErrorAttributes.ERROR_TYPE; import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_OPERATION; import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_SYSTEM; import static org.assertj.core.api.Assertions.assertThat; @@ -17,14 +18,17 @@ import static org.awaitility.Awaitility.await; import static org.elasticsearch.cluster.ClusterName.CLUSTER_NAME_SETTING; import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.instrumentation.api.internal.SemconvStability; import io.opentelemetry.instrumentation.testing.internal.AutoCleanupExtension; import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.sdk.testing.assertj.AttributeAssertion; import io.opentelemetry.sdk.trace.data.StatusData; import io.opentelemetry.semconv.incubating.DbIncubatingAttributes; import java.io.File; import java.time.Duration; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -162,6 +166,21 @@ class Elasticsearch53SpringTemplateTest { assertThatThrownBy(() -> template.refresh(indexName)) .isInstanceOf(IndexNotFoundException.class); + List assertions = + new ArrayList<>( + Arrays.asList( + equalTo( + maybeStable(DB_SYSTEM), + DbIncubatingAttributes.DbSystemIncubatingValues.ELASTICSEARCH), + equalTo(maybeStable(DB_OPERATION), "RefreshAction"), + equalTo(stringKey("elasticsearch.action"), "RefreshAction"), + equalTo(stringKey("elasticsearch.request"), "RefreshRequest"), + equalTo(stringKey("elasticsearch.request.indices"), indexName))); + + if (SemconvStability.emitStableDatabaseSemconv()) { + assertions.add(equalTo(ERROR_TYPE, "org.elasticsearch.index.IndexNotFoundException")); + } + IndexNotFoundException expectedException = new IndexNotFoundException("no such index"); testing.waitAndAssertTraces( trace -> @@ -172,14 +191,7 @@ class Elasticsearch53SpringTemplateTest { .hasNoParent() .hasStatus(StatusData.error()) .hasException(expectedException) - .hasAttributesSatisfyingExactly( - equalTo( - maybeStable(DB_SYSTEM), - DbIncubatingAttributes.DbSystemIncubatingValues.ELASTICSEARCH), - equalTo(maybeStable(DB_OPERATION), "RefreshAction"), - equalTo(stringKey("elasticsearch.action"), "RefreshAction"), - equalTo(stringKey("elasticsearch.request"), "RefreshRequest"), - equalTo(stringKey("elasticsearch.request.indices"), indexName)))); + .hasAttributesSatisfyingExactly(assertions))); } @Test diff --git a/instrumentation/elasticsearch/elasticsearch-transport-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/ElasticsearchTransportAttributesGetter.java b/instrumentation/elasticsearch/elasticsearch-transport-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/ElasticsearchTransportAttributesGetter.java index 1034e52075..90411c26e9 100644 --- a/instrumentation/elasticsearch/elasticsearch-transport-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/ElasticsearchTransportAttributesGetter.java +++ b/instrumentation/elasticsearch/elasticsearch-transport-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/ElasticsearchTransportAttributesGetter.java @@ -8,9 +8,10 @@ package io.opentelemetry.javaagent.instrumentation.elasticsearch.transport; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientAttributesGetter; import io.opentelemetry.semconv.incubating.DbIncubatingAttributes; import javax.annotation.Nullable; +import org.elasticsearch.action.ActionResponse; final class ElasticsearchTransportAttributesGetter - implements DbClientAttributesGetter { + implements DbClientAttributesGetter { @SuppressWarnings("deprecation") // using deprecated DbSystemIncubatingValues @Override diff --git a/instrumentation/elasticsearch/elasticsearch-transport-common/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/AbstractElasticsearchNodeClientTest.java b/instrumentation/elasticsearch/elasticsearch-transport-common/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/AbstractElasticsearchNodeClientTest.java index 80061f2fc8..e697c9e5e5 100644 --- a/instrumentation/elasticsearch/elasticsearch-transport-common/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/AbstractElasticsearchNodeClientTest.java +++ b/instrumentation/elasticsearch/elasticsearch-transport-common/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/AbstractElasticsearchNodeClientTest.java @@ -9,6 +9,7 @@ import static io.opentelemetry.api.common.AttributeKey.longKey; import static io.opentelemetry.api.common.AttributeKey.stringKey; import static io.opentelemetry.instrumentation.testing.junit.db.SemconvStabilityUtil.maybeStable; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; +import static io.opentelemetry.semconv.ErrorAttributes.ERROR_TYPE; import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_OPERATION; import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_SYSTEM; import static org.assertj.core.api.Assertions.assertThat; @@ -16,6 +17,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Named.named; import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.instrumentation.api.internal.SemconvStability; import io.opentelemetry.instrumentation.testing.util.ThrowingSupplier; import io.opentelemetry.sdk.testing.assertj.AttributeAssertion; import io.opentelemetry.sdk.trace.data.StatusData; @@ -103,6 +105,21 @@ public abstract class AbstractElasticsearchNodeClientTest extends AbstractElasti .isInstanceOf(IndexNotFoundException.class) .hasMessage(expectedException.getMessage()); + List assertions = + new ArrayList<>( + Arrays.asList( + equalTo( + maybeStable(DB_SYSTEM), + DbIncubatingAttributes.DbSystemIncubatingValues.ELASTICSEARCH), + equalTo(maybeStable(DB_OPERATION), "GetAction"), + equalTo(ELASTICSEARCH_ACTION, "GetAction"), + equalTo(ELASTICSEARCH_REQUEST, "GetRequest"), + equalTo(ELASTICSEARCH_REQUEST_INDICES, "invalid-index"))); + + if (SemconvStability.emitStableDatabaseSemconv()) { + assertions.add(equalTo(ERROR_TYPE, "org.elasticsearch.index.IndexNotFoundException")); + } + testing.waitAndAssertTraces( trace -> trace.hasSpansSatisfyingExactly( @@ -118,14 +135,7 @@ public abstract class AbstractElasticsearchNodeClientTest extends AbstractElasti .hasParent(trace.getSpan(0)) .hasStatus(StatusData.error()) .hasException(expectedException) - .hasAttributesSatisfyingExactly( - equalTo( - maybeStable(DB_SYSTEM), - DbIncubatingAttributes.DbSystemIncubatingValues.ELASTICSEARCH), - equalTo(maybeStable(DB_OPERATION), "GetAction"), - equalTo(ELASTICSEARCH_ACTION, "GetAction"), - equalTo(ELASTICSEARCH_REQUEST, "GetRequest"), - equalTo(ELASTICSEARCH_REQUEST_INDICES, "invalid-index")), + .hasAttributesSatisfyingExactly(assertions), span -> span.hasName("callback") .hasKind(SpanKind.INTERNAL) diff --git a/instrumentation/elasticsearch/elasticsearch-transport-common/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/AbstractElasticsearchTransportClientTest.java b/instrumentation/elasticsearch/elasticsearch-transport-common/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/AbstractElasticsearchTransportClientTest.java index 51ba20b9be..a7298b0346 100644 --- a/instrumentation/elasticsearch/elasticsearch-transport-common/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/AbstractElasticsearchTransportClientTest.java +++ b/instrumentation/elasticsearch/elasticsearch-transport-common/testing/src/main/java/io/opentelemetry/javaagent/instrumentation/elasticsearch/transport/AbstractElasticsearchTransportClientTest.java @@ -11,6 +11,7 @@ import static io.opentelemetry.instrumentation.testing.junit.db.SemconvStability import static io.opentelemetry.instrumentation.testing.util.TelemetryDataUtil.orderByRootSpanName; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies; +import static io.opentelemetry.semconv.ErrorAttributes.ERROR_TYPE; import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_TYPE; import static io.opentelemetry.semconv.NetworkAttributes.NETWORK_PEER_ADDRESS; import static io.opentelemetry.semconv.NetworkAttributes.NETWORK_PEER_PORT; @@ -22,6 +23,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Named.named; import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.instrumentation.api.internal.SemconvStability; import io.opentelemetry.instrumentation.testing.util.ThrowingSupplier; import io.opentelemetry.sdk.testing.assertj.AttributeAssertion; import io.opentelemetry.sdk.trace.data.StatusData; @@ -118,6 +120,21 @@ public abstract class AbstractElasticsearchTransportClientTest .isInstanceOf(IndexNotFoundException.class) .hasMessage(expectedException.getMessage()); + List assertions = + new ArrayList<>( + Arrays.asList( + equalTo( + maybeStable(DB_SYSTEM), + DbIncubatingAttributes.DbSystemIncubatingValues.ELASTICSEARCH), + equalTo(maybeStable(DB_OPERATION), "GetAction"), + equalTo(ELASTICSEARCH_ACTION, "GetAction"), + equalTo(ELASTICSEARCH_REQUEST, "GetRequest"), + equalTo(ELASTICSEARCH_REQUEST_INDICES, "invalid-index"))); + + if (SemconvStability.emitStableDatabaseSemconv()) { + assertions.add(equalTo(ERROR_TYPE, "org.elasticsearch.transport.RemoteTransportException")); + } + testing.waitAndAssertTraces( trace -> trace.hasSpansSatisfyingExactly( @@ -140,14 +157,7 @@ public abstract class AbstractElasticsearchTransportClientTest equalTo( EXCEPTION_TYPE, RemoteTransportException.class.getName()))) - .hasAttributesSatisfyingExactly( - equalTo( - maybeStable(DB_SYSTEM), - DbIncubatingAttributes.DbSystemIncubatingValues.ELASTICSEARCH), - equalTo(maybeStable(DB_OPERATION), "GetAction"), - equalTo(ELASTICSEARCH_ACTION, "GetAction"), - equalTo(ELASTICSEARCH_REQUEST, "GetRequest"), - equalTo(ELASTICSEARCH_REQUEST_INDICES, "invalid-index")), + .hasAttributesSatisfyingExactly(assertions), span -> span.hasName("callback") .hasKind(SpanKind.INTERNAL) diff --git a/instrumentation/geode-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/GeodeDbAttributesGetter.java b/instrumentation/geode-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/GeodeDbAttributesGetter.java index 55ee8476db..4e7fed4525 100644 --- a/instrumentation/geode-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/GeodeDbAttributesGetter.java +++ b/instrumentation/geode-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/geode/GeodeDbAttributesGetter.java @@ -11,7 +11,7 @@ import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import io.opentelemetry.semconv.incubating.DbIncubatingAttributes; import javax.annotation.Nullable; -final class GeodeDbAttributesGetter implements DbClientAttributesGetter { +final class GeodeDbAttributesGetter implements DbClientAttributesGetter { private static final SqlStatementSanitizer sanitizer = SqlStatementSanitizer.create(AgentCommonConfig.get().isStatementSanitizationEnabled()); diff --git a/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbAttributesGetter.java b/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbAttributesGetter.java index 39460c14a1..a4c5ef73c0 100644 --- a/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbAttributesGetter.java +++ b/instrumentation/influxdb-2.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/influxdb/v2_4/InfluxDbAttributesGetter.java @@ -8,7 +8,7 @@ package io.opentelemetry.javaagent.instrumentation.influxdb.v2_4; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientAttributesGetter; import javax.annotation.Nullable; -final class InfluxDbAttributesGetter implements DbClientAttributesGetter { +final class InfluxDbAttributesGetter implements DbClientAttributesGetter { @Nullable @Override diff --git a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcAttributesGetter.java b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcAttributesGetter.java index 7a0fcc1e20..74cd1c52d5 100644 --- a/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcAttributesGetter.java +++ b/instrumentation/jdbc/library/src/main/java/io/opentelemetry/instrumentation/jdbc/internal/JdbcAttributesGetter.java @@ -7,6 +7,7 @@ package io.opentelemetry.instrumentation.jdbc.internal; import io.opentelemetry.instrumentation.api.incubator.semconv.db.SqlClientAttributesGetter; import io.opentelemetry.instrumentation.jdbc.internal.dbinfo.DbInfo; +import java.sql.SQLException; import java.util.Collection; import javax.annotation.Nullable; @@ -14,7 +15,7 @@ import javax.annotation.Nullable; * This class is internal and is hence not for public use. Its APIs are unstable and can change at * any time. */ -public final class JdbcAttributesGetter implements SqlClientAttributesGetter { +public final class JdbcAttributesGetter implements SqlClientAttributesGetter { @Nullable @Override @@ -52,4 +53,13 @@ public final class JdbcAttributesGetter implements SqlClientAttributesGetter + testing.runWithSpan( + "parent", + () -> dataSource.getConnection().createStatement().execute("SELECT 1;"))) + .isInstanceOf(SQLException.class); + + testing.waitAndAssertTraces( + trace -> + trace.hasSpansSatisfyingExactly( + span -> span.hasName("parent"), + span -> span.hasName("TestDataSource.getConnection"), + span -> + span.hasName("SELECT dbname") + .hasAttributesSatisfyingExactly( + equalTo(DB_SYSTEM_NAME, "postgresql"), + equalTo(DB_OPERATION_NAME, "SELECT"), + equalTo(DB_NAMESPACE, "dbname"), + equalTo(DB_QUERY_TEXT, "SELECT ?;"), + equalTo(DB_RESPONSE_STATUS_CODE, "42"), + equalTo(SERVER_ADDRESS, "127.0.0.1"), + equalTo(SERVER_PORT, 5432), + equalTo(ERROR_TYPE, "java.sql.SQLException")))); + + assertDurationMetric( + testing, + "io.opentelemetry.jdbc", + DB_NAMESPACE, + DB_OPERATION_NAME, + DB_RESPONSE_STATUS_CODE, + DB_SYSTEM_NAME, + ERROR_TYPE, + SERVER_ADDRESS, + SERVER_PORT); + } + @Test void buildWithAllInstrumentersDisabled() throws SQLException { JdbcTelemetry telemetry = diff --git a/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisDbAttributesGetter.java b/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisDbAttributesGetter.java index 3824cf0a19..1514d62d63 100644 --- a/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisDbAttributesGetter.java +++ b/instrumentation/jedis/jedis-1.4/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v1_4/JedisDbAttributesGetter.java @@ -11,7 +11,7 @@ import io.opentelemetry.javaagent.bootstrap.internal.AgentCommonConfig; import io.opentelemetry.semconv.incubating.DbIncubatingAttributes; import javax.annotation.Nullable; -final class JedisDbAttributesGetter implements DbClientAttributesGetter { +final class JedisDbAttributesGetter implements DbClientAttributesGetter { private static final RedisCommandSanitizer sanitizer = RedisCommandSanitizer.create(AgentCommonConfig.get().isStatementSanitizationEnabled()); diff --git a/instrumentation/jedis/jedis-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v3_0/JedisDbAttributesGetter.java b/instrumentation/jedis/jedis-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v3_0/JedisDbAttributesGetter.java index 861e6cd19b..74393542aa 100644 --- a/instrumentation/jedis/jedis-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v3_0/JedisDbAttributesGetter.java +++ b/instrumentation/jedis/jedis-3.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v3_0/JedisDbAttributesGetter.java @@ -9,7 +9,7 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientAttribu import io.opentelemetry.semconv.incubating.DbIncubatingAttributes; import javax.annotation.Nullable; -final class JedisDbAttributesGetter implements DbClientAttributesGetter { +final class JedisDbAttributesGetter implements DbClientAttributesGetter { @SuppressWarnings("deprecation") // using deprecated DbSystemIncubatingValues @Override diff --git a/instrumentation/jedis/jedis-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v4_0/JedisDbAttributesGetter.java b/instrumentation/jedis/jedis-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v4_0/JedisDbAttributesGetter.java index b38b202b67..56e009c445 100644 --- a/instrumentation/jedis/jedis-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v4_0/JedisDbAttributesGetter.java +++ b/instrumentation/jedis/jedis-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/jedis/v4_0/JedisDbAttributesGetter.java @@ -9,7 +9,7 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientAttribu import io.opentelemetry.semconv.incubating.DbIncubatingAttributes; import javax.annotation.Nullable; -final class JedisDbAttributesGetter implements DbClientAttributesGetter { +final class JedisDbAttributesGetter implements DbClientAttributesGetter { @SuppressWarnings("deprecation") // using deprecated DbSystemIncubatingValues @Override diff --git a/instrumentation/lettuce/lettuce-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceDbAttributesGetter.java b/instrumentation/lettuce/lettuce-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceDbAttributesGetter.java index c41ca34776..e57379f762 100644 --- a/instrumentation/lettuce/lettuce-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceDbAttributesGetter.java +++ b/instrumentation/lettuce/lettuce-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceDbAttributesGetter.java @@ -10,7 +10,8 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientAttribu import io.opentelemetry.semconv.incubating.DbIncubatingAttributes; import javax.annotation.Nullable; -final class LettuceDbAttributesGetter implements DbClientAttributesGetter> { +final class LettuceDbAttributesGetter + implements DbClientAttributesGetter, Void> { @SuppressWarnings("deprecation") // using deprecated DbSystemIncubatingValues @Override diff --git a/instrumentation/lettuce/lettuce-4.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceAsyncClientTest.java b/instrumentation/lettuce/lettuce-4.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceAsyncClientTest.java index bf8bb6bb93..976b555b01 100644 --- a/instrumentation/lettuce/lettuce-4.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceAsyncClientTest.java +++ b/instrumentation/lettuce/lettuce-4.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/lettuce/v4_0/LettuceAsyncClientTest.java @@ -8,6 +8,7 @@ package io.opentelemetry.javaagent.instrumentation.lettuce.v4_0; import static io.opentelemetry.api.common.AttributeKey.booleanKey; import static io.opentelemetry.instrumentation.testing.junit.db.SemconvStabilityUtil.maybeStable; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; +import static io.opentelemetry.semconv.ErrorAttributes.ERROR_TYPE; import static io.opentelemetry.semconv.ServerAttributes.SERVER_ADDRESS; import static io.opentelemetry.semconv.ServerAttributes.SERVER_PORT; import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_OPERATION; @@ -30,11 +31,16 @@ import com.lambdaworks.redis.codec.Utf8StringCodec; import com.lambdaworks.redis.protocol.AsyncCommand; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.instrumentation.api.internal.SemconvStability; import io.opentelemetry.instrumentation.test.utils.PortUtils; import io.opentelemetry.instrumentation.testing.internal.AutoCleanupExtension; import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.sdk.testing.assertj.AttributeAssertion; import io.opentelemetry.sdk.trace.data.StatusData; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import java.util.Map; import java.util.concurrent.CancellationException; import java.util.concurrent.CompletableFuture; @@ -412,6 +418,15 @@ class LettuceAsyncClientTest { assertThat(completedExceptionally).isTrue(); }); + List assertions = + new ArrayList<>( + Arrays.asList( + equalTo(maybeStable(DB_SYSTEM), "redis"), + equalTo(maybeStable(DB_OPERATION), "DEL"))); + if (SemconvStability.emitStableDatabaseSemconv()) { + assertions.add(equalTo(ERROR_TYPE, "java.lang.IllegalStateException")); + } + testing.waitAndAssertTraces( trace -> trace.hasSpansSatisfyingExactly( @@ -420,9 +435,7 @@ class LettuceAsyncClientTest { .hasKind(SpanKind.CLIENT) .hasStatus(StatusData.error()) .hasException(new IllegalStateException("TestException")) - .hasAttributesSatisfyingExactly( - equalTo(maybeStable(DB_SYSTEM), "redis"), - equalTo(maybeStable(DB_OPERATION), "DEL")))); + .hasAttributesSatisfyingExactly(assertions))); } @Test diff --git a/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceDbAttributesGetter.java b/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceDbAttributesGetter.java index edb8850e85..0d85f4ca2d 100644 --- a/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceDbAttributesGetter.java +++ b/instrumentation/lettuce/lettuce-5.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceDbAttributesGetter.java @@ -15,7 +15,8 @@ import java.util.Collections; import java.util.List; import javax.annotation.Nullable; -final class LettuceDbAttributesGetter implements DbClientAttributesGetter> { +final class LettuceDbAttributesGetter + implements DbClientAttributesGetter, Void> { private static final RedisCommandSanitizer sanitizer = RedisCommandSanitizer.create(AgentCommonConfig.get().isStatementSanitizationEnabled()); diff --git a/instrumentation/lettuce/lettuce-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceAsyncClientTest.java b/instrumentation/lettuce/lettuce-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceAsyncClientTest.java index c6f1d40ca6..da1c3f2c23 100644 --- a/instrumentation/lettuce/lettuce-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceAsyncClientTest.java +++ b/instrumentation/lettuce/lettuce-5.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/lettuce/v5_0/LettuceAsyncClientTest.java @@ -9,6 +9,7 @@ import static io.opentelemetry.api.common.AttributeKey.booleanKey; import static io.opentelemetry.instrumentation.testing.junit.db.SemconvStabilityUtil.maybeStable; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies; +import static io.opentelemetry.semconv.ErrorAttributes.ERROR_TYPE; import static io.opentelemetry.semconv.ServerAttributes.SERVER_ADDRESS; import static io.opentelemetry.semconv.ServerAttributes.SERVER_PORT; import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_OPERATION; @@ -32,10 +33,15 @@ import io.lettuce.core.protocol.AsyncCommand; import io.opentelemetry.api.common.AttributeKey; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.instrumentation.api.internal.SemconvStability; import io.opentelemetry.instrumentation.test.utils.PortUtils; +import io.opentelemetry.sdk.testing.assertj.AttributeAssertion; import io.opentelemetry.sdk.trace.data.StatusData; import java.net.InetAddress; import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import java.util.Map; import java.util.concurrent.CancellationException; import java.util.concurrent.CompletableFuture; @@ -412,6 +418,17 @@ class LettuceAsyncClientTest extends AbstractLettuceClientTest { assertThat(completedExceptionally).isTrue(); }); + List assertions = + new ArrayList<>( + Arrays.asList( + equalTo(maybeStable(DB_SYSTEM), "redis"), + equalTo(maybeStable(DB_STATEMENT), "DEL key1 key2"), + equalTo(maybeStable(DB_OPERATION), "DEL"))); + + if (SemconvStability.emitStableDatabaseSemconv()) { + assertions.add(equalTo(ERROR_TYPE, "java.lang.IllegalStateException")); + } + testing.waitAndAssertTraces( trace -> trace.hasSpansSatisfyingExactly( @@ -420,10 +437,7 @@ class LettuceAsyncClientTest extends AbstractLettuceClientTest { .hasKind(SpanKind.CLIENT) .hasStatus(StatusData.error()) .hasException(new IllegalStateException("TestException")) - .hasAttributesSatisfyingExactly( - equalTo(maybeStable(DB_SYSTEM), "redis"), - equalTo(maybeStable(DB_STATEMENT), "DEL key1 key2"), - equalTo(maybeStable(DB_OPERATION), "DEL")))); + .hasAttributesSatisfyingExactly(assertions))); } @Test diff --git a/instrumentation/mongo/mongo-3.1/library/src/main/java/io/opentelemetry/instrumentation/mongo/v3_1/MongoDbAttributesGetter.java b/instrumentation/mongo/mongo-3.1/library/src/main/java/io/opentelemetry/instrumentation/mongo/v3_1/MongoDbAttributesGetter.java index 06ae481de2..e22d8baede 100644 --- a/instrumentation/mongo/mongo-3.1/library/src/main/java/io/opentelemetry/instrumentation/mongo/v3_1/MongoDbAttributesGetter.java +++ b/instrumentation/mongo/mongo-3.1/library/src/main/java/io/opentelemetry/instrumentation/mongo/v3_1/MongoDbAttributesGetter.java @@ -5,6 +5,7 @@ package io.opentelemetry.instrumentation.mongo.v3_1; +import com.mongodb.MongoException; import com.mongodb.ServerAddress; import com.mongodb.connection.ConnectionDescription; import com.mongodb.event.CommandStartedEvent; @@ -23,7 +24,7 @@ import org.bson.codecs.EncoderContext; import org.bson.json.JsonWriter; import org.bson.json.JsonWriterSettings; -class MongoDbAttributesGetter implements DbClientAttributesGetter { +class MongoDbAttributesGetter implements DbClientAttributesGetter { // copied from DbIncubatingAttributes.DbSystemIncubatingValues private static final String MONGODB = "mongodb"; @@ -97,6 +98,15 @@ class MongoDbAttributesGetter implements DbClientAttributesGetter { + implements DbClientAttributesGetter { @SuppressWarnings("deprecation") // using deprecated DbSystemIncubatingValues @Override @@ -49,4 +50,14 @@ final class OpenSearchRestAttributesGetter public String getDbOperationName(OpenSearchRestRequest request) { return request.getMethod(); } + + @Nullable + @Override + public String getResponseStatus(@Nullable Response response, @Nullable Throwable error) { + if (response != null) { + int httpStatus = response.getStatusLine().getStatusCode(); + return httpStatus >= 400 && httpStatus < 600 ? Integer.toString(httpStatus) : null; + } + return null; + } } diff --git a/instrumentation/r2dbc-1.0/library/src/main/java/io/opentelemetry/instrumentation/r2dbc/v1_0/internal/R2dbcSqlAttributesGetter.java b/instrumentation/r2dbc-1.0/library/src/main/java/io/opentelemetry/instrumentation/r2dbc/v1_0/internal/R2dbcSqlAttributesGetter.java index f894710b73..8184434bbb 100644 --- a/instrumentation/r2dbc-1.0/library/src/main/java/io/opentelemetry/instrumentation/r2dbc/v1_0/internal/R2dbcSqlAttributesGetter.java +++ b/instrumentation/r2dbc-1.0/library/src/main/java/io/opentelemetry/instrumentation/r2dbc/v1_0/internal/R2dbcSqlAttributesGetter.java @@ -8,6 +8,7 @@ package io.opentelemetry.instrumentation.r2dbc.v1_0.internal; import static java.util.Collections.singleton; import io.opentelemetry.instrumentation.api.incubator.semconv.db.SqlClientAttributesGetter; +import io.r2dbc.spi.R2dbcException; import java.util.Collection; import javax.annotation.Nullable; @@ -15,7 +16,7 @@ import javax.annotation.Nullable; * This class is internal and is hence not for public use. Its APIs are unstable and can change at * any time. */ -public enum R2dbcSqlAttributesGetter implements SqlClientAttributesGetter { +public enum R2dbcSqlAttributesGetter implements SqlClientAttributesGetter { INSTANCE; @Override @@ -47,4 +48,13 @@ public enum R2dbcSqlAttributesGetter implements SqlClientAttributesGetter getRawQueryTexts(DbExecution request) { return singleton(request.getRawQueryText()); } + + @Nullable + @Override + public String getResponseStatus(@Nullable Void response, @Nullable Throwable error) { + if (error instanceof R2dbcException) { + return ((R2dbcException) error).getSqlState(); + } + return null; + } } diff --git a/instrumentation/rediscala-1.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/RediscalaAttributesGetter.java b/instrumentation/rediscala-1.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/RediscalaAttributesGetter.java index 04f495c1a5..3936dbc0ef 100644 --- a/instrumentation/rediscala-1.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/RediscalaAttributesGetter.java +++ b/instrumentation/rediscala-1.8/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/rediscala/RediscalaAttributesGetter.java @@ -11,7 +11,8 @@ import java.util.Locale; import javax.annotation.Nullable; import redis.RedisCommand; -final class RediscalaAttributesGetter implements DbClientAttributesGetter> { +final class RediscalaAttributesGetter + implements DbClientAttributesGetter, Void> { @SuppressWarnings("deprecation") // using deprecated DbSystemIncubatingValues @Override diff --git a/instrumentation/redisson/redisson-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/RedissonDbAttributesGetter.java b/instrumentation/redisson/redisson-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/RedissonDbAttributesGetter.java index 8bddd00632..eece9af720 100644 --- a/instrumentation/redisson/redisson-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/RedissonDbAttributesGetter.java +++ b/instrumentation/redisson/redisson-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/redisson/RedissonDbAttributesGetter.java @@ -9,7 +9,7 @@ import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientAttribu import io.opentelemetry.semconv.incubating.DbIncubatingAttributes; import javax.annotation.Nullable; -final class RedissonDbAttributesGetter implements DbClientAttributesGetter { +final class RedissonDbAttributesGetter implements DbClientAttributesGetter { @SuppressWarnings("deprecation") // using deprecated DbSystemIncubatingValues @Override diff --git a/instrumentation/spymemcached-2.12/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/SpymemcachedAttributesGetter.java b/instrumentation/spymemcached-2.12/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/SpymemcachedAttributesGetter.java index 086c2dc656..6eed4eb79d 100644 --- a/instrumentation/spymemcached-2.12/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/SpymemcachedAttributesGetter.java +++ b/instrumentation/spymemcached-2.12/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spymemcached/SpymemcachedAttributesGetter.java @@ -8,7 +8,8 @@ package io.opentelemetry.javaagent.instrumentation.spymemcached; import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientAttributesGetter; import javax.annotation.Nullable; -public class SpymemcachedAttributesGetter implements DbClientAttributesGetter { +public class SpymemcachedAttributesGetter + implements DbClientAttributesGetter { @Override public String getDbSystem(SpymemcachedRequest spymemcachedRequest) { diff --git a/instrumentation/spymemcached-2.12/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spymemcached/SpymemcachedTest.java b/instrumentation/spymemcached-2.12/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spymemcached/SpymemcachedTest.java index adef33c28b..4b5a323147 100644 --- a/instrumentation/spymemcached-2.12/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spymemcached/SpymemcachedTest.java +++ b/instrumentation/spymemcached-2.12/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spymemcached/SpymemcachedTest.java @@ -10,6 +10,7 @@ import static io.opentelemetry.api.common.AttributeKey.stringKey; import static io.opentelemetry.instrumentation.testing.junit.db.SemconvStabilityUtil.maybeStable; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies; +import static io.opentelemetry.semconv.ErrorAttributes.ERROR_TYPE; import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_MESSAGE; import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_STACKTRACE; import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_TYPE; @@ -24,17 +25,21 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import com.google.common.util.concurrent.MoreExecutors; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.instrumentation.api.internal.SemconvStability; import io.opentelemetry.instrumentation.testing.internal.AutoCleanupExtension; import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.sdk.testing.assertj.AttributeAssertion; import io.opentelemetry.sdk.trace.data.StatusData; import io.opentelemetry.semconv.incubating.DbIncubatingAttributes; import java.net.InetSocketAddress; import java.time.Duration; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; @@ -258,10 +263,22 @@ class SpymemcachedTest { EXCEPTION_STACKTRACE, val -> val.isInstanceOf(String.class)))) .hasAttributesSatisfyingExactly( - equalTo( - maybeStable(DB_SYSTEM), - DbIncubatingAttributes.DbSystemIncubatingValues.MEMCACHED), - equalTo(maybeStable(DB_OPERATION), "get")))); + withErrorType( + "net.spy.memcached.internal.CheckedOperationTimeoutException", + equalTo( + maybeStable(DB_SYSTEM), + DbIncubatingAttributes.DbSystemIncubatingValues.MEMCACHED), + equalTo(maybeStable(DB_OPERATION), "get"))))); + } + + private static List withErrorType( + String errorType, AttributeAssertion... assertions) { + List list = new ArrayList<>(Arrays.asList(assertions)); + + if (SemconvStability.emitStableDatabaseSemconv()) { + list.add(equalTo(ERROR_TYPE, errorType)); + } + return list; } @Test @@ -879,10 +896,12 @@ class SpymemcachedTest { .hasException( new IllegalArgumentException("Key is too long (maxlen = 250)")) .hasAttributesSatisfyingExactly( - equalTo( - maybeStable(DB_SYSTEM), - DbIncubatingAttributes.DbSystemIncubatingValues.MEMCACHED), - equalTo(maybeStable(DB_OPERATION), "decr")))); + withErrorType( + "java.lang.IllegalArgumentException", + equalTo( + maybeStable(DB_SYSTEM), + DbIncubatingAttributes.DbSystemIncubatingValues.MEMCACHED), + equalTo(maybeStable(DB_OPERATION), "decr"))))); } @Test @@ -965,10 +984,12 @@ class SpymemcachedTest { .hasException( new IllegalArgumentException("Key is too long (maxlen = 250)")) .hasAttributesSatisfyingExactly( - equalTo( - maybeStable(DB_SYSTEM), - DbIncubatingAttributes.DbSystemIncubatingValues.MEMCACHED), - equalTo(maybeStable(DB_OPERATION), "incr")))); + withErrorType( + "java.lang.IllegalArgumentException", + equalTo( + maybeStable(DB_SYSTEM), + DbIncubatingAttributes.DbSystemIncubatingValues.MEMCACHED), + equalTo(maybeStable(DB_OPERATION), "incr"))))); } private static String key(String k) { diff --git a/instrumentation/vertx/vertx-redis-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/redis/VertxRedisClientAttributesGetter.java b/instrumentation/vertx/vertx-redis-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/redis/VertxRedisClientAttributesGetter.java index 233839ad08..a6330addd2 100644 --- a/instrumentation/vertx/vertx-redis-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/redis/VertxRedisClientAttributesGetter.java +++ b/instrumentation/vertx/vertx-redis-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/redis/VertxRedisClientAttributesGetter.java @@ -13,7 +13,7 @@ import io.opentelemetry.semconv.incubating.DbIncubatingAttributes; import javax.annotation.Nullable; public enum VertxRedisClientAttributesGetter - implements DbClientAttributesGetter { + implements DbClientAttributesGetter { INSTANCE; private static final RedisCommandSanitizer sanitizer = diff --git a/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/sql/VertxSqlClientAttributesGetter.java b/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/sql/VertxSqlClientAttributesGetter.java index 0ef35ccd2d..63a4e04cfd 100644 --- a/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/sql/VertxSqlClientAttributesGetter.java +++ b/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/sql/VertxSqlClientAttributesGetter.java @@ -8,11 +8,12 @@ package io.opentelemetry.javaagent.instrumentation.vertx.v4_0.sql; import static java.util.Collections.singleton; import io.opentelemetry.instrumentation.api.incubator.semconv.db.SqlClientAttributesGetter; +import java.lang.reflect.InvocationTargetException; import java.util.Collection; import javax.annotation.Nullable; public enum VertxSqlClientAttributesGetter - implements SqlClientAttributesGetter { + implements SqlClientAttributesGetter { INSTANCE; @Override @@ -44,4 +45,22 @@ public enum VertxSqlClientAttributesGetter public Collection getRawQueryTexts(VertxSqlClientRequest request) { return singleton(request.getQueryText()); } + + @Nullable + @Override + public String getResponseStatus(@Nullable Void response, @Nullable Throwable error) { + try { + // loaded via reflection, because this class is not available in all versions that we support + Class ex = Class.forName("io.vertx.pgclient.PgException"); + if (ex.isInstance(error)) { + return (String) ex.getMethod("getCode").invoke(error); + } + } catch (ClassNotFoundException + | NoSuchMethodException + | IllegalAccessException + | InvocationTargetException e) { + return null; + } + return null; + } } diff --git a/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/sql/VertxSqlClientTest.java b/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/sql/VertxSqlClientTest.java index 5b30c2efe6..a109c12350 100644 --- a/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/sql/VertxSqlClientTest.java +++ b/instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/sql/VertxSqlClientTest.java @@ -9,6 +9,7 @@ import static io.opentelemetry.instrumentation.api.internal.SemconvStability.emi import static io.opentelemetry.instrumentation.testing.junit.db.SemconvStabilityUtil.maybeStable; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies; +import static io.opentelemetry.semconv.ErrorAttributes.ERROR_TYPE; import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_MESSAGE; import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_STACKTRACE; import static io.opentelemetry.semconv.ExceptionAttributes.EXCEPTION_TYPE; @@ -16,14 +17,17 @@ import static io.opentelemetry.semconv.ServerAttributes.SERVER_ADDRESS; import static io.opentelemetry.semconv.ServerAttributes.SERVER_PORT; import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_NAME; import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_OPERATION; +import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_RESPONSE_STATUS_CODE; import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_SQL_TABLE; import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_STATEMENT; import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_USER; import io.opentelemetry.api.trace.SpanKind; +import io.opentelemetry.instrumentation.api.internal.SemconvStability; import io.opentelemetry.instrumentation.testing.internal.AutoCleanupExtension; import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; +import io.opentelemetry.sdk.testing.assertj.AttributeAssertion; import io.opentelemetry.sdk.testing.assertj.TraceAssert; import io.opentelemetry.sdk.trace.data.StatusData; import io.vertx.core.Vertx; @@ -174,6 +178,20 @@ class VertxSqlClientTest { latch.await(30, TimeUnit.SECONDS); + List assertions = + new ArrayList<>( + Arrays.asList( + equalTo(maybeStable(DB_NAME), DB), + equalTo(DB_USER, emitStableDatabaseSemconv() ? null : USER_DB), + equalTo(maybeStable(DB_STATEMENT), "invalid"), + equalTo(SERVER_ADDRESS, host), + equalTo(SERVER_PORT, port))); + + if (SemconvStability.emitStableDatabaseSemconv()) { + assertions.add(equalTo(DB_RESPONSE_STATUS_CODE, "42601")); + assertions.add(equalTo(ERROR_TYPE, "io.vertx.pgclient.PgException")); + } + testing.waitAndAssertTraces( trace -> trace.hasSpansSatisfyingExactly( @@ -195,12 +213,7 @@ class VertxSqlClientTest { satisfies( EXCEPTION_STACKTRACE, val -> val.isInstanceOf(String.class)))) - .hasAttributesSatisfyingExactly( - equalTo(maybeStable(DB_NAME), DB), - equalTo(DB_USER, emitStableDatabaseSemconv() ? null : USER_DB), - equalTo(maybeStable(DB_STATEMENT), "invalid"), - equalTo(SERVER_ADDRESS, host), - equalTo(SERVER_PORT, port)), + .hasAttributesSatisfyingExactly(assertions), span -> span.hasName("callback") .hasKind(SpanKind.INTERNAL)