Split out camel experimental assertions (#14433)

This commit is contained in:
Jay DeLuca 2025-08-15 13:12:44 -04:00 committed by GitHub
parent 092fde6b28
commit 5b1ad52adb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 200 additions and 27 deletions

View File

@ -50,9 +50,11 @@
-->
<module name="TreeWalker">
<!-- Enforce static imports for OpenTelemetryAssertions methods (lowercase), but allow inner
classes (uppercase). The negative lookahead is needed so we don't match import lines. -->
<module name="RegexpSinglelineJava">
<property name="format"
value="(?&lt;!import static io.opentelemetry.sdk.testing.assertj.)OpenTelemetryAssertions\."/>
value="^(?!.*import).*OpenTelemetryAssertions\.[a-z]"/>
<property name="message"
value="Please statically import methods from OpenTelemetryAssertions"/>
</module>

View File

@ -1663,6 +1663,115 @@ libraries:
Enable the capture of experimental `camel.uri`, `camel.kafka.partitionKey`, `camel.kafka.key` and `camel.kafka.offset` span attributes.
type: boolean
default: false
telemetry:
- when: default
spans:
- span_kind: CLIENT
attributes:
- name: db.name
type: STRING
- name: db.statement
type: STRING
- name: db.system
type: STRING
- name: http.request.method
type: STRING
- name: http.response.status_code
type: LONG
- name: url.full
type: STRING
- span_kind: INTERNAL
attributes:
- name: http.request.method
type: STRING
- name: messaging.destination.name
type: STRING
- name: messaging.message.id
type: STRING
- name: url.full
type: STRING
- span_kind: SERVER
attributes:
- name: http.request.method
type: STRING
- name: http.response.status_code
type: LONG
- name: url.full
type: STRING
- when: otel.instrumentation.camel.experimental-span-attributes=true
spans:
- span_kind: CLIENT
attributes:
- name: camel.uri
type: STRING
- name: db.name
type: STRING
- name: db.statement
type: STRING
- name: db.system
type: STRING
- name: http.request.method
type: STRING
- name: http.response.status_code
type: LONG
- name: url.full
type: STRING
- span_kind: INTERNAL
attributes:
- name: camel.uri
type: STRING
- name: http.request.method
type: STRING
- name: messaging.destination.name
type: STRING
- name: messaging.message.id
type: STRING
- name: url.full
type: STRING
- span_kind: SERVER
attributes:
- name: camel.uri
type: STRING
- name: http.request.method
type: STRING
- name: http.response.status_code
type: LONG
- name: url.full
type: STRING
- when: otel.semconv-stability.opt-in=database
spans:
- span_kind: CLIENT
attributes:
- name: db.namespace
type: STRING
- name: db.query.text
type: STRING
- name: db.system.name
type: STRING
- name: http.request.method
type: STRING
- name: http.response.status_code
type: LONG
- name: url.full
type: STRING
- span_kind: INTERNAL
attributes:
- name: http.request.method
type: STRING
- name: messaging.destination.name
type: STRING
- name: messaging.message.id
type: STRING
- name: url.full
type: STRING
- span_kind: SERVER
attributes:
- name: http.request.method
type: STRING
- name: http.response.status_code
type: LONG
- name: url.full
type: STRING
cassandra:
- name: cassandra-3.0
description: |

View File

@ -122,6 +122,9 @@ readonly INSTRUMENTATIONS=(
"cassandra:cassandra-4.0:javaagent:testStableSemconv"
"cassandra:cassandra-4.4:javaagent:test"
"cassandra:cassandra-4.4:javaagent:testStableSemconv"
"camel-2.20:javaagent:test"
"camel-2.20:javaagent:testStableSemconv"
"camel-2.20:javaagent:testExperimental"
)
# Some instrumentation test suites don't run ARM, so we use colima to run them in an x86_64

View File

@ -69,8 +69,6 @@ dependencies {
tasks {
withType<Test>().configureEach {
// TODO run tests both with and without experimental span attributes
jvmArgs("-Dotel.instrumentation.camel.experimental-span-attributes=true")
jvmArgs("-Dotel.instrumentation.aws-sdk.experimental-span-attributes=true")
// TODO: fix camel instrumentation so that it uses semantic attributes extractors
@ -81,14 +79,22 @@ tasks {
jvmArgs("-XX:+IgnoreUnrecognizedVMOptions")
jvmArgs("-Dotel.instrumentation.common.experimental.controller-telemetry.enabled=true")
systemProperty("collectMetadata", findProperty("collectMetadata")?.toString() ?: "false")
}
val testExperimental by registering(Test::class) {
jvmArgs("-Dotel.instrumentation.camel.experimental-span-attributes=true")
systemProperty("metadataConfig", "otel.instrumentation.camel.experimental-span-attributes=true")
}
val testStableSemconv by registering(Test::class) {
jvmArgs("-Dotel.semconv-stability.opt-in=database")
systemProperty("metadataConfig", "otel.semconv-stability.opt-in=database")
}
check {
dependsOn(testStableSemconv)
dependsOn(testStableSemconv, testExperimental)
}
}

View File

@ -6,6 +6,7 @@
package io.opentelemetry.javaagent.instrumentation.apachecamel;
import static io.opentelemetry.api.common.AttributeKey.stringKey;
import static io.opentelemetry.javaagent.instrumentation.apachecamel.ExperimentalTest.experimental;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
import io.opentelemetry.api.trace.SpanKind;
@ -70,12 +71,12 @@ class DirectCamelTest extends AbstractHttpServerUsingTest<ConfigurableApplicatio
.hasKind(SpanKind.INTERNAL)
.hasNoParent()
.hasAttributesSatisfyingExactly(
equalTo(stringKey("camel.uri"), "direct://input")),
equalTo(stringKey("camel.uri"), experimental("direct://input"))),
span ->
span.hasName("receiver")
.hasKind(SpanKind.INTERNAL)
.hasParent(trace.getSpan(0))
.hasAttributesSatisfyingExactly(
equalTo(stringKey("camel.uri"), "direct://receiver"))));
equalTo(stringKey("camel.uri"), experimental("direct://receiver")))));
}
}

