Skip to content

Commit 29ea551

Browse files
authored
Db error type (open-telemetry#13640)
1 parent b0a1691 commit 29ea551

File tree

7 files changed

+108
-57
lines changed

7 files changed

+108
-57
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.instrumentation.api.incubator.semconv.db.internal;
7+
8+
import javax.annotation.Nullable;
9+
10+
/**
11+
* This class is internal and experimental. Its APIs are unstable and can change at any time. Its
12+
* APIs (or a version of them) may be promoted to the public stable API in the future, but no
13+
* guarantees are made.
14+
*/
15+
public final class DbResponseStatusUtil {
16+
private DbResponseStatusUtil() {}
17+
18+
@Nullable
19+
public static String dbResponseStatusCode(int responseStatusCode) {
20+
return isError(responseStatusCode) ? Integer.toString(responseStatusCode) : null;
21+
}
22+
23+
private static boolean isError(int responseStatusCode) {
24+
return responseStatusCode >= 400
25+
||
26+
// invalid status code, does not exist
27+
responseStatusCode < 100;
28+
}
29+
}

instrumentation-api/src/main/java/io/opentelemetry/instrumentation/api/semconv/http/HttpStatusCodeConverter.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ enum HttpStatusCodeConverter {
1212
boolean isError(int responseStatusCode) {
1313
return responseStatusCode >= 500
1414
||
15-
// invalid status code, does not exists
15+
// invalid status code, does not exist
1616
responseStatusCode < 100;
1717
}
1818
},
@@ -21,7 +21,7 @@ boolean isError(int responseStatusCode) {
2121
boolean isError(int responseStatusCode) {
2222
return responseStatusCode >= 400
2323
||
24-
// invalid status code, does not exists
24+
// invalid status code, does not exist
2525
responseStatusCode < 100;
2626
}
2727
};

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

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
package io.opentelemetry.instrumentation.elasticsearch.rest.common.v5_0.internal;
77

8+
import static io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.DbResponseStatusUtil.dbResponseStatusCode;
89
import static java.util.logging.Level.FINE;
910

1011
import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientAttributesGetter;
@@ -96,10 +97,6 @@ public String getDbOperationName(ElasticsearchRestRequest request) {
9697
@Nullable
9798
@Override
9899
public String getResponseStatus(@Nullable Response response, @Nullable Throwable error) {
99-
if (response != null) {
100-
int httpStatus = response.getStatusLine().getStatusCode();
101-
return httpStatus >= 400 && httpStatus < 600 ? Integer.toString(httpStatus) : null;
102-
}
103-
return null;
100+
return response != null ? dbResponseStatusCode(response.getStatusLine().getStatusCode()) : null;
104101
}
105102
}

instrumentation/opensearch/opensearch-rest-common/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/opensearch/rest/OpenSearchRestAttributesGetter.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
package io.opentelemetry.javaagent.instrumentation.opensearch.rest;
77

8+
import static io.opentelemetry.instrumentation.api.incubator.semconv.db.internal.DbResponseStatusUtil.dbResponseStatusCode;
9+
810
import io.opentelemetry.instrumentation.api.incubator.semconv.db.DbClientAttributesGetter;
911
import io.opentelemetry.semconv.incubating.DbIncubatingAttributes;
1012
import javax.annotation.Nullable;
@@ -54,10 +56,6 @@ public String getDbOperationName(OpenSearchRestRequest request) {
5456
@Nullable
5557
@Override
5658
public String getResponseStatus(@Nullable Response response, @Nullable Throwable error) {
57-
if (response != null) {
58-
int httpStatus = response.getStatusLine().getStatusCode();
59-
return httpStatus >= 400 && httpStatus < 600 ? Integer.toString(httpStatus) : null;
60-
}
61-
return null;
59+
return response != null ? dbResponseStatusCode(response.getStatusLine().getStatusCode()) : null;
6260
}
6361
}

instrumentation/spymemcached-2.12/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spymemcached/SpymemcachedTest.java

Lines changed: 27 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,14 @@
2929
import io.opentelemetry.instrumentation.testing.internal.AutoCleanupExtension;
3030
import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
3131
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
32-
import io.opentelemetry.sdk.testing.assertj.AttributeAssertion;
3332
import io.opentelemetry.sdk.trace.data.StatusData;
3433
import io.opentelemetry.semconv.incubating.DbIncubatingAttributes;
3534
import java.net.InetSocketAddress;
3635
import java.time.Duration;
37-
import java.util.ArrayList;
3836
import java.util.Arrays;
3937
import java.util.Collection;
4038
import java.util.Collections;
4139
import java.util.HashMap;
42-
import java.util.List;
4340
import java.util.Map;
4441
import java.util.concurrent.ArrayBlockingQueue;
4542
import java.util.concurrent.BlockingQueue;
@@ -263,22 +260,15 @@ void getTimeout() throws InterruptedException {
263260
EXCEPTION_STACKTRACE,
264261
val -> val.isInstanceOf(String.class))))
265262
.hasAttributesSatisfyingExactly(
266-
withErrorType(
267-
"net.spy.memcached.internal.CheckedOperationTimeoutException",
268-
equalTo(
269-
maybeStable(DB_SYSTEM),
270-
DbIncubatingAttributes.DbSystemIncubatingValues.MEMCACHED),
271-
equalTo(maybeStable(DB_OPERATION), "get")))));
272-
}
273-
274-
private static List<AttributeAssertion> withErrorType(
275-
String errorType, AttributeAssertion... assertions) {
276-
List<AttributeAssertion> list = new ArrayList<>(Arrays.asList(assertions));
277-
278-
if (SemconvStability.emitStableDatabaseSemconv()) {
279-
list.add(equalTo(ERROR_TYPE, errorType));
280-
}
281-
return list;
263+
equalTo(
264+
ERROR_TYPE,
265+
SemconvStability.emitStableDatabaseSemconv()
266+
? "net.spy.memcached.internal.CheckedOperationTimeoutException"
267+
: null),
268+
equalTo(
269+
maybeStable(DB_SYSTEM),
270+
DbIncubatingAttributes.DbSystemIncubatingValues.MEMCACHED),
271+
equalTo(maybeStable(DB_OPERATION), "get"))));
282272
}
283273

