[
https://issues.apache.org/jira/browse/CAMEL-22672?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18039073#comment-18039073
]
Pasquale Congiusti edited comment on CAMEL-22672 at 11/18/25 8:42 AM:
----------------------------------------------------------------------
Hello. Yeah, all these spring magics behind the scene are making
troubleshooting confusing. Let's set the ground for a common reproducer and we
can see if that is working on both side. Each application specific may add
noise to the root cause analysis. I have a very simple reproducer in this
github repo: https://github.com/squakez/camel-22672
I've built it via `mvn clean package` and run it via `java -jar
target/ObservationTest-1.0-SNAPSHOT.jar` for the different camel versions we
have released since the failure was detected. Let's start with 4.10.0.
{code}
$ curl http://localhost:9876/observe/metrics | jq | grep timer
"timer",
"timer.Lets create a lot of metrics: 1821",
"timer.Lets create a lot of metrics: 2592",
"timer.Lets create a lot of metrics: 274",
"timer.Lets create a lot of metrics: 3358",
"timer.Lets create a lot of metrics: 5893",
"timer.Lets create a lot of metrics: 7356",
"timer.Lets create a lot of metrics: 8020",
"timer.Lets create a lot of metrics: 8860",
"timer.active",
{code}
4.11.0 to 4.14.0 (fixed):
{code}
$ curl http://localhost:9876/observe/metrics | jq | grep timer
"timer",
"timer.active",
"timer.log",
{code}
Since 4.15.0:
{code}
$ curl http://localhost:9876/observe/metrics | jq | grep timer
{code}
It misses at all any component metric. So, maybe is this the problem? Are you
expecting those metrics previously exposed as "timer", "timer.active" ... to be
still available?
was (Author: squakez):
Hello. Yeah, all these spring magics behind the scene are making
troubleshooting confusing. Let's set the ground for a common reproducer and we
can see if that is working on both side. Each application specific may add
noise to the root cause analysis. I have a very simple reproducer in this
github repo: https://github.com/squakez/camel-22672
I've built it via `mvn clean package` and run it via `java -jar
target/ObservationTest-1.0-SNAPSHOT.jar` for the different camel versions we
have released since the failure was detected. Let's start with 4.10.0.
{code}
$ curl http://localhost:9876/observe/metrics | jq | grep timer
"timer",
"timer.Lets create a lot of metrics: 1821",
"timer.Lets create a lot of metrics: 2592",
"timer.Lets create a lot of metrics: 274",
"timer.Lets create a lot of metrics: 3358",
"timer.Lets create a lot of metrics: 5893",
"timer.Lets create a lot of metrics: 7356",
"timer.Lets create a lot of metrics: 8020",
"timer.Lets create a lot of metrics: 8860",
"timer.active",
{code}
4.11.0 to 4.14.0 (fixed):
{code}
$ curl http://localhost:9876/observe/metrics | jq | grep timer
"timer",
"timer.active",
"timer.log",
{code}
Since 4.15.0:
It misses at all any component metric. So, maybe is this the problem? Are you
expecting those metrics previously exposed as "timer", "timer.active" ... to be
still available?
> [camel-observation] observations and metrics
> --------------------------------------------
>
> Key: CAMEL-22672
> URL: https://issues.apache.org/jira/browse/CAMEL-22672
> Project: Camel
> Issue Type: Bug
> Affects Versions: 4.13.0
> Reporter: Jonas Beyer
> Assignee: Pasquale Congiusti
> Priority: Minor
>
> This is a bit of a revival of CAMEL-22349, which as far as I can tell has not
> been resolved. The idea seems to be that
> [https://github.com/apache/camel-spring-boot/pull/1493/files] would cause
> {{@ConditionalOnMissingBean(MeterObservationHandler.class)}} in
> {{org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration}}
> to fail, which would prevent the creation of metrics ... in the whole
> context.
> This did not work because the Camel {{ObservationAutoConfiguration}} has
> {{@AutoConfigureAfter}} the Spring one. And so Spring tried to create both
> beans leading to CAMEL-22612. The fix renamed the bean, so now both are
> successfully created and with the Spring one also metrics.
> I ran into the problem of many metrics on 4.14.0 and my main issue was the
> naming, as {{process2}} or {{to13}} are no sensible identifiers. By naming
> them hierarchically they could be conveniently suppressed via the property
> {{management.metrics.enable.[prefix]: false}} or a configurable
> {{MeterFilter}} instead of disabling the functionality.
> Our current workaround is:
> {code:java}
> import java.util.Map;
> import java.util.concurrent.ConcurrentHashMap;
> import java.util.concurrent.atomic.AtomicInteger;
> import org.apache.camel.Endpoint;
> import org.apache.camel.Exchange;
> import org.apache.camel.NamedNode;
> import org.apache.camel.observation.MicrometerObservationTracer;
> import org.apache.camel.spi.NodeIdFactory;
> import org.apache.camel.support.ExtendedExchangeExtension;
> import org.apache.commons.lang3.Strings;
> import lombok.RequiredArgsConstructor;
> import lombok.experimental.Delegate;
> import lombok.val;
> public class CamelNodeIdFactory implements NodeIdFactory {
> private static final String PREFIX = "camel-node";
> private static final Map<String, AtomicInteger> NODE_COUNTERS = new
> ConcurrentHashMap<>();
> @Override
> public String createId(NamedNode definition) {
> val id = getId(definition);
> val counter = NODE_COUNTERS.computeIfAbsent(id, k -> new
> AtomicInteger()).incrementAndGet();
> return id + (counter > 1 ? counter : "");
> }
> private String getId(NamedNode definition) {
> if (definition == null) {
> return PREFIX;
> } else if (definition.getId() != null) {
> return Strings.CS.prependIfMissing(definition.getId(), PREFIX + ".");
> } else {
> val parentId = getId(definition.getParent());
> return parentId + "." + definition.getShortName();
> }
> }
> @RequiredArgsConstructor
> public static class SpanDecorator implements
> org.apache.camel.tracing.SpanDecorator {
> @Delegate
> private final org.apache.camel.tracing.SpanDecorator delegate;
> @Override
> public String getOperationName(Exchange exchange, Endpoint endpoint) {
> val exchangeExtension = (ExtendedExchangeExtension)
> exchange.getExchangeExtension();
> val nodeId = exchangeExtension.getHistoryNodeId();
> return nodeId != null ? nodeId :
> Strings.CS.prependIfMissing(exchangeExtension.getFromRouteId(), PREFIX + ".");
> }
> }
> public static class Tracer extends MicrometerObservationTracer {
> @Override
> protected org.apache.camel.tracing.SpanDecorator
> getSpanDecorator(Endpoint endpoint) {
> return new SpanDecorator(super.getSpanDecorator(endpoint));
> }
> }
> }{code}
> with
> {code:java}
> @Bean(initMethod = "", destroyMethod = "") // Camel handles the lifecycle
> of this bean
> public MicrometerObservationTracer micrometerObservationTracer(CamelContext
> camelContext,
> Tracer tracer,
> ObservationRegistry registry) {
>
> camelContext.getCamelContextExtension().addContextPlugin(NodeIdFactory.class,
> new CamelNodeIdFactory());
> val micrometerObservationTracer = new CamelNodeIdFactory.Tracer();
> micrometerObservationTracer.setTracer(tracer);
> micrometerObservationTracer.setObservationRegistry(registry);
> micrometerObservationTracer.setTracingStrategy(new
> MicrometerTracingStrategy(micrometerObservationTracer));
> micrometerObservationTracer.init(camelContext);
> return micrometerObservationTracer;
> } {code}
> This could of course be cleaner if properly integrated into Camel.
> It already enables us to turn off all route-specific metrics by default
> {code:java}
> management.metrics.enable.camel-node: false{code}
> and turn on specific ones
> {code:java}
> management.metrics.enable.camel-node.[node-id]: true {code}
>
> This is not perfect as the node id is part of the metric name instead of a
> tag, but it is clear which part of the route is measured
> ({{{}camel_node_heartbeat_log_seconds{}}} instead of {{{}log[n]{}}}) - and it
> doesn't interfere with the rest of the Spring Boot context.
> cc [~squakez]
--
This message was sent by Atlassian Jira
(v8.20.10#820010)