View File

@ -0,0 +1,36 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.apachecamel;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.sdk.testing.assertj.AttributeAssertion;
import io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.StringAssertConsumer;
public class ExperimentalTest {
private static final String EXPERIMENTAL_FLAG =
"otel.instrumentation.camel.experimental-span-attributes";
public static String experimental(String value) {
if (!Boolean.getBoolean(EXPERIMENTAL_FLAG)) {
return null;
}
return value;
}
static AttributeAssertion experimentalSatisfies(
AttributeKey<String> key, StringAssertConsumer assertion) {
if (Boolean.getBoolean(EXPERIMENTAL_FLAG)) {
return satisfies(key, assertion);
} else {
return equalTo(key, null);
}
}
private ExperimentalTest() {}
}

View File

@ -6,6 +6,7 @@
package io.opentelemetry.javaagent.instrumentation.apachecamel;
import static io.opentelemetry.api.common.AttributeKey.stringKey;
import static io.opentelemetry.javaagent.instrumentation.apachecamel.ExperimentalTest.experimental;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
import io.opentelemetry.api.trace.SpanKind;
@ -70,18 +71,18 @@ class MulticastDirectCamelTest extends AbstractHttpServerUsingTest<ConfigurableA
.hasKind(SpanKind.INTERNAL)
.hasNoParent()
.hasAttributesSatisfyingExactly(
equalTo(stringKey("camel.uri"), "direct://input")),
equalTo(stringKey("camel.uri"), experimental("direct://input"))),
span ->
span.hasName("first")
.hasKind(SpanKind.INTERNAL)
.hasParent(trace.getSpan(0))
.hasAttributesSatisfyingExactly(
equalTo(stringKey("camel.uri"), "direct://first")),
equalTo(stringKey("camel.uri"), experimental("direct://first"))),
span ->
span.hasName("second")
.hasKind(SpanKind.INTERNAL)
.hasParent(trace.getSpan(0))
.hasAttributesSatisfyingExactly(
equalTo(stringKey("camel.uri"), "direct://second"))));
equalTo(stringKey("camel.uri"), experimental("direct://second")))));
}
}

View File

