You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2024/03/06 13:32:46 UTC

(camel) 01/07: CAMEL-20461: camel-micrometer - Add statistics for context level

This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch mm
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 9d486c7a385f6b45b3e8a103bfce43948dd58729
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Mar 6 05:51:46 2024 +0100

    CAMEL-20461: camel-micrometer - Add statistics for context level
---
 .../prometheus/MicrometerPrometheusConfigurer.java |   6 ++
 .../prometheus/MicrometerPrometheus.java           |  23 +++++
 .../src/main/docs/micrometer-component.adoc        |   2 +
 .../micrometer/json/AbstractMicrometerService.java |   2 +-
 .../routepolicy/ContextMetricsStatistics.java      |  71 +++++++++++++
 .../routepolicy/MicrometerRoutePolicy.java         | 114 +++++++++++++++------
 .../MicrometerRoutePolicyConfiguration.java        |  18 ++++
 .../routepolicy/MicrometerRoutePolicyFactory.java  |  39 ++++++-
 .../MicrometerRoutePolicyNamingStrategy.java       |  23 ++++-
 .../micrometer/routepolicy/RouteMetric.java        |  29 ++++++
 .../AbstractMicrometerRoutePolicyTest.java         |  19 ++--
 .../LegacyMicrometerRoutePolicyTest.java           |   1 +
 .../routepolicy/MicrometerContextPolicyTest.java   |  78 ++++++++++++++
 .../MicrometerRoutePolicyConfigrationTest.java     |   1 +
 .../SharedMicrometerRoutePolicyTest.java           |   2 +-
 .../MetricsConfigurationPropertiesConfigurer.java  |   6 ++
 .../camel-main-configuration-metadata.json         |   1 +
 core/camel-main/src/main/docs/main.adoc            |   3 +-
 .../camel/main/MetricsConfigurationProperties.java |  21 ++++
 .../camel/main/OtelConfigurationProperties.java    |   3 +-
 20 files changed, 410 insertions(+), 52 deletions(-)

diff --git a/components/camel-micrometer-prometheus/src/generated/java/org/apache/camel/component/micrometer/prometheus/MicrometerPrometheusConfigurer.java b/components/camel-micrometer-prometheus/src/generated/java/org/apache/camel/component/micrometer/prometheus/MicrometerPrometheusConfigurer.java
index 3466314c9cd..211bcde62d7 100644
--- a/components/camel-micrometer-prometheus/src/generated/java/org/apache/camel/component/micrometer/prometheus/MicrometerPrometheusConfigurer.java
+++ b/components/camel-micrometer-prometheus/src/generated/java/org/apache/camel/component/micrometer/prometheus/MicrometerPrometheusConfigurer.java
@@ -37,6 +37,8 @@ public class MicrometerPrometheusConfigurer extends org.apache.camel.support.com
         case "EnableRoutePolicy": target.setEnableRoutePolicy(property(camelContext, boolean.class, value)); return true;
         case "namingstrategy":
         case "NamingStrategy": target.setNamingStrategy(property(camelContext, java.lang.String.class, value)); return true;
+        case "routepolicylevel":
+        case "RoutePolicyLevel": target.setRoutePolicyLevel(property(camelContext, java.lang.String.class, value)); return true;
         case "textformatversion":
         case "TextFormatVersion": target.setTextFormatVersion(property(camelContext, java.lang.String.class, value)); return true;
         default: return false;
@@ -62,6 +64,8 @@ public class MicrometerPrometheusConfigurer extends org.apache.camel.support.com
         case "EnableRoutePolicy": return boolean.class;
         case "namingstrategy":
         case "NamingStrategy": return java.lang.String.class;
+        case "routepolicylevel":
+        case "RoutePolicyLevel": return java.lang.String.class;
         case "textformatversion":
         case "TextFormatVersion": return java.lang.String.class;
         default: return null;
@@ -88,6 +92,8 @@ public class MicrometerPrometheusConfigurer extends org.apache.camel.support.com
         case "EnableRoutePolicy": return target.isEnableRoutePolicy();
         case "namingstrategy":
         case "NamingStrategy": return target.getNamingStrategy();
+        case "routepolicylevel":
+        case "RoutePolicyLevel": return target.getRoutePolicyLevel();
         case "textformatversion":
         case "TextFormatVersion": return target.getTextFormatVersion();
         default: return null;
diff --git a/components/camel-micrometer-prometheus/src/main/java/org/apache/camel/component/micrometer/prometheus/MicrometerPrometheus.java b/components/camel-micrometer-prometheus/src/main/java/org/apache/camel/component/micrometer/prometheus/MicrometerPrometheus.java
index 5ef866cdf95..e9a16feb5a6 100644
--- a/components/camel-micrometer-prometheus/src/main/java/org/apache/camel/component/micrometer/prometheus/MicrometerPrometheus.java
+++ b/components/camel-micrometer-prometheus/src/main/java/org/apache/camel/component/micrometer/prometheus/MicrometerPrometheus.java
@@ -84,6 +84,8 @@ public class MicrometerPrometheus extends ServiceSupport implements CamelMetrics
     private String namingStrategy;
     @Metadata(defaultValue = "true")
     private boolean enableRoutePolicy = true;
+    @Metadata(defaultValue = "all", enums = "all,route,context")
+    private String routePolicyLevel = "all";
     @Metadata(defaultValue = "false")
     private boolean enableMessageHistory;
     @Metadata(defaultValue = "true")
@@ -131,6 +133,17 @@ public class MicrometerPrometheus extends ServiceSupport implements CamelMetrics
         this.enableRoutePolicy = enableRoutePolicy;
     }
 
