This is an automated email from the ASF dual-hosted git repository. JiriOndrusek pushed a commit to branch camel-main in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
commit efdf386baa591469d03c83c48f184fda95ec2cb4 Author: Pasquale Congiusti <[email protected]> AuthorDate: Thu May 14 14:34:21 2026 +0200 chore(extensions): telemetry disable core processors --- .../pages/reference/extensions/opentelemetry2.adoc | 9 +- .../pages/reference/extensions/telemetry-dev.adoc | 9 +- .../opentelemetry2/CamelOpenTelemetry2Config.java | 11 ++- .../OpenTelemetry2TracerProducer.java | 1 + .../telemetry/dev/CamelTelemetryDevConfig.java | 11 ++- .../telemetry/dev/TelemetryDevTracerProducer.java | 4 + .../src/main/resources/application.properties | 1 + .../opentelemetry2/it/OpenTelemetry2Resource.java | 7 ++ .../it/OpenTelemetry2RouteBuilder.java | 8 +- .../opentelemetry2/it/Opentelemetry2Test.java | 106 ++++++++++++++------- 10 files changed, 128 insertions(+), 39 deletions(-) diff --git a/docs/modules/ROOT/pages/reference/extensions/opentelemetry2.adoc b/docs/modules/ROOT/pages/reference/extensions/opentelemetry2.adoc index 21ff27decf..da7d5d96c9 100644 --- a/docs/modules/ROOT/pages/reference/extensions/opentelemetry2.adoc +++ b/docs/modules/ROOT/pages/reference/extensions/opentelemetry2.adoc @@ -138,11 +138,18 @@ pattern can take the following forms: a| [[quarkus-camel-opentelemetry2-trace-processors]]`link:#quarkus-camel-opentelemetry2-trace-processors[quarkus.camel.opentelemetry2.trace-processors]` -Sets whether to create new OpenTelemetry spans for each Camel Processor. Use the excludePatterns property to filter +Sets whether to create new telemetry spans for each Camel custom Processor. Use the excludePatterns property to +filter out Processors. | `boolean` | `false` +a| [[quarkus-camel-opentelemetry2-disable-core-processors]]`link:#quarkus-camel-opentelemetry2-disable-core-processors[quarkus.camel.opentelemetry2.disable-core-processors]` + +Disable any inner core processors (any core DSL processor provided in the route, for example `bean`, `log`, ...). +| `boolean` +| `false` + a| [[quarkus-camel-opentelemetry2-trace-headers-inclusion]]`link:#quarkus-camel-opentelemetry2-trace-headers-inclusion[quarkus.camel.opentelemetry2.trace-headers-inclusion]` If set to `true`, adds the generated telemetry `CAMEL_TRACE_ID` and `CAMEL_SPAN_ID` Exchange headers. diff --git a/docs/modules/ROOT/pages/reference/extensions/telemetry-dev.adoc b/docs/modules/ROOT/pages/reference/extensions/telemetry-dev.adoc index f7a9164078..b7ec28941c 100644 --- a/docs/modules/ROOT/pages/reference/extensions/telemetry-dev.adoc +++ b/docs/modules/ROOT/pages/reference/extensions/telemetry-dev.adoc @@ -67,11 +67,18 @@ pattern can take the following forms: a| [[quarkus-camel-telemetrydev-trace-processors]]`link:#quarkus-camel-telemetrydev-trace-processors[quarkus.camel.telemetryDev.trace-processors]` -Sets whether to create new OpenTelemetry spans for each Camel Processor. Use the excludePatterns property to filter +Sets whether to create new telemetry spans for each Camel custom Processor. Use the excludePatterns property to +filter out Processors. | `boolean` | `false` +a| [[quarkus-camel-telemetrydev-disable-core-processors]]`link:#quarkus-camel-telemetrydev-disable-core-processors[quarkus.camel.telemetryDev.disable-core-processors]` + +Disable any inner core processors (any core DSL processor provided in the route, for example `bean`, `log`, ...). +| `boolean` +| `false` + a| [[quarkus-camel-telemetrydev-trace-format]]`link:#quarkus-camel-telemetrydev-trace-format[quarkus.camel.telemetryDev.trace-format]` The output format for traces 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 d9cd4d582a..4b38327425 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 @@ -41,7 +41,8 @@ public interface CamelOpenTelemetry2Config { Optional<String> excludePatterns(); /** - * Sets whether to create new OpenTelemetry spans for each Camel Processor. Use the excludePatterns property to filter + * Sets whether to create new telemetry spans for each Camel custom Processor. Use the excludePatterns property to + * filter * out Processors. * * @asciidoclet @@ -49,6 +50,14 @@ public interface CamelOpenTelemetry2Config { @WithDefault("false") boolean traceProcessors(); + /** + * Disable any inner core processors (any core DSL processor provided in the route, for example `bean`, `log`, ...). + * + * @asciidoclet + */ + @WithDefault("false") + public boolean disableCoreProcessors(); + /** * If set to `true`, adds the generated telemetry `CAMEL_TRACE_ID` and `CAMEL_SPAN_ID` Exchange headers. * 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 4457ab406d..4d1ed9733c 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 @@ -41,6 +41,7 @@ public class OpenTelemetry2TracerProducer { OpenTelemetryTracer openTelemetryTracer = new OpenTelemetryTracer(); config.excludePatterns().ifPresent(openTelemetryTracer::setExcludePatterns); openTelemetryTracer.setTraceProcessors(config.traceProcessors()); + openTelemetryTracer.setDisableCoreProcessors(config.disableCoreProcessors()); openTelemetryTracer.setTraceHeadersInclusion(config.traceHeadersInclusion()); openTelemetryTracer.init(camelContext); return openTelemetryTracer; diff --git a/extensions/telemetry-dev/runtime/src/main/java/org/apache/camel/quarkus/component/telemetry/dev/CamelTelemetryDevConfig.java b/extensions/telemetry-dev/runtime/src/main/java/org/apache/camel/quarkus/component/telemetry/dev/CamelTelemetryDevConfig.java index 69cb349511..66c7bbd304 100644 --- a/extensions/telemetry-dev/runtime/src/main/java/org/apache/camel/quarkus/component/telemetry/dev/CamelTelemetryDevConfig.java +++ b/extensions/telemetry-dev/runtime/src/main/java/org/apache/camel/quarkus/component/telemetry/dev/CamelTelemetryDevConfig.java @@ -42,7 +42,8 @@ public interface CamelTelemetryDevConfig { Optional<String> excludePatterns(); /** - * Sets whether to create new OpenTelemetry spans for each Camel Processor. Use the excludePatterns property to filter + * Sets whether to create new telemetry spans for each Camel custom Processor. Use the excludePatterns property to + * filter * out Processors. * * @asciidoclet @@ -50,6 +51,14 @@ public interface CamelTelemetryDevConfig { @WithDefault("false") boolean traceProcessors(); + /** + * Disable any inner core processors (any core DSL processor provided in the route, for example `bean`, `log`, ...). + * + * @asciidoclet + */ + @WithDefault("false") + public boolean disableCoreProcessors(); + /** * The output format for traces * diff --git a/extensions/telemetry-dev/runtime/src/main/java/org/apache/camel/quarkus/component/telemetry/dev/TelemetryDevTracerProducer.java b/extensions/telemetry-dev/runtime/src/main/java/org/apache/camel/quarkus/component/telemetry/dev/TelemetryDevTracerProducer.java index cfb068af79..186475ac43 100644 --- a/extensions/telemetry-dev/runtime/src/main/java/org/apache/camel/quarkus/component/telemetry/dev/TelemetryDevTracerProducer.java +++ b/extensions/telemetry-dev/runtime/src/main/java/org/apache/camel/quarkus/component/telemetry/dev/TelemetryDevTracerProducer.java @@ -41,6 +41,10 @@ public class TelemetryDevTracerProducer { telemetryDevTracer.setTraceProcessors(config.traceProcessors()); } + if (config.disableCoreProcessors()) { + telemetryDevTracer.setDisableCoreProcessors(config.disableCoreProcessors()); + } + if (config.traceFormat().isPresent()) { telemetryDevTracer.setTraceFormat(config.traceFormat().get()); } diff --git a/integration-tests/observability-services/src/main/resources/application.properties b/integration-tests/observability-services/src/main/resources/application.properties index 75eac8f864..5f8be048ca 100644 --- a/integration-tests/observability-services/src/main/resources/application.properties +++ b/integration-tests/observability-services/src/main/resources/application.properties @@ -16,6 +16,7 @@ ## --------------------------------------------------------------------------- camel.context.name=observability-services-context +quarkus.camel.opentelemetry2.disable-core-processors=true quarkus.otel.sdk.disabled=false quarkus.otel.bsp.export.timeout=1s 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 9038dc22c8..7f217f4041 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 @@ -50,6 +50,13 @@ public class OpenTelemetry2Resource { return producerTemplate.requestBody("direct:greet", name, String.class); } + @Path("/greetBean/{name}") + @GET + @Produces(MediaType.TEXT_PLAIN) + public String traceBeanRoute(@PathParam("name") String name) { + return producerTemplate.requestBody("direct:greetBean", name, String.class); + } + @Path("/jdbc/query") @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 17169f11e4..6da3617310 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 @@ -34,14 +34,20 @@ public class OpenTelemetry2RouteBuilder extends RouteBuilder { from("direct:start") .setBody().constant("Traced direct:start"); + // NOTE: when we call the bean in this way, the resulting inner span will depends directly on the + // "to" processor node from("direct:greet") .to("bean:greetingsBean"); + // When, instead, it is called by a bean processor, then, the inner span will depends on the "bean" + // processor node + from("direct:greetBean") + .bean(GreetingsBean.class); from("timer:filtered?repeatCount=5&delay=-1") .setBody().constant("Route filtered from tracing").id("timer-setbody"); from("direct:jdbcQuery") - .to("bean:jdbcQueryBean"); + .bean(JdbcQueryBean.class); from("direct:traceHeaderInclusion") .log("Trace info: CAMEL_SPAN_ID=${header.CAMEL_SPAN_ID}, CAMEL_TRACE_ID=${header.CAMEL_TRACE_ID}"); diff --git a/integration-tests/opentelemetry2/src/test/java/org/apache/camel/quarkus/component/opentelemetry2/it/Opentelemetry2Test.java b/integration-tests/opentelemetry2/src/test/java/org/apache/camel/quarkus/component/opentelemetry2/it/Opentelemetry2Test.java index fda4a5dec6..0b033e0aa3 100644 --- a/integration-tests/opentelemetry2/src/test/java/org/apache/camel/quarkus/component/opentelemetry2/it/Opentelemetry2Test.java +++ b/integration-tests/opentelemetry2/src/test/java/org/apache/camel/quarkus/component/opentelemetry2/it/Opentelemetry2Test.java @@ -49,8 +49,10 @@ class Opentelemetry2Test { @Test public void testTraceRoute() { + int nTraces = 5; + int spanPerTrace = 4; // Generate messages - for (int i = 0; i < 5; i++) { + for (int i = 0; i < nTraces; i++) { RestAssured.get("/opentelemetry2/test/trace/") .then() .statusCode(200); @@ -65,16 +67,19 @@ class Opentelemetry2Test { } // Retrieve recorded spans - await().atMost(30, TimeUnit.SECONDS).pollDelay(50, TimeUnit.MILLISECONDS).until(() -> getSpans().size() == 10); + await().atMost(30, TimeUnit.SECONDS).pollDelay(50, TimeUnit.MILLISECONDS) + .until(() -> getSpans().size() == (nTraces * spanPerTrace)); List<Map<String, String>> spans = getSpans(); - assertEquals(10, spans.size()); + assertEquals(nTraces * spanPerTrace, spans.size()); // for (int i = spans.size() - 1; i >= 0; i--) { Map<String, String> span = spans.get(i); // Verify the span hierarchy is Quarkus Vert.x HTTP server -> Platform HTTP Endpoint - if (i % 2 == 0) { + // NOTE: we expect 4 spans for each trace, being the last 2 the ones we want to check to verify http hierarchy + // This is a bit fragile and we may rethink how to properly extract span hierarchically from each trace instead. + if (i % 4 == 2) { assertEquals("camel-platform-http", span.get("component")); assertEquals("200", span.get("http.status_code")); assertEquals("GET", span.get("http.method")); @@ -82,7 +87,7 @@ class Opentelemetry2Test { assertTrue(span.get("http.url").endsWith("/opentelemetry2/test/trace/")); assertEquals(SpanKind.SERVER.name(), span.get("kind")); assertEquals(spans.get(i + 1).get("spanId"), span.get("parentId")); - } else { + } else if (i % 4 == 3) { assertEquals("200", span.get("http.response.status_code")); assertEquals("GET", span.get("http.request.method")); assertEquals("/opentelemetry2/test/trace/", span.get("url.path")); @@ -94,41 +99,70 @@ class Opentelemetry2Test { @Test public void testTracedCamelRouteInvokedFromJaxRsService() { + int spanPerTrace = 4; RestAssured.get("/opentelemetry2/trace") .then() .statusCode(200) .body(equalTo("Traced direct:start")); // Verify the span hierarchy is JAX-RS Service -> Direct Endpoint - await().atMost(30, TimeUnit.SECONDS).pollDelay(50, TimeUnit.MILLISECONDS).until(() -> getSpans().size() == 3); + await().atMost(30, TimeUnit.SECONDS).pollDelay(50, TimeUnit.MILLISECONDS) + .until(() -> getSpans().size() == spanPerTrace); List<Map<String, String>> spans = getSpans(); - assertEquals(3, spans.size()); + assertEquals(spanPerTrace, spans.size()); assertEquals(spans.get(0).get("parentId"), spans.get(1).get("spanId")); assertEquals(SpanKind.INTERNAL.name(), spans.get(1).get("kind")); - assertEquals(SpanKind.SERVER.name(), spans.get(2).get("kind")); + assertEquals(SpanKind.INTERNAL.name(), spans.get(2).get("kind")); + assertEquals(SpanKind.SERVER.name(), spans.get(3).get("kind")); } @Test public void testTracedBean() { + int spanPerTrace = 5; String name = "Camel Quarkus OpenTelemetry"; - RestAssured.get("/opentelemetry2/greet/" + name) + RestAssured.get("/opentelemetry2/greetBean/" + name) .then() .statusCode(200) .body(equalTo("Hello " + name)); // Verify the span hierarchy is JAX-RS Service -> Direct Endpoint -> Bean Method - await().atMost(30, TimeUnit.SECONDS).pollDelay(50, TimeUnit.MILLISECONDS).until(() -> getSpans().size() == 5); + await().atMost(30, TimeUnit.SECONDS).pollDelay(50, TimeUnit.MILLISECONDS) + .until(() -> getSpans().size() == spanPerTrace); List<Map<String, String>> spans = getSpans(); - assertEquals(5, spans.size()); - assertEquals(spans.get(0).get("parentId"), spans.get(1).get("spanId")); - assertEquals(spans.get(1).get("parentId"), spans.get(2).get("spanId")); - assertEquals(spans.get(2).get("parentId"), spans.get(3).get("spanId")); - assertEquals(SpanKind.INTERNAL.name(), spans.get(3).get("kind")); + assertEquals(spanPerTrace, spans.size()); + + assertEquals(spans.get(1).get("spanId"), spans.get(0).get("parentId")); + assertEquals(spans.get(2).get("spanId"), spans.get(1).get("parentId")); + assertEquals(spans.get(3).get("spanId"), spans.get(2).get("parentId")); assertEquals(SpanKind.SERVER.name(), spans.get(4).get("kind")); } + @Test + public void testTracedBeanTo() { + int spanPerTrace = 6; + String name = "Camel Quarkus OpenTelemetry"; + RestAssured.get("/opentelemetry2/greet/" + name) + .then() + .statusCode(200) + .body(equalTo("Hello " + name)); + + // Verify the span hierarchy is JAX-RS Service -> Direct Endpoint -> To Bean + await().atMost(30, TimeUnit.SECONDS).pollDelay(50, TimeUnit.MILLISECONDS) + .until(() -> getSpans().size() == spanPerTrace); + List<Map<String, String>> spans = getSpans(); + assertEquals(spanPerTrace, spans.size()); + + // The inner span generated will depend on the "to" processor node + assertEquals(spans.get(2).get("spanId"), spans.get(0).get("parentId")); + assertEquals(spans.get(2).get("spanId"), spans.get(1).get("parentId")); + assertEquals(spans.get(3).get("spanId"), spans.get(2).get("parentId")); + assertEquals(SpanKind.INTERNAL.name(), spans.get(4).get("kind")); + assertEquals(SpanKind.SERVER.name(), spans.get(5).get("kind")); + } + @Test public void testTracedJdbcQuery() { + int spanPerTrace = 5; String timestamp = RestAssured.get("/opentelemetry2/jdbc/query") .then() .statusCode(200) @@ -139,30 +173,31 @@ class Opentelemetry2Test { assertTrue(Long.parseLong(timestamp) > 0); // Verify the span hierarchy is JAX-RS Service -> Direct Endpoint -> Bean Endpoint -> JDBC query - await().atMost(30, TimeUnit.SECONDS).pollDelay(50, TimeUnit.MILLISECONDS).until(() -> getSpans().size() == 5); + await().atMost(30, TimeUnit.SECONDS).pollDelay(50, TimeUnit.MILLISECONDS) + .until(() -> getSpans().size() == spanPerTrace); List<Map<String, String>> spans = getSpans(); - assertEquals(5, spans.size()); + assertEquals(spanPerTrace, spans.size()); // JDBC SELECT operation span - assertEquals(spans.get(0).get("parentId"), spans.get(1).get("spanId")); + assertEquals(spans.get(1).get("spanId"), spans.get(0).get("parentId")); assertEquals("SELECT", spans.get(0).get("db.operation")); // Bean endpoint span - assertEquals(spans.get(1).get("parentId"), spans.get(2).get("spanId")); - assertEquals("bean://jdbcQueryBean", spans.get(1).get("camel.uri")); + assertEquals(spans.get(2).get("spanId"), spans.get(1).get("parentId")); + assertTrue(spans.get(1).get("component").contains("bean")); // Direct endpoint EVENT_RECEIVED span - assertEquals(spans.get(2).get("parentId"), spans.get(3).get("spanId")); + assertEquals(spans.get(3).get("spanId"), spans.get(2).get("parentId")); assertEquals("direct://jdbcQuery", spans.get(2).get("camel.uri")); assertEquals("EVENT_RECEIVED", spans.get(2).get("op")); // Direct endpoint EVENT_SENT span - assertEquals(spans.get(3).get("parentId"), spans.get(4).get("spanId")); + assertEquals(spans.get(4).get("spanId"), spans.get(3).get("parentId")); assertEquals("direct://jdbcQuery", spans.get(3).get("camel.uri")); assertEquals("EVENT_SENT", spans.get(3).get("op")); // JAX-RS Server span (root) - assertEquals(spans.get(4).get("parentId"), "0000000000000000"); + assertEquals("0000000000000000", spans.get(4).get("parentId")); assertEquals("org.apache.camel.quarkus.component.opentelemetry2.it.OpenTelemetry2Resource.jdbcQuery", spans.get(4).get(CODE_FUNCTION_NAME.getKey())); } @@ -179,6 +214,7 @@ class Opentelemetry2Test { @ParameterizedTest @ValueSource(strings = { "http", "vertx-http" }) void testHttpInvocation(String httpComponent) { + int spanPerTrace = 10; RestAssured.given() .queryParam("httpComponent", httpComponent) .get("/greeting") @@ -186,24 +222,26 @@ class Opentelemetry2Test { .statusCode(200) .body(equalTo("Hello From Camel Quarkus!")); - await().atMost(30, TimeUnit.SECONDS).pollDelay(50, TimeUnit.MILLISECONDS).until(() -> getSpans().size() == 5); + await().atMost(30, TimeUnit.SECONDS).pollDelay(50, TimeUnit.MILLISECONDS) + .until(() -> getSpans().size() == spanPerTrace); List<Map<String, String>> spans = getSpans(); - assertEquals(5, spans.size()); + assertEquals(spanPerTrace, spans.size()); + // Verify root doesn't have parent - assertEquals("0000000000000000", spans.get(4).get("parentId")); + assertEquals("0000000000000000", spans.get(9).get("parentId")); // Verify the span hierarchy - assertEquals(spans.get(4).get("spanId"), spans.get(3).get("parentId")); - assertEquals(spans.get(3).get("spanId"), spans.get(2).get("parentId")); + assertEquals(spans.get(8).get("parentId"), spans.get(9).get("spanId")); + assertEquals(spans.get(7).get("parentId"), spans.get(8).get("spanId")); // Last two spans have the same parent // For /greeting there is no existing tracing in progress. For /greeting-provider there is, so its related to the trace propagation - assertEquals(spans.get(2).get("spanId"), spans.get(1).get("parentId")); - assertEquals(spans.get(2).get("spanId"), spans.get(0).get("parentId")); + assertEquals(spans.get(1).get("parentId"), spans.get(2).get("spanId")); + assertEquals(spans.get(0).get("parentId"), spans.get(2).get("spanId")); - assertEquals(SpanKind.SERVER.name(), spans.get(4).get("kind")); - assertEquals(SpanKind.SERVER.name(), spans.get(1).get("kind")); + assertEquals(SpanKind.SERVER.name(), spans.get(9).get("kind")); + assertEquals(SpanKind.SERVER.name(), spans.get(2).get("kind")); - assertEquals(SpanKind.SERVER.name(), spans.get(0).get("kind")); - assertEquals(SpanKind.CLIENT.name(), spans.get(2).get("kind")); assertEquals(SpanKind.SERVER.name(), spans.get(3).get("kind")); + assertEquals(SpanKind.CLIENT.name(), spans.get(4).get("kind")); + assertEquals(SpanKind.SERVER.name(), spans.get(8).get("kind")); } }
