diff --git a/components/camel-micrometer-observability/src/generated/java/org/apache/camel/micrometer/observability/MicrometerObservabilityTracerConfigurer.java b/components/camel-micrometer-observability/src/generated/java/org/apache/camel/micrometer/observability/MicrometerObservabilityTracerConfigurer.java index 81a5e30fb4b1e..35a9d8baf3a80 100644 --- a/components/camel-micrometer-observability/src/generated/java/org/apache/camel/micrometer/observability/MicrometerObservabilityTracerConfigurer.java +++ b/components/camel-micrometer-observability/src/generated/java/org/apache/camel/micrometer/observability/MicrometerObservabilityTracerConfigurer.java @@ -25,6 +25,8 @@ public boolean configure(CamelContext camelContext, Object obj, String name, Obj switch (ignoreCase ? name.toLowerCase() : name) { case "camelcontext": case "camelContext": target.setCamelContext(property(camelContext, org.apache.camel.CamelContext.class, value)); return true; + case "disablecoreprocessors": + case "disableCoreProcessors": target.setDisableCoreProcessors(property(camelContext, boolean.class, value)); return true; case "excludepatterns": case "excludePatterns": target.setExcludePatterns(property(camelContext, java.lang.String.class, value)); return true; case "observationregistry": @@ -46,6 +48,8 @@ public Class getOptionType(String name, boolean ignoreCase) { switch (ignoreCase ? name.toLowerCase() : name) { case "camelcontext": case "camelContext": return org.apache.camel.CamelContext.class; + case "disablecoreprocessors": + case "disableCoreProcessors": return boolean.class; case "excludepatterns": case "excludePatterns": return java.lang.String.class; case "observationregistry": @@ -68,6 +72,8 @@ public Object getOptionValue(Object obj, String name, boolean ignoreCase) { switch (ignoreCase ? name.toLowerCase() : name) { case "camelcontext": case "camelContext": return target.getCamelContext(); + case "disablecoreprocessors": + case "disableCoreProcessors": return target.isDisableCoreProcessors(); case "excludepatterns": case "excludePatterns": return target.getExcludePatterns(); case "observationregistry": diff --git a/components/camel-micrometer-observability/src/main/docs/micrometer-observability.adoc b/components/camel-micrometer-observability/src/main/docs/micrometer-observability.adoc index 017e1b79b8226..45bf7e99be2b4 100644 --- a/components/camel-micrometer-observability/src/main/docs/micrometer-observability.adoc +++ b/components/camel-micrometer-observability/src/main/docs/micrometer-observability.adoc @@ -28,9 +28,10 @@ The configuration properties for the component are: [width="100%",cols="10%,10%,80%",options="header",] |======================================================================= |Option |Default |Description +|`enabled`| false | Turn the tracing on/off. +|`traceProcessors`| false | Trace inner custom processors (i.e., any `process` configured in the route). +|`disableCoreProcessors`| false | Disable any inner core processors (any core DSL processor provided in the route, for example `bean`, `log`, ...). |`excludePatterns` | | Sets exclude pattern that will disable tracing for those spans that matches the pattern. The variable is a comma separated values of filters to execute (eg, `log*,direct*,setBody*`, ...) -|`traceProcessors` | `false` | Setting this to true will create new spans for each Camel Processors. -Use the excludePattern property to filter out Processors |`traceHeadersInclusion`| false | Add the generated telemetry `CAMEL_TRACE_ID` and `CAMEL_SPAN_ID` Exchange headers. |======================================================================= diff --git a/components/camel-micrometer-observability/src/test/java/org/apache/camel/micrometer/observability/BaggageInjectionTest.java b/components/camel-micrometer-observability/src/test/java/org/apache/camel/micrometer/observability/BaggageInjectionTest.java index 0fa31081e97e2..c83666f608d0a 100644 --- a/components/camel-micrometer-observability/src/test/java/org/apache/camel/micrometer/observability/BaggageInjectionTest.java +++ b/components/camel-micrometer-observability/src/test/java/org/apache/camel/micrometer/observability/BaggageInjectionTest.java @@ -44,8 +44,11 @@ public class BaggageInjectionTest extends MicrometerObservabilityTracerPropagati @Override protected CamelContext createCamelContext() throws Exception { + CamelContext ctx = super.createCamelContext(); tst.setTraceProcessors(true); - return super.createCamelContext(); + tst.setDisableCoreProcessors(false); + + return ctx; } @Test diff --git a/components/camel-micrometer-observability/src/test/java/org/apache/camel/micrometer/observability/EnableProcessorsTest.java b/components/camel-micrometer-observability/src/test/java/org/apache/camel/micrometer/observability/EnableProcessorsTest.java index 84395878723b7..13b42a399b8bc 100644 --- a/components/camel-micrometer-observability/src/test/java/org/apache/camel/micrometer/observability/EnableProcessorsTest.java +++ b/components/camel-micrometer-observability/src/test/java/org/apache/camel/micrometer/observability/EnableProcessorsTest.java @@ -39,8 +39,11 @@ public class EnableProcessorsTest extends MicrometerObservabilityTracerPropagati @Override protected CamelContext createCamelContext() throws Exception { + CamelContext ctx = super.createCamelContext(); tst.setTraceProcessors(true); - return super.createCamelContext(); + tst.setDisableCoreProcessors(false); + + return ctx; } @Test diff --git a/components/camel-micrometer-observability/src/test/java/org/apache/camel/micrometer/observability/MicrometerObservabilityTracerPropagationTestSupport.java b/components/camel-micrometer-observability/src/test/java/org/apache/camel/micrometer/observability/MicrometerObservabilityTracerPropagationTestSupport.java index f5b266408de98..b99d1c8c2e6e1 100644 --- a/components/camel-micrometer-observability/src/test/java/org/apache/camel/micrometer/observability/MicrometerObservabilityTracerPropagationTestSupport.java +++ b/components/camel-micrometer-observability/src/test/java/org/apache/camel/micrometer/observability/MicrometerObservabilityTracerPropagationTestSupport.java @@ -74,6 +74,7 @@ protected CamelContext createCamelContext() throws Exception { CamelContextAware.trySetCamelContext(tst, context); tst.init(context); + tst.setDisableCoreProcessors(true); return context; } diff --git a/components/camel-micrometer-observability/src/test/java/org/apache/camel/micrometer/observability/SpanBeanTest.java b/components/camel-micrometer-observability/src/test/java/org/apache/camel/micrometer/observability/SpanBeanTest.java new file mode 100644 index 0000000000000..aedb256e9f2c6 --- /dev/null +++ b/components/camel-micrometer-observability/src/test/java/org/apache/camel/micrometer/observability/SpanBeanTest.java @@ -0,0 +1,132 @@ +/* + * 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.micrometer.observability; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import io.opentelemetry.api.common.AttributeKey; +import io.opentelemetry.sdk.trace.data.SpanData; +import org.apache.camel.CamelContext; +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.camel.RoutesBuilder; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.micrometer.observability.CamelOpenTelemetryExtension.OtelTrace; +import org.apache.camel.telemetry.Op; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class SpanBeanTest extends MicrometerObservabilityTracerPropagationTestSupport { + + @Override + protected CamelContext createCamelContext() throws Exception { + CamelContext ctx = super.createCamelContext(); + tst.setDisableCoreProcessors(false); + + return ctx; + } + + @Test + void testRouteSingleRequest() throws IOException { + template.request("direct:start", null); + Map traces = otelExtension.getTraces(); + assertEquals(1, traces.size()); + checkTrace(traces.values().iterator().next()); + } + + private void checkTrace(OtelTrace trace) { + List spans = trace.getSpans(); + assertEquals(7, spans.size()); + SpanData testProducer = spans.get(0); + SpanData direct = spans.get(1); + SpanData innerLog = spans.get(2); + SpanData beanProcessor = spans.get(3); + SpanData customSpan = spans.get(4); + SpanData log = spans.get(5); + SpanData innerToLog = spans.get(6); + + // Validate span completion + assertTrue(testProducer.hasEnded()); + assertTrue(direct.hasEnded()); + assertTrue(innerLog.hasEnded()); + assertTrue(beanProcessor.hasEnded()); + assertTrue(customSpan.hasEnded()); + assertTrue(log.hasEnded()); + assertTrue(innerToLog.hasEnded()); + + // Validate same trace + assertEquals(testProducer.getSpanContext().getTraceId(), direct.getSpanContext().getTraceId()); + assertEquals(testProducer.getSpanContext().getTraceId(), direct.getSpanContext().getTraceId()); + assertEquals(testProducer.getSpanContext().getTraceId(), innerLog.getSpanContext().getTraceId()); + assertEquals(testProducer.getSpanContext().getTraceId(), beanProcessor.getSpanContext().getTraceId()); + assertEquals(testProducer.getSpanContext().getTraceId(), customSpan.getSpanContext().getTraceId()); + assertEquals(testProducer.getSpanContext().getTraceId(), log.getSpanContext().getTraceId()); + assertEquals(testProducer.getSpanContext().getTraceId(), innerToLog.getSpanContext().getTraceId()); + + // Validate operations + assertEquals(Op.EVENT_RECEIVED.toString(), direct.getAttributes().get(AttributeKey.stringKey("op"))); + assertEquals(Op.EVENT_PROCESS.toString(), beanProcessor.getAttributes().get(AttributeKey.stringKey("op"))); + + // Validate hierarchy + assertFalse(testProducer.getParentSpanContext().isValid()); + assertEquals(testProducer.getSpanContext().getSpanId(), direct.getParentSpanContext().getSpanId()); + assertEquals(direct.getSpanContext().getSpanId(), beanProcessor.getParentSpanContext().getSpanId()); + assertEquals(beanProcessor.getSpanContext().getSpanId(), customSpan.getParentSpanContext().getSpanId()); + + // Validate custom span + assertEquals("mySpan", customSpan.getName()); + } + + @Override + protected RoutesBuilder createRouteBuilder() { + return new RouteBuilder() { + @Override + public void configure() { + MyBean myBean = new MyBean(); + this.getCamelContext().getRegistry().bind("myBean", myBean); + + from("direct:start") + .routeId("start") + .log("A message") + .bean(MyBean.class) + .process(new Processor() { + @Override + public void process(Exchange exchange) throws Exception { + // noop + } + }) + .to("log:info"); + } + }; + } + + class MyBean { + // NOTE: the commented annotation below would work only when an agent or a runtime framework (quarkus or spring) + // is available. We simulate it creating the Span by hand instead. + //@WithSpan + public void helloWorld() { + io.opentelemetry.api.trace.Span mySpan = otelTracer.spanBuilder("mySpan").startSpan(); + // Do the work here + mySpan.end(); + } + } +} diff --git a/components/camel-micrometer-observability/src/test/java/org/apache/camel/micrometer/observability/SpanCustomizationTest.java b/components/camel-micrometer-observability/src/test/java/org/apache/camel/micrometer/observability/SpanCustomizationTest.java index 8e866bbf8d37a..4b86e4480cfca 100644 --- a/components/camel-micrometer-observability/src/test/java/org/apache/camel/micrometer/observability/SpanCustomizationTest.java +++ b/components/camel-micrometer-observability/src/test/java/org/apache/camel/micrometer/observability/SpanCustomizationTest.java @@ -40,8 +40,11 @@ public class SpanCustomizationTest extends MicrometerObservabilityTracerPropagat @Override protected CamelContext createCamelContext() throws Exception { + CamelContext ctx = super.createCamelContext(); tst.setTraceProcessors(true); - return super.createCamelContext(); + tst.setDisableCoreProcessors(false); + + return ctx; } @Test diff --git a/components/camel-micrometer-observability/src/test/java/org/apache/camel/micrometer/observability/SpanInjectionTest.java b/components/camel-micrometer-observability/src/test/java/org/apache/camel/micrometer/observability/SpanInjectionTest.java index 3a236df892dd3..908b5343c3126 100644 --- a/components/camel-micrometer-observability/src/test/java/org/apache/camel/micrometer/observability/SpanInjectionTest.java +++ b/components/camel-micrometer-observability/src/test/java/org/apache/camel/micrometer/observability/SpanInjectionTest.java @@ -43,8 +43,11 @@ public class SpanInjectionTest extends MicrometerObservabilityTracerPropagationT @Override protected CamelContext createCamelContext() throws Exception { + CamelContext ctx = super.createCamelContext(); tst.setTraceProcessors(true); - return super.createCamelContext(); + tst.setDisableCoreProcessors(false); + + return ctx; } @Test diff --git a/components/camel-opentelemetry2/src/generated/java/org/apache/camel/opentelemetry2/OpenTelemetryTracerConfigurer.java b/components/camel-opentelemetry2/src/generated/java/org/apache/camel/opentelemetry2/OpenTelemetryTracerConfigurer.java index cc561a6e98412..61762fd7d7121 100644 --- a/components/camel-opentelemetry2/src/generated/java/org/apache/camel/opentelemetry2/OpenTelemetryTracerConfigurer.java +++ b/components/camel-opentelemetry2/src/generated/java/org/apache/camel/opentelemetry2/OpenTelemetryTracerConfigurer.java @@ -25,6 +25,8 @@ public boolean configure(CamelContext camelContext, Object obj, String name, Obj switch (ignoreCase ? name.toLowerCase() : name) { case "camelcontext": case "camelContext": target.setCamelContext(property(camelContext, org.apache.camel.CamelContext.class, value)); return true; + case "disablecoreprocessors": + case "disableCoreProcessors": target.setDisableCoreProcessors(property(camelContext, boolean.class, value)); return true; case "excludepatterns": case "excludePatterns": target.setExcludePatterns(property(camelContext, java.lang.String.class, value)); return true; case "spanlifecyclemanager": @@ -42,6 +44,8 @@ public Class getOptionType(String name, boolean ignoreCase) { switch (ignoreCase ? name.toLowerCase() : name) { case "camelcontext": case "camelContext": return org.apache.camel.CamelContext.class; + case "disablecoreprocessors": + case "disableCoreProcessors": return boolean.class; case "excludepatterns": case "excludePatterns": return java.lang.String.class; case "spanlifecyclemanager": @@ -60,6 +64,8 @@ public Object getOptionValue(Object obj, String name, boolean ignoreCase) { switch (ignoreCase ? name.toLowerCase() : name) { case "camelcontext": case "camelContext": return target.getCamelContext(); + case "disablecoreprocessors": + case "disableCoreProcessors": return target.isDisableCoreProcessors(); case "excludepatterns": case "excludePatterns": return target.getExcludePatterns(); case "spanlifecyclemanager": diff --git a/components/camel-opentelemetry2/src/main/docs/opentelemetry2.adoc b/components/camel-opentelemetry2/src/main/docs/opentelemetry2.adoc index 5c06dd31bb50b..e443cebd3e839 100644 --- a/components/camel-opentelemetry2/src/main/docs/opentelemetry2.adoc +++ b/components/camel-opentelemetry2/src/main/docs/opentelemetry2.adoc @@ -24,8 +24,10 @@ The configuration properties for the OpenTelemetry2 tracer are: [width="100%",cols="10%,10%,80%",options="header",] |======================================================================= | Option | Default | Description +|`enabled`| false | Turn the tracing on/off. +|`traceProcessors`| false | Trace inner custom processors (i.e., any `process` configured in the route). +|`disableCoreProcessors`| false | Disable any inner core processors (any core DSL processor provided in the route, for example `bean`, `log`, ...). | `excludePatterns` | | A comma-separated list of patterns (e.g., `log*,direct*,setBody*`) to exclude from tracing. Spans matching these patterns will be disabled. -| `traceProcessors` | `false` | If set to `true`, Camel creates OpenTelemetry Spans for each processor in your routes. You can use `excludePatterns` to filter which processors are traced. | `traceHeadersInclusion`| `false` | If set to `true`, adds the generated telemetry `CAMEL_TRACE_ID` and `CAMEL_SPAN_ID` Exchange headers. |======================================================================= diff --git a/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/AsyncCXFTest.java b/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/AsyncCXFTest.java index 278fddd9076f0..59a5e5168d03b 100644 --- a/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/AsyncCXFTest.java +++ b/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/AsyncCXFTest.java @@ -50,6 +50,7 @@ protected CamelContext createCamelContext() throws Exception { OpenTelemetryTracer tst = new OpenTelemetryTracer(); tst.setTracer(otelExtension.getOpenTelemetry().getTracer("traceTest")); tst.setContextPropagators(otelExtension.getOpenTelemetry().getPropagators()); + tst.setDisableCoreProcessors(true); CamelContext context = super.createCamelContext(); CamelContextAware.trySetCamelContext(tst, context); tst.init(context); diff --git a/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/AsyncDirectTest.java b/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/AsyncDirectTest.java index 4b010c617e1e4..4d29fbb89ad12 100644 --- a/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/AsyncDirectTest.java +++ b/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/AsyncDirectTest.java @@ -42,6 +42,7 @@ protected CamelContext createCamelContext() throws Exception { OpenTelemetryTracer tst = new OpenTelemetryTracer(); tst.setTracer(otelExtension.getOpenTelemetry().getTracer("traceTest")); tst.setContextPropagators(otelExtension.getOpenTelemetry().getPropagators()); + tst.setDisableCoreProcessors(true); CamelContext context = super.createCamelContext(); CamelContextAware.trySetCamelContext(tst, context); tst.init(context); diff --git a/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/AsyncTest.java b/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/AsyncTest.java index 546ef24c226ef..e73af302fe8f3 100644 --- a/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/AsyncTest.java +++ b/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/AsyncTest.java @@ -46,6 +46,7 @@ protected CamelContext createCamelContext() throws Exception { OpenTelemetryTracer tst = new OpenTelemetryTracer(); tst.setTracer(otelExtension.getOpenTelemetry().getTracer("traceTest")); tst.setContextPropagators(otelExtension.getOpenTelemetry().getPropagators()); + tst.setDisableCoreProcessors(true); CamelContext context = super.createCamelContext(); CamelContextAware.trySetCamelContext(tst, context); tst.init(context); diff --git a/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/AsyncWiretapTest.java b/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/AsyncWiretapTest.java index 6b1ced29627e1..81075b3b82d47 100644 --- a/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/AsyncWiretapTest.java +++ b/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/AsyncWiretapTest.java @@ -47,6 +47,7 @@ protected CamelContext createCamelContext() throws Exception { OpenTelemetryTracer tst = new OpenTelemetryTracer(); tst.setTracer(otelExtension.getOpenTelemetry().getTracer("traceTest")); tst.setContextPropagators(otelExtension.getOpenTelemetry().getPropagators()); + tst.setDisableCoreProcessors(true); CamelContext context = super.createCamelContext(); CamelContextAware.trySetCamelContext(tst, context); tst.init(context); diff --git a/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/MDCHeadersTraceTest.java b/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/MDCHeadersTraceTest.java index 0eab0a484a076..5d6cc8a460452 100644 --- a/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/MDCHeadersTraceTest.java +++ b/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/MDCHeadersTraceTest.java @@ -40,6 +40,7 @@ protected CamelContext createCamelContext() throws Exception { tst.setTraceHeadersInclusion(true); tst.setTracer(otelExtension.getOpenTelemetry().getTracer("traceTest")); tst.setContextPropagators(otelExtension.getOpenTelemetry().getPropagators()); + tst.setDisableCoreProcessors(true); CamelContextAware.trySetCamelContext(tst, context); tst.init(context); return context; diff --git a/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/OpenTelemetryTracerTest.java b/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/OpenTelemetryTracerTest.java index 3b4118656f63b..471151678ca47 100644 --- a/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/OpenTelemetryTracerTest.java +++ b/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/OpenTelemetryTracerTest.java @@ -43,6 +43,7 @@ protected CamelContext createCamelContext() throws Exception { OpenTelemetryTracer tst = new OpenTelemetryTracer(); tst.setTracer(otelExtension.getOpenTelemetry().getTracer("traceTest")); tst.setContextPropagators(otelExtension.getOpenTelemetry().getPropagators()); + tst.setDisableCoreProcessors(true); CamelContext context = super.createCamelContext(); CamelContextAware.trySetCamelContext(tst, context); tst.init(context); diff --git a/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/SpanBeanTest.java b/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/SpanBeanTest.java new file mode 100644 index 0000000000000..a785de244f28c --- /dev/null +++ b/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/SpanBeanTest.java @@ -0,0 +1,146 @@ +/* + * 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.opentelemetry2; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import io.opentelemetry.api.common.AttributeKey; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.sdk.trace.data.SpanData; +import org.apache.camel.CamelContext; +import org.apache.camel.CamelContextAware; +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.camel.RoutesBuilder; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.opentelemetry2.CamelOpenTelemetryExtension.OtelTrace; +import org.apache.camel.telemetry.Op; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class SpanBeanTest extends OpenTelemetryTracerTestSupport { + + Tracer tracer = otelExtension.getOpenTelemetry().getTracer("spanInjection"); + + @Override + protected CamelContext createCamelContext() throws Exception { + OpenTelemetryTracer tst = new OpenTelemetryTracer(); + tst.setTracer(tracer); + tst.setContextPropagators(otelExtension.getOpenTelemetry().getPropagators()); + CamelContext context = super.createCamelContext(); + CamelContextAware.trySetCamelContext(tst, context); + tst.init(context); + return context; + } + + @Test + void testRouteSingleRequest() throws IOException { + template.sendBody("direct:start", "my-body"); + Map traces = otelExtension.getTraces(); + assertEquals(1, traces.size()); + checkTrace(traces.values().iterator().next()); + } + + private void checkTrace(OtelTrace trace) { + List spans = trace.getSpans(); + assertEquals(7, spans.size()); + SpanData testProducer = spans.get(0); + SpanData direct = spans.get(1); + SpanData innerLog = spans.get(2); + SpanData beanProcessor = spans.get(3); + SpanData beanMethod = spans.get(4); + SpanData log = spans.get(5); + SpanData innerToLog = spans.get(6); + + // Validate span completion + assertTrue(testProducer.hasEnded()); + assertTrue(direct.hasEnded()); + assertTrue(innerLog.hasEnded()); + assertTrue(beanProcessor.hasEnded()); + assertTrue(beanMethod.hasEnded()); + assertTrue(log.hasEnded()); + assertTrue(innerToLog.hasEnded()); + + // Validate same trace + assertEquals(testProducer.getSpanContext().getTraceId(), direct.getSpanContext().getTraceId()); + assertEquals(testProducer.getSpanContext().getTraceId(), innerLog.getSpanContext().getTraceId()); + assertEquals(testProducer.getSpanContext().getTraceId(), beanProcessor.getSpanContext().getTraceId()); + assertEquals(testProducer.getSpanContext().getTraceId(), beanMethod.getSpanContext().getTraceId()); + assertEquals(testProducer.getSpanContext().getTraceId(), log.getSpanContext().getTraceId()); + assertEquals(testProducer.getSpanContext().getTraceId(), innerToLog.getSpanContext().getTraceId()); + + // Validate operations + assertEquals(Op.EVENT_RECEIVED.toString(), direct.getAttributes().get(AttributeKey.stringKey("op"))); + assertEquals(Op.EVENT_PROCESS.toString(), beanProcessor.getAttributes().get(AttributeKey.stringKey("op"))); + + // Validate hierarchy + assertFalse(testProducer.getParentSpanContext().isValid()); + + assertEquals(testProducer.getSpanContext().getSpanId(), direct.getParentSpanContext().getSpanId()); + assertEquals(direct.getSpanContext().getSpanId(), innerLog.getParentSpanContext().getSpanId()); + assertEquals(direct.getSpanContext().getSpanId(), beanProcessor.getParentSpanContext().getSpanId()); + assertEquals(beanProcessor.getSpanContext().getSpanId(), beanMethod.getParentSpanContext().getSpanId()); + assertEquals(direct.getSpanContext().getSpanId(), log.getParentSpanContext().getSpanId()); + assertEquals(log.getSpanContext().getSpanId(), innerToLog.getParentSpanContext().getSpanId()); + + // Validate message logging + assertEquals("A message", innerLog.getEvents().get(0).getAttributes().get(AttributeKey.stringKey("message"))); + assertEquals( + "Exchange[ExchangePattern: InOnly, BodyType: String, Body: my-body]", + innerToLog.getEvents().get(0).getAttributes().get(AttributeKey.stringKey("message"))); + } + + @Override + protected RoutesBuilder createRouteBuilder() { + return new RouteBuilder() { + @Override + public void configure() { + MyBean myBean = new MyBean(); + this.getCamelContext().getRegistry().bind("myBean", myBean); + + from("direct:start") + .routeId("start") + .log("A message") + .bean(MyBean.class) + .process(new Processor() { + @Override + public void process(Exchange exchange) throws Exception { + // noop + } + }) + .to("log:info"); + } + }; + } + + class MyBean { + // NOTE: the commented annotation below would work only when an agent or a runtime framework (quarkus or spring) + // is available. We simulate it creating the Span by hand instead. + //@WithSpan + public void helloWorld() { + Span mySpan = tracer.spanBuilder("helloworld").startSpan(); + // Do the work here + mySpan.end(); + } + } +} diff --git a/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/SpanKindTest.java b/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/SpanKindTest.java index 41e0d021d6d5a..7746b7515bd33 100644 --- a/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/SpanKindTest.java +++ b/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/SpanKindTest.java @@ -45,6 +45,7 @@ protected CamelContext createCamelContext() throws Exception { OpenTelemetryTracer tst = new OpenTelemetryTracer(); tst.setTracer(otelExtension.getOpenTelemetry().getTracer("spanKindTest")); tst.setContextPropagators(otelExtension.getOpenTelemetry().getPropagators()); + tst.setDisableCoreProcessors(true); CamelContext context = super.createCamelContext(); // Register mock HTTP component for testing diff --git a/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/SpanPropagationDownstreamTest.java b/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/SpanPropagationDownstreamTest.java index 0c28617a1ffc0..1d99a67bf4d6e 100644 --- a/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/SpanPropagationDownstreamTest.java +++ b/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/SpanPropagationDownstreamTest.java @@ -32,6 +32,7 @@ protected CamelContext createCamelContext() throws Exception { OpenTelemetryTracer tst = new OpenTelemetryTracer(); tst.setTracer(otelExtension.getOpenTelemetry().getTracer("traceTest")); tst.setContextPropagators(otelExtension.getOpenTelemetry().getPropagators()); + tst.setDisableCoreProcessors(true); CamelContext context = super.createCamelContext(); CamelContextAware.trySetCamelContext(tst, context); tst.init(context); diff --git a/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/SpanPropagationUpstreamTest.java b/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/SpanPropagationUpstreamTest.java index 3938d39a3662c..16d474d1da70b 100644 --- a/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/SpanPropagationUpstreamTest.java +++ b/components/camel-opentelemetry2/src/test/java/org/apache/camel/opentelemetry2/SpanPropagationUpstreamTest.java @@ -38,6 +38,7 @@ protected CamelContext createCamelContext() throws Exception { OpenTelemetryTracer tst = new OpenTelemetryTracer(); tst.setTracer(otelExtension.getOpenTelemetry().getTracer("traceTest")); tst.setContextPropagators(otelExtension.getOpenTelemetry().getPropagators()); + tst.setDisableCoreProcessors(true); CamelContext context = super.createCamelContext(); CamelContextAware.trySetCamelContext(tst, context); tst.init(context); diff --git a/components/camel-telemetry-dev/src/generated/java/org/apache/camel/telemetrydev/TelemetryDevTracerConfigurer.java b/components/camel-telemetry-dev/src/generated/java/org/apache/camel/telemetrydev/TelemetryDevTracerConfigurer.java index 20d9f04a5fee1..ba9d4911c60d2 100644 --- a/components/camel-telemetry-dev/src/generated/java/org/apache/camel/telemetrydev/TelemetryDevTracerConfigurer.java +++ b/components/camel-telemetry-dev/src/generated/java/org/apache/camel/telemetrydev/TelemetryDevTracerConfigurer.java @@ -25,6 +25,8 @@ public boolean configure(CamelContext camelContext, Object obj, String name, Obj switch (ignoreCase ? name.toLowerCase() : name) { case "camelcontext": case "camelContext": target.setCamelContext(property(camelContext, org.apache.camel.CamelContext.class, value)); return true; + case "disablecoreprocessors": + case "disableCoreProcessors": target.setDisableCoreProcessors(property(camelContext, boolean.class, value)); return true; case "excludepatterns": case "excludePatterns": target.setExcludePatterns(property(camelContext, java.lang.String.class, value)); return true; case "spanlifecyclemanager": @@ -44,6 +46,8 @@ public Class getOptionType(String name, boolean ignoreCase) { switch (ignoreCase ? name.toLowerCase() : name) { case "camelcontext": case "camelContext": return org.apache.camel.CamelContext.class; + case "disablecoreprocessors": + case "disableCoreProcessors": return boolean.class; case "excludepatterns": case "excludePatterns": return java.lang.String.class; case "spanlifecyclemanager": @@ -64,6 +68,8 @@ public Object getOptionValue(Object obj, String name, boolean ignoreCase) { switch (ignoreCase ? name.toLowerCase() : name) { case "camelcontext": case "camelContext": return target.getCamelContext(); + case "disablecoreprocessors": + case "disableCoreProcessors": return target.isDisableCoreProcessors(); case "excludepatterns": case "excludePatterns": return target.getExcludePatterns(); case "spanlifecyclemanager": diff --git a/components/camel-telemetry-dev/src/main/docs/telemetry-dev.adoc b/components/camel-telemetry-dev/src/main/docs/telemetry-dev.adoc index d3d9894814be9..2eba44a3a7677 100644 --- a/components/camel-telemetry-dev/src/main/docs/telemetry-dev.adoc +++ b/components/camel-telemetry-dev/src/main/docs/telemetry-dev.adoc @@ -28,7 +28,8 @@ The configuration properties for the Telemetry component are: |Option |Default |Description |`enabled`| false | Turn the tracing on/off. |`traceFormat`| default | The format used to trace in the log (default, tree, json). -|`traceProcessors`| false | Trace inner processors. +|`traceProcessors`| false | Trace inner custom processors (i.e., any `process` configured in the route). +|`disableCoreProcessors`| false | Disable any inner core processors (any core DSL processor provided in the route, for example `bean`, `log`, ...). |`excludePatterns` | | Sets exclude pattern that will disable tracing for those spans that matches the pattern. The variable is a comma separated values of filters to execute (eg, `log*,direct*,setBody*`, ...) |`traceHeadersInclusion`| false | Add the generated telemetry `CAMEL_TRACE_ID` and `CAMEL_SPAN_ID` Exchange headers. |======================================================================= diff --git a/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/AsyncCXFTest.java b/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/AsyncCXFTest.java index 2ca776917e17f..a2887afead91f 100644 --- a/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/AsyncCXFTest.java +++ b/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/AsyncCXFTest.java @@ -45,6 +45,7 @@ public class AsyncCXFTest extends TelemetryDevTracerTestSupport { protected CamelContext createCamelContext() throws Exception { TelemetryDevTracer tst = new TelemetryDevTracer(); tst.setTraceFormat("json"); + tst.setDisableCoreProcessors(true); CamelContext context = super.createCamelContext(); CamelContextAware.trySetCamelContext(tst, context); tst.init(context); diff --git a/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/AsyncDirectTest.java b/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/AsyncDirectTest.java index d41399686f841..0fc1c1731da86 100644 --- a/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/AsyncDirectTest.java +++ b/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/AsyncDirectTest.java @@ -37,6 +37,7 @@ public class AsyncDirectTest extends TelemetryDevTracerTestSupport { protected CamelContext createCamelContext() throws Exception { TelemetryDevTracer tst = new TelemetryDevTracer(); tst.setTraceFormat("json"); + tst.setDisableCoreProcessors(true); CamelContext context = super.createCamelContext(); CamelContextAware.trySetCamelContext(tst, context); tst.init(context); diff --git a/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/AsyncTest.java b/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/AsyncTest.java index ff794ef5a3487..c8fc668b02e33 100644 --- a/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/AsyncTest.java +++ b/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/AsyncTest.java @@ -41,6 +41,7 @@ public class AsyncTest extends TelemetryDevTracerTestSupport { protected CamelContext createCamelContext() throws Exception { TelemetryDevTracer tst = new TelemetryDevTracer(); tst.setTraceFormat("json"); + tst.setDisableCoreProcessors(true); CamelContext context = super.createCamelContext(); CamelContextAware.trySetCamelContext(tst, context); tst.init(context); diff --git a/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/AsyncWiretapTest.java b/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/AsyncWiretapTest.java index 67fd4384ddabe..3f08e4f18f132 100644 --- a/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/AsyncWiretapTest.java +++ b/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/AsyncWiretapTest.java @@ -42,6 +42,7 @@ public class AsyncWiretapTest extends TelemetryDevTracerTestSupport { protected CamelContext createCamelContext() throws Exception { TelemetryDevTracer tst = new TelemetryDevTracer(); tst.setTraceFormat("json"); + tst.setDisableCoreProcessors(true); CamelContext context = super.createCamelContext(); CamelContextAware.trySetCamelContext(tst, context); tst.init(context); diff --git a/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/MDCHeadersTraceTest.java b/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/MDCHeadersTraceTest.java index 2e9472aece6bc..0bfe182dd0dd2 100644 --- a/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/MDCHeadersTraceTest.java +++ b/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/MDCHeadersTraceTest.java @@ -38,6 +38,7 @@ protected CamelContext createCamelContext() throws Exception { TelemetryDevTracer tst = new TelemetryDevTracer(); tst.setTraceFormat("json"); tst.setTraceHeadersInclusion(true); + tst.setDisableCoreProcessors(true); CamelContextAware.trySetCamelContext(tst, context); tst.init(context); return context; diff --git a/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/SpanBeanTest.java b/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/SpanBeanTest.java new file mode 100644 index 0000000000000..b0f02f990bda7 --- /dev/null +++ b/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/SpanBeanTest.java @@ -0,0 +1,140 @@ +/* + * 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.telemetrydev; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import org.apache.camel.CamelContext; +import org.apache.camel.CamelContextAware; +import org.apache.camel.Exchange; +import org.apache.camel.RoutesBuilder; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.telemetry.Op; +import org.apache.camel.telemetry.Span; +import org.apache.camel.telemetry.SpanStorageManagerExchange; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; + +public class SpanBeanTest extends TelemetryDevTracerTestSupport { + + TelemetryDevTracer tracer; + + @Override + protected CamelContext createCamelContext() throws Exception { + tracer = new TelemetryDevTracer(); + tracer.setTraceFormat("json"); + CamelContext context = super.createCamelContext(); + CamelContextAware.trySetCamelContext(tracer, context); + tracer.init(context); + return context; + } + + @Test + void testRouteSingleRequest() throws IOException { + Exchange result = template.request("direct:start", null); + // Make sure the trace is propagated downstream + assertNotNull(result.getIn().getHeader("traceparent")); + Map traces = tracesFromLog(); + assertEquals(1, traces.size()); + checkTrace(traces.values().iterator().next(), null); + } + + private void checkTrace(DevTrace trace, String expectedBody) { + List spans = trace.getSpans(); + assertEquals(7, spans.size()); + DevSpanAdapter testProducer = spans.get(0); + DevSpanAdapter direct = spans.get(1); + DevSpanAdapter logProcessor = spans.get(2); + DevSpanAdapter beanProcessor = spans.get(3); + DevSpanAdapter beanMySpan = spans.get(4); + DevSpanAdapter to = spans.get(5); + DevSpanAdapter toProcessor = spans.get(6); + + // Validate span completion + assertEquals("true", testProducer.getTag("isDone")); + assertEquals("true", direct.getTag("isDone")); + assertEquals("true", logProcessor.getTag("isDone")); + assertEquals("true", beanProcessor.getTag("isDone")); + assertEquals("true", beanMySpan.getTag("isDone")); + assertEquals("true", to.getTag("isDone")); + assertEquals("true", toProcessor.getTag("isDone")); + + // Validate same trace + assertEquals(testProducer.getTag("traceid"), direct.getTag("traceid")); + assertEquals(direct.getTag("traceid"), to.getTag("traceid")); + assertEquals(testProducer.getTag("traceid"), logProcessor.getTag("traceid")); + assertEquals(testProducer.getTag("traceid"), toProcessor.getTag("traceid")); + assertEquals(testProducer.getTag("traceid"), beanProcessor.getTag("traceid")); + assertEquals(testProducer.getTag("traceid"), beanMySpan.getTag("traceid")); + + // Validate hierarchy + assertNull(testProducer.getTag("parentSpan")); + assertEquals(testProducer.getTag("spanid"), direct.getTag("parentSpan")); + assertEquals(direct.getTag("spanid"), logProcessor.getTag("parentSpan")); + assertEquals(direct.getTag("spanid"), beanProcessor.getTag("parentSpan")); + assertEquals(beanProcessor.getTag("spanid"), beanMySpan.getTag("parentSpan")); + assertEquals(direct.getTag("spanid"), to.getTag("parentSpan")); + assertEquals(to.getTag("spanid"), toProcessor.getTag("parentSpan")); + + // Validate operations + assertEquals(Op.EVENT_SENT.toString(), testProducer.getTag("op")); + assertEquals(Op.EVENT_RECEIVED.toString(), direct.getTag("op")); + + // Validate message logging + assertEquals("A message", logProcessor.getLogEntries().get(0).getFields().get("message")); + assertEquals( + "Exchange[ExchangePattern: InOut, BodyType: null, Body: [Body is null]]", + toProcessor.getLogEntries().get(0).getFields().get("message")); + + } + + @Override + protected RoutesBuilder createRouteBuilder() { + return new RouteBuilder() { + @Override + public void configure() { + MyBean myBean = new MyBean(); + this.getCamelContext().getRegistry().bind("myBean", myBean); + + from("direct:start") + .routeId("start") + .log("A message") + .bean(MyBean.class) + .to("log:info"); + } + }; + } + + class MyBean { + // We simulate the creation of a Span by hand. + public void helloWorld(Exchange exchange) { + // We just simulate the creation of a span and proper nesting. In a real implementation + // it is up to the telemetry technology to do so (for example, via method annotations) + Span parentSpan = new SpanStorageManagerExchange().peek(exchange); + Span span = tracer.getSpanLifecycleManager().create("mySpan", "empty", parentSpan, null); + tracer.getSpanLifecycleManager().activate(span); + tracer.getSpanLifecycleManager().deactivate(span); + tracer.getSpanLifecycleManager().close(span); + } + } + +} diff --git a/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/SpanPropagationDownstreamTest.java b/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/SpanPropagationDownstreamTest.java index 840a3b2e18002..09b43abf3bfb6 100644 --- a/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/SpanPropagationDownstreamTest.java +++ b/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/SpanPropagationDownstreamTest.java @@ -32,6 +32,7 @@ public class SpanPropagationDownstreamTest extends ExchangeTestSupport { protected CamelContext createCamelContext() throws Exception { TelemetryDevTracer tst = new TelemetryDevTracer(); tst.setTraceFormat("json"); + tst.setDisableCoreProcessors(true); CamelContext context = super.createCamelContext(); CamelContextAware.trySetCamelContext(tst, context); tst.init(context); diff --git a/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/SpanPropagationUpstreamTest.java b/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/SpanPropagationUpstreamTest.java index 19af81965cc1e..44c8b3b6b40a7 100644 --- a/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/SpanPropagationUpstreamTest.java +++ b/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/SpanPropagationUpstreamTest.java @@ -34,6 +34,7 @@ public class SpanPropagationUpstreamTest extends TelemetryDevTracerTestSupport { protected CamelContext createCamelContext() throws Exception { TelemetryDevTracer tst = new TelemetryDevTracer(); tst.setTraceFormat("json"); + tst.setDisableCoreProcessors(true); CamelContext context = super.createCamelContext(); CamelContextAware.trySetCamelContext(tst, context); tst.init(context); diff --git a/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/TelemetryDevTracerTest.java b/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/TelemetryDevTracerTest.java index 6fea7695553d3..cd0c4f838bf30 100644 --- a/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/TelemetryDevTracerTest.java +++ b/components/camel-telemetry-dev/src/test/java/org/apache/camel/telemetrydev/TelemetryDevTracerTest.java @@ -38,6 +38,7 @@ public class TelemetryDevTracerTest extends TelemetryDevTracerTestSupport { protected CamelContext createCamelContext() throws Exception { TelemetryDevTracer tst = new TelemetryDevTracer(); tst.setTraceFormat("json"); + tst.setDisableCoreProcessors(true); CamelContext context = super.createCamelContext(); CamelContextAware.trySetCamelContext(tst, context); tst.init(context); diff --git a/components/camel-telemetry/src/main/docs/telemetry.adoc b/components/camel-telemetry/src/main/docs/telemetry.adoc index 148d7a9cfe67b..9d09d5fafbf39 100644 --- a/components/camel-telemetry/src/main/docs/telemetry.adoc +++ b/components/camel-telemetry/src/main/docs/telemetry.adoc @@ -26,7 +26,8 @@ The configuration properties for the Telemetry component are: [width="100%",cols="10%,10%,80%",options="header",] |======================================================================= |Option |Default |Description -|`traceProcessors`| false | Trace inner processors. +|`traceProcessors`| false | Trace inner custom processors (i.e., any `process` configured in the route). +|`disableCoreProcessors`| false | Disable any inner core processors (any core DSL processor provided in the route, for example `bean`, `log`, ...). |`excludePatterns` | | Sets exclude pattern that will disable tracing for those spans that matches the pattern. The variable is a comma separated values of filters to execute (eg, `log*,direct*,setBody*`, ...) |`traceHeadersInclusion`| false | Add the generated telemetry `CAMEL_TRACE_ID` and `CAMEL_SPAN_ID` Exchange headers. |======================================================================= @@ -121,12 +122,14 @@ The upstream application must inject the context into the event sent (typically This feature is implementation specific, the abstraction just provide the interface that must be implemented concretely in each of the implementation. -=== Processor tracing +=== Custom Processor tracing When this feature is enabled, you will be able to collect a finer grain number of Spans into a Trace. Each of the different endpoint processors will be collected. You can enable the feature using the `traceProcessors` parameter (default `false`). NOTE: enabling this feature will provide many more Spans for each Trace. +By default, the "core" processors part of any Camel DSL (for example, `bean`, `log`, ...) are included in order to manage properly any further instrumentation done at this level. Disabling this feature is not recommended but it can be done via `disableCoreProcessors` parameter. + == Implementation specific abstraction NOTE: the following chapter is dedicate exclusively to developers willing to create a concrete implementation for this component. diff --git a/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/TraceProcessorsInterceptStrategy.java b/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/TraceProcessorsInterceptStrategy.java index 5b4ea9c53ba2d..bad5cadafaa8b 100644 --- a/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/TraceProcessorsInterceptStrategy.java +++ b/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/TraceProcessorsInterceptStrategy.java @@ -57,7 +57,9 @@ public TraceProcessor(Processor target, NamedNode processorDefinition) { @Override public void process(Exchange exchange) throws Exception { String processorName = processorDefinition.getId() + "-" + processorDefinition.getShortName(); - if (tracer.isTraceProcessors() && !tracer.exclude(processorName, exchange.getContext())) { + if ((isCoreProcessEnabled(tracer.isDisableCoreProcessors(), processorDefinition.getShortName()) || + isCustomProcessEnabled(tracer.isTraceProcessors(), processorDefinition.getShortName())) + && !tracer.exclude(processorName, exchange.getContext())) { tracer.beginProcessorSpan(exchange, processorName); try { processor.process(exchange); @@ -73,7 +75,10 @@ public void process(Exchange exchange) throws Exception { @Override public boolean process(Exchange exchange, AsyncCallback callback) { String processorName = processorDefinition.getId() + "-" + processorDefinition.getShortName(); - boolean isTraceProcessor = tracer.isTraceProcessors() && !tracer.exclude(processorName, exchange.getContext()); + boolean isTraceProcessor + = (isCoreProcessEnabled(tracer.isDisableCoreProcessors(), processorDefinition.getShortName()) || + isCustomProcessEnabled(tracer.isTraceProcessors(), processorDefinition.getShortName())) + && !tracer.exclude(processorName, exchange.getContext()); if (isTraceProcessor) { try { tracer.beginProcessorSpan(exchange, processorName); @@ -105,4 +110,13 @@ public CompletableFuture processAsync(Exchange exchange) { } } + private boolean isCoreProcessEnabled(boolean isDisableCoreProcessors, String processDefinitionShortName) { + // Any enabled core process which is not a "custom" processor. + return !isDisableCoreProcessors && !processDefinitionShortName.equals("process"); + } + + private boolean isCustomProcessEnabled(boolean isTraceProcessors, String processDefinitionShortName) { + // Any custom core process. + return isTraceProcessors && processDefinitionShortName.equals("process"); + } } diff --git a/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/Tracer.java b/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/Tracer.java index 0c5ada29eb238..9677ee55e5050 100644 --- a/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/Tracer.java +++ b/components/camel-telemetry/src/main/java/org/apache/camel/telemetry/Tracer.java @@ -56,6 +56,7 @@ public abstract class Tracer extends ServiceSupport implements CamelTracingServi */ private String excludePatterns; private boolean traceProcessors; + private boolean disableCoreProcessors; private boolean traceHeadersInclusion; private final TracingEventNotifier eventNotifier = new TracingEventNotifier(); @@ -106,6 +107,15 @@ public void setTraceProcessors(boolean traceProcessors) { this.traceProcessors = traceProcessors; } + @ManagedAttribute + public boolean isDisableCoreProcessors() { + return disableCoreProcessors; + } + + public void setDisableCoreProcessors(boolean disableCoreProcessors) { + this.disableCoreProcessors = disableCoreProcessors; + } + public SpanLifecycleManager getSpanLifecycleManager() { return this.spanLifecycleManager; } diff --git a/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/AsyncCXFTest.java b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/AsyncCXFTest.java index 011e8213f9dba..7852e4689e8f9 100644 --- a/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/AsyncCXFTest.java +++ b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/AsyncCXFTest.java @@ -49,6 +49,7 @@ public class AsyncCXFTest extends ExchangeTestSupport { protected CamelContext createCamelContext() throws Exception { CamelContext context = super.createCamelContext(); this.mockTracer = new MockTracer(); + this.mockTracer.setDisableCoreProcessors(true); CamelContextAware.trySetCamelContext(mockTracer, context); mockTracer.init(context); return context; diff --git a/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/AsyncDirectTest.java b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/AsyncDirectTest.java index a8a417e7e62f5..1022a70ef52cf 100644 --- a/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/AsyncDirectTest.java +++ b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/AsyncDirectTest.java @@ -41,6 +41,7 @@ public class AsyncDirectTest extends ExchangeTestSupport { protected CamelContext createCamelContext() throws Exception { CamelContext context = super.createCamelContext(); this.mockTracer = new MockTracer(); + this.mockTracer.setDisableCoreProcessors(true); CamelContextAware.trySetCamelContext(mockTracer, context); mockTracer.init(context); return context; diff --git a/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/AsyncTest.java b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/AsyncTest.java index 78e0824e65b5d..9d3d0b298c719 100644 --- a/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/AsyncTest.java +++ b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/AsyncTest.java @@ -45,6 +45,7 @@ public class AsyncTest extends ExchangeTestSupport { protected CamelContext createCamelContext() throws Exception { CamelContext context = super.createCamelContext(); this.mockTracer = new MockTracer(); + this.mockTracer.setDisableCoreProcessors(true); CamelContextAware.trySetCamelContext(mockTracer, context); mockTracer.init(context); return context; diff --git a/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/AsyncWiretapTest.java b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/AsyncWiretapTest.java index e08ca11974b70..359c5ca7d25f3 100644 --- a/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/AsyncWiretapTest.java +++ b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/AsyncWiretapTest.java @@ -46,6 +46,7 @@ public class AsyncWiretapTest extends ExchangeTestSupport { protected CamelContext createCamelContext() throws Exception { CamelContext context = super.createCamelContext(); this.mockTracer = new MockTracer(); + this.mockTracer.setDisableCoreProcessors(true); CamelContextAware.trySetCamelContext(mockTracer, context); mockTracer.init(context); return context; diff --git a/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/DisableEndpointTest.java b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/DisableEndpointTest.java index c74e930b00883..2dc23f570c4d1 100644 --- a/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/DisableEndpointTest.java +++ b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/DisableEndpointTest.java @@ -44,6 +44,7 @@ protected CamelContext createCamelContext() throws Exception { CamelContext context = super.createCamelContext(); this.mockTracer = new MockTracer(); mockTracer.setTraceProcessors(true); + this.mockTracer.setDisableCoreProcessors(true); mockTracer.setExcludePatterns("log*,to*,setVariable*"); CamelContextAware.trySetCamelContext(mockTracer, context); mockTracer.init(context); diff --git a/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/EnableCoreProcessorsTest.java b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/EnableCoreProcessorsTest.java new file mode 100644 index 0000000000000..62c50a27899d2 --- /dev/null +++ b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/EnableCoreProcessorsTest.java @@ -0,0 +1,112 @@ +/* + * 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.telemetry; + +import java.util.List; +import java.util.Map; + +import org.apache.camel.CamelContext; +import org.apache.camel.CamelContextAware; +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.camel.RoutesBuilder; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.telemetry.mock.MockSpanAdapter; +import org.apache.camel.telemetry.mock.MockTrace; +import org.apache.camel.telemetry.mock.MockTracer; +import org.apache.camel.test.junit6.ExchangeTestSupport; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +public class EnableCoreProcessorsTest extends ExchangeTestSupport { + + MockTracer mockTracer; + + @Override + protected CamelContext createCamelContext() throws Exception { + CamelContext context = super.createCamelContext(); + this.mockTracer = new MockTracer(); + CamelContextAware.trySetCamelContext(mockTracer, context); + mockTracer.init(context); + return context; + } + + @Test + void testProcessorsTraceRequest() { + template.sendBody("direct:start", "my-body"); + Map traces = mockTracer.traces(); + assertEquals(1, traces.size()); + checkTrace(traces.values().iterator().next()); + } + + private void checkTrace(MockTrace trace) { + List spans = trace.spans(); + assertEquals(5, spans.size()); + // Cast to implementation object to be able to + // inspect the status of the Span. + MockSpanAdapter testProducer = (MockSpanAdapter) spans.get(0); + MockSpanAdapter direct = (MockSpanAdapter) spans.get(1); + MockSpanAdapter innerLog = (MockSpanAdapter) spans.get(2); + MockSpanAdapter log = (MockSpanAdapter) spans.get(3); + MockSpanAdapter innerToLog = (MockSpanAdapter) spans.get(4); + + // Validate span completion + assertEquals("true", testProducer.getTag("isDone")); + assertEquals("true", direct.getTag("isDone")); + assertEquals("true", innerLog.getTag("isDone")); + assertEquals("true", log.getTag("isDone")); + assertEquals("true", innerToLog.getTag("isDone")); + + // Validate same trace + assertEquals(testProducer.getTag("traceid"), direct.getTag("traceid")); + assertEquals(testProducer.getTag("traceid"), innerLog.getTag("traceid")); + assertEquals(testProducer.getTag("traceid"), log.getTag("traceid")); + assertEquals(testProducer.getTag("traceid"), innerToLog.getTag("traceid")); + + // Validate op + assertEquals(Op.EVENT_RECEIVED.toString(), direct.getTag("op")); + + // Validate hierarchy + assertNull(testProducer.getTag("parentSpan")); + assertEquals(testProducer.getTag("spanid"), direct.getTag("parentSpan")); + assertEquals(direct.getTag("spanid"), innerLog.getTag("parentSpan")); + assertEquals(direct.getTag("spanid"), log.getTag("parentSpan")); + assertEquals(log.getTag("spanid"), innerToLog.getTag("parentSpan")); + } + + @Override + protected RoutesBuilder createRouteBuilder() { + return new RouteBuilder() { + @Override + public void configure() { + from("direct:start") + .routeId("start") + .log("A message") + .process(new Processor() { + @Override + public void process(Exchange exchange) throws Exception { + exchange.getIn().setHeader("operation", "fake"); + } + }) + .to("log:info"); + } + }; + } + +} diff --git a/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/EnableProcessorsTest.java b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/EnableProcessorsTest.java index a2d2ddbb564f2..f7a255d704f49 100644 --- a/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/EnableProcessorsTest.java +++ b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/EnableProcessorsTest.java @@ -43,6 +43,7 @@ protected CamelContext createCamelContext() throws Exception { CamelContext context = super.createCamelContext(); this.mockTracer = new MockTracer(); mockTracer.setTraceProcessors(true); + this.mockTracer.setDisableCoreProcessors(true); CamelContextAware.trySetCamelContext(mockTracer, context); mockTracer.init(context); return context; @@ -58,30 +59,24 @@ void testProcessorsTraceRequest() { private void checkTrace(MockTrace trace) { List spans = trace.spans(); - assertEquals(6, spans.size()); + assertEquals(4, spans.size()); // Cast to implementation object to be able to // inspect the status of the Span. MockSpanAdapter testProducer = (MockSpanAdapter) spans.get(0); MockSpanAdapter direct = (MockSpanAdapter) spans.get(1); - MockSpanAdapter innerLog = (MockSpanAdapter) spans.get(2); - MockSpanAdapter innerProcessor = (MockSpanAdapter) spans.get(3); - MockSpanAdapter log = (MockSpanAdapter) spans.get(4); - MockSpanAdapter innerToLog = (MockSpanAdapter) spans.get(5); + MockSpanAdapter innerProcessor = (MockSpanAdapter) spans.get(2); + MockSpanAdapter log = (MockSpanAdapter) spans.get(3); // Validate span completion assertEquals("true", testProducer.getTag("isDone")); assertEquals("true", direct.getTag("isDone")); - assertEquals("true", innerLog.getTag("isDone")); assertEquals("true", innerProcessor.getTag("isDone")); assertEquals("true", log.getTag("isDone")); - assertEquals("true", innerToLog.getTag("isDone")); // Validate same trace assertEquals(testProducer.getTag("traceid"), direct.getTag("traceid")); - assertEquals(testProducer.getTag("traceid"), innerLog.getTag("traceid")); assertEquals(testProducer.getTag("traceid"), innerProcessor.getTag("traceid")); assertEquals(testProducer.getTag("traceid"), log.getTag("traceid")); - assertEquals(testProducer.getTag("traceid"), innerToLog.getTag("traceid")); // Validate op assertEquals(Op.EVENT_RECEIVED.toString(), direct.getTag("op")); @@ -90,10 +85,8 @@ private void checkTrace(MockTrace trace) { // Validate hierarchy assertNull(testProducer.getTag("parentSpan")); assertEquals(testProducer.getTag("spanid"), direct.getTag("parentSpan")); - assertEquals(direct.getTag("spanid"), innerLog.getTag("parentSpan")); assertEquals(direct.getTag("spanid"), innerProcessor.getTag("parentSpan")); assertEquals(direct.getTag("spanid"), log.getTag("parentSpan")); - assertEquals(log.getTag("spanid"), innerToLog.getTag("parentSpan")); } @Override diff --git a/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/HeadersTraceTest.java b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/HeadersTraceTest.java index cce41c81d2032..d131e447ece59 100644 --- a/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/HeadersTraceTest.java +++ b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/HeadersTraceTest.java @@ -41,6 +41,7 @@ protected CamelContext createCamelContext() throws Exception { CamelContext context = super.createCamelContext(); this.mockTracer = new MockTracer(); mockTracer.setTraceHeadersInclusion(true); + this.mockTracer.setDisableCoreProcessors(true); CamelContextAware.trySetCamelContext(mockTracer, context); mockTracer.init(context); return context; diff --git a/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/SpanBeanTest.java b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/SpanBeanTest.java new file mode 100644 index 0000000000000..ed2cba75226d8 --- /dev/null +++ b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/SpanBeanTest.java @@ -0,0 +1,147 @@ +/* + * 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.telemetry; + +import java.util.List; +import java.util.Map; + +import org.apache.camel.CamelContext; +import org.apache.camel.CamelContextAware; +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.camel.RoutesBuilder; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.telemetry.mock.MockSpanAdapter; +import org.apache.camel.telemetry.mock.MockTrace; +import org.apache.camel.telemetry.mock.MockTracer; +import org.apache.camel.test.junit6.ExchangeTestSupport; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +public class SpanBeanTest extends ExchangeTestSupport { + + MockTracer mockTracer; + + @Override + protected CamelContext createCamelContext() throws Exception { + CamelContext context = super.createCamelContext(); + this.mockTracer = new MockTracer(); + CamelContextAware.trySetCamelContext(mockTracer, context); + mockTracer.init(context); + return context; + } + + @Test + void testProcessorsTraceRequest() { + template.sendBody("direct:start", "my-body"); + Map traces = mockTracer.traces(); + assertEquals(1, traces.size()); + checkTrace(traces.values().iterator().next()); + } + + private void checkTrace(MockTrace trace) { + List spans = trace.spans(); + assertEquals(7, spans.size()); + // Cast to implementation object to be able to + // inspect the status of the Span. + MockSpanAdapter testProducer = (MockSpanAdapter) spans.get(0); + MockSpanAdapter direct = (MockSpanAdapter) spans.get(1); + MockSpanAdapter innerLog = (MockSpanAdapter) spans.get(2); + MockSpanAdapter bean = (MockSpanAdapter) spans.get(3); + MockSpanAdapter beanMethod = (MockSpanAdapter) spans.get(4); + MockSpanAdapter log = (MockSpanAdapter) spans.get(5); + MockSpanAdapter innerToLog = (MockSpanAdapter) spans.get(6); + + // Validate span completion + assertEquals("true", testProducer.getTag("isDone")); + assertEquals("true", direct.getTag("isDone")); + assertEquals("true", innerLog.getTag("isDone")); + assertEquals("true", bean.getTag("isDone")); + assertEquals("true", beanMethod.getTag("isDone")); + assertEquals("true", log.getTag("isDone")); + assertEquals("true", innerToLog.getTag("isDone")); + + // Validate same trace + assertEquals(testProducer.getTag("traceid"), direct.getTag("traceid")); + assertEquals(testProducer.getTag("traceid"), innerLog.getTag("traceid")); + assertEquals(testProducer.getTag("traceid"), log.getTag("traceid")); + assertEquals(testProducer.getTag("traceid"), bean.getTag("traceid")); + assertEquals(testProducer.getTag("traceid"), beanMethod.getTag("traceid")); + assertEquals(testProducer.getTag("traceid"), innerToLog.getTag("traceid")); + + // Validate op + assertEquals(Op.EVENT_RECEIVED.toString(), direct.getTag("op")); + + // Validate hierarchy + assertNull(testProducer.getTag("parentSpan")); + assertEquals(testProducer.getTag("spanid"), direct.getTag("parentSpan")); + assertEquals(direct.getTag("spanid"), innerLog.getTag("parentSpan")); + assertEquals(direct.getTag("spanid"), log.getTag("parentSpan")); + assertEquals(direct.getTag("spanid"), bean.getTag("parentSpan")); + assertEquals(bean.getTag("spanid"), beanMethod.getTag("parentSpan")); + assertEquals(log.getTag("spanid"), innerToLog.getTag("parentSpan")); + + // Validate operations + assertEquals(Op.EVENT_SENT.toString(), testProducer.getTag("op")); + assertEquals(Op.EVENT_RECEIVED.toString(), direct.getTag("op")); + + // Validate message logging + assertEquals("A message", innerLog.logEntries().get(0).fields().get("message")); + assertEquals( + "Exchange[ExchangePattern: InOnly, BodyType: String, Body: my-body]", + innerToLog.logEntries().get(0).fields().get("message")); + } + + @Override + protected RoutesBuilder createRouteBuilder() { + return new RouteBuilder() { + @Override + public void configure() { + MyBean myBean = new MyBean(); + this.getCamelContext().getRegistry().bind("myBean", myBean); + + from("direct:start") + .routeId("start") + .log("A message") + .bean(MyBean.class) + .process(new Processor() { + @Override + public void process(Exchange exchange) throws Exception { + exchange.getIn().setHeader("operation", "fake"); + } + }) + .to("log:info"); + } + }; + } + + class MyBean { + // We simulate the creation of a Span by hand. + public void helloWorld(Exchange exchange) { + // We just simulate the creation of a span and proper nesting. In a real implementation + // it is up to the telemetry technology to do so (for example, via method annotations) + Span parentSpan = new SpanStorageManagerExchange().peek(exchange); + Span span = mockTracer.getSpanLifecycleManager().create("mySpan", "bo", parentSpan, null); + mockTracer.getSpanLifecycleManager().activate(span); + mockTracer.getSpanLifecycleManager().deactivate(span); + mockTracer.getSpanLifecycleManager().close(span); + } + } + +} diff --git a/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/SpanLifecycleManagerTest.java b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/SpanLifecycleManagerTest.java index ceefe59e720c8..d7f52704ac47b 100644 --- a/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/SpanLifecycleManagerTest.java +++ b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/SpanLifecycleManagerTest.java @@ -42,6 +42,7 @@ public class SpanLifecycleManagerTest extends ExchangeTestSupport { protected CamelContext createCamelContext() throws Exception { CamelContext context = super.createCamelContext(); this.mockTracer = new MockTracer(); + this.mockTracer.setDisableCoreProcessors(true); CamelContextAware.trySetCamelContext(mockTracer, context); mockTracer.init(context); return context; diff --git a/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/SpanPropagationDownstreamTest.java b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/SpanPropagationDownstreamTest.java index dbaf38241a28a..94879366473b6 100644 --- a/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/SpanPropagationDownstreamTest.java +++ b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/SpanPropagationDownstreamTest.java @@ -35,6 +35,7 @@ public class SpanPropagationDownstreamTest extends ExchangeTestSupport { protected CamelContext createCamelContext() throws Exception { CamelContext context = super.createCamelContext(); this.mockTracer = new MockTracer(); + this.mockTracer.setDisableCoreProcessors(true); CamelContextAware.trySetCamelContext(mockTracer, context); mockTracer.init(context); return context; diff --git a/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/SpanPropagationUpstreamTest.java b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/SpanPropagationUpstreamTest.java index 45cc960942bfc..cbc352573675b 100644 --- a/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/SpanPropagationUpstreamTest.java +++ b/components/camel-telemetry/src/test/java/org/apache/camel/telemetry/SpanPropagationUpstreamTest.java @@ -39,6 +39,7 @@ public class SpanPropagationUpstreamTest extends ExchangeTestSupport { protected CamelContext createCamelContext() throws Exception { CamelContext context = super.createCamelContext(); this.mockTracer = new MockTracer(); + this.mockTracer.setDisableCoreProcessors(true); CamelContextAware.trySetCamelContext(mockTracer, context); mockTracer.init(context); return context; diff --git a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_21.adoc b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_21.adoc index b0a07f7b1a7ee..13e8e9282ff00 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_21.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_21.adoc @@ -218,7 +218,17 @@ Camel Grape was deprecated with Camel 4.0. The component is now removed. === camel-telemetry -If you have custom telemetry implementations, the following interfaces have changed: +In order to prevent some potential span leakage in `camel-opentelemetry2` (see notes below) we had to perform some changes and introduce the following parameter: + +``` +|`disableCoreProcessors`| false | Disable any inner core processors (any core DSL processor provided in the route, for example `bean`, `log`, ...). +``` + +This is required in order to distinguish the older `traceProcessors` parameter which now accounts **exclusively** for custom processors. Keeping the default parameter (`false`) could increase the number of spans generated, though, this is required to guarantee consistency and memory sealing. If you need to reduce the number of spans for any reason you can explicitly provide exclusion configuration. + +NOTE: turn `disableCoreProcessors` to `true` and `traceProcessors` to `false` to skip entirely all processors. However it is not recommended to disable core processors in order to avoid the generation of third party dependencies orphaned spans. + +In this version we have also changed certain interfaces, so, if you have custom telemetry implementations, you may need to adjust to them: ==== `org.apache.camel.telemetry.SpanLifecycleManager` @@ -265,4 +275,3 @@ The component camel-digitalocean is deprecated. The java library used has been u === Deprecation of camel-irc The component camel-irc is deprecated. The library used had no stable release since 2007. There is no Java library very active for this protocol. -