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