+    public String getRoutePolicyLevel() {
+        return routePolicyLevel;
+    }
+
+    /**
+     * Sets the level of information to capture. all = both context and routes.
+     */
+    public void setRoutePolicyLevel(String routePolicyLevel) {
+        this.routePolicyLevel = routePolicyLevel;
+    }
+
     public boolean isEnableMessageHistory() {
         return enableMessageHistory;
     }
@@ -240,6 +253,16 @@ public class MicrometerPrometheus extends ServiceSupport implements CamelMetrics
             if ("legacy".equalsIgnoreCase(namingStrategy)) {
                 factory.setNamingStrategy(MicrometerRoutePolicyNamingStrategy.LEGACY);
             }
+            if ("all".equalsIgnoreCase(routePolicyLevel)) {
+                factory.getPolicyConfiguration().setContextEnabled(true);
+                factory.getPolicyConfiguration().setRouteEnabled(true);
+            } else if ("context".equalsIgnoreCase(routePolicyLevel)) {
+                factory.getPolicyConfiguration().setContextEnabled(true);
+                factory.getPolicyConfiguration().setRouteEnabled(false);
+            } else {
+                factory.getPolicyConfiguration().setContextEnabled(false);
+                factory.getPolicyConfiguration().setRouteEnabled(true);
+            }
             factory.setMeterRegistry(meterRegistry);
             camelContext.addRoutePolicyFactory(factory);
         }
diff --git a/components/camel-micrometer/src/main/docs/micrometer-component.adoc b/components/camel-micrometer/src/main/docs/micrometer-component.adoc
index b296a54dd9e..45a0540c927 100644
--- a/components/camel-micrometer/src/main/docs/micrometer-component.adoc
+++ b/components/camel-micrometer/src/main/docs/micrometer-component.adoc
@@ -407,6 +407,8 @@ following options:
 [width="100%",options="header"]
 |=======================================================================
 |Name |Default |Description
+|contextEnabled | true | whether to include counter for context level metrics
+|routeEnabled | true | whether to include counter for route level metrics
 |additionalCounters | true | activates all additional counters
 |exchangesSucceeded | true | activates counter for succeeded exchanges
 |exchangesFailed | true | activates counter for failed exchanges
diff --git a/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/json/AbstractMicrometerService.java b/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/json/AbstractMicrometerService.java
index fcfff985ca3..574cd8bf596 100644
--- a/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/json/AbstractMicrometerService.java
+++ b/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/json/AbstractMicrometerService.java
@@ -137,6 +137,6 @@ public class AbstractMicrometerService extends ServiceSupport {
 
     @Override
     protected void doStop() {
-
+        // noop
     }
 }
