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");
+    }
+}

Reply via email to