@ -6,6 +6,8 @@
package io.opentelemetry.javaagent.instrumentation.apachecamel;
import static io.opentelemetry.api.common.AttributeKey.stringKey;
import static io.opentelemetry.javaagent.instrumentation.apachecamel.ExperimentalTest.experimental;
import static io.opentelemetry.javaagent.instrumentation.apachecamel.ExperimentalTest.experimentalSatisfies;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies;
import static io.opentelemetry.semconv.ClientAttributes.CLIENT_ADDRESS;
@ -92,7 +94,7 @@ class RestCamelTest extends AbstractHttpServerUsingTest<ConfigurableApplicationC
span.hasName("start")
.hasKind(SpanKind.INTERNAL)
.hasAttributesSatisfyingExactly(
equalTo(stringKey("camel.uri"), "direct://start")),
equalTo(stringKey("camel.uri"), experimental("direct://start"))),
span ->
span.hasName("GET")
.hasKind(SpanKind.CLIENT)
@ -100,7 +102,7 @@ class RestCamelTest extends AbstractHttpServerUsingTest<ConfigurableApplicationC
.hasAttributesSatisfyingExactly(
equalTo(
stringKey("camel.uri"),
"rest://get:api/%7Bmodule%7D/unit/%7BunitId%7D"),
experimental("rest://get:api/%7Bmodule%7D/unit/%7BunitId%7D")),
equalTo(HTTP_REQUEST_METHOD, "GET"),
equalTo(HTTP_RESPONSE_STATUS_CODE, 200L)),
span ->
@ -129,13 +131,13 @@ class RestCamelTest extends AbstractHttpServerUsingTest<ConfigurableApplicationC
equalTo(
URL_FULL,
"http://localhost:" + port + "/api/firstModule/unit/unitOne"),
satisfies(
experimentalSatisfies(
stringKey("camel.uri"), val -> val.isInstanceOf(String.class))),
span ->
span.hasName("moduleUnit")
.hasKind(SpanKind.INTERNAL)
.hasParent(trace.getSpan(3))
.hasAttributesSatisfyingExactly(
equalTo(stringKey("camel.uri"), "direct://moduleUnit"))));
equalTo(stringKey("camel.uri"), experimental("direct://moduleUnit")))));
}
}

View File

@ -6,6 +6,7 @@
package io.opentelemetry.javaagent.instrumentation.apachecamel;
import static io.opentelemetry.api.common.AttributeKey.stringKey;
import static io.opentelemetry.javaagent.instrumentation.apachecamel.ExperimentalTest.experimental;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
import static io.opentelemetry.semconv.HttpAttributes.HTTP_REQUEST_METHOD;
import static io.opentelemetry.semconv.UrlAttributes.URL_FULL;
@ -56,7 +57,7 @@ class SingleServiceCamelTest extends AbstractHttpServerUsingTest<ConfigurableApp
}
@Test
public void singleCamelServiceSpan() {
void singleCamelServiceSpan() {
URI requestUrl = address.resolve("/camelService");
client.post(requestUrl.toString(), "testContent").aggregate().join();
@ -72,6 +73,7 @@ class SingleServiceCamelTest extends AbstractHttpServerUsingTest<ConfigurableApp
equalTo(URL_FULL, requestUrl.toString()),
equalTo(
stringKey("camel.uri"),
requestUrl.toString().replace("localhost", "0.0.0.0")))));
experimental(
requestUrl.toString().replace("localhost", "0.0.0.0"))))));
}
}

View File

@ -6,6 +6,7 @@
package io.opentelemetry.javaagent.instrumentation.apachecamel;
import static io.opentelemetry.api.common.AttributeKey.stringKey;
import static io.opentelemetry.javaagent.instrumentation.apachecamel.ExperimentalTest.experimental;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies;
import static io.opentelemetry.semconv.ClientAttributes.CLIENT_ADDRESS;
@ -111,7 +112,7 @@ class TwoServicesWithDirectClientCamelTest
.hasKind(SpanKind.INTERNAL)
.hasNoParent()
.hasAttributesSatisfyingExactly(
equalTo(stringKey("camel.uri"), "direct://input")),
equalTo(stringKey("camel.uri"), experimental("direct://input"))),
span ->
span.hasName("POST")
.hasKind(SpanKind.CLIENT)
@ -122,7 +123,7 @@ class TwoServicesWithDirectClientCamelTest
equalTo(HTTP_RESPONSE_STATUS_CODE, 200L),
equalTo(
stringKey("camel.uri"),
"http://localhost:" + portOne + "/serviceOne")),
experimental("http://localhost:" + portOne + "/serviceOne"))),
span ->
span.hasName("POST /serviceOne")
.hasKind(SpanKind.SERVER)
@ -133,7 +134,7 @@ class TwoServicesWithDirectClientCamelTest
equalTo(HTTP_RESPONSE_STATUS_CODE, 200L),
equalTo(
stringKey("camel.uri"),
"http://0.0.0.0:" + portOne + "/serviceOne")),
experimental("http://0.0.0.0:" + portOne + "/serviceOne"))),
span ->
span.hasName("POST")
.hasKind(SpanKind.CLIENT)
@ -144,7 +145,7 @@ class TwoServicesWithDirectClientCamelTest
equalTo(HTTP_RESPONSE_STATUS_CODE, 200L),
equalTo(
stringKey("camel.uri"),
"http://127.0.0.1:" + portTwo + "/serviceTwo")),
experimental("http://127.0.0.1:" + portTwo + "/serviceTwo"))),
span ->
span.hasName("POST /serviceTwo")
.hasKind(SpanKind.SERVER)
@ -171,6 +172,9 @@ class TwoServicesWithDirectClientCamelTest
equalTo(URL_FULL, "http://127.0.0.1:" + portTwo + "/serviceTwo"),
equalTo(
stringKey("camel.uri"),
"jetty:http://0.0.0.0:" + portTwo + "/serviceTwo?arg=value"))));
experimental(
"jetty:http://0.0.0.0:"
+ portTwo
+ "/serviceTwo?arg=value")))));
}
}