diff --git a/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/routepolicy/ContextMetricsStatistics.java b/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/routepolicy/ContextMetricsStatistics.java
new file mode 100644
index 00000000000..1e39d8d683a
--- /dev/null
+++ b/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/routepolicy/ContextMetricsStatistics.java
@@ -0,0 +1,71 @@
+/*
+ * 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.component.micrometer.routepolicy;
+
+import io.micrometer.core.instrument.MeterRegistry;
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.spi.UnitOfWork;
+
+final class ContextMetricsStatistics extends MicrometerRoutePolicy.MetricsStatistics {
+
+    private final boolean registerKamelets;
+    private final boolean registerTemplates;
+
+    ContextMetricsStatistics(MeterRegistry meterRegistry, CamelContext camelContext,
+                             MicrometerRoutePolicyNamingStrategy namingStrategy,
+                             MicrometerRoutePolicyConfiguration configuration, boolean registerKamelets,
+                             boolean registerTemplates) {
+        super(meterRegistry, camelContext, null, namingStrategy, configuration);
+        this.registerKamelets = registerKamelets;
+        this.registerTemplates = registerTemplates;
+    }
+
+    @Override
+    public void onExchangeBegin(Exchange exchange) {
+        // this metric is triggered for every route
+        // so we must only trigger on the root level, otherwise this metric
+        // total counter will be incorrect. For example if an exchange is routed via 3 routes
+        // we should only count this as 1 instead of 3.
+        UnitOfWork uow = exchange.getUnitOfWork();
+        if (uow != null) {
+            int level = uow.routeStackLevel(registerTemplates, registerKamelets);
+            if (level <= 1) {
+                super.onExchangeBegin(exchange);
+            }
+        } else {
+            super.onExchangeBegin(exchange);
+        }
+    }
+
+    @Override
+    public void onExchangeDone(Exchange exchange) {
+        // this metric is triggered for every route
+        // so we must only trigger on the root level, otherwise this metric
+        // total counter will be incorrect. For example if an exchange is routed via 3 routes
+        // we should only count this as 1 instead of 3.
+        UnitOfWork uow = exchange.getUnitOfWork();
+        if (uow != null) {
+            int level = uow.routeStackLevel(registerTemplates, registerKamelets);
+            if (level <= 1) {
+                super.onExchangeDone(exchange);
+            }
+        } else {
+            super.onExchangeDone(exchange);
+        }
+    }
+}
diff --git a/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/routepolicy/MicrometerRoutePolicy.java b/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/routepolicy/MicrometerRoutePolicy.java
index 74681d8797d..7df31be65bd 100644
--- a/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/routepolicy/MicrometerRoutePolicy.java
+++ b/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/routepolicy/MicrometerRoutePolicy.java
@@ -26,6 +26,7 @@ import io.micrometer.core.instrument.LongTaskTimer;
 import io.micrometer.core.instrument.MeterRegistry;
 import io.micrometer.core.instrument.Tags;
 import io.micrometer.core.instrument.Timer;
+import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
 import org.apache.camel.NonManagedService;
 import org.apache.camel.Route;
@@ -48,6 +49,7 @@ import static org.apache.camel.component.micrometer.MicrometerConstants.SERVICE_
  */
 public class MicrometerRoutePolicy extends RoutePolicySupport implements NonManagedService {
 
+    private final MicrometerRoutePolicyFactory factory;
     private MeterRegistry meterRegistry;
     private boolean prettyPrint;
     private TimeUnit durationUnit = TimeUnit.MILLISECONDS;
@@ -55,11 +57,13 @@ public class MicrometerRoutePolicy extends RoutePolicySupport implements NonMana
     private MicrometerRoutePolicyConfiguration configuration = MicrometerRoutePolicyConfiguration.DEFAULT;
 
     private final Map<Route, MetricsStatistics> statisticsMap = new HashMap<>();
+    private RouteMetric contextStatistic;
     boolean registerKamelets;
     boolean registerTemplates = true;
 
-    private static final class MetricsStatistics {
+    static class MetricsStatistics implements RouteMetric {
         private final MeterRegistry meterRegistry;
+        private final CamelContext camelContext;
         private final Route route;
         private final MicrometerRoutePolicyNamingStrategy namingStrategy;
         private final MicrometerRoutePolicyConfiguration configuration;
@@ -71,12 +75,13 @@ public class MicrometerRoutePolicy extends RoutePolicySupport implements NonMana
         private Timer timer;
         private LongTaskTimer longTaskTimer;
 
-        private MetricsStatistics(MeterRegistry meterRegistry, Route route,
-                                  MicrometerRoutePolicyNamingStrategy namingStrategy,
-                                  MicrometerRoutePolicyConfiguration configuration) {
+        MetricsStatistics(MeterRegistry meterRegistry, CamelContext camelContext, Route route,
+                          MicrometerRoutePolicyNamingStrategy namingStrategy,
+                          MicrometerRoutePolicyConfiguration configuration) {
             this.configuration = ObjectHelper.notNull(configuration, "MicrometerRoutePolicyConfiguration", this);
             this.meterRegistry = ObjectHelper.notNull(meterRegistry, "MeterRegistry", this);
             this.namingStrategy = ObjectHelper.notNull(namingStrategy, "MicrometerRoutePolicyNamingStrategy", this);
+            this.camelContext = camelContext;
             this.route = route;
             if (configuration.isAdditionalCounters()) {
                 initAdditionalCounters();
@@ -106,8 +111,8 @@ public class MicrometerRoutePolicy extends RoutePolicySupport implements NonMana
             }
             if (configuration.isLongTask()) {
                 LongTaskTimer.Builder builder = LongTaskTimer.builder(namingStrategy.getLongTaskName(route))
-                        .tags(namingStrategy.getTags(route))
-                        .description("Route long task metric");
+                        .tags(route != null ? namingStrategy.getTags(route) : namingStrategy.getTags(camelContext))
+                        .description(route != null ? "Route long task metric" : "CamelContext long task metric");
                 if (configuration.getLongTaskInitiator() != null) {
                     configuration.getLongTaskInitiator().accept(builder);
                 }
@@ -128,8 +133,8 @@ public class MicrometerRoutePolicy extends RoutePolicySupport implements NonMana
             if (sample != null) {
                 if (timer == null) {
                     Timer.Builder builder = Timer.builder(namingStrategy.getName(route))
-                            .tags(namingStrategy.getTags(route))
-                            .description("Route performance metrics");
+                            .tags(route != null ? namingStrategy.getTags(route) : namingStrategy.getTags(camelContext))
+                            .description(route != null ? "Route performance metrics" : "CamelContext performance metrics");
                     if (configuration.getTimerInitiator() != null) {
                         configuration.getTimerInitiator().accept(builder);
                     }
@@ -147,6 +152,30 @@ public class MicrometerRoutePolicy extends RoutePolicySupport implements NonMana
             }
         }
 
+        public void remove() {
+            if (exchangesSucceeded != null) {
+                meterRegistry.remove(exchangesSucceeded);
+            }
+            if (exchangesFailed != null) {
+                meterRegistry.remove(exchangesFailed);
+            }
+            if (exchangesTotal != null) {
+                meterRegistry.remove(exchangesTotal);
+            }
+            if (externalRedeliveries != null) {
+                meterRegistry.remove(externalRedeliveries);
+            }
+            if (failuresHandled != null) {
+                meterRegistry.remove(failuresHandled);
+            }
+            if (timer != null) {
+                meterRegistry.remove(timer);
+            }
+            if (longTaskTimer != null) {
+                meterRegistry.remove(longTaskTimer);
+            }
+        }
+
         private void updateAdditionalCounters(Exchange exchange) {
             if (exchangesTotal != null) {
                 exchangesTotal.increment();
@@ -169,17 +198,32 @@ public class MicrometerRoutePolicy extends RoutePolicySupport implements NonMana
         }
 
         private String propertyName(Exchange exchange) {
-            return String.format("%s-%s-%s", DEFAULT_CAMEL_ROUTE_POLICY_METER_NAME, route.getId(), exchange.getExchangeId());
+            String id;
+            if (route != null) {
+                id = route.getId();
+            } else {
+                id = "context:" + camelContext.getName();
+            }
+            return String.format("%s-%s-%s", DEFAULT_CAMEL_ROUTE_POLICY_METER_NAME, id, exchange.getExchangeId());
         }
 
         private Counter createCounter(String meterName, String description) {
             return Counter.builder(meterName)
-                    .tags(namingStrategy.getExchangeStatusTags(route))
+                    .tags(route != null
+                            ? namingStrategy.getExchangeStatusTags(route) : namingStrategy.getExchangeStatusTags(camelContext))
                     .description(description)
                     .register(meterRegistry);
         }
     }
 
+    public MicrometerRoutePolicy() {
+        this.factory = null;
+    }
+
+    public MicrometerRoutePolicy(MicrometerRoutePolicyFactory factory) {
+        this.factory = factory;
+    }
+
     public MeterRegistry getMeterRegistry() {
         return meterRegistry;
     }
@@ -249,6 +293,18 @@ public class MicrometerRoutePolicy extends RoutePolicySupport implements NonMana
         } catch (Exception e) {
             throw RuntimeCamelException.wrapRuntimeCamelException(e);
         }
+
+        if (factory != null && configuration.isContextEnabled() && contextStatistic == null) {
+            contextStatistic = factory.createOrGetContextMetric(this);
+        }
+    }
+
+    boolean isRegisterKamelets() {
+        return registerKamelets;
+    }
+
+    boolean isRegisterTemplates() {
+        return registerTemplates;
     }
 
     @Override
@@ -258,13 +314,17 @@ public class MicrometerRoutePolicy extends RoutePolicySupport implements NonMana
         // we have in-flight / total statistics already from camel-core
         statisticsMap.computeIfAbsent(route,
                 it -> {
+                    boolean skip = !configuration.isRouteEnabled();
                     // skip routes that should not be included
-                    boolean skip = (it.isCreatedByKamelet() && !registerKamelets)
-                            || (it.isCreatedByRouteTemplate() && !registerTemplates);
+                    if (!skip) {
+                        skip = (it.isCreatedByKamelet() && !registerKamelets)
+                                || (it.isCreatedByRouteTemplate() && !registerTemplates);
+                    }
                     if (skip) {
                         return null;
                     }
-                    return new MetricsStatistics(getMeterRegistry(), it, getNamingStrategy(), configuration);
+                    return new MetricsStatistics(
+                            getMeterRegistry(), it.getCamelContext(), it, getNamingStrategy(), configuration);
                 });
     }
 
@@ -273,38 +333,24 @@ public class MicrometerRoutePolicy extends RoutePolicySupport implements NonMana
         // route is removed, so remove metrics from micrometer
         MetricsStatistics stats = statisticsMap.remove(route);
         if (stats != null) {
-            if (stats.exchangesSucceeded != null) {
-                meterRegistry.remove(stats.exchangesSucceeded);
-            }
-            if (stats.exchangesFailed != null) {
-                meterRegistry.remove(stats.exchangesFailed);
-            }
-            if (stats.exchangesTotal != null) {
-                meterRegistry.remove(stats.exchangesTotal);
-            }
-            if (stats.externalRedeliveries != null) {
-                meterRegistry.remove(stats.externalRedeliveries);
-            }
-            if (stats.failuresHandled != null) {
-                meterRegistry.remove(stats.failuresHandled);
-            }
-            if (stats.timer != null) {
-                meterRegistry.remove(stats.timer);
-            }
-            if (stats.longTaskTimer != null) {
-                meterRegistry.remove(stats.longTaskTimer);
-            }
+            stats.remove();
         }
     }
 
     @Override
     public void onExchangeBegin(Route route, Exchange exchange) {
+        if (contextStatistic != null) {
+            contextStatistic.onExchangeBegin(exchange);
+        }
         Optional.ofNullable(statisticsMap.get(route))
                 .ifPresent(statistics -> statistics.onExchangeBegin(exchange));
     }
 
     @Override
     public void onExchangeDone(Route route, Exchange exchange) {
+        if (contextStatistic != null) {
+            contextStatistic.onExchangeDone(exchange);
+        }
         Optional.ofNullable(statisticsMap.get(route))
                 .ifPresent(statistics -> statistics.onExchangeDone(exchange));
     }
diff --git a/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/routepolicy/MicrometerRoutePolicyConfiguration.java b/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/routepolicy/MicrometerRoutePolicyConfiguration.java
index 1c1f57966e5..6b1f9eca8be 100644
--- a/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/routepolicy/MicrometerRoutePolicyConfiguration.java
+++ b/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/routepolicy/MicrometerRoutePolicyConfiguration.java
@@ -23,6 +23,8 @@ import io.micrometer.core.instrument.Timer;
 
 public class MicrometerRoutePolicyConfiguration {
     public static final MicrometerRoutePolicyConfiguration DEFAULT = new MicrometerRoutePolicyConfiguration();
+    private boolean contextEnabled = true;
+    private boolean routeEnabled = true;
     private boolean additionalCounters = true;
     private boolean exchangesSucceeded = true;
     private boolean exchangesFailed = true;
@@ -33,6 +35,22 @@ public class MicrometerRoutePolicyConfiguration {
     private Consumer<Timer.Builder> timerInitiator;
     private Consumer<LongTaskTimer.Builder> longTaskInitiator;
 
+    public boolean isContextEnabled() {
+        return contextEnabled;
+    }
+
+    public void setContextEnabled(boolean contextEnabled) {
+        this.contextEnabled = contextEnabled;
+    }
+
+    public boolean isRouteEnabled() {
+        return routeEnabled;
+    }
+
+    public void setRouteEnabled(boolean routeEnabled) {
+        this.routeEnabled = routeEnabled;
+    }
+
     public boolean isAdditionalCounters() {
         return additionalCounters;
     }
diff --git a/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/routepolicy/MicrometerRoutePolicyFactory.java b/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/routepolicy/MicrometerRoutePolicyFactory.java
index dde82239a9f..446b1de8034 100644
--- a/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/routepolicy/MicrometerRoutePolicyFactory.java
+++ b/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/routepolicy/MicrometerRoutePolicyFactory.java
@@ -20,22 +20,39 @@ import java.util.concurrent.TimeUnit;
 
 import io.micrometer.core.instrument.MeterRegistry;
 import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
 import org.apache.camel.NamedNode;
+import org.apache.camel.NonManagedService;
+import org.apache.camel.StaticService;
 import org.apache.camel.spi.RoutePolicy;
 import org.apache.camel.spi.RoutePolicyFactory;
+import org.apache.camel.support.service.ServiceSupport;
 
 /**
  * A {@link org.apache.camel.spi.RoutePolicyFactory} to plugin and use metrics for gathering route utilization
  * statistics
  */
-public class MicrometerRoutePolicyFactory implements RoutePolicyFactory {
+public class MicrometerRoutePolicyFactory extends ServiceSupport
+        implements RoutePolicyFactory, CamelContextAware, NonManagedService, StaticService {
 
+    private CamelContext camelContext;
     private MeterRegistry meterRegistry;
+    private RouteMetric contextMetric;
     private boolean prettyPrint = true;
     private TimeUnit durationUnit = TimeUnit.MILLISECONDS;
     private MicrometerRoutePolicyNamingStrategy namingStrategy = MicrometerRoutePolicyNamingStrategy.DEFAULT;
     private MicrometerRoutePolicyConfiguration policyConfiguration = MicrometerRoutePolicyConfiguration.DEFAULT;
 
+    @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
     /**
      * To use a specific {@link io.micrometer.core.instrument.MeterRegistry} instance.
      * <p/>
@@ -90,9 +107,19 @@ public class MicrometerRoutePolicyFactory implements RoutePolicyFactory {
         this.policyConfiguration = policyConfiguration;
     }
 
+    public RouteMetric createOrGetContextMetric(MicrometerRoutePolicy policy) {
+        if (contextMetric == null) {
+            contextMetric = new ContextMetricsStatistics(
+                    policy.getMeterRegistry(), camelContext,
+                    policy.getNamingStrategy(), policy.getConfiguration(),
+                    policy.isRegisterKamelets(), policy.isRegisterTemplates());
+        }
+        return contextMetric;
+    }
+
     @Override
     public RoutePolicy createRoutePolicy(CamelContext camelContext, String routeId, NamedNode routeDefinition) {
-        MicrometerRoutePolicy answer = new MicrometerRoutePolicy();
+        MicrometerRoutePolicy answer = new MicrometerRoutePolicy(this);
         answer.setMeterRegistry(getMeterRegistry());
         answer.setPrettyPrint(isPrettyPrint());
         answer.setDurationUnit(getDurationUnit());
@@ -101,4 +128,12 @@ public class MicrometerRoutePolicyFactory implements RoutePolicyFactory {
         return answer;
     }
 
+    @Override
+    protected void doShutdown() throws Exception {
+        super.doShutdown();
+        if (contextMetric != null) {
+            contextMetric.remove();
+            contextMetric = null;
+        }
+    }
 }
diff --git a/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/routepolicy/MicrometerRoutePolicyNamingStrategy.java b/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/routepolicy/MicrometerRoutePolicyNamingStrategy.java
index f3e05e5e534..3ec3d138897 100644
--- a/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/routepolicy/MicrometerRoutePolicyNamingStrategy.java
+++ b/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/routepolicy/MicrometerRoutePolicyNamingStrategy.java
@@ -20,6 +20,7 @@ import java.util.function.Predicate;
 
 import io.micrometer.core.instrument.Meter;
 import io.micrometer.core.instrument.Tags;
+import org.apache.camel.CamelContext;
 import org.apache.camel.Route;
 import org.apache.camel.component.micrometer.MicrometerUtils;
 
@@ -87,13 +88,31 @@ public interface MicrometerRoutePolicyNamingStrategy {
         return Tags.of(
                 CAMEL_CONTEXT_TAG, route.getCamelContext().getName(),
                 SERVICE_NAME, MicrometerRoutePolicyService.class.getSimpleName(),
-                ROUTE_ID_TAG, route.getId());
+                ROUTE_ID_TAG, route.getId(),
+                EVENT_TYPE_TAG, "route");
+    }
+
+    default Tags getTags(CamelContext camelContext) {
+        return Tags.of(
+                CAMEL_CONTEXT_TAG, camelContext.getName(),
+                SERVICE_NAME, MicrometerRoutePolicyService.class.getSimpleName(),
+                ROUTE_ID_TAG, "",
+                EVENT_TYPE_TAG, "context");
     }
 
     default Tags getExchangeStatusTags(Route route) {
         return Tags.of(
                 CAMEL_CONTEXT_TAG, route.getCamelContext().getName(),
                 SERVICE_NAME, MicrometerRoutePolicyService.class.getSimpleName(),
-                ROUTE_ID_TAG, route.getId());
+                ROUTE_ID_TAG, route.getId(),
+                EVENT_TYPE_TAG, "route");
+    }
+
+    default Tags getExchangeStatusTags(CamelContext camelContext) {
+        return Tags.of(
+                CAMEL_CONTEXT_TAG, camelContext.getName(),
+                SERVICE_NAME, MicrometerRoutePolicyService.class.getSimpleName(),
+                ROUTE_ID_TAG, "",
+                EVENT_TYPE_TAG, "context");
     }
 }
diff --git a/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/routepolicy/RouteMetric.java b/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/routepolicy/RouteMetric.java
new file mode 100644
index 00000000000..89d0b1f5cc9
--- /dev/null
+++ b/components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/routepolicy/RouteMetric.java
@@ -0,0 +1,29 @@
+/*
+ * 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.component.micrometer.routepolicy;
+
+import org.apache.camel.Exchange;
+
+public interface RouteMetric {
+
+    void onExchangeBegin(Exchange exchange);
+
+    void onExchangeDone(Exchange exchange);
+
+    void remove();
+
+}
diff --git a/components/camel-micrometer/src/test/java/org/apache/camel/component/micrometer/routepolicy/AbstractMicrometerRoutePolicyTest.java b/components/camel-micrometer/src/test/java/org/apache/camel/component/micrometer/routepolicy/AbstractMicrometerRoutePolicyTest.java
index feb1dd369c5..14c39df7f17 100644
--- a/components/camel-micrometer/src/test/java/org/apache/camel/component/micrometer/routepolicy/AbstractMicrometerRoutePolicyTest.java
+++ b/components/camel-micrometer/src/test/java/org/apache/camel/component/micrometer/routepolicy/AbstractMicrometerRoutePolicyTest.java
@@ -21,7 +21,6 @@ import io.micrometer.core.instrument.composite.CompositeMeterRegistry;
 import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
 import io.micrometer.core.instrument.util.HierarchicalNameMapper;
 import io.micrometer.jmx.JmxMeterRegistry;
-import org.apache.camel.BindToRegistry;
 import org.apache.camel.CamelContext;
 import org.apache.camel.component.micrometer.CamelJmxConfig;
 import org.apache.camel.component.micrometer.MicrometerConstants;
@@ -39,16 +38,10 @@ public abstract class AbstractMicrometerRoutePolicyTest extends CamelTestSupport
         return true;
     }
 
-    @BindToRegistry(MicrometerConstants.METRICS_REGISTRY_NAME)
-    public CompositeMeterRegistry addRegistry() {
-        meterRegistry = new CompositeMeterRegistry();
-        meterRegistry.add(new SimpleMeterRegistry());
-        meterRegistry.add(new JmxMeterRegistry(CamelJmxConfig.DEFAULT, Clock.SYSTEM, HierarchicalNameMapper.DEFAULT));
-        return meterRegistry;
-    }
-
     protected MicrometerRoutePolicyFactory createMicrometerRoutePolicyFactory() {
-        return new MicrometerRoutePolicyFactory();
+        MicrometerRoutePolicyFactory factory = new MicrometerRoutePolicyFactory();
+        factory.getPolicyConfiguration().setContextEnabled(false);
+        return factory;
     }
 
     protected String formatMetricName(String name) {
@@ -57,10 +50,16 @@ public abstract class AbstractMicrometerRoutePolicyTest extends CamelTestSupport
 
     @Override
     protected CamelContext createCamelContext() throws Exception {
+        meterRegistry = new CompositeMeterRegistry();
+        meterRegistry.add(new SimpleMeterRegistry());
+        meterRegistry.add(new JmxMeterRegistry(CamelJmxConfig.DEFAULT, Clock.SYSTEM, HierarchicalNameMapper.DEFAULT));
+
         CamelContext context = super.createCamelContext();
         MicrometerRoutePolicyFactory factory = createMicrometerRoutePolicyFactory();
+        factory.setCamelContext(context);
         factory.setMeterRegistry(meterRegistry);
         context.addRoutePolicyFactory(factory);
+        context.getRegistry().bind(MicrometerConstants.METRICS_REGISTRY_NAME, meterRegistry);
         return context;
     }
 
diff --git a/components/camel-micrometer/src/test/java/org/apache/camel/component/micrometer/routepolicy/LegacyMicrometerRoutePolicyTest.java b/components/camel-micrometer/src/test/java/org/apache/camel/component/micrometer/routepolicy/LegacyMicrometerRoutePolicyTest.java
index f3989e47bd2..ed49b797a41 100644
--- a/components/camel-micrometer/src/test/java/org/apache/camel/component/micrometer/routepolicy/LegacyMicrometerRoutePolicyTest.java
+++ b/components/camel-micrometer/src/test/java/org/apache/camel/component/micrometer/routepolicy/LegacyMicrometerRoutePolicyTest.java
@@ -26,6 +26,7 @@ public class LegacyMicrometerRoutePolicyTest extends MicrometerRoutePolicyTest {
     @Override
     protected MicrometerRoutePolicyFactory createMicrometerRoutePolicyFactory() {
         MicrometerRoutePolicyFactory factory = new MicrometerRoutePolicyFactory();
+        factory.getPolicyConfiguration().setContextEnabled(false);
         factory.setNamingStrategy(MicrometerRoutePolicyNamingStrategy.LEGACY);
         return factory;
     }
diff --git a/components/camel-micrometer/src/test/java/org/apache/camel/component/micrometer/routepolicy/MicrometerContextPolicyTest.java b/components/camel-micrometer/src/test/java/org/apache/camel/component/micrometer/routepolicy/MicrometerContextPolicyTest.java
new file mode 100644
index 00000000000..d5badf455a6
--- /dev/null
+++ b/components/camel-micrometer/src/test/java/org/apache/camel/component/micrometer/routepolicy/MicrometerContextPolicyTest.java
@@ -0,0 +1,78 @@
+/*
+ * 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.component.micrometer.routepolicy;
+
+import io.micrometer.core.instrument.Timer;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.jupiter.api.Test;
+
+import static org.apache.camel.component.micrometer.MicrometerConstants.DEFAULT_CAMEL_ROUTE_POLICY_METER_NAME;
+import static org.apache.camel.component.micrometer.MicrometerConstants.EVENT_TYPE_TAG;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class MicrometerContextPolicyTest extends AbstractMicrometerRoutePolicyTest {
+
+    private static final long DELAY_FOO = 20;
+    private static final long DELAY_BAR = 50;
+
+    @Override
+    protected MicrometerRoutePolicyFactory createMicrometerRoutePolicyFactory() {
+        MicrometerRoutePolicyFactory factory = super.createMicrometerRoutePolicyFactory();
+        factory.getPolicyConfiguration().setContextEnabled(true);
+        factory.getPolicyConfiguration().setRouteEnabled(false);
+        return factory;
+    }
+
+    @Test
+    public void testMetricsRoutePolicy() throws Exception {
+        int count = 10;
+        MockEndpoint mockEndpoint = getMockEndpoint("mock:result");
+        mockEndpoint.expectedMessageCount(count);
+
+        for (int i = 0; i < count; i++) {
+            if (i % 2 == 0) {
+                template.sendBody("direct:foo", "Hello " + i);
+            } else {
+                template.sendBody("direct:bar", "Hello " + i);
+            }
+        }
+
+        MockEndpoint.assertIsSatisfied(context);
+
+        Timer fooTimer
+                = meterRegistry.find(formatMetricName(DEFAULT_CAMEL_ROUTE_POLICY_METER_NAME)).tag(EVENT_TYPE_TAG, "context")
+                        .timer();
+        assertEquals(count, fooTimer.count());
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:foo").routeId("foo")
+                        .delay(DELAY_FOO)
+                        .to("mock:result");
+
+                from("direct:bar").routeId("bar")
+                        .delay(DELAY_BAR)
+                        .to("mock:result");
+            }
+        };
+    }
+}
diff --git a/components/camel-micrometer/src/test/java/org/apache/camel/component/micrometer/routepolicy/MicrometerRoutePolicyConfigrationTest.java b/components/camel-micrometer/src/test/java/org/apache/camel/component/micrometer/routepolicy/MicrometerRoutePolicyConfigrationTest.java
index db6d8d05aeb..a408b84862d 100644
--- a/components/camel-micrometer/src/test/java/org/apache/camel/component/micrometer/routepolicy/MicrometerRoutePolicyConfigrationTest.java
+++ b/components/camel-micrometer/src/test/java/org/apache/camel/component/micrometer/routepolicy/MicrometerRoutePolicyConfigrationTest.java
@@ -32,6 +32,7 @@ public class MicrometerRoutePolicyConfigrationTest extends AbstractMicrometerRou
     protected MicrometerRoutePolicyFactory createMicrometerRoutePolicyFactory() {
         MicrometerRoutePolicyFactory factory = new MicrometerRoutePolicyFactory();
         MicrometerRoutePolicyConfiguration policyConfiguration = new MicrometerRoutePolicyConfiguration();
+        policyConfiguration.setContextEnabled(false);
         policyConfiguration.setExchangesSucceeded(false);
         policyConfiguration.setExchangesFailed(false);
         policyConfiguration.setExchangesTotal(false);
diff --git a/components/camel-micrometer/src/test/java/org/apache/camel/component/micrometer/routepolicy/SharedMicrometerRoutePolicyTest.java b/components/camel-micrometer/src/test/java/org/apache/camel/component/micrometer/routepolicy/SharedMicrometerRoutePolicyTest.java
index 966382beb48..536b82204de 100644
--- a/components/camel-micrometer/src/test/java/org/apache/camel/component/micrometer/routepolicy/SharedMicrometerRoutePolicyTest.java
+++ b/components/camel-micrometer/src/test/java/org/apache/camel/component/micrometer/routepolicy/SharedMicrometerRoutePolicyTest.java
@@ -34,7 +34,7 @@ public class SharedMicrometerRoutePolicyTest extends CamelTestSupport {
 
     protected MeterRegistry meterRegistry = new SimpleMeterRegistry();
 
-    protected MicrometerRoutePolicy singletonPolicy = new MicrometerRoutePolicy();
+    protected MicrometerRoutePolicy singletonPolicy = new MicrometerRoutePolicy(null);
 
     @Test
     public void testSharedPolicy() throws Exception {
diff --git a/core/camel-main/src/generated/java/org/apache/camel/main/MetricsConfigurationPropertiesConfigurer.java b/core/camel-main/src/generated/java/org/apache/camel/main/MetricsConfigurationPropertiesConfigurer.java
index 59fd581efe0..a035e5cc26c 100644
--- a/core/camel-main/src/generated/java/org/apache/camel/main/MetricsConfigurationPropertiesConfigurer.java
+++ b/core/camel-main/src/generated/java/org/apache/camel/main/MetricsConfigurationPropertiesConfigurer.java
@@ -37,6 +37,8 @@ public class MetricsConfigurationPropertiesConfigurer extends org.apache.camel.s
         case "Enabled": target.setEnabled(property(camelContext, boolean.class, value)); return true;
         case "namingstrategy":
         case "NamingStrategy": target.setNamingStrategy(property(camelContext, java.lang.String.class, value)); return true;
+        case "routepolicylevel":
+        case "RoutePolicyLevel": target.setRoutePolicyLevel(property(camelContext, java.lang.String.class, value)); return true;
         case "textformatversion":
         case "TextFormatVersion": target.setTextFormatVersion(property(camelContext, java.lang.String.class, value)); return true;
         default: return false;
@@ -62,6 +64,8 @@ public class MetricsConfigurationPropertiesConfigurer extends org.apache.camel.s
         case "Enabled": return boolean.class;
         case "namingstrategy":
         case "NamingStrategy": return java.lang.String.class;
+        case "routepolicylevel":
+        case "RoutePolicyLevel": return java.lang.String.class;
         case "textformatversion":
         case "TextFormatVersion": return java.lang.String.class;
         default: return null;
@@ -88,6 +92,8 @@ public class MetricsConfigurationPropertiesConfigurer extends org.apache.camel.s
         case "Enabled": return target.isEnabled();
         case "namingstrategy":
         case "NamingStrategy": return target.getNamingStrategy();
+        case "routepolicylevel":
+        case "RoutePolicyLevel": return target.getRoutePolicyLevel();
         case "textformatversion":
         case "TextFormatVersion": return target.getTextFormatVersion();
         default: return null;
diff --git a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
index 2c8368e3122..2d3a5c16711 100644
--- a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
+++ b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
@@ -182,6 +182,7 @@
     { "name": "camel.metrics.enableRouteEventNotifier", "description": "Set whether to enable the MicrometerRouteEventNotifier for capturing metrics on the total number of routes and total number of routes running.", "sourceType": "org.apache.camel.main.MetricsConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": true },
     { "name": "camel.metrics.enableRoutePolicy", "description": "Set whether to enable the MicrometerRoutePolicyFactory for capturing metrics on route processing times.", "sourceType": "org.apache.camel.main.MetricsConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": true },
     { "name": "camel.metrics.namingStrategy", "description": "Controls the name style to use for metrics. Default = uses micrometer naming convention. Legacy = uses the classic naming style (camelCase)", "sourceType": "org.apache.camel.main.MetricsConfigurationProperties", "type": "string", "javaType": "java.lang.String", "defaultValue": "default", "enum": [ "default", "legacy" ] },
+    { "name": "camel.metrics.routePolicyLevel", "description": "Sets the level of information to capture. all = both context and routes.", "sourceType": "org.apache.camel.main.MetricsConfigurationProperties", "type": "string", "javaType": "java.lang.String", "defaultValue": "all", "enum": [ "all", "route", "context" ] },
     { "name": "camel.metrics.textFormatVersion", "description": "The text-format version to use with Prometheus scraping. 0.0.4 = text\/plain; version=0.0.4; charset=utf-8 1.0.0 = application\/openmetrics-text; version=1.0.0; charset=utf-8", "sourceType": "org.apache.camel.main.MetricsConfigurationProperties", "type": "string", "javaType": "java.lang.String", "defaultValue": "0.0.4", "enum": [ "0.0.4", "1.0.0" ] },
     { "name": "camel.opentelemetry.enabled", "description": "To enable OpenTelemetry", "sourceType": "org.apache.camel.main.OtelConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": "false" },
     { "name": "camel.opentelemetry.encoding", "description": "Sets whether the header keys need to be encoded (connector specific) or not. The value is a boolean. Dashes need for instances to be encoded for JMS property keys.", "sourceType": "org.apache.camel.main.OtelConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": "false" },
diff --git a/core/camel-main/src/main/docs/main.adoc b/core/camel-main/src/main/docs/main.adoc
index 3274ceb9c04..7f70eafc246 100644
--- a/core/camel-main/src/main/docs/main.adoc
+++ b/core/camel-main/src/main/docs/main.adoc
@@ -386,7 +386,7 @@ The camel.opentelemetry supports 4 options, which are listed below.
 
 
 === Camel Micrometer Metrics configurations
-The camel.metrics supports 9 options, which are listed below.
+The camel.metrics supports 10 options, which are listed below.
 
 [width="100%",cols="2,5,^1,2",options="header"]
 |===
@@ -399,6 +399,7 @@ The camel.metrics supports 9 options, which are listed below.
 | *camel.metrics.enableRouteEvent{zwsp}Notifier* | Set whether to enable the MicrometerRouteEventNotifier for capturing metrics on the total number of routes and total number of routes running. | true | boolean
 | *camel.metrics.enableRoute{zwsp}Policy* | Set whether to enable the MicrometerRoutePolicyFactory for capturing metrics on route processing times. | true | boolean
 | *camel.metrics.namingStrategy* | Controls the name style to use for metrics. Default = uses micrometer naming convention. Legacy = uses the classic naming style (camelCase) | default | String
+| *camel.metrics.routePolicyLevel* | Sets the level of information to capture. all = both context and routes. | all | String
 | *camel.metrics.textFormat{zwsp}Version* | The text-format version to use with Prometheus scraping. 0.0.4 = text/plain; version=0.0.4; charset=utf-8 1.0.0 = application/openmetrics-text; version=1.0.0; charset=utf-8 | 0.0.4 | String
 |===
 
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/MetricsConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/MetricsConfigurationProperties.java
index 108c9dfc2a8..772d3242c17 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/MetricsConfigurationProperties.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/MetricsConfigurationProperties.java
@@ -33,6 +33,8 @@ public class MetricsConfigurationProperties implements BootstrapCloseable {
     private String namingStrategy;
     @Metadata(defaultValue = "true")
     private boolean enableRoutePolicy = true;
+    @Metadata(defaultValue = "all", enums = "all,route,context")
+    private String routePolicyLevel = "all";
     private boolean enableMessageHistory;
     @Metadata(defaultValue = "true")
     private boolean enableExchangeEventNotifier = true;
@@ -88,6 +90,17 @@ public class MetricsConfigurationProperties implements BootstrapCloseable {
         this.enableRoutePolicy = enableRoutePolicy;
     }
 
+    public String getRoutePolicyLevel() {
+        return routePolicyLevel;
+    }
+
+    /**
+     * Sets the level of information to capture. all = both context and routes.
+     */
+    public void setRoutePolicyLevel(String routePolicyLevel) {
+        this.routePolicyLevel = routePolicyLevel;
+    }
+
     public boolean isEnableMessageHistory() {
         return enableMessageHistory;
     }
@@ -180,6 +193,14 @@ public class MetricsConfigurationProperties implements BootstrapCloseable {
         return this;
     }
 
+    /**
+     * Sets the level of information to capture. all = both context and routes.
+     */
+    public MetricsConfigurationProperties withRoutePolicyLevel(String routePolicyLevel) {
+        this.routePolicyLevel = routePolicyLevel;
+        return this;
+    }
+
     /**
      * To enable Micrometer metrics.
      */
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/OtelConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/OtelConfigurationProperties.java
index 567356d5d02..9e3b04eefd4 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/OtelConfigurationProperties.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/OtelConfigurationProperties.java
@@ -24,7 +24,8 @@ import org.apache.camel.spi.Metadata;
  * Global configuration for OpenTelemetry
  */
 @Configurer(bootstrap = true)
-public class OtelConfigurationProperties implements BootstrapCloseable {
+public class
+OtelConfigurationProperties implements BootstrapCloseable {
 
     private MainConfigurationProperties parent;