284274
@Test
@@ -896,12 +886,15 @@ void decrException() {
896886
.hasException(
897887
new IllegalArgumentException("Key is too long (maxlen = 250)"))
898888
.hasAttributesSatisfyingExactly(
899-
withErrorType(
900-
"java.lang.IllegalArgumentException",
901-
equalTo(
902-
maybeStable(DB_SYSTEM),
903-
DbIncubatingAttributes.DbSystemIncubatingValues.MEMCACHED),
904-
equalTo(maybeStable(DB_OPERATION), "decr")))));
889+
equalTo(
890+
ERROR_TYPE,
891+
SemconvStability.emitStableDatabaseSemconv()
892+
? "java.lang.IllegalArgumentException"
893+
: null),
894+
equalTo(
895+
maybeStable(DB_SYSTEM),
896+
DbIncubatingAttributes.DbSystemIncubatingValues.MEMCACHED),
897+
equalTo(maybeStable(DB_OPERATION), "decr"))));
905898
}
906899

907900
@Test
@@ -984,12 +977,15 @@ void incrException() {
984977
.hasException(
985978
new IllegalArgumentException("Key is too long (maxlen = 250)"))
986979
.hasAttributesSatisfyingExactly(
987-
withErrorType(
988-
"java.lang.IllegalArgumentException",
989-
equalTo(
990-
maybeStable(DB_SYSTEM),
991-
DbIncubatingAttributes.DbSystemIncubatingValues.MEMCACHED),
992-
equalTo(maybeStable(DB_OPERATION), "incr")))));
980+
equalTo(
981+
ERROR_TYPE,
982+
SemconvStability.emitStableDatabaseSemconv()
983+
? "java.lang.IllegalArgumentException"
984+
: null),
985+
equalTo(
986+
maybeStable(DB_SYSTEM),
987+
DbIncubatingAttributes.DbSystemIncubatingValues.MEMCACHED),
988+
equalTo(maybeStable(DB_OPERATION), "incr"))));
993989
}
994990

