This is an automated email from the ASF dual-hosted git repository.
jamesnetherton pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
The following commit(s) were added to refs/heads/main by this push:
new 31cc0bff94 Add opentelemetry2 traceCustomIdOnly configuration option
31cc0bff94 is described below
commit 31cc0bff9499fc8017a410b6201f3977b7953440
Author: James Netherton <[email protected]>
AuthorDate: Wed Sep 23 21:52:50 2026 +0100
Add opentelemetry2 traceCustomIdOnly configuration option
Fixes #9213.
Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
---
.../pages/reference/extensions/opentelemetry2.adoc | 6 ++
.../deployment/Opentelemetry2Test.java | 2 +
.../opentelemetry2/CamelOpenTelemetry2Config.java | 8 ++
.../OpenTelemetry2TracerProducer.java | 1 +
.../opentelemetry2/it/OpenTelemetry2Resource.java | 7 ++
.../it/OpenTelemetry2RouteBuilder.java | 5 +
.../it/OpenTelemetry2TraceCustomIdOnlyIT.java | 23 +++++
.../it/OpenTelemetry2TraceCustomIdOnlyTest.java | 105 +++++++++++++++++++++
.../it/TraceCustomIdOnlyTestProfile.java | 28 ++++++
9 files changed, 185 insertions(+)
diff --git a/docs/modules/ROOT/pages/reference/extensions/opentelemetry2.adoc
b/docs/modules/ROOT/pages/reference/extensions/opentelemetry2.adoc
index 4adb5723e4..df584e3dbc 100644
--- a/docs/modules/ROOT/pages/reference/extensions/opentelemetry2.adoc
+++ b/docs/modules/ROOT/pages/reference/extensions/opentelemetry2.adoc
@@ -162,6 +162,12 @@ a|
[[quarkus-camel-opentelemetry2-trace-headers-inclusion]]`link:#quarkus-camel-
If set to `true`, adds the generated telemetry `CAMEL_TRACE_ID` and
`CAMEL_SPAN_ID` Exchange headers.
| `boolean`
| `false`
+
+a|
[[quarkus-camel-opentelemetry2-trace-custom-id-only]]`link:#quarkus-camel-opentelemetry2-trace-custom-id-only[quarkus.camel.opentelemetry2.trace-custom-id-only]`
+
+If set to `true`, only creates trace spans for routes and nodes that have a
custom id assigned.
+| `boolean`
+| `false`
|===
[.configuration-legend]
diff --git
a/extensions/opentelemetry2/deployment/src/test/java/org/apache/camel/quarkus/component/opentelemetry2/deployment/Opentelemetry2Test.java
b/extensions/opentelemetry2/deployment/src/test/java/org/apache/camel/quarkus/component/opentelemetry2/deployment/Opentelemetry2Test.java
index 82739ba406..5920484093 100644
---
a/extensions/opentelemetry2/deployment/src/test/java/org/apache/camel/quarkus/component/opentelemetry2/deployment/Opentelemetry2Test.java
+++
b/extensions/opentelemetry2/deployment/src/test/java/org/apache/camel/quarkus/component/opentelemetry2/deployment/Opentelemetry2Test.java
@@ -43,6 +43,7 @@ public class Opentelemetry2Test {
.overrideConfigKey("quarkus.camel.opentelemetry2.exclude-patterns",
EXCLUDE_PATTERNS)
.overrideConfigKey("quarkus.camel.opentelemetry2.trace-processors", "true")
.overrideConfigKey("quarkus.camel.opentelemetry2.trace-headers-inclusion",
"true")
+
.overrideConfigKey("quarkus.camel.opentelemetry2.trace-custom-id-only", "true")
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class));
@Inject
@@ -59,5 +60,6 @@ public class Opentelemetry2Test {
assertEquals(EXCLUDE_PATTERNS, tracer.getExcludePatterns());
assertTrue(tracer.isTraceProcessors());
assertTrue(tracer.isTraceHeadersInclusion());
+ assertTrue(tracer.isTraceCustomIdOnly());
}
}
diff --git
a/extensions/opentelemetry2/runtime/src/main/java/org/apache/camel/quarkus/component/opentelemetry2/CamelOpenTelemetry2Config.java
b/extensions/opentelemetry2/runtime/src/main/java/org/apache/camel/quarkus/component/opentelemetry2/CamelOpenTelemetry2Config.java
index 5486c03a47..17d73d6abd 100644
---
a/extensions/opentelemetry2/runtime/src/main/java/org/apache/camel/quarkus/component/opentelemetry2/CamelOpenTelemetry2Config.java
+++
b/extensions/opentelemetry2/runtime/src/main/java/org/apache/camel/quarkus/component/opentelemetry2/CamelOpenTelemetry2Config.java
@@ -73,4 +73,12 @@ public interface CamelOpenTelemetry2Config {
*/
@WithDefault("false")
boolean traceHeadersInclusion();
+
+ /**
+ * If set to `true`, only creates trace spans for routes and nodes that
have a custom id assigned.
+ *
+ * @asciidoclet
+ */
+ @WithDefault("false")
+ boolean traceCustomIdOnly();
}
diff --git
a/extensions/opentelemetry2/runtime/src/main/java/org/apache/camel/quarkus/component/opentelemetry2/OpenTelemetry2TracerProducer.java
b/extensions/opentelemetry2/runtime/src/main/java/org/apache/camel/quarkus/component/opentelemetry2/OpenTelemetry2TracerProducer.java
index 69e597d64c..8ed5a78702 100644
---
a/extensions/opentelemetry2/runtime/src/main/java/org/apache/camel/quarkus/component/opentelemetry2/OpenTelemetry2TracerProducer.java
+++
b/extensions/opentelemetry2/runtime/src/main/java/org/apache/camel/quarkus/component/opentelemetry2/OpenTelemetry2TracerProducer.java
@@ -44,6 +44,7 @@ public class OpenTelemetry2TracerProducer {
openTelemetryTracer.setTraceProcessors(config.traceProcessors());
openTelemetryTracer.setDisableCoreProcessors(config.disableCoreProcessors());
openTelemetryTracer.setTraceHeadersInclusion(config.traceHeadersInclusion());
+
openTelemetryTracer.setTraceCustomIdOnly(config.traceCustomIdOnly());
openTelemetryTracer.init(camelContext);
return openTelemetryTracer;
}
diff --git
a/integration-tests/opentelemetry2/src/main/java/org/apache/camel/quarkus/component/opentelemetry2/it/OpenTelemetry2Resource.java
b/integration-tests/opentelemetry2/src/main/java/org/apache/camel/quarkus/component/opentelemetry2/it/OpenTelemetry2Resource.java
index 7f217f4041..62427ad95d 100644
---
a/integration-tests/opentelemetry2/src/main/java/org/apache/camel/quarkus/component/opentelemetry2/it/OpenTelemetry2Resource.java
+++
b/integration-tests/opentelemetry2/src/main/java/org/apache/camel/quarkus/component/opentelemetry2/it/OpenTelemetry2Resource.java
@@ -43,6 +43,13 @@ public class OpenTelemetry2Resource {
return producerTemplate.requestBody("direct:start", null,
String.class);
}
+ @Path("/trace/customIdOnly")
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public String traceCustomIdOnlyRoute() {
+ return producerTemplate.requestBody("direct:customIdOnly", null,
String.class);
+ }
+
@Path("/greet/{name}")
@GET
@Produces(MediaType.TEXT_PLAIN)
diff --git
a/integration-tests/opentelemetry2/src/main/java/org/apache/camel/quarkus/component/opentelemetry2/it/OpenTelemetry2RouteBuilder.java
b/integration-tests/opentelemetry2/src/main/java/org/apache/camel/quarkus/component/opentelemetry2/it/OpenTelemetry2RouteBuilder.java
index 54f9d1a262..fe75021238 100644
---
a/integration-tests/opentelemetry2/src/main/java/org/apache/camel/quarkus/component/opentelemetry2/it/OpenTelemetry2RouteBuilder.java
+++
b/integration-tests/opentelemetry2/src/main/java/org/apache/camel/quarkus/component/opentelemetry2/it/OpenTelemetry2RouteBuilder.java
@@ -35,6 +35,11 @@ public class OpenTelemetry2RouteBuilder extends RouteBuilder
{
.routeId("tracedRoute")
.setBody().constant("Traced direct:start");
+ // Route and node both have a custom id assigned, so both are traced
when trace-custom-id-only is enabled
+ from("direct:customIdOnly")
+ .routeId("customIdOnlyRoute")
+ .setBody().constant("Traced
direct:customIdOnly").id("customIdOnlySetBody");
+
// NOTE: when we call the bean in this way, the resulting inner span
will depends directly on the
// "to" processor node
from("direct:greet")
diff --git
a/integration-tests/opentelemetry2/src/test/java/org/apache/camel/quarkus/component/opentelemetry2/it/OpenTelemetry2TraceCustomIdOnlyIT.java
b/integration-tests/opentelemetry2/src/test/java/org/apache/camel/quarkus/component/opentelemetry2/it/OpenTelemetry2TraceCustomIdOnlyIT.java
new file mode 100644
index 0000000000..15e6aef372
--- /dev/null
+++
b/integration-tests/opentelemetry2/src/test/java/org/apache/camel/quarkus/component/opentelemetry2/it/OpenTelemetry2TraceCustomIdOnlyIT.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.component.opentelemetry2.it;
+
+import io.quarkus.test.junit.QuarkusIntegrationTest;
+
+@QuarkusIntegrationTest
+class OpenTelemetry2TraceCustomIdOnlyIT extends
OpenTelemetry2TraceCustomIdOnlyTest {
+}
diff --git
a/integration-tests/opentelemetry2/src/test/java/org/apache/camel/quarkus/component/opentelemetry2/it/OpenTelemetry2TraceCustomIdOnlyTest.java
b/integration-tests/opentelemetry2/src/test/java/org/apache/camel/quarkus/component/opentelemetry2/it/OpenTelemetry2TraceCustomIdOnlyTest.java
new file mode 100644
index 0000000000..c2251dd1c8
--- /dev/null
+++
b/integration-tests/opentelemetry2/src/test/java/org/apache/camel/quarkus/component/opentelemetry2/it/OpenTelemetry2TraceCustomIdOnlyTest.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.component.opentelemetry2.it;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import io.opentelemetry.api.trace.SpanKind;
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.TestProfile;
+import io.restassured.RestAssured;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+
+import static
org.apache.camel.quarkus.component.opentelemetry2.it.OpenTelemetry2TestHelper.getSpans;
+import static org.awaitility.Awaitility.await;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@TestProfile(TraceCustomIdOnlyTestProfile.class)
+@QuarkusTest
+class OpenTelemetry2TraceCustomIdOnlyTest {
+ @AfterEach
+ public void afterEach() {
+ RestAssured.post("/opentelemetry2/exporter/spans/reset")
+ .then()
+ .statusCode(204);
+ }
+
+ @Test
+ void customIdRouteAndNodeAreTraced() {
+ RestAssured.get("/opentelemetry2/trace/customIdOnly")
+ .then()
+ .statusCode(200)
+ .body(equalTo("Traced direct:customIdOnly"));
+
+ // Verify the span hierarchy is JAX-RS Service -> Direct Endpoint ->
SetBody
+ await().atMost(30, TimeUnit.SECONDS).pollDelay(50,
TimeUnit.MILLISECONDS).until(() -> getSpans().size() == 4);
+
+ List<Map<String, String>> spans = getSpans();
+ assertEquals(4, spans.size());
+ assertEquals("EVENT_PROCESS", spans.get(0).get("op"));
+ assertEquals("customIdOnlySetBody-setBody",
spans.get(0).get("component"));
+ assertEquals(spans.get(1).get("spanId"), spans.get(0).get("parentId"));
+ assertEquals("EVENT_RECEIVED", spans.get(1).get("op"));
+ assertEquals("customIdOnlyRoute", spans.get(1).get("camel.route.id"));
+ assertEquals(spans.get(2).get("spanId"), spans.get(1).get("parentId"));
+ assertEquals("EVENT_SENT", spans.get(2).get("op"));
+ assertEquals(spans.get(3).get("spanId"), spans.get(2).get("parentId"));
+ assertEquals(SpanKind.SERVER.name(), spans.get(3).get("kind"));
+ }
+
+ @Test
+ void nonCustomIdNodeIsNotTraced() {
+ RestAssured.get("/opentelemetry2/trace")
+ .then()
+ .statusCode(200)
+ .body(equalTo("Traced direct:start"));
+
+ // The route has a custom id, so it is traced, but its setBody node
does not, so no processor span is created
+ await().atMost(30, TimeUnit.SECONDS).pollDelay(50,
TimeUnit.MILLISECONDS).until(() -> getSpans().size() == 3);
+
+ List<Map<String, String>> spans = getSpans();
+ assertEquals(3, spans.size());
+ assertEquals("EVENT_RECEIVED", spans.get(0).get("op"));
+ assertEquals("tracedRoute", spans.get(0).get("camel.route.id"));
+ assertEquals("EVENT_SENT", spans.get(1).get("op"));
+ assertEquals(SpanKind.SERVER.name(), spans.get(2).get("kind"));
+ assertTrue(spans.stream().noneMatch(span ->
"EVENT_PROCESS".equals(span.get("op"))));
+ }
+
+ @Test
+ void nonCustomIdRouteIsNotTraced() {
+ String name = "Camel Quarkus OpenTelemetry";
+ RestAssured.get("/opentelemetry2/greetBean/" + name)
+ .then()
+ .statusCode(200)
+ .body(equalTo("Hello " + name));
+
+ // The route has no custom id, so no Camel spans are created for it
+ await().atMost(30, TimeUnit.SECONDS).pollDelay(50,
TimeUnit.MILLISECONDS).until(() -> getSpans().size() == 2);
+
+ List<Map<String, String>> spans = getSpans();
+ assertEquals(2, spans.size());
+ assertTrue(spans.stream().noneMatch(span ->
span.containsKey("camel.route.id")));
+ assertTrue(spans.stream().noneMatch(span -> span.containsKey("op")));
+ assertEquals(SpanKind.SERVER.name(), spans.get(1).get("kind"));
+ }
+}
diff --git
a/integration-tests/opentelemetry2/src/test/java/org/apache/camel/quarkus/component/opentelemetry2/it/TraceCustomIdOnlyTestProfile.java
b/integration-tests/opentelemetry2/src/test/java/org/apache/camel/quarkus/component/opentelemetry2/it/TraceCustomIdOnlyTestProfile.java
new file mode 100644
index 0000000000..9a0316ce9d
--- /dev/null
+++
b/integration-tests/opentelemetry2/src/test/java/org/apache/camel/quarkus/component/opentelemetry2/it/TraceCustomIdOnlyTestProfile.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.component.opentelemetry2.it;
+
+import java.util.Map;
+
+import io.quarkus.test.junit.QuarkusTestProfile;
+
+public class TraceCustomIdOnlyTestProfile implements QuarkusTestProfile {
+ @Override
+ public Map<String, String> getConfigOverrides() {
+ return Map.of("quarkus.camel.opentelemetry2.trace-custom-id-only",
"true");
+ }
+}