You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@camel.apache.org by "Pasquale Congiusti (Jira)" <ji...@apache.org> on 2025/12/17 12:07:00 UTC

[jira] [Commented] (CAMEL-22672) [camel-observation] observations and metrics

    [ https://issues.apache.org/jira/browse/CAMEL-22672?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18045814#comment-18045814 ] 

Pasquale Congiusti commented on CAMEL-22672:
--------------------------------------------

Hello, what's the status of this? Please [~plchldr] have a look at my previous comment and let me know if that is the original issue problem to solve.

> [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
>             Fix For: 4.17.0
>
>
> 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)