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

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


The following commit(s) were added to refs/heads/main by this push:
     new 6995589abe2d CAMEL-16866 add route-policy (#19929)
6995589abe2d is described below

commit 6995589abe2ded2acff95f254c5a4818e0d36a6c
Author: Jono Morris <[email protected]>
AuthorDate: Sat Nov 15 04:57:01 2025 +1300

    CAMEL-16866 add route-policy (#19929)
---
 .../catalog/components/opentelemetry-metrics.json  |   2 +-
 .../metrics/opentelemetry-metrics.json             |   2 +-
 .../metrics/OpenTelemetryConstants.java            |  12 +-
 .../routepolicy/OpenTelemetryRoutePolicy.java      | 308 +++++++++++++++++++++
 .../OpenTelemetryRoutePolicyConfiguration.java     | 121 ++++++++
 .../OpenTelemetryRoutePolicyFactory.java           | 104 +++++++
 .../OpenTelemetryRoutePolicyNamingStrategy.java    |  86 ++++++
 .../metrics/routepolicy/RouteMetric.java           |  28 ++
 .../AbstractOpenTelemetryRoutePolicyTest.java      |  40 +++
 ...OpenTelemetryRoutePolicyExchangeStatusTest.java |  77 ++++++
 ...OpenTelemetryRoutePolicyExcludePatternTest.java |  79 ++++++
 ...nTelemetryRoutePolicyMulticastSubRouteTest.java | 125 +++++++++
 .../OpenTelemetryRoutePolicySubRouteTest.java      |  81 ++++++
 .../routepolicy/OpenTelemetryRoutePolicyTest.java  | 141 ++++++++++
 .../OpenTelemetrySharedRoutePolicyTest.java        |  66 +++++
 .../dsl/OpenTelemetryEndpointBuilderFactory.java   |   2 +-
 16 files changed, 1270 insertions(+), 4 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/opentelemetry-metrics.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/opentelemetry-metrics.json
index fd6253f7178e..8a7c8e9e2733 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/opentelemetry-metrics.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/opentelemetry-metrics.json
@@ -29,7 +29,7 @@
     "meter": { "index": 2, "kind": "property", "displayName": "Meter", 
"group": "advanced", "label": "advanced", "required": false, "type": "object", 
"javaType": "io.opentelemetry.api.metrics.Meter", "deprecated": false, 
"autowired": false, "secret": false, "description": "To use a custom configured 
Meter." }
   },
   "headers": {
-    "CamelMetricsTimerAction": { "index": 0, "kind": "header", "displayName": 
"", "group": "producer", "label": "", "required": false, "javaType": 
"org.apache.camel.opentelemetry2.component.OpenTelemetryTimerAction", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "Override timer action in URI", "constantName": 
"org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants#HEADER_TIMER_ACTION"
 },
+    "CamelMetricsTimerAction": { "index": 0, "kind": "header", "displayName": 
"", "group": "producer", "label": "", "required": false, "javaType": 
"org.apache.camel.opentelemetry.metrics.OpenTelemetryTimerAction", "enum": [ 
"START", "STOP" ], "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Override timer action in URI", 
"constantName": 
"org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants#HEADER_TIMER_ACTION"
 },
     "CamelMetricsHistogramValue": { "index": 1, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Override histogram value in URI", 
"constantName": 
"org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants#HEADER_HISTOGRAM_VALUE"
 },
     "CamelMetricsCounterDecrement": { "index": 2, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "Double", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Override decrement value in URI", 
"constantName": 
"org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants#HEADER_COUNTER_DECREMENT"
 },
     "CamelMetricsCounterIncrement": { "index": 3, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "Double", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Override increment value in URI", 
"constantName": 
"org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants#HEADER_COUNTER_INCREMENT"
 },
diff --git 
a/components/camel-opentelemetry-metrics/src/generated/resources/META-INF/org/apache/camel/opentelemetry/metrics/opentelemetry-metrics.json
 
b/components/camel-opentelemetry-metrics/src/generated/resources/META-INF/org/apache/camel/opentelemetry/metrics/opentelemetry-metrics.json
index fd6253f7178e..8a7c8e9e2733 100644
--- 
a/components/camel-opentelemetry-metrics/src/generated/resources/META-INF/org/apache/camel/opentelemetry/metrics/opentelemetry-metrics.json
+++ 
b/components/camel-opentelemetry-metrics/src/generated/resources/META-INF/org/apache/camel/opentelemetry/metrics/opentelemetry-metrics.json
@@ -29,7 +29,7 @@
     "meter": { "index": 2, "kind": "property", "displayName": "Meter", 
"group": "advanced", "label": "advanced", "required": false, "type": "object", 
"javaType": "io.opentelemetry.api.metrics.Meter", "deprecated": false, 
"autowired": false, "secret": false, "description": "To use a custom configured 
Meter." }
   },
   "headers": {
-    "CamelMetricsTimerAction": { "index": 0, "kind": "header", "displayName": 
"", "group": "producer", "label": "", "required": false, "javaType": 
"org.apache.camel.opentelemetry2.component.OpenTelemetryTimerAction", 
"deprecated": false, "deprecationNote": "", "autowired": false, "secret": 
false, "description": "Override timer action in URI", "constantName": 
"org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants#HEADER_TIMER_ACTION"
 },
+    "CamelMetricsTimerAction": { "index": 0, "kind": "header", "displayName": 
"", "group": "producer", "label": "", "required": false, "javaType": 
"org.apache.camel.opentelemetry.metrics.OpenTelemetryTimerAction", "enum": [ 
"START", "STOP" ], "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Override timer action in URI", 
"constantName": 
"org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants#HEADER_TIMER_ACTION"
 },
     "CamelMetricsHistogramValue": { "index": 1, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "long", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Override histogram value in URI", 
"constantName": 
"org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants#HEADER_HISTOGRAM_VALUE"
 },
     "CamelMetricsCounterDecrement": { "index": 2, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "Double", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Override decrement value in URI", 
"constantName": 
"org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants#HEADER_COUNTER_DECREMENT"
 },
     "CamelMetricsCounterIncrement": { "index": 3, "kind": "header", 
"displayName": "", "group": "producer", "label": "", "required": false, 
"javaType": "Double", "deprecated": false, "deprecationNote": "", "autowired": 
false, "secret": false, "description": "Override increment value in URI", 
"constantName": 
"org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants#HEADER_COUNTER_INCREMENT"
 },
diff --git 
a/components/camel-opentelemetry-metrics/src/main/java/org/apache/camel/opentelemetry/metrics/OpenTelemetryConstants.java
 
b/components/camel-opentelemetry-metrics/src/main/java/org/apache/camel/opentelemetry/metrics/OpenTelemetryConstants.java
index 7a3592f0964c..e3748d7b1d80 100644
--- 
a/components/camel-opentelemetry-metrics/src/main/java/org/apache/camel/opentelemetry/metrics/OpenTelemetryConstants.java
+++ 
b/components/camel-opentelemetry-metrics/src/main/java/org/apache/camel/opentelemetry/metrics/OpenTelemetryConstants.java
@@ -22,7 +22,7 @@ public class OpenTelemetryConstants {
 
     public static final String HEADER_PREFIX = "CamelMetrics";
     @Metadata(description = "Override timer action in URI",
-              javaType = 
"org.apache.camel.opentelemetry2.component.OpenTelemetryTimerAction")
+              javaType = 
"org.apache.camel.opentelemetry.metrics.OpenTelemetryTimerAction")
     public static final String HEADER_TIMER_ACTION = HEADER_PREFIX + 
"TimerAction";
     @Metadata(description = "Override histogram value in URI", javaType = 
"long")
     public static final String HEADER_HISTOGRAM_VALUE = HEADER_PREFIX + 
"HistogramValue";
@@ -39,6 +39,16 @@ public class OpenTelemetryConstants {
 
     public static final String HEADER_METRIC_ATTRIBUTES = HEADER_PREFIX + 
"Attributes";
 
+    // Route-policy metrics
+    public static final String 
DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_FAILED_METER_NAME = 
"camel.exchanges.failed";
+    public static final String 
DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_SUCCEEDED_METER_NAME = 
"camel.exchanges.succeeded";
+    public static final String 
DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_TOTAL_METER_NAME = "camel.exchanges.total";
+    public static final String 
DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_FAILURES_HANDLED_METER_NAME
+            = "camel.exchanges.failures.handled";
+    public static final String 
DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_EXTERNAL_REDELIVERIES_METER_NAME
+            = "camel.exchanges.external.redeliveries";
+    public static final String DEFAULT_CAMEL_ROUTE_POLICY_METER_NAME = 
"camel.route.policy";
+
     // Exchange-event metrics
     public static final String DEFAULT_CAMEL_ROUTES_EXCHANGES_INFLIGHT = 
"camel.exchanges.inflight";
     public static final String DEFAULT_CAMEL_EXCHANGE_ELAPSED_TIMER = 
"camel.exchange.elapsed";
diff --git 
a/components/camel-opentelemetry-metrics/src/main/java/org/apache/camel/opentelemetry/metrics/routepolicy/OpenTelemetryRoutePolicy.java
 
b/components/camel-opentelemetry-metrics/src/main/java/org/apache/camel/opentelemetry/metrics/routepolicy/OpenTelemetryRoutePolicy.java
new file mode 100644
index 000000000000..c404bec04585
--- /dev/null
+++ 
b/components/camel-opentelemetry-metrics/src/main/java/org/apache/camel/opentelemetry/metrics/routepolicy/OpenTelemetryRoutePolicy.java
@@ -0,0 +1,308 @@
+/*
+ * 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.opentelemetry.metrics.routepolicy;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.TimeUnit;
+
+import io.opentelemetry.api.GlobalOpenTelemetry;
+import io.opentelemetry.api.common.AttributeKey;
+import io.opentelemetry.api.common.Attributes;
+import io.opentelemetry.api.metrics.LongCounter;
+import io.opentelemetry.api.metrics.LongHistogram;
+import io.opentelemetry.api.metrics.Meter;
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.NonManagedService;
+import org.apache.camel.Route;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.opentelemetry.metrics.TaskTimer;
+import org.apache.camel.spi.ManagementStrategy;
+import org.apache.camel.support.CamelContextHelper;
+import org.apache.camel.support.ExchangeHelper;
+import org.apache.camel.support.PatternHelper;
+import org.apache.camel.support.RoutePolicySupport;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static 
org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants.CAMEL_CONTEXT_ATTRIBUTE;
+import static 
org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants.DEFAULT_CAMEL_ROUTE_POLICY_METER_NAME;
+import static 
org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants.EVENT_TYPE_ATTRIBUTE;
+import static 
org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants.KIND_ATTRIBUTE;
+import static 
org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants.KIND_ROUTE;
+import static 
org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants.ROUTE_ID_ATTRIBUTE;
+
+/**
+ * A {@link org.apache.camel.spi.RoutePolicy} to plugin and use OpenTelemetry 
metrics for gathering route utilization
+ * statistics.
+ */
+public class OpenTelemetryRoutePolicy extends RoutePolicySupport implements 
NonManagedService {
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(OpenTelemetryRoutePolicy.class);
+
+    private final OpenTelemetryRoutePolicyFactory factory;
+    private Meter meter;
+    boolean registerKamelets;
+    boolean registerTemplates = true;
+
+    private OpenTelemetryRoutePolicyNamingStrategy namingStrategy = 
OpenTelemetryRoutePolicyNamingStrategy.DEFAULT;
+    private OpenTelemetryRoutePolicyConfiguration configuration = new 
OpenTelemetryRoutePolicyConfiguration();
+    private TimeUnit timeUnit = TimeUnit.MILLISECONDS;
+    private final Map<Route, MetricsStatistics> statisticsMap = new 
HashMap<>();
+
+    public OpenTelemetryRoutePolicy(OpenTelemetryRoutePolicyFactory factory) {
+        this.factory = factory;
+    }
+
+    public Meter getMeter() {
+        return meter;
+    }
+
+    public void setMeter(Meter meter) {
+        this.meter = meter;
+    }
+
+    public OpenTelemetryRoutePolicyNamingStrategy getNamingStrategy() {
+        return namingStrategy;
+    }
+
+    public void setNamingStrategy(OpenTelemetryRoutePolicyNamingStrategy 
namingStrategy) {
+        this.namingStrategy = namingStrategy;
+    }
+
+    public OpenTelemetryRoutePolicyConfiguration getConfiguration() {
+        return configuration;
+    }
+
+    public void setConfiguration(OpenTelemetryRoutePolicyConfiguration 
configuration) {
+        this.configuration = configuration;
+    }
+
+    public TimeUnit getTimeUnit() {
+        return timeUnit;
+    }
+
+    public void setTimeUnit(TimeUnit timeUnit) {
+        this.timeUnit = timeUnit;
+    }
+
+    boolean isRegisterKamelets() {
+        return registerKamelets;
+    }
+
+    boolean isRegisterTemplates() {
+        return registerTemplates;
+    }
+
+    @Override
+    public void onInit(Route route) {
+        super.onInit(route);
+        if (meter == null) {
+            this.meter = 
CamelContextHelper.findSingleByType(route.getCamelContext(), Meter.class);
+        }
+        if (meter == null) {
+            this.meter = GlobalOpenTelemetry.get().getMeter("camel");
+        }
+        if (meter == null) {
+            throw new RuntimeCamelException("Could not find any OpenTelemetry 
meter!");
+        }
+
+        ManagementStrategy ms = 
route.getCamelContext().getManagementStrategy();
+        if (ms != null && ms.getManagementAgent() != null) {
+            registerKamelets = 
ms.getManagementAgent().getRegisterRoutesCreateByKamelet();
+            registerTemplates = 
ms.getManagementAgent().getRegisterRoutesCreateByTemplate();
+        }
+    }
+
+    @Override
+    public void onStart(Route route) {
+        // create statistics holder
+        statisticsMap.computeIfAbsent(route,
+                it -> {
+                    boolean skip = !configuration.isRouteEnabled();
+                    // skip routes that should not be included
+                    if (!skip) {
+                        skip = (it.isCreatedByKamelet() && !registerKamelets)
+                                || (it.isCreatedByRouteTemplate() && 
!registerTemplates);
+                    }
+                    if (!skip && configuration.getExcludePattern() != null) {
+                        String[] patterns = 
configuration.getExcludePattern().split(",");
+                        skip = PatternHelper.matchPatterns(route.getRouteId(), 
patterns);
+                    }
+                    LOG.debug("Capturing metrics for route: {} -> {}", 
route.getRouteId(), skip);
+                    if (skip) {
+                        return null;
+                    }
+                    return new MetricsStatistics(
+                            meter, it.getCamelContext(), it, 
getNamingStrategy(), configuration, timeUnit);
+                });
+    }
+
+    @Override
+    public void onRemove(Route route) {
+        statisticsMap.remove(route);
+    }
+
+    @Override
+    public void onExchangeBegin(Route route, Exchange exchange) {
+        Optional.ofNullable(statisticsMap.get(route))
+                .ifPresent(statistics -> statistics.onExchangeBegin(exchange));
+    }
+
+    @Override
+    public void onExchangeDone(Route route, Exchange exchange) {
+        Optional.ofNullable(statisticsMap.get(route))
+                .ifPresent(statistics -> statistics.onExchangeDone(exchange));
+    }
+
+    static class MetricsStatistics implements RouteMetric {
+        private final CamelContext camelContext;
+        private final Route route;
+
+        // Configuration
+        private final OpenTelemetryRoutePolicyNamingStrategy namingStrategy;
+        private final OpenTelemetryRoutePolicyConfiguration configuration;
+        private final TimeUnit timeUnit;
+
+        // OpenTelemetry objects
+        private final Meter meter;
+        private final Attributes attributes;
+
+        // OpenTelemetry instruments
+        private final LongHistogram timer;
+        private LongCounter exchangesSucceeded;
+        private LongCounter exchangesFailed;
+        private LongCounter exchangesTotal;
+        private LongCounter externalRedeliveries;
+        private LongCounter failuresHandled;
+
+        MetricsStatistics(Meter meter, CamelContext camelContext, Route route,
+                          OpenTelemetryRoutePolicyNamingStrategy 
namingStrategy,
+                          OpenTelemetryRoutePolicyConfiguration configuration,
+                          TimeUnit timeUnit) {
+
+            this.configuration = ObjectHelper.notNull(configuration, 
"OpenTelemetryRoutePolicyConfiguration", this);
+            this.namingStrategy = ObjectHelper.notNull(namingStrategy, 
"OpenTelemetryRoutePolicyNamingStrategy", this);
+            this.meter = ObjectHelper.notNull(meter, "Meter", this);
+            this.camelContext = camelContext;
+            this.route = route;
+            this.timeUnit = timeUnit;
+            this.attributes = Attributes.of(
+                    AttributeKey.stringKey(CAMEL_CONTEXT_ATTRIBUTE),
+                    route != null ? route.getCamelContext().getName() : 
camelContext.getName(),
+                    AttributeKey.stringKey(KIND_ATTRIBUTE), KIND_ROUTE,
+                    AttributeKey.stringKey(ROUTE_ID_ATTRIBUTE), route != null 
? route.getId() : "",
+                    AttributeKey.stringKey(EVENT_TYPE_ATTRIBUTE), route != 
null ? "route" : "context");
+            this.timer = meter
+                    .histogramBuilder(namingStrategy.getName(route))
+                    .setDescription(route != null ? "Route performance 
metrics" : "CamelContext performance metrics")
+                    .setUnit(timeUnit.name().toLowerCase())
+                    .ofLongs().build();
+
+            if (configuration.isAdditionalCounters()) {
+                initAdditionalCounters();
+            }
+        }
+
+        private void initAdditionalCounters() {
+            if (configuration.isExchangesSucceeded()) {
+                this.exchangesSucceeded = 
createCounter(namingStrategy.getExchangesSucceededName(route),
+                        "Number of successfully completed exchanges");
+            }
+            if (configuration.isExchangesFailed()) {
+                this.exchangesFailed
+                        = 
createCounter(namingStrategy.getExchangesFailedName(route),
+                                "Number of failed exchanges");
+            }
+            if (configuration.isExchangesTotal()) {
+                this.exchangesTotal
+                        = 
createCounter(namingStrategy.getExchangesTotalName(route),
+                                "Total number of processed exchanges");
+            }
+            if (configuration.isExternalRedeliveries()) {
+                this.externalRedeliveries = 
createCounter(namingStrategy.getExternalRedeliveriesName(route),
+                        "Number of external initiated redeliveries (such as 
from JMS broker)");
+            }
+            if (configuration.isFailuresHandled()) {
+                this.failuresHandled
+                        = 
createCounter(namingStrategy.getFailuresHandledName(route),
+                                "Number of failures handled");
+            }
+        }
+
+        @Override
+        public void onExchangeBegin(Exchange exchange) {
+            String propertyName = propertyName(exchange);
+            exchange.setProperty(propertyName, new TaskTimer());
+        }
+
+        @Override
+        public void onExchangeDone(Exchange exchange) {
+            String propertyName = propertyName(exchange);
+            TaskTimer task = (TaskTimer) exchange.removeProperty(propertyName);
+            if (task != null) {
+                this.timer.record(task.duration(timeUnit), attributes);
+            }
+            TaskTimer longTask = (TaskTimer) 
exchange.removeProperty(propertyName + "_long_task");
+            if (longTask != null) {
+                longTask.stop();
+            }
+            if (configuration.isAdditionalCounters()) {
+                updateAdditionalCounters(exchange);
+            }
+        }
+
+        @Override
+        public void remove() {
+            // no-op
+        }
+
+        private void updateAdditionalCounters(Exchange exchange) {
+            if (exchangesTotal != null) {
+                exchangesTotal.add(1L, attributes);
+            }
+            if (exchange.isFailed()) {
+                if (exchangesFailed != null) {
+                    exchangesFailed.add(1L, attributes);
+                }
+            } else {
+                if (exchangesSucceeded != null) {
+                    exchangesSucceeded.add(1L, attributes);
+                }
+                if (failuresHandled != null && 
ExchangeHelper.isFailureHandled(exchange)) {
+                    failuresHandled.add(1L, attributes);
+                }
+                if (externalRedeliveries != null && 
exchange.isExternalRedelivered()) {
+                    externalRedeliveries.add(1L, attributes);
+                }
+            }
+        }
+
+        private String propertyName(Exchange exchange) {
+            String id = route != null ? route.getId() : "context:" + 
camelContext.getName();
+            return String.format("%s-%s-%s", 
DEFAULT_CAMEL_ROUTE_POLICY_METER_NAME, id, exchange.getExchangeId());
+        }
+
+        private LongCounter createCounter(String meterName, String 
description) {
+            return meter.counterBuilder(meterName)
+                    .setDescription(description).build();
+        }
+    }
+}
diff --git 
a/components/camel-opentelemetry-metrics/src/main/java/org/apache/camel/opentelemetry/metrics/routepolicy/OpenTelemetryRoutePolicyConfiguration.java
 
b/components/camel-opentelemetry-metrics/src/main/java/org/apache/camel/opentelemetry/metrics/routepolicy/OpenTelemetryRoutePolicyConfiguration.java
new file mode 100644
index 000000000000..7ae0d4c33786
--- /dev/null
+++ 
b/components/camel-opentelemetry-metrics/src/main/java/org/apache/camel/opentelemetry/metrics/routepolicy/OpenTelemetryRoutePolicyConfiguration.java
@@ -0,0 +1,121 @@
+/*
+ * 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.opentelemetry.metrics.routepolicy;
+
+/**
+ * Configuration for enabling and disabling metrics collected by the 
OpenTelemetry route policy.
+ */
+public class OpenTelemetryRoutePolicyConfiguration {
+
+    private boolean routeEnabled = true;
+    private String excludePattern;
+    private boolean additionalCounters = true;
+    private boolean exchangesSucceeded = true;
+    private boolean exchangesFailed = true;
+    private boolean exchangesTotal = true;
+    private boolean externalRedeliveries = true;
+    private boolean failuresHandled = true;
+
+    public boolean isRouteEnabled() {
+        return routeEnabled;
+    }
+
+    /**
+     * Enable route level metrics.
+     */
+    public void setRouteEnabled(boolean routeEnabled) {
+        this.routeEnabled = routeEnabled;
+    }
+
+    public String getExcludePattern() {
+        return excludePattern;
+    }
+
+    /**
+     * A comma separated list of regex patterns to that are used to exclude 
routes from metrics.
+     */
+    public void setExcludePattern(String excludePattern) {
+        this.excludePattern = excludePattern;
+    }
+
+    public boolean isAdditionalCounters() {
+        return additionalCounters;
+    }
+
+    /**
+     * Enable all additional route metrics such as exchanges succeeded, 
failed, total exchanges, external redeliveries
+     * and handled failures are enabled.
+     */
+    public void setAdditionalCounters(boolean additionalCounters) {
+        this.additionalCounters = additionalCounters;
+    }
+
+    public boolean isExchangesSucceeded() {
+        return exchangesSucceeded;
+    }
+
+    /**
+     * Enable 'succeeded exchanges' counter.
+     */
+    public void setExchangesSucceeded(boolean exchangesSucceeded) {
+        this.exchangesSucceeded = exchangesSucceeded;
+    }
+
+    public boolean isExchangesFailed() {
+        return exchangesFailed;
+    }
+
+    /**
+     * Enable 'failed exchanges' counter.
+     */
+    public void setExchangesFailed(boolean exchangesFailed) {
+        this.exchangesFailed = exchangesFailed;
+    }
+
+    public boolean isExchangesTotal() {
+        return exchangesTotal;
+    }
+
+    /**
+     * Enable 'total exchanges' counter.
+     */
+    public void setExchangesTotal(boolean exchangesTotal) {
+        this.exchangesTotal = exchangesTotal;
+    }
+
+    public boolean isExternalRedeliveries() {
+        return externalRedeliveries;
+    }
+
+    /**
+     * Enable 'external redeliveries' counter.
+     */
+    public void setExternalRedeliveries(boolean externalRedeliveries) {
+        this.externalRedeliveries = externalRedeliveries;
+    }
+
+    public boolean isFailuresHandled() {
+        return failuresHandled;
+    }
+
+    /**
+     * Enable 'handled failures' counter.
+     */
+    public void setFailuresHandled(boolean failuresHandled) {
+        this.failuresHandled = failuresHandled;
+    }
+}
diff --git 
a/components/camel-opentelemetry-metrics/src/main/java/org/apache/camel/opentelemetry/metrics/routepolicy/OpenTelemetryRoutePolicyFactory.java
 
b/components/camel-opentelemetry-metrics/src/main/java/org/apache/camel/opentelemetry/metrics/routepolicy/OpenTelemetryRoutePolicyFactory.java
new file mode 100644
index 000000000000..f451f5785b06
--- /dev/null
+++ 
b/components/camel-opentelemetry-metrics/src/main/java/org/apache/camel/opentelemetry/metrics/routepolicy/OpenTelemetryRoutePolicyFactory.java
@@ -0,0 +1,104 @@
+/*
+ * 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.opentelemetry.metrics.routepolicy;
+
+import java.util.concurrent.TimeUnit;
+
+import io.opentelemetry.api.metrics.Meter;
+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 RoutePolicyFactory} to plugin and use metrics for gathering route 
utilization statistics
+ */
+public class OpenTelemetryRoutePolicyFactory extends ServiceSupport
+        implements RoutePolicyFactory, CamelContextAware, NonManagedService, 
StaticService {
+
+    private CamelContext camelContext;
+    private Meter meter;
+    private RouteMetric contextMetric;
+    private OpenTelemetryRoutePolicyNamingStrategy namingStrategy = 
OpenTelemetryRoutePolicyNamingStrategy.DEFAULT;
+    private OpenTelemetryRoutePolicyConfiguration policyConfiguration = new 
OpenTelemetryRoutePolicyConfiguration();
+    private TimeUnit timeUnit = TimeUnit.MILLISECONDS;
+
+    @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    public void setMeter(Meter meter) {
+        this.meter = meter;
+    }
+
+    public Meter getMeter() {
+        return meter;
+    }
+
+    public OpenTelemetryRoutePolicyNamingStrategy getNamingStrategy() {
+        return namingStrategy;
+    }
+
+    public void setNamingStrategy(OpenTelemetryRoutePolicyNamingStrategy 
namingStrategy) {
+        this.namingStrategy = namingStrategy;
+    }
+
+    public OpenTelemetryRoutePolicyConfiguration getPolicyConfiguration() {
+        return policyConfiguration;
+    }
+
+    public void setPolicyConfiguration(OpenTelemetryRoutePolicyConfiguration 
policyConfiguration) {
+        this.policyConfiguration = policyConfiguration;
+    }
+
+    public TimeUnit getTimeUnit() {
+        return timeUnit;
+    }
+
+    public void setTimeUnit(TimeUnit timeUnit) {
+        this.timeUnit = timeUnit;
+    }
+
+    @Override
+    public RoutePolicy createRoutePolicy(CamelContext camelContext, String 
routeId, NamedNode routeDefinition) {
+        OpenTelemetryRoutePolicy routePolicy = new 
OpenTelemetryRoutePolicy(this);
+        routePolicy.setNamingStrategy(getNamingStrategy());
+        routePolicy.setConfiguration(getPolicyConfiguration());
+        routePolicy.setTimeUnit(getTimeUnit());
+        routePolicy.setMeter(meter);
+        return routePolicy;
+    }
+
+    @Override
+    protected void doShutdown() throws Exception {
+        super.doShutdown();
+        if (contextMetric != null) {
+            contextMetric.remove();
+            contextMetric = null;
+        }
+    }
+}
diff --git 
a/components/camel-opentelemetry-metrics/src/main/java/org/apache/camel/opentelemetry/metrics/routepolicy/OpenTelemetryRoutePolicyNamingStrategy.java
 
b/components/camel-opentelemetry-metrics/src/main/java/org/apache/camel/opentelemetry/metrics/routepolicy/OpenTelemetryRoutePolicyNamingStrategy.java
new file mode 100644
index 000000000000..25f58bdb344a
--- /dev/null
+++ 
b/components/camel-opentelemetry-metrics/src/main/java/org/apache/camel/opentelemetry/metrics/routepolicy/OpenTelemetryRoutePolicyNamingStrategy.java
@@ -0,0 +1,86 @@
+/*
+ * 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.opentelemetry.metrics.routepolicy;
+
+import org.apache.camel.Route;
+
+import static 
org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants.DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_EXTERNAL_REDELIVERIES_METER_NAME;
+import static 
org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants.DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_FAILED_METER_NAME;
+import static 
org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants.DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_FAILURES_HANDLED_METER_NAME;
+import static 
org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants.DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_SUCCEEDED_METER_NAME;
+import static 
org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants.DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_TOTAL_METER_NAME;
+import static 
org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants.DEFAULT_CAMEL_ROUTE_POLICY_METER_NAME;
+
+/**
+ * Provides a strategy to provide metric names for OpenTelemetry route policy 
metrics.
+ */
+public interface OpenTelemetryRoutePolicyNamingStrategy {
+
+    /**
+     * Default naming strategy that uses opentelemetry naming convention.
+     */
+    OpenTelemetryRoutePolicyNamingStrategy DEFAULT = new 
OpenTelemetryRoutePolicyNamingStrategy() {
+        @Override
+        public String getName(Route route) {
+            return DEFAULT_CAMEL_ROUTE_POLICY_METER_NAME;
+        }
+
+        @Override
+        public String formatName(String name) {
+            return name;
+        }
+
+        @Override
+        public String getExchangesSucceededName(Route route) {
+            return 
formatName(DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_SUCCEEDED_METER_NAME);
+        }
+
+        @Override
+        public String getExchangesFailedName(Route route) {
+            return 
formatName(DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_FAILED_METER_NAME);
+        }
+
+        @Override
+        public String getExchangesTotalName(Route route) {
+            return 
formatName(DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_TOTAL_METER_NAME);
+        }
+
+        @Override
+        public String getFailuresHandledName(Route route) {
+            return 
formatName(DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_FAILURES_HANDLED_METER_NAME);
+        }
+
+        @Override
+        public String getExternalRedeliveriesName(Route route) {
+            return 
formatName(DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_EXTERNAL_REDELIVERIES_METER_NAME);
+        }
+    };
+
+    String getName(Route route);
+
+    String formatName(String name);
+
+    String getExchangesSucceededName(Route route);
+
+    String getExchangesFailedName(Route route);
+
+    String getExchangesTotalName(Route route);
+
+    String getFailuresHandledName(Route route);
+
+    String getExternalRedeliveriesName(Route route);
+}
diff --git 
a/components/camel-opentelemetry-metrics/src/main/java/org/apache/camel/opentelemetry/metrics/routepolicy/RouteMetric.java
 
b/components/camel-opentelemetry-metrics/src/main/java/org/apache/camel/opentelemetry/metrics/routepolicy/RouteMetric.java
new file mode 100644
index 000000000000..ca4de3d50d28
--- /dev/null
+++ 
b/components/camel-opentelemetry-metrics/src/main/java/org/apache/camel/opentelemetry/metrics/routepolicy/RouteMetric.java
@@ -0,0 +1,28 @@
+/*
+ * 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.opentelemetry.metrics.routepolicy;
+
+import org.apache.camel.Exchange;
+
+public interface RouteMetric {
+
+    void onExchangeBegin(Exchange exchange);
+
+    void onExchangeDone(Exchange exchange);
+
+    void remove();
+}
diff --git 
a/components/camel-opentelemetry-metrics/src/test/java/org/apache/camel/opentelemetry/metrics/routepolicy/AbstractOpenTelemetryRoutePolicyTest.java
 
b/components/camel-opentelemetry-metrics/src/test/java/org/apache/camel/opentelemetry/metrics/routepolicy/AbstractOpenTelemetryRoutePolicyTest.java
new file mode 100644
index 000000000000..2ef5734487d5
--- /dev/null
+++ 
b/components/camel-opentelemetry-metrics/src/test/java/org/apache/camel/opentelemetry/metrics/routepolicy/AbstractOpenTelemetryRoutePolicyTest.java
@@ -0,0 +1,40 @@
+/*
+ * 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.opentelemetry.metrics.routepolicy;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.opentelemetry.metrics.AbstractOpenTelemetryTest;
+
+public abstract class AbstractOpenTelemetryRoutePolicyTest extends 
AbstractOpenTelemetryTest {
+
+    protected OpenTelemetryRoutePolicyFactory 
createOpenTelemetryRoutePolicyFactory() {
+        OpenTelemetryRoutePolicyFactory factory = new 
OpenTelemetryRoutePolicyFactory();
+        factory.getPolicyConfiguration().setExcludePattern(null);
+        return factory;
+    }
+
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        CamelContext context = super.createCamelContext();
+        OpenTelemetryRoutePolicyFactory factory = 
createOpenTelemetryRoutePolicyFactory();
+        factory.setCamelContext(context);
+        
factory.setMeter(otelExtension.getOpenTelemetry().getMeter("meterTest"));
+        context.addRoutePolicyFactory(factory);
+        context.addService(factory);
+        return context;
+    }
+}
diff --git 
a/components/camel-opentelemetry-metrics/src/test/java/org/apache/camel/opentelemetry/metrics/routepolicy/OpenTelemetryRoutePolicyExchangeStatusTest.java
 
b/components/camel-opentelemetry-metrics/src/test/java/org/apache/camel/opentelemetry/metrics/routepolicy/OpenTelemetryRoutePolicyExchangeStatusTest.java
new file mode 100644
index 000000000000..0f72df43ec8c
--- /dev/null
+++ 
b/components/camel-opentelemetry-metrics/src/test/java/org/apache/camel/opentelemetry/metrics/routepolicy/OpenTelemetryRoutePolicyExchangeStatusTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.opentelemetry.metrics.routepolicy;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.jupiter.api.Test;
+
+import static 
org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants.DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_FAILED_METER_NAME;
+import static 
org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants.DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_SUCCEEDED_METER_NAME;
+import static 
org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants.DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_TOTAL_METER_NAME;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class OpenTelemetryRoutePolicyExchangeStatusTest extends 
AbstractOpenTelemetryRoutePolicyTest {
+
+    @Test
+    public void testMetricsExchangeStatus() throws Exception {
+        int count = 10;
+        MockEndpoint mockEndpoint = getMockEndpoint("mock:result");
+        mockEndpoint.expectedMessageCount(count / 2);
+        for (int i = 0; i < count; i++) {
+            if (i % 2 == 0) {
+                template.sendBody("direct:completing", "Hello");
+            } else {
+                assertThrows(RuntimeException.class, () -> 
template.sendBody("direct:failing", "Hello"));
+            }
+        }
+        MockEndpoint.assertIsSatisfied(context);
+
+        // total meter
+        assertEquals(count / 2,
+                
getSingleLongPointData(DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_TOTAL_METER_NAME, 
"completing").getValue());
+        assertEquals(count / 2,
+                
getSingleLongPointData(DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_TOTAL_METER_NAME, 
"failing").getValue());
+
+        // succeeded meter
+        assertEquals(count / 2,
+                
getSingleLongPointData(DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_SUCCEEDED_METER_NAME,
 "completing").getValue());
+        
assertTrue(getAllPointDataForRouteId(DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_SUCCEEDED_METER_NAME,
 "failing").isEmpty());
+
+        // failed meter
+        
assertTrue(getAllPointDataForRouteId(DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_FAILED_METER_NAME,
 "completing").isEmpty());
+        assertEquals(count / 2,
+                
getSingleLongPointData(DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_FAILED_METER_NAME, 
"failing").getValue());
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:completing").routeId("completing")
+                        .to("mock:result");
+
+                from("direct:failing").routeId("failing")
+                        .throwException(RuntimeException.class, "Failing")
+                        .to("mock:result");
+            }
+        };
+    }
+}
diff --git 
a/components/camel-opentelemetry-metrics/src/test/java/org/apache/camel/opentelemetry/metrics/routepolicy/OpenTelemetryRoutePolicyExcludePatternTest.java
 
b/components/camel-opentelemetry-metrics/src/test/java/org/apache/camel/opentelemetry/metrics/routepolicy/OpenTelemetryRoutePolicyExcludePatternTest.java
new file mode 100644
index 000000000000..ffaac5fa7dcb
--- /dev/null
+++ 
b/components/camel-opentelemetry-metrics/src/test/java/org/apache/camel/opentelemetry/metrics/routepolicy/OpenTelemetryRoutePolicyExcludePatternTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.opentelemetry.metrics.routepolicy;
+
+import java.util.List;
+
+import io.opentelemetry.sdk.metrics.data.LongPointData;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.jupiter.api.Test;
+
+import static 
org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants.DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_SUCCEEDED_METER_NAME;
+import static 
org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants.DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_TOTAL_METER_NAME;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class OpenTelemetryRoutePolicyExcludePatternTest extends 
AbstractOpenTelemetryRoutePolicyTest {
+
+    @Override
+    public OpenTelemetryRoutePolicyFactory 
createOpenTelemetryRoutePolicyFactory() {
+        OpenTelemetryRoutePolicyFactory factory = new 
OpenTelemetryRoutePolicyFactory();
+        factory.getPolicyConfiguration().setRouteEnabled(true);
+        factory.getPolicyConfiguration().setExcludePattern("bar");
+        return factory;
+    }
+
+    // verify that metrics are collected for route foo but not for route bar
+    @Test
+    public void testMetricsRoutePolicy() throws Exception {
+        int count = 5;
+        getMockEndpoint("mock:foo").expectedMessageCount(count);
+        getMockEndpoint("mock:bar").expectedMessageCount(count);
+
+        for (int i = 0; i < count; i++) {
+            template.sendBody("direct:foo", "Hello World");
+        }
+
+        MockEndpoint.assertIsSatisfied(context);
+
+        for (String metricName : List.of(
+                DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_SUCCEEDED_METER_NAME,
+                DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_TOTAL_METER_NAME)) {
+
+            LongPointData lpd = getSingleLongPointData(metricName, "foo");
+            assertEquals(count, lpd.getValue());
+
+            assertTrue(getAllPointDataForRouteId(metricName, "bar").isEmpty());
+        }
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:foo").routeId("foo")
+                        .to("direct:bar")
+                        .to("mock:foo");
+
+                from("direct:bar").routeId("bar")
+                        .to("mock:bar");
+            }
+        };
+    }
+}
diff --git 
a/components/camel-opentelemetry-metrics/src/test/java/org/apache/camel/opentelemetry/metrics/routepolicy/OpenTelemetryRoutePolicyMulticastSubRouteTest.java
 
b/components/camel-opentelemetry-metrics/src/test/java/org/apache/camel/opentelemetry/metrics/routepolicy/OpenTelemetryRoutePolicyMulticastSubRouteTest.java
new file mode 100644
index 000000000000..a916d785d285
--- /dev/null
+++ 
b/components/camel-opentelemetry-metrics/src/test/java/org/apache/camel/opentelemetry/metrics/routepolicy/OpenTelemetryRoutePolicyMulticastSubRouteTest.java
@@ -0,0 +1,125 @@
+/*
+ * 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.opentelemetry.metrics.routepolicy;
+
+import java.util.List;
+
+import io.opentelemetry.sdk.metrics.data.HistogramPointData;
+import io.opentelemetry.sdk.metrics.data.LongPointData;
+import io.opentelemetry.sdk.metrics.data.PointData;
+import org.apache.camel.builder.RouteBuilder;
+import org.junit.jupiter.api.Test;
+
+import static 
org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants.DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_FAILED_METER_NAME;
+import static 
org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants.DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_FAILURES_HANDLED_METER_NAME;
+import static 
org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants.DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_SUCCEEDED_METER_NAME;
+import static 
org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants.DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_TOTAL_METER_NAME;
+import static 
org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants.DEFAULT_CAMEL_ROUTE_POLICY_METER_NAME;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+
+public class OpenTelemetryRoutePolicyMulticastSubRouteTest extends 
AbstractOpenTelemetryRoutePolicyTest {
+
+    // verify that metrics are recorded on the 'timer' for 'exchange done' 
events
+    @Test
+    public void testRouteTimerMeter() {
+        int count = 5;
+        for (int i = 0; i < count; i++) {
+            template.sendBody("direct:multicast", "Hello World");
+            template.send("direct:failure", e -> e.getMessage().setBody("Hello 
World"));
+        }
+        for (String route : List.of("foo", "bar", "multicast", 
"failureHandled", "failure")) {
+            PointData pd = 
getPointDataForRouteId(DEFAULT_CAMEL_ROUTE_POLICY_METER_NAME, route);
+            assertInstanceOf(HistogramPointData.class, pd);
+            HistogramPointData hpd = (HistogramPointData) pd;
+            assertEquals(count, hpd.getCount(), "count for route " + route);
+        }
+    }
+
+    // verify that 'succeeded' counts are recorded
+    @Test
+    public void testSucceededMeter() {
+        int count = 5;
+        for (int i = 0; i < count; i++) {
+            template.sendBody("direct:multicast", "Hello World");
+        }
+        for (String route : List.of("foo", "multicast", "bar", 
"failureHandled")) {
+            LongPointData lpd = 
getSingleLongPointData(DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_SUCCEEDED_METER_NAME,
 route);
+            assertEquals(count, lpd.getValue(), "count for route " + route);
+        }
+    }
+
+    // verify that 'handled failure' counts are recorded
+    @Test
+    public void testHandledFailuresMeter() {
+        int count = 5;
+        for (int i = 0; i < count; i++) {
+            template.sendBody("direct:multicast", "Hello World");
+        }
+        for (String route : List.of("multicast", "failureHandled")) {
+            LongPointData lpd = 
getSingleLongPointData(DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_FAILURES_HANDLED_METER_NAME,
 route);
+            assertEquals(count, lpd.getValue(), "count for route " + route);
+        }
+    }
+
+    // verify that 'failed' counts are recorded
+    @Test
+    public void testFailuresMeter() {
+        int count = 5;
+        for (int i = 0; i < count; i++) {
+            template.send("direct:failure", e -> e.getMessage().setBody("Hello 
World"));
+        }
+        LongPointData lpd = 
getSingleLongPointData(DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_FAILED_METER_NAME, 
"failure");
+        assertEquals(count, lpd.getValue(), "count for route failure");
+    }
+
+    // verify that 'total' counts are recorded
+    @Test
+    public void testTotalExchangesMeter() {
+        int count = 5;
+        for (int i = 0; i < count; i++) {
+            template.sendBody("direct:multicast", "Hello World");
+            template.send("direct:failure", e -> e.getMessage().setBody("Hello 
World"));
+        }
+        for (String route : List.of("foo", "bar", "multicast", 
"failureHandled", "failure")) {
+            LongPointData lpd = 
getSingleLongPointData(DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_TOTAL_METER_NAME, 
route);
+            assertEquals(count, lpd.getValue(), "count for route " + route);
+        }
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                onException(IllegalStateException.class)
+                        .handled(true);
+
+                from("direct:foo").routeId("foo").to("mock:foo");
+
+                from("direct:bar").routeId("bar").multicast().to("mock:bar1", 
"mock:bar2");
+
+                
from("direct:multicast").routeId("multicast").multicast().to("direct:foo", 
"direct:bar",
+                        "direct:failureHandled");
+
+                from("direct:failure").routeId("failure").throwException(new 
Exception("forced"));
+
+                
from("direct:failureHandled").routeId("failureHandled").throwException(new 
IllegalStateException("forced"));
+            }
+        };
+    }
+}
diff --git 
a/components/camel-opentelemetry-metrics/src/test/java/org/apache/camel/opentelemetry/metrics/routepolicy/OpenTelemetryRoutePolicySubRouteTest.java
 
b/components/camel-opentelemetry-metrics/src/test/java/org/apache/camel/opentelemetry/metrics/routepolicy/OpenTelemetryRoutePolicySubRouteTest.java
new file mode 100644
index 000000000000..348ad8c16d8e
--- /dev/null
+++ 
b/components/camel-opentelemetry-metrics/src/test/java/org/apache/camel/opentelemetry/metrics/routepolicy/OpenTelemetryRoutePolicySubRouteTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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.opentelemetry.metrics.routepolicy;
+
+import java.util.List;
+
+import io.opentelemetry.sdk.metrics.data.LongPointData;
+import io.opentelemetry.sdk.metrics.data.PointData;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.jupiter.api.Test;
+
+import static 
org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants.DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_SUCCEEDED_METER_NAME;
+import static 
org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants.DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_TOTAL_METER_NAME;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+public class OpenTelemetryRoutePolicySubRouteTest extends 
AbstractOpenTelemetryRoutePolicyTest {
+
+    @Test
+    public void testTotalMetric() throws Exception {
+        int count = 5;
+        getMockEndpoint("mock:foo").expectedMessageCount(count);
+        getMockEndpoint("mock:bar").expectedMessageCount(count);
+
+        for (int i = 0; i < count; i++) {
+            template.sendBody("direct:foo", "Hello World");
+        }
+        MockEndpoint.assertIsSatisfied(context);
+
+        for (String routeId : List.of("foo", "bar")) {
+            PointData pd = 
getPointDataForRouteId(DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_TOTAL_METER_NAME, 
routeId);
+            assertNotNull(pd, "No metric found for routeId " + routeId);
+            assertEquals(count, ((LongPointData) pd).getValue(), "Value for 
routeId " + routeId);
+        }
+    }
+
+    @Test
+    public void testSucceededMetric() throws Exception {
+        int count = 5;
+        for (int i = 0; i < count; i++) {
+            template.sendBody("direct:foo", "Hello World");
+        }
+        MockEndpoint.assertIsSatisfied(context);
+
+        for (String routeId : List.of("foo", "bar")) {
+            PointData pd = 
getPointDataForRouteId(DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_SUCCEEDED_METER_NAME,
 routeId);
+            assertNotNull(pd, "No metric found for routeId " + routeId);
+            assertEquals(count, ((LongPointData) pd).getValue(), "Value for 
routeId " + routeId);
+        }
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:foo").routeId("foo")
+                        .to("direct:bar")
+                        .to("mock:foo");
+
+                from("direct:bar").routeId("bar")
+                        .to("mock:bar");
+            }
+        };
+    }
+}
diff --git 
a/components/camel-opentelemetry-metrics/src/test/java/org/apache/camel/opentelemetry/metrics/routepolicy/OpenTelemetryRoutePolicyTest.java
 
b/components/camel-opentelemetry-metrics/src/test/java/org/apache/camel/opentelemetry/metrics/routepolicy/OpenTelemetryRoutePolicyTest.java
new file mode 100644
index 000000000000..708eed5e9471
--- /dev/null
+++ 
b/components/camel-opentelemetry-metrics/src/test/java/org/apache/camel/opentelemetry/metrics/routepolicy/OpenTelemetryRoutePolicyTest.java
@@ -0,0 +1,141 @@
+/*
+ * 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.opentelemetry.metrics.routepolicy;
+
+import io.opentelemetry.sdk.metrics.data.HistogramPointData;
+import io.opentelemetry.sdk.metrics.data.PointData;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.jupiter.api.Test;
+
+import static 
org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants.DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_FAILED_METER_NAME;
+import static 
org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants.DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_FAILURES_HANDLED_METER_NAME;
+import static 
org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants.DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_SUCCEEDED_METER_NAME;
+import static 
org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants.DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_TOTAL_METER_NAME;
+import static 
org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants.DEFAULT_CAMEL_ROUTE_POLICY_METER_NAME;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class OpenTelemetryRoutePolicyTest extends 
AbstractOpenTelemetryRoutePolicyTest {
+
+    private static final long DELAY_FOO = 20;
+    private static final long DELAY_BAR = 50;
+    private static final long TOLERANCE = 20L;
+
+    @Override
+    public OpenTelemetryRoutePolicyFactory 
createOpenTelemetryRoutePolicyFactory() {
+        OpenTelemetryRoutePolicyFactory factory = new 
OpenTelemetryRoutePolicyFactory();
+        factory.getPolicyConfiguration().setExcludePattern(null);
+        factory.getPolicyConfiguration().setAdditionalCounters(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);
+
+        PointData pd = 
getPointDataForRouteId(DEFAULT_CAMEL_ROUTE_POLICY_METER_NAME, "foo");
+        verifyHistogramMetric(pd, DELAY_FOO, count / 2);
+
+        pd = getPointDataForRouteId(DEFAULT_CAMEL_ROUTE_POLICY_METER_NAME, 
"bar");
+        verifyHistogramMetric(pd, DELAY_BAR, count / 2);
+    }
+
+    // verify no 'succeeded' meter name since 'additionalCounters' is false
+    @Test
+    public void testNoSucceededCounter() throws Exception {
+        MockEndpoint mockEndpoint = getMockEndpoint("mock:result");
+        mockEndpoint.expectedMessageCount(1);
+        template.sendBody("direct:foo", "Hello");
+
+        MockEndpoint.assertIsSatisfied(context);
+        
assertTrue(getMetricData(DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_SUCCEEDED_METER_NAME).isEmpty());
+    }
+
+    // verify no 'total' meter name since 'additionalCounters' is false
+    @Test
+    public void testNoTotalCounter() throws Exception {
+        MockEndpoint mockEndpoint = getMockEndpoint("mock:result");
+        mockEndpoint.expectedMessageCount(1);
+        template.sendBody("direct:foo", "Hello");
+
+        MockEndpoint.assertIsSatisfied(context);
+        
assertTrue(getMetricData(DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_TOTAL_METER_NAME).isEmpty());
+    }
+
+    // verify no 'failed' meter name since 'additionalCounters' is false
+    @Test
+    public void testNoFailuresMeter() {
+        int count = 3;
+        for (int i = 0; i < count; i++) {
+            template.send("direct:failure", e -> e.getMessage().setBody("Hello 
World"));
+        }
+        
assertTrue(getMetricData(DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_FAILED_METER_NAME).isEmpty());
+    }
+
+    // verify no 'handled failures' meter name since 'additionalCounters' is 
false
+    @Test
+    public void testNoHandledFailuresMeter() {
+        int count = 3;
+        for (int i = 0; i < count; i++) {
+            template.send("direct:failureHandled", e -> 
e.getMessage().setBody("Hello World"));
+        }
+        
assertTrue(getMetricData(DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_FAILURES_HANDLED_METER_NAME).isEmpty());
+    }
+
+    private void verifyHistogramMetric(PointData pd, long delay, int msgCount) 
{
+        assertTrue(pd instanceof HistogramPointData);
+        HistogramPointData hpd = (HistogramPointData) pd;
+        assertTrue(hpd.getMax() < delay + TOLERANCE, "max value");
+        assertTrue(hpd.getMin() >= delay, "min value");
+        assertEquals(msgCount, hpd.getCount(), "count");
+        assertTrue(hpd.getSum() >= msgCount * delay, "sum");
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                onException(IllegalStateException.class)
+                        .handled(true);
+
+                from("direct:foo").routeId("foo")
+                        .delay(DELAY_FOO)
+                        .to("mock:result");
+
+                from("direct:bar").routeId("bar")
+                        .delay(DELAY_BAR)
+                        .to("mock:result");
+
+                from("direct:failure").routeId("failure").throwException(new 
Exception("forced"));
+
+                
from("direct:failureHandled").routeId("failureHandled").throwException(new 
IllegalStateException("forced"));
+            }
+        };
+    }
+}
diff --git 
a/components/camel-opentelemetry-metrics/src/test/java/org/apache/camel/opentelemetry/metrics/routepolicy/OpenTelemetrySharedRoutePolicyTest.java
 
b/components/camel-opentelemetry-metrics/src/test/java/org/apache/camel/opentelemetry/metrics/routepolicy/OpenTelemetrySharedRoutePolicyTest.java
new file mode 100644
index 000000000000..71475d985da3
--- /dev/null
+++ 
b/components/camel-opentelemetry-metrics/src/test/java/org/apache/camel/opentelemetry/metrics/routepolicy/OpenTelemetrySharedRoutePolicyTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.opentelemetry.metrics.routepolicy;
+
+import io.opentelemetry.api.metrics.Meter;
+import io.opentelemetry.sdk.metrics.data.LongPointData;
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.builder.RouteBuilder;
+import org.junit.jupiter.api.Test;
+
+import static 
org.apache.camel.opentelemetry.metrics.OpenTelemetryConstants.DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_TOTAL_METER_NAME;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class OpenTelemetrySharedRoutePolicyTest extends 
AbstractOpenTelemetryRoutePolicyTest {
+
+    protected Meter meter = 
otelExtension.getOpenTelemetry().getMeter("meterTest");
+    // use a single shared instance of the policy
+    protected OpenTelemetryRoutePolicy singletonPolicy = new 
OpenTelemetryRoutePolicy(null);
+
+    @BindToRegistry("meter")
+    public Meter addRegistry() {
+        return meter;
+    }
+
+    @Test
+    public void testSharedPolicy() throws Exception {
+        template.request("direct:foo", x -> {
+        });
+        template.request("direct:bar", x -> {
+        });
+
+        LongPointData lpd = 
getSingleLongPointData(DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_TOTAL_METER_NAME, 
"foo");
+        assertEquals(2L, lpd.getValue());
+
+        lpd = 
getSingleLongPointData(DEFAULT_CAMEL_ROUTE_POLICY_EXCHANGES_TOTAL_METER_NAME, 
"bar");
+        assertEquals(2L, lpd.getValue());
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("direct:foo").routeId("foo").routePolicy(singletonPolicy)
+                        .to("mock:result");
+
+                from("direct:bar").routeId("bar").routePolicy(singletonPolicy)
+                        .to("mock:result");
+            }
+        };
+    }
+}
diff --git 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/OpenTelemetryEndpointBuilderFactory.java
 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/OpenTelemetryEndpointBuilderFactory.java
index 7e02f0b5d10e..23d96aaf5c13 100644
--- 
a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/OpenTelemetryEndpointBuilderFactory.java
+++ 
b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/OpenTelemetryEndpointBuilderFactory.java
@@ -324,7 +324,7 @@ public interface OpenTelemetryEndpointBuilderFactory {
          * Override timer action in URI.
          * 
          * The option is a: {@code
-         * org.apache.camel.opentelemetry2.component.OpenTelemetryTimerAction}
+         * org.apache.camel.opentelemetry.metrics.OpenTelemetryTimerAction}
          * type.
          * 
          * Group: producer

Reply via email to