You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by "fernandobalieiro (via GitHub)" <gi...@apache.org> on 2026/06/08 16:10:27 UTC

[PR] fix(camel-micrometer): Ensure Prometheus Event Notification when RouteId is set [camel]

fernandobalieiro opened a new pull request, #23864:
URL: https://github.com/apache/camel/pull/23864

   # Description
   
   The goal of this PR is to ensure that the Prometheus Event Notification happens when a RouteId is configured in the destination Route of a message sent through a ProducerTemplate.
   
   ## Current Scenario
   
   When a project is configured to use `quarkus-micrometer-registry-prometheus` and a message is sent to a `SEDA` endpoint through `ProducerTemplate`, the following warning appears in the logs:
   
   ```
   2026-06-08 14:32:45,577 WARN  [org.apache.camel.support.EventHelper] (Camel (camel-6) thread #21 - seda://producer) Error notifying event C99DFEF70A95789-0000000000000001 exchange completed took: 3ms. This exception will be ignored.: java.lang.IllegalArgumentException: Prometheus requires that all meters with the same name have the same set of tag keys. There is already an existing meter named 'camel_exchange_event_notifier_seconds' containing tag keys [camelContext, endpointName, eventType, failed, kind]. The meter you are attempting to register has keys [camelContext, endpointName, eventType, failed, kind, routeId].
           at io.micrometer.prometheus.PrometheusMeterRegistry.lambda$throwExceptionOnRegistrationFailure$19(PrometheusMeterRegistry.java:619)
           at io.micrometer.core.instrument.MeterRegistry.meterRegistrationFailed(MeterRegistry.java:1291)
           at io.micrometer.prometheus.PrometheusMeterRegistry.lambda$applyToCollector$18(PrometheusMeterRegistry.java:593)
           at java.base/java.util.concurrent.ConcurrentHashMap.compute(ConcurrentHashMap.java:1956)
           at io.micrometer.prometheus.PrometheusMeterRegistry.applyToCollector(PrometheusMeterRegistry.java:579)
           at io.micrometer.prometheus.PrometheusMeterRegistry.newTimer(PrometheusMeterRegistry.java:328)
           at io.micrometer.core.instrument.MeterRegistry.lambda$timer$6(MeterRegistry.java:379)
           at io.micrometer.core.instrument.MeterRegistry.getOrCreateMeter(MeterRegistry.java:725)
           at io.micrometer.core.instrument.MeterRegistry.registerMeterIfNecessary(MeterRegistry.java:652)
           at io.micrometer.core.instrument.MeterRegistry.timer(MeterRegistry.java:377)
           at io.micrometer.core.instrument.Timer$Builder.register(Timer.java:471)
           at io.micrometer.core.instrument.Timer$Builder.register(Timer.java:465)
           at io.micrometer.core.instrument.composite.CompositeTimer.registerNewMeter(CompositeTimer.java:205)
           at io.micrometer.core.instrument.composite.CompositeTimer.registerNewMeter(CompositeTimer.java:35)
           at io.micrometer.core.instrument.composite.AbstractCompositeMeter.add(AbstractCompositeMeter.java:67)
           at java.base/java.lang.Iterable.forEach(Iterable.java:75)
           at java.base/java.util.Collections$SetFromMap.forEach(Collections.java:6060)
           at io.micrometer.core.instrument.composite.CompositeMeterRegistry.lambda$new$0(CompositeMeterRegistry.java:67)
           at io.micrometer.core.instrument.composite.CompositeMeterRegistry.lock(CompositeMeterRegistry.java:189)
           at io.micrometer.core.instrument.composite.CompositeMeterRegistry.lambda$new$1(CompositeMeterRegistry.java:67)
           at io.micrometer.core.instrument.MeterRegistry.getOrCreateMeter(MeterRegistry.java:735)
           at io.micrometer.core.instrument.MeterRegistry.registerMeterIfNecessary(MeterRegistry.java:652)
           at io.micrometer.core.instrument.MeterRegistry.timer(MeterRegistry.java:377)
           at io.micrometer.core.instrument.MeterRegistry.timer(MeterRegistry.java:534)
           at org.apache.camel.component.micrometer.eventnotifier.MicrometerExchangeEventNotifier.handleDoneEvent(MicrometerExchangeEventNotifier.java:204)
           at org.apache.camel.component.micrometer.eventnotifier.MicrometerExchangeEventNotifier.notify(MicrometerExchangeEventNotifier.java:179)
           at org.apache.camel.support.EventHelper.doNotifyEvent(EventHelper.java:1575)
           at org.apache.camel.support.EventHelper.notifyExchangeDone(EventHelper.java:783)
           at org.apache.camel.impl.engine.DefaultUnitOfWork.done(DefaultUnitOfWork.java:280)
           at org.apache.camel.support.UnitOfWorkHelper.doneUow(UnitOfWorkHelper.java:53)
           at org.apache.camel.impl.engine.CamelInternalProcessor$UnitOfWorkProcessorAdvice.after(CamelInternalProcessor.java:1178)
           at org.apache.camel.impl.engine.CamelInternalProcessor$UnitOfWorkProcessorAdvice.after(CamelInternalProcessor.java:1115)
           at org.apache.camel.impl.engine.AdviceIterator.runAfterTask(AdviceIterator.java:45)
           at org.apache.camel.impl.engine.AdviceIterator.runAfterTasks(AdviceIterator.java:39)
           at org.apache.camel.impl.engine.CamelInternalProcessor$AsyncAfterTask.done(CamelInternalProcessor.java:263)
           at org.apache.camel.AsyncCallback.run(AsyncCallback.java:44)
           at org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.doRun(DefaultReactiveExecutor.java:202)
           at org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.executeReactiveWork(DefaultReactiveExecutor.java:192)
           at org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.tryExecuteReactiveWork(DefaultReactiveExecutor.java:169)
           at org.apache.camel.impl.engine.DefaultReactiveExecutor$Worker.schedule(DefaultReactiveExecutor.java:143)
           at org.apache.camel.impl.engine.DefaultReactiveExecutor.scheduleMain(DefaultReactiveExecutor.java:59)
           at org.apache.camel.processor.Pipeline.process(Pipeline.java:162)
           at org.apache.camel.impl.engine.CamelInternalProcessor.processNonTransacted(CamelInternalProcessor.java:385)
           at org.apache.camel.impl.engine.CamelInternalProcessor.process(CamelInternalProcessor.java:361)
           at org.apache.camel.component.seda.SedaConsumer.sendToConsumers(SedaConsumer.java:351)
           at org.apache.camel.component.seda.SedaConsumer.processPolledExchange(SedaConsumer.java:267)
           at org.apache.camel.component.seda.SedaConsumer.doRun(SedaConsumer.java:210)
           at org.apache.camel.component.seda.SedaConsumer.run(SedaConsumer.java:146)
           at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1090)
           at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:614)
           at java.base/java.lang.Thread.run(Thread.java:1474)
   ```
   
   The issue seems to be caused by recent changes in the Micrometer framework, as reported in the Quarkus 3.35 Release Notes:
   https://github.com/quarkusio/quarkus/wiki/Migration-Guide-3.35#micrometer-prometheus-registry
   
   
   A reproducer can be found in [this repository](https://github.com/fernandobalieiro/camel-event-notifier-reproducer). The message will appear by either running the project in Quarkus dev mode and invoking http://localhost:8080/hello endpoint or by executing the `ProducerRouteIT` test.
   
   1. Clone the repository:
   ```bash
   git clone https://github.com/fernandobalieiro/camel-event-notifier-reproducer
   ```
   2. Start the server:
   ```bash
   ./mvnw quarkus:dev
   ```
   3. Invoke the endpoint:
   ```bash
   curl http://localhost:8080/hello
   ```
   Or execute the integration tests directly:
   
   ```bash
    ./mvnw verify -DskipITs=false
   ```
   
   The warning message containing the stack trace should appear in the logs.
   
   ## Expected Scenario
   
   The event should be properly registered and no warning message should be visible in the logs.
   
   ## Consideration
   
   I'm aware that this is maybe not the best approach, as the solution requires iterating over all routes to retrieve the target routeId, so I'm open to suggestions.
   
   
   # Target
   
   - [X] I checked that the commit is targeting the correct branch (Camel 4 uses the `main` branch)
   
   # Tracking
   - [X] If this is a large change, bug fix, or code improvement, I checked there is a [JIRA issue](https://issues.apache.org/jira/browse/CAMEL) filed for the change (usually before you start working on it).
   
   # Apache Camel coding standards and style
   
   - [X] I checked that each commit in the pull request has a meaningful subject line and body.
   
   - [X] I have run `mvn clean install -DskipTests` locally from root folder and I have committed all auto-generated changes.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-23719: camel-micrometer - when ProducerTemplate sends to a SEDA endpoint, Exchange.getFromRouteId() returns null [camel]

Posted by "fernandobalieiro (via GitHub)" <gi...@apache.org>.
fernandobalieiro commented on PR #23864:
URL: https://github.com/apache/camel/pull/23864#issuecomment-4831668736

   Hello @davsclaus and @gnodet!
   I saw that tag 4.21 was created. Do you have an ETA when will this be released?
   Thanks in advance.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-23719: camel-micrometer - when ProducerTemplate sends to a SEDA endpoint, Exchange.getFromRouteId() returns null [camel]

Posted by "fernandobalieiro (via GitHub)" <gi...@apache.org>.
fernandobalieiro commented on code in PR #23864:
URL: https://github.com/apache/camel/pull/23864#discussion_r3379316099


##########
components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/eventnotifier/MicrometerExchangeEventNotifierNamingStrategy.java:
##########
@@ -73,22 +75,29 @@ default Tags getTags(ExchangeEvent event, Endpoint endpoint) {
             }
         }
         String routeId = event.getExchange().getFromRouteId();
-        if (routeId != null) {
-            return Tags.of(
-                    CAMEL_CONTEXT_TAG, event.getExchange().getContext().getName(),
-                    KIND, KIND_EXCHANGE,
-                    EVENT_TYPE_TAG, event.getClass().getSimpleName(),
-                    ROUTE_ID_TAG, routeId,
-                    ENDPOINT_NAME, uri,
-                    FAILED_TAG, Boolean.toString(event.getExchange().isFailed()));
-        } else {
-            return Tags.of(
-                    CAMEL_CONTEXT_TAG, event.getExchange().getContext().getName(),
-                    KIND, KIND_EXCHANGE,
-                    EVENT_TYPE_TAG, event.getClass().getSimpleName(),
-                    ENDPOINT_NAME, uri,
-                    FAILED_TAG, Boolean.toString(event.getExchange().isFailed()));
+        if (routeId == null) {
+            final String finalUri = uri;
+            final Optional<Route> eventRoute = event.getExchange().getContext().getRoutes().stream()
+                    .filter(route -> finalUri.equals(route.getEndpoint().getEndpointBaseUri())).findFirst();
+
+            if (eventRoute.isEmpty()) {
+                return Tags.of(
+                        CAMEL_CONTEXT_TAG, event.getExchange().getContext().getName(),
+                        KIND, KIND_EXCHANGE,
+                        EVENT_TYPE_TAG, event.getClass().getSimpleName(),
+                        ENDPOINT_NAME, uri,
+                        FAILED_TAG, Boolean.toString(event.getExchange().isFailed()));
+            }
+

Review Comment:
   Done. Is that according the expectation?
   Thanks.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-23719: camel-micrometer - when ProducerTemplate sends to a SEDA endpoint, Exchange.getFromRouteId() returns null [camel]

Posted by "fernandobalieiro (via GitHub)" <gi...@apache.org>.
fernandobalieiro commented on PR #23864:
URL: https://github.com/apache/camel/pull/23864#issuecomment-4659064531

   > Probably the issue is not the tag settings but registering or not the meter. We had a similar issue with `app.info` - have a look at that to get inspiration for the fix: #17526
   
   Hello @squakez, makes sense to me, I just pushed the requested changes. Can you review and let me know if something else is needed?


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-23719: camel-micrometer - when ProducerTemplate sends to a SEDA endpoint, Exchange.getFromRouteId() returns null [camel]

Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on PR #23864:
URL: https://github.com/apache/camel/pull/23864#issuecomment-4668276650

   <!-- ci-tested-modules -->
   :test_tube: **CI tested the following changed modules:**
   
   - `components/camel-micrometer`
   - `docs`
   
   :white_check_mark: **POM dependency changes: targeted tests included**
   
   <details><summary>Modules affected by dependency changes (2)</summary>
   
   - `:camel-micrometer`
   - `:docs`
   
   </details>
   
   <details><summary>All tested modules (12 modules)</summary>
   
   - Camel :: Docs
   - Camel :: JBang :: MCP
   - Camel :: JBang :: Plugin :: Route Parser
   - Camel :: JBang :: Plugin :: TUI
   - Camel :: JBang :: Plugin :: Validate
   - Camel :: Launcher :: Container
   - Camel :: Micrometer
   - Camel :: Micrometer :: Prometheus
   - Camel :: Observability Services
   - Camel :: Resilience4j :: Micrometer
   - Camel :: YAML DSL :: Validator
   - Camel :: YAML DSL :: Validator Maven Plugin
   
   </details>
   
   ---
   :gear: [View full build and test results](https://github.com/apache/camel/actions/runs/27256663253)


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-23719: camel-micrometer - when ProducerTemplate sends to a SEDA endpoint, Exchange.getFromRouteId() returns null [camel]

Posted by "fernandobalieiro (via GitHub)" <gi...@apache.org>.
fernandobalieiro commented on PR #23864:
URL: https://github.com/apache/camel/pull/23864#issuecomment-4669767055

   > Thanks for the help
   
   No problem at all, thank you for the quick review and merge.
   Regards.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-23719: camel-micrometer - when ProducerTemplate sends to a SEDA endpoint, Exchange.getFromRouteId() returns null [camel]

Posted by "fernandobalieiro (via GitHub)" <gi...@apache.org>.
fernandobalieiro commented on code in PR #23864:
URL: https://github.com/apache/camel/pull/23864#discussion_r3379161444


##########
components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/eventnotifier/MicrometerExchangeEventNotifierNamingStrategy.java:
##########
@@ -73,22 +75,29 @@ default Tags getTags(ExchangeEvent event, Endpoint endpoint) {
             }
         }
         String routeId = event.getExchange().getFromRouteId();
-        if (routeId != null) {
-            return Tags.of(
-                    CAMEL_CONTEXT_TAG, event.getExchange().getContext().getName(),
-                    KIND, KIND_EXCHANGE,
-                    EVENT_TYPE_TAG, event.getClass().getSimpleName(),
-                    ROUTE_ID_TAG, routeId,
-                    ENDPOINT_NAME, uri,
-                    FAILED_TAG, Boolean.toString(event.getExchange().isFailed()));
-        } else {
-            return Tags.of(
-                    CAMEL_CONTEXT_TAG, event.getExchange().getContext().getName(),
-                    KIND, KIND_EXCHANGE,
-                    EVENT_TYPE_TAG, event.getClass().getSimpleName(),
-                    ENDPOINT_NAME, uri,
-                    FAILED_TAG, Boolean.toString(event.getExchange().isFailed()));
+        if (routeId == null) {
+            final String finalUri = uri;
+            final Optional<Route> eventRoute = event.getExchange().getContext().getRoutes().stream()
+                    .filter(route -> finalUri.equals(route.getEndpoint().getEndpointBaseUri())).findFirst();
+
+            if (eventRoute.isEmpty()) {
+                return Tags.of(
+                        CAMEL_CONTEXT_TAG, event.getExchange().getContext().getName(),
+                        KIND, KIND_EXCHANGE,
+                        EVENT_TYPE_TAG, event.getClass().getSimpleName(),
+                        ENDPOINT_NAME, uri,
+                        FAILED_TAG, Boolean.toString(event.getExchange().isFailed()));
+            }
+

Review Comment:
   Thanks for the quick review @davsclaus!
   
   I have created [CAMEL-23719](https://issues.apache.org/jira/browse/CAMEL-23719), updated the PR title and I'll submit the changes.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-23719: camel-micrometer - when ProducerTemplate sends to a SEDA endpoint, Exchange.getFromRouteId() returns null [camel]

Posted by "github-actions[bot] (via GitHub)" <gi...@apache.org>.
github-actions[bot] commented on PR #23864:
URL: https://github.com/apache/camel/pull/23864#issuecomment-4659757996

   :star2: Thank you for your contribution to the Apache Camel project! :star2:
     :robot: CI automation will test this PR automatically.
   
     :camel: Apache Camel Committers, please review the following items:
   
     * First-time contributors **require MANUAL approval** for the GitHub Actions to run
     * You can use the command `/component-test (camel-)component-name1 (camel-)component-name2..` to request a test from the test bot although they are normally detected and executed by CI.
     * You can label PRs using `skip-tests` and `test-dependents` to fine-tune the checks executed by this PR.
     * Build and test logs are available in the summary page. **Only** [Apache Camel committers](https://camel.apache.org/community/team/#committers) have access to the summary.
     
     :warning: Be careful when sharing logs. Review their contents before sharing them publicly.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] fix(camel-micrometer): Ensure Prometheus Event Notification when RouteId is set [camel]

Posted by "davsclaus (via GitHub)" <gi...@apache.org>.
davsclaus commented on code in PR #23864:
URL: https://github.com/apache/camel/pull/23864#discussion_r3375125713


##########
components/camel-micrometer/src/main/java/org/apache/camel/component/micrometer/eventnotifier/MicrometerExchangeEventNotifierNamingStrategy.java:
##########
@@ -73,22 +75,29 @@ default Tags getTags(ExchangeEvent event, Endpoint endpoint) {
             }
         }
         String routeId = event.getExchange().getFromRouteId();
-        if (routeId != null) {
-            return Tags.of(
-                    CAMEL_CONTEXT_TAG, event.getExchange().getContext().getName(),
-                    KIND, KIND_EXCHANGE,
-                    EVENT_TYPE_TAG, event.getClass().getSimpleName(),
-                    ROUTE_ID_TAG, routeId,
-                    ENDPOINT_NAME, uri,
-                    FAILED_TAG, Boolean.toString(event.getExchange().isFailed()));
-        } else {
-            return Tags.of(
-                    CAMEL_CONTEXT_TAG, event.getExchange().getContext().getName(),
-                    KIND, KIND_EXCHANGE,
-                    EVENT_TYPE_TAG, event.getClass().getSimpleName(),
-                    ENDPOINT_NAME, uri,
-                    FAILED_TAG, Boolean.toString(event.getExchange().isFailed()));
+        if (routeId == null) {
+            final String finalUri = uri;
+            final Optional<Route> eventRoute = event.getExchange().getContext().getRoutes().stream()
+                    .filter(route -> finalUri.equals(route.getEndpoint().getEndpointBaseUri())).findFirst();
+
+            if (eventRoute.isEmpty()) {
+                return Tags.of(
+                        CAMEL_CONTEXT_TAG, event.getExchange().getContext().getName(),
+                        KIND, KIND_EXCHANGE,
+                        EVENT_TYPE_TAG, event.getClass().getSimpleName(),
+                        ENDPOINT_NAME, uri,
+                        FAILED_TAG, Boolean.toString(event.getExchange().isFailed()));
+            }
+

Review Comment:
   This route lookup by endpoint URI is problematic:
   
   1. It finds the *destination* route, but `fromRouteId` should be the *originating* route
   2. Multiple routes can share the same `from` endpoint — `findFirst()` is arbitrary
   3. Iterating all routes on every exchange event doesn't scale
   
   The simpler fix is to always include the `routeId` tag with an empty string when null:
   
   ```suggestion
           if (routeId == null) {
               routeId = "";
           }
   ```
   
   This ensures Prometheus always sees the same tag keys, which is the actual root cause of the error.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-23719: camel-micrometer - when ProducerTemplate sends to a SEDA endpoint, Exchange.getFromRouteId() returns null [camel]

Posted by "davsclaus (via GitHub)" <gi...@apache.org>.
davsclaus commented on PR #23864:
URL: https://github.com/apache/camel/pull/23864#issuecomment-4668904982

   Thanks for the help


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] CAMEL-23719: camel-micrometer - when ProducerTemplate sends to a SEDA endpoint, Exchange.getFromRouteId() returns null [camel]

Posted by "davsclaus (via GitHub)" <gi...@apache.org>.
davsclaus merged PR #23864:
URL: https://github.com/apache/camel/pull/23864


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@camel.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org