995991
private static String key(String k) {

instrumentation/vertx/vertx-sql-client-4.0/javaagent/build.gradle.kts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,14 @@ muzzle {
1212
}
1313

1414
dependencies {
15-
library("io.vertx:vertx-sql-client:4.0.0")
16-
compileOnly("io.vertx:vertx-codegen:4.0.0")
15+
val version = "4.0.0"
16+
library("io.vertx:vertx-sql-client:$version")
17+
compileOnly("io.vertx:vertx-codegen:$version")
1718

1819
testInstrumentation(project(":instrumentation:netty:netty-4.1:javaagent"))
1920

20-
testLibrary("io.vertx:vertx-pg-client:4.0.0")
21-
testLibrary("io.vertx:vertx-codegen:4.0.0")
21+
testLibrary("io.vertx:vertx-pg-client:$version")
22+
testLibrary("io.vertx:vertx-codegen:$version")
2223
}
2324

2425
tasks {

instrumentation/vertx/vertx-sql-client-4.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/vertx/v4_0/sql/VertxSqlClientAttributesGetter.java

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,20 @@
99

1010
import io.opentelemetry.instrumentation.api.incubator.semconv.db.SqlClientAttributesGetter;
1111
import java.lang.reflect.InvocationTargetException;
12+
import java.lang.reflect.Method;
13+
import java.util.Arrays;
1214
import java.util.Collection;
15+
import java.util.List;
16+
import java.util.function.Function;
1317
import javax.annotation.Nullable;
1418

1519
public enum VertxSqlClientAttributesGetter
1620
implements SqlClientAttributesGetter<VertxSqlClientRequest, Void> {
1721
INSTANCE;
1822

23+
private static final List<Function<Exception, String>> responseStatusExtractors =
24+
createResponseStatusExtractors();
25+
1926
@Override
2027
public String getDbSystem(VertxSqlClientRequest request) {
2128
return null;
@@ -49,18 +56,41 @@ public Collection<String> getRawQueryTexts(VertxSqlClientRequest request) {
4956
@Nullable
5057
@Override
5158
public String getResponseStatus(@Nullable Void response, @Nullable Throwable error) {
52-
try {
53-
// loaded via reflection, because this class is not available in all versions that we support
54-
Class<?> ex = Class.forName("io.vertx.pgclient.PgException");
55-
if (ex.isInstance(error)) {
56-
return (String) ex.getMethod("getCode").invoke(error);
59+
for (Function<Exception, String> extractor : responseStatusExtractors) {
60+
String status = extractor.apply((Exception) error);
61+
if (status != null) {
62+
return status;
5763
}
58-
} catch (ClassNotFoundException
59-
| NoSuchMethodException
60-
| IllegalAccessException
61-
| InvocationTargetException e) {
62-
return null;
6364
}
6465
return null;
6566
}
67+
68+
private static List<Function<Exception, String>> createResponseStatusExtractors() {
69+
return Arrays.asList(
70+
responseStatusExtractor("io.vertx.sqlclient.DatabaseException", "getSqlState"),
71+
// older version only have this method
72+
responseStatusExtractor("io.vertx.pgclient.PgException", "getCode"));
73+
}
74+
75+
private static Function<Exception, String> responseStatusExtractor(
76+
String className, String methodName) {
77+
try {
78+
// loaded via reflection, because this class is not available in all versions that we support
79+
Class<?> exClass = Class.forName(className);
80+
Method method = exClass.getDeclaredMethod(methodName);
81+
82+
return (error) -> {
83+
if (exClass.isInstance(error)) {
84+
try {
85+
return String.valueOf(method.invoke(error)); // can be String or int
86+
} catch (IllegalAccessException | InvocationTargetException e) {
87+
return null;
88+
}
89+
}
90+
return null;
91+
};
92+
} catch (ClassNotFoundException | NoSuchMethodException e) {
93+
return (error) -> null;
94+
}
95+
}
6696
}

0 commit comments

Comments
 (0)