[ 
https://issues.apache.org/jira/browse/CAMEL-22672?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Claus Ibsen updated CAMEL-22672:
--------------------------------
    Fix Version/s: 4.18.0
                       (was: 4.17.0)

> [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.18.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)

Reply via email to