View File

@ -6,6 +6,7 @@
package io.opentelemetry.javaagent.instrumentation.apachecamel.aws;
import static io.opentelemetry.api.common.AttributeKey.stringKey;
import static io.opentelemetry.javaagent.instrumentation.apachecamel.ExperimentalTest.experimental;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies;
import static io.opentelemetry.semconv.incubating.MessagingIncubatingAttributes.MESSAGING_DESTINATION_NAME;
@ -22,7 +23,8 @@ class CamelSpanAssertions {
span.hasName(spanName)
.hasKind(SpanKind.INTERNAL)
.hasNoParent()
.hasAttributesSatisfyingExactly(equalTo(stringKey("camel.uri"), "direct://" + spanName));
.hasAttributesSatisfyingExactly(
equalTo(stringKey("camel.uri"), experimental("direct://" + spanName)));
}
static SpanDataAssert sqsProduce(SpanDataAssert span, String queueName) {
@ -31,7 +33,8 @@ class CamelSpanAssertions {
.hasAttributesSatisfyingExactly(
equalTo(
stringKey("camel.uri"),
"aws-sqs://" + queueName + "?amazonSQSClient=%23sqsClient&delay=1000"),
experimental(
"aws-sqs://" + queueName + "?amazonSQSClient=%23sqsClient&delay=1000")),
equalTo(MESSAGING_DESTINATION_NAME, queueName));
}
@ -45,7 +48,8 @@ class CamelSpanAssertions {
.hasAttributesSatisfyingExactly(
equalTo(
stringKey("camel.uri"),
"aws-sqs://" + queueName + "?amazonSQSClient=%23sqsClient&delay=" + delay),
experimental(
"aws-sqs://" + queueName + "?amazonSQSClient=%23sqsClient&delay=" + delay)),
equalTo(MESSAGING_DESTINATION_NAME, queueName),
satisfies(
MESSAGING_MESSAGE_ID, stringAssert -> stringAssert.isInstanceOf(String.class)));
@ -56,7 +60,8 @@ class CamelSpanAssertions {
.hasKind(SpanKind.INTERNAL)
.hasAttributesSatisfyingExactly(
equalTo(
stringKey("camel.uri"), "aws-sns://" + topicName + "?amazonSNSClient=%23snsClient"),
stringKey("camel.uri"),
experimental("aws-sns://" + topicName + "?amazonSNSClient=%23snsClient")),
equalTo(MESSAGING_DESTINATION_NAME, topicName));
}
@ -65,6 +70,7 @@ class CamelSpanAssertions {
.hasKind(SpanKind.INTERNAL)
.hasAttributesSatisfyingExactly(
equalTo(
stringKey("camel.uri"), "aws-s3://" + bucketName + "?amazonS3Client=%23s3Client"));
stringKey("camel.uri"),
experimental("aws-s3://" + bucketName + "?amazonS3Client=%23s3Client")));
}
}

View File

@ -7,6 +7,7 @@ package io.opentelemetry.javaagent.instrumentation.apachecamel.decorators;
import static io.opentelemetry.api.common.AttributeKey.stringKey;
import static io.opentelemetry.instrumentation.testing.junit.db.SemconvStabilityUtil.maybeStable;
import static io.opentelemetry.javaagent.instrumentation.apachecamel.ExperimentalTest.experimental;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_NAME;
import static io.opentelemetry.semconv.incubating.DbIncubatingAttributes.DB_STATEMENT;
@ -112,13 +113,13 @@ class CassandraTest extends AbstractHttpServerUsingTest<ConfigurableApplicationC
span.hasKind(SpanKind.INTERNAL)
.hasNoParent()
.hasAttributesSatisfyingExactly(
equalTo(stringKey("camel.uri"), "direct://input")),
equalTo(stringKey("camel.uri"), experimental("direct://input"))),
span ->
span.hasKind(SpanKind.CLIENT)
.hasAttributesSatisfyingExactly(
equalTo(
stringKey("camel.uri"),
"cql://" + host + ":" + cassandraPort + "/test"),
experimental("cql://" + host + ":" + cassandraPort + "/test")),
equalTo(maybeStable(DB_NAME), "test"),
equalTo(
maybeStable(DB_STATEMENT),