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 7b5d129971f0 CAMEL-25716: camel-management - remote exchange counters 
per route, for camel get processor --remote (#27996)
7b5d129971f0 is described below

commit 7b5d129971f07a59d90e4498fc2911dca8e7d442
Author: Claus Ibsen <[email protected]>
AuthorDate: Sat Oct 17 09:07:49 2026 +0200

    CAMEL-25716: camel-management - remote exchange counters per route, for 
camel get processor --remote (#27996)
    
    The routes count the exchanges that came from a remote endpoint, as the 
CamelContext does (CAMEL-20879): ManagedRouteMBean has RemoteExchangesTotal, 
Completed, Failed and Inflight. A route with a remote consumer uses its own 
counters; a route with an internal consumer counts the exchanges that came from 
a remote endpoint. The route dev console has the remote counters, so camel get 
processor --remote shows remote/total pairs; camel get route and camel top 
route have --remote, and the J [...]
    
    Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
---
 .../apache/camel/catalog/dev-consoles-openapi.json |  15 ++
 .../apache/camel/catalog/dev-consoles/route.json   |  15 ++
 .../org/apache/camel/dev-console/route.json        |  15 ++
 .../apache/camel/impl/console/RouteDevConsole.java |   4 +
 .../management/mbean/ManagedCamelContextMBean.java |   2 +-
 .../api/management/mbean/ManagedRouteMBean.java    |  32 ++++
 .../management/mbean/ManagedCamelContext.java      |   2 +-
 .../camel/management/mbean/ManagedRoute.java       |  72 +++++++++
 .../ManagedRouteRemoteExchangesTest.java           | 161 +++++++++++++++++++++
 .../modules/ROOT/pages/camel-jbang-managing.adoc   |   6 +
 .../jbang-commands/camel-jbang-get-route.adoc      |   1 +
 .../jbang-commands/camel-jbang-top-route.adoc      |   1 +
 .../META-INF/camel-jbang-commands-metadata.json    |   4 +-
 .../core/commands/process/CamelContextStatus.java  |   4 +
 .../commands/process/CamelProcessorStatus.java     |   4 +
 .../core/commands/process/CamelRouteStatus.java    |  27 ++++
 .../commands/process/CamelContextStatusTest.java   |  29 ++++
 .../commands/process/CamelProcessorStatusTest.java |  17 +++
 .../commands/process/CamelRouteStatusTest.java     |  25 ++++
 19 files changed, 432 insertions(+), 4 deletions(-)

diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles-openapi.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles-openapi.json
index f0ac82aaa95a..af65e7bcd600 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles-openapi.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles-openapi.json
@@ -5891,6 +5891,18 @@
                                                                                
                                                "type": "integer",
                                                                                
                                                "description": "Number of 
inflight exchanges"
                                                                                
                                        },
+                                                                               
                                        "remoteExchangesTotal": {
+                                                                               
                                                "type": "integer",
+                                                                               
                                                "description": "Total number of 
exchanges that came from a remote endpoint"
+                                                                               
                                        },
+                                                                               
                                        "remoteExchangesFailed": {
+                                                                               
                                                "type": "integer",
+                                                                               
                                                "description": "Number of 
failed exchanges that came from a remote endpoint"
+                                                                               
                                        },
+                                                                               
                                        "remoteExchangesInflight": {
+                                                                               
                                                "type": "integer",
+                                                                               
                                                "description": "Number of 
inflight exchanges that came from a remote endpoint"
+                                                                               
                                        },
                                                                                
                                        "meanProcessingTime": {
                                                                                
                                                "type": "integer",
                                                                                
                                                "description": "Mean processing 
time in milliseconds"
@@ -5945,6 +5957,9 @@
                                                                                
                                        "exchangesTotal",
                                                                                
                                        "exchangesFailed",
                                                                                
                                        "exchangesInflight",
+                                                                               
                                        "remoteExchangesTotal",
+                                                                               
                                        "remoteExchangesFailed",
+                                                                               
                                        "remoteExchangesInflight",
                                                                                
                                        "meanProcessingTime",
                                                                                
                                        "maxProcessingTime",
                                                                                
                                        "minProcessingTime"
diff --git 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles/route.json
 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles/route.json
index c95b21423df2..1bb1f2388b79 100644
--- 
a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles/route.json
+++ 
b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles/route.json
@@ -212,6 +212,18 @@
                   "type": "integer",
                   "description": "Number of inflight exchanges"
                 },
+                "remoteExchangesTotal": {
+                  "type": "integer",
+                  "description": "Total number of exchanges that came from a 
remote endpoint"
+                },
+                "remoteExchangesFailed": {
+                  "type": "integer",
+                  "description": "Number of failed exchanges that came from a 
remote endpoint"
+                },
+                "remoteExchangesInflight": {
+                  "type": "integer",
+                  "description": "Number of inflight exchanges that came from 
a remote endpoint"
+                },
                 "meanProcessingTime": {
                   "type": "integer",
                   "description": "Mean processing time in milliseconds"
@@ -266,6 +278,9 @@
                 "exchangesTotal",
                 "exchangesFailed",
                 "exchangesInflight",
+                "remoteExchangesTotal",
+                "remoteExchangesFailed",
+                "remoteExchangesInflight",
                 "meanProcessingTime",
                 "maxProcessingTime",
                 "minProcessingTime"
diff --git 
a/core/camel-console/src/generated/resources/META-INF/org/apache/camel/dev-console/route.json
 
b/core/camel-console/src/generated/resources/META-INF/org/apache/camel/dev-console/route.json
index c95b21423df2..1bb1f2388b79 100644
--- 
a/core/camel-console/src/generated/resources/META-INF/org/apache/camel/dev-console/route.json
+++ 
b/core/camel-console/src/generated/resources/META-INF/org/apache/camel/dev-console/route.json
@@ -212,6 +212,18 @@
                   "type": "integer",
                   "description": "Number of inflight exchanges"
                 },
+                "remoteExchangesTotal": {
+                  "type": "integer",
+                  "description": "Total number of exchanges that came from a 
remote endpoint"
+                },
+                "remoteExchangesFailed": {
+                  "type": "integer",
+                  "description": "Number of failed exchanges that came from a 
remote endpoint"
+                },
+                "remoteExchangesInflight": {
+                  "type": "integer",
+                  "description": "Number of inflight exchanges that came from 
a remote endpoint"
+                },
                 "meanProcessingTime": {
                   "type": "integer",
                   "description": "Mean processing time in milliseconds"
@@ -266,6 +278,9 @@
                 "exchangesTotal",
                 "exchangesFailed",
                 "exchangesInflight",
+                "remoteExchangesTotal",
+                "remoteExchangesFailed",
+                "remoteExchangesInflight",
                 "meanProcessingTime",
                 "maxProcessingTime",
                 "minProcessingTime"
diff --git 
a/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteDevConsole.java
 
b/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteDevConsole.java
index 50fba785f6f9..1bcd7d302a5f 100644
--- 
a/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteDevConsole.java
+++ 
b/core/camel-console/src/main/java/org/apache/camel/impl/console/RouteDevConsole.java
@@ -67,6 +67,9 @@ public class RouteDevConsole extends AbstractDevConsole {
             @Metadata(description = "Total number of exchanges") long 
exchangesTotal,
             @Metadata(description = "Number of failed exchanges") long 
exchangesFailed,
             @Metadata(description = "Number of inflight exchanges") long 
exchangesInflight,
+            @Metadata(description = "Total number of exchanges that came from 
a remote endpoint") long remoteExchangesTotal,
+            @Metadata(description = "Number of failed exchanges that came from 
a remote endpoint") long remoteExchangesFailed,
+            @Metadata(description = "Number of inflight exchanges that came 
from a remote endpoint") long remoteExchangesInflight,
             @Metadata(description = "Mean processing time in milliseconds") 
long meanProcessingTime,
             @Metadata(description = "Max processing time in milliseconds") 
long maxProcessingTime,
             @Metadata(description = "Min processing time in milliseconds") 
long minProcessingTime,
@@ -544,6 +547,7 @@ public class RouteDevConsole extends AbstractDevConsole {
                 coverage, hasLoad ? load1 : null, hasLoad ? load5 : null, 
hasLoad ? load15 : null,
                 thp.isEmpty() ? null : thp,
                 mrb.getIdleSince(), mrb.getExchangesTotal(), 
mrb.getExchangesFailed(), mrb.getExchangesInflight(),
+                mrb.getRemoteExchangesTotal(), mrb.getRemoteExchangesFailed(), 
mrb.getRemoteExchangesInflight(),
                 mrb.getMeanProcessingTime(), mrb.getMaxProcessingTime(), 
mrb.getMinProcessingTime(),
                 p50, p95, p99, lastProcessingTime, deltaProcessingTime,
                 lastCreated, lastCompleted, lastFailureHandled, lastFailed);
diff --git 
a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedCamelContextMBean.java
 
b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedCamelContextMBean.java
index 9a27de8483f7..8b2640d55ec5 100644
--- 
a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedCamelContextMBean.java
+++ 
b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedCamelContextMBean.java
@@ -144,7 +144,7 @@ public interface ManagedCamelContextMBean extends 
ManagedPerformanceCounterMBean
     @ManagedAttribute(description = "Failed number of exchanges processed from 
remote endpoints only")
     long getRemoteExchangesFailed();
 
-    @ManagedAttribute(description = "Total number of exchanges inflight from 
remote endpoints only")
+    @ManagedAttribute(description = "Number of inflight exchanges from remote 
endpoints only")
     long getRemoteExchangesInflight();
 
     @ManagedAttribute(description = "Whether breadcrumbs is in use")
diff --git 
a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedRouteMBean.java
 
b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedRouteMBean.java
index ec05aa6110c9..25b5c673b98b 100644
--- 
a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedRouteMBean.java
+++ 
b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedRouteMBean.java
@@ -209,4 +209,36 @@ public interface ManagedRouteMBean extends 
ManagedPerformanceCounterMBean {
     @ManagedAttribute(description = "Whether the consumer connects to remote 
or local systems")
     boolean isRemoteEndpoint();
 
+    /**
+     * Total number of exchanges the route processed that came from a remote 
endpoint.
+     *
+     * @since 4.24
+     */
+    @ManagedAttribute(description = "Total number of exchanges processed from 
remote endpoints only")
+    long getRemoteExchangesTotal();
+
+    /**
+     * Completed (success) number of exchanges the route processed that came 
from a remote endpoint.
+     *
+     * @since 4.24
+     */
+    @ManagedAttribute(description = "Completed (success) number of exchanges 
processed from remote endpoints only")
+    long getRemoteExchangesCompleted();
+
+    /**
+     * Failed number of exchanges the route processed that came from a remote 
endpoint.
+     *
+     * @since 4.24
+     */
+    @ManagedAttribute(description = "Failed number of exchanges processed from 
remote endpoints only")
+    long getRemoteExchangesFailed();
+
+    /**
+     * Number of exchanges inflight in the route that came from a remote 
endpoint.
+     *
+     * @since 4.24
+     */
+    @ManagedAttribute(description = "Number of inflight exchanges from remote 
endpoints only")
+    long getRemoteExchangesInflight();
+
 }
diff --git 
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedCamelContext.java
 
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedCamelContext.java
index 7960bb32c55d..342212324621 100644
--- 
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedCamelContext.java
+++ 
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedCamelContext.java
@@ -100,7 +100,7 @@ public class ManagedCamelContext extends 
ManagedPerformanceCounter implements Ma
         remoteExchangesTotal.reset();
         remoteExchangesCompleted.reset();
         remoteExchangesFailed.reset();
-        remoteExchangesInflight.reset();
+        // do not reset remoteExchangesInflight
     }
 
     @Override
diff --git 
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedRoute.java
 
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedRoute.java
index ef8271313045..9a54c5331053 100644
--- 
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedRoute.java
+++ 
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedRoute.java
@@ -86,10 +86,18 @@ public class ManagedRoute extends ManagedPerformanceCounter 
implements ManagedRo
     protected final CamelContext context;
     private final LoadTriplet load = new LoadTriplet();
     private final String jmxDomain;
+    // whether the consumer of the route is remote, so all its exchanges came 
from a remote endpoint
+    private final boolean remoteConsumer;
+    // the exchanges from a remote endpoint that a route with an internal 
consumer processed
+    private final Statistic remoteExchangesTotal = new StatisticCounter();
+    private final Statistic remoteExchangesCompleted = new StatisticCounter();
+    private final Statistic remoteExchangesFailed = new StatisticCounter();
+    private final Statistic remoteExchangesInflight = new StatisticCounter();
 
     public ManagedRoute(CamelContext context, Route route) {
         this.route = route;
         this.context = context;
+        this.remoteConsumer = route.getEndpoint() != null && 
route.getEndpoint().isRemote();
         this.description = route.getDescription();
         this.note = route.getNote();
         this.configurationId = route.getConfigurationId();
@@ -793,6 +801,70 @@ public class ManagedRoute extends 
ManagedPerformanceCounter implements ManagedRo
     public void reset() {
         super.reset();
         load.reset();
+        remoteExchangesTotal.reset();
+        remoteExchangesCompleted.reset();
+        remoteExchangesFailed.reset();
+        // do not reset remoteExchangesInflight
+    }
+
+    @Override
+    public void processExchange(Exchange exchange, String type) {
+        super.processExchange(exchange, type);
+        if (fromRemote(exchange)) {
+            remoteExchangesInflight.increment();
+        }
+    }
+
+    @Override
+    public void completedExchange(Exchange exchange, long time) {
+        super.completedExchange(exchange, time);
+        if (fromRemote(exchange)) {
+            remoteExchangesInflight.decrement();
+            if (isStatisticsEnabled()) {
+                remoteExchangesTotal.increment();
+                remoteExchangesCompleted.increment();
+            }
+        }
+    }
+
+    @Override
+    public void failedExchange(Exchange exchange) {
+        super.failedExchange(exchange);
+        if (fromRemote(exchange)) {
+            remoteExchangesInflight.decrement();
+            if (isStatisticsEnabled()) {
+                remoteExchangesTotal.increment();
+                remoteExchangesFailed.increment();
+            }
+        }
+    }
+
+    /**
+     * Whether the exchange came from a remote endpoint, counted by a route 
with an internal consumer only: all the
+     * exchanges of a route with a remote consumer came from it, so its own 
counters are its remote counters.
+     */
+    private boolean fromRemote(Exchange exchange) {
+        return !remoteConsumer && exchange.getFromEndpoint() != null && 
exchange.getFromEndpoint().isRemote();
+    }
+
+    @Override
+    public long getRemoteExchangesTotal() {
+        return remoteConsumer ? getExchangesTotal() : 
remoteExchangesTotal.getValue();
+    }
+
+    @Override
+    public long getRemoteExchangesCompleted() {
+        return remoteConsumer ? getExchangesCompleted() : 
remoteExchangesCompleted.getValue();
+    }
+
+    @Override
+    public long getRemoteExchangesFailed() {
+        return remoteConsumer ? getExchangesFailed() : 
remoteExchangesFailed.getValue();
+    }
+
+    @Override
+    public long getRemoteExchangesInflight() {
+        return remoteConsumer ? getExchangesInflight() : 
remoteExchangesInflight.getValue();
     }
 
     @Override
diff --git 
a/core/camel-management/src/test/java/org/apache/camel/management/ManagedRouteRemoteExchangesTest.java
 
b/core/camel-management/src/test/java/org/apache/camel/management/ManagedRouteRemoteExchangesTest.java
new file mode 100644
index 000000000000..3a61a518a308
--- /dev/null
+++ 
b/core/camel-management/src/test/java/org/apache/camel/management/ManagedRouteRemoteExchangesTest.java
@@ -0,0 +1,161 @@
+/*
+ * 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.management;
+
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Endpoint;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.direct.DirectComponent;
+import org.apache.camel.component.direct.DirectEndpoint;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.DisabledOnOs;
+import org.junit.jupiter.api.condition.OS;
+
+import static 
org.apache.camel.management.DefaultManagementObjectNameStrategy.TYPE_ROUTE;
+import static org.awaitility.Awaitility.await;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * The remote exchange counters of the routes: the exchanges a route processed 
that came from a remote endpoint. Here
+ * the remote endpoint is a direct endpoint that says it is remote.
+ */
+@DisabledOnOs(OS.AIX)
+public class ManagedRouteRemoteExchangesTest extends ManagementTestSupport {
+
+    private final CountDownLatch held = new CountDownLatch(1);
+    private final CountDownLatch release = new CountDownLatch(1);
+
+    @Test
+    public void testRemoteExchangesOfTheRoutes() throws Exception {
+        getMockEndpoint("mock:result").expectedMessageCount(3);
+
+        template.sendBody("remote:orders", "order 1");
+        template.sendBody("remote:orders", "order 2");
+        template.sendBody("direct:internal", "tick");
+        assertThrows(Exception.class, () -> template.sendBody("remote:orders", 
"boom"));
+
+        assertMockEndpointsSatisfied();
+
+        // a route with a remote consumer: all its exchanges came from a 
remote endpoint
+        assertCounters("orders", 3, 2, 1, 0);
+        // a route with an internal consumer that a remote and an internal 
route call: only some came from remote
+        assertExchangesTotal("audit", 4);
+        assertCounters("audit", 3, 2, 1, 0);
+        // a route with an internal consumer called internally
+        assertCounters("internal", 0, 0, 0, 0);
+    }
+
+    @Test
+    public void testResetTheRemoteExchanges() throws Exception {
+        template.sendBody("remote:orders", "order 1");
+
+        MBeanServer mbeanServer = getMBeanServer();
+        mbeanServer.invoke(getCamelObjectName(TYPE_ROUTE, "audit"), "reset", 
null, null);
+
+        assertCounters("audit", 0, 0, 0, 0);
+    }
+
+    @Test
+    public void testResetKeepsTheRemoteExchangesInflight() throws Exception {
+        // an exchange from remote that is in the route while the counters are 
reset
+        CompletableFuture<Object> reply = 
template.asyncRequestBody("remote:held", "order");
+        assertTrue(held.await(10, TimeUnit.SECONDS));
+
+        MBeanServer mbeanServer = getMBeanServer();
+        mbeanServer.invoke(getCamelObjectName(TYPE_ROUTE, "hold"), "reset", 
null, null);
+        mbeanServer.invoke(getContextObjectName(), "reset", null, null);
+
+        assertCounters("hold", 0, 0, 0, 1);
+        assertEquals(1L, (Long) 
mbeanServer.getAttribute(getContextObjectName(), "RemoteExchangesInflight"));
+
+        release.countDown();
+        reply.get(10, TimeUnit.SECONDS);
+
+        // the inflight counters go back to 0, and not below
+        await().atMost(10, TimeUnit.SECONDS).untilAsserted(() -> {
+            assertCounters("hold", 1, 1, 0, 0);
+            assertEquals(0L, (Long) 
mbeanServer.getAttribute(getContextObjectName(), "RemoteExchangesInflight"));
+        });
+    }
+
+    private void assertCounters(String routeId, long total, long completed, 
long failed, long inflight)
+            throws Exception {
+        MBeanServer mbeanServer = getMBeanServer();
+        ObjectName on = getCamelObjectName(TYPE_ROUTE, routeId);
+        assertEquals(total, (Long) mbeanServer.getAttribute(on, 
"RemoteExchangesTotal"), routeId + " total");
+        assertEquals(completed, (Long) mbeanServer.getAttribute(on, 
"RemoteExchangesCompleted"), routeId + " completed");
+        assertEquals(failed, (Long) mbeanServer.getAttribute(on, 
"RemoteExchangesFailed"), routeId + " failed");
+        assertEquals(inflight, (Long) mbeanServer.getAttribute(on, 
"RemoteExchangesInflight"), routeId + " inflight");
+    }
+
+    private void assertExchangesTotal(String routeId, long total) throws 
Exception {
+        ObjectName on = getCamelObjectName(TYPE_ROUTE, routeId);
+        assertEquals(total, (Long) getMBeanServer().getAttribute(on, 
"ExchangesTotal"), routeId + " exchanges");
+    }
+
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        CamelContext context = super.createCamelContext();
+        // a direct component with remote endpoints, as a messaging broker or 
an http server has
+        context.addComponent("remote", new DirectComponent() {
+            @Override
+            protected Endpoint createEndpoint(String uri, String remaining, 
Map<String, Object> parameters)
+                    throws Exception {
+                Endpoint endpoint = new DirectEndpoint(uri, this) {
+                    @Override
+                    public boolean isRemote() {
+                        return true;
+                    }
+                };
+                setProperties(endpoint, parameters);
+                return endpoint;
+            }
+        });
+        return context;
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            @Override
+            public void configure() {
+                from("remote:orders").routeId("orders").to("direct:audit");
+                from("direct:internal").routeId("internal").to("direct:audit");
+                from("direct:audit").routeId("audit")
+                        .filter(body().isEqualTo("boom")).throwException(new 
IllegalArgumentException("Forced")).end()
+                        .to("mock:result");
+                from("remote:held").routeId("held").to("direct:hold");
+                from("direct:hold").routeId("hold").process(exchange -> {
+                    held.countDown();
+                    if (!release.await(10, TimeUnit.SECONDS)) {
+                        throw new IllegalStateException("The exchange was not 
released");
+                    }
+                });
+            }
+        };
+    }
+}
diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang-managing.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-jbang-managing.adoc
index d46af59be16d..9293339bb643 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-jbang-managing.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-jbang-managing.adoc
@@ -148,6 +148,12 @@ camel get route
  63051  dude      java    timer://java?period=1000    Running    46s     46    
   0         0     0    0    9     0s/0s/-
 ----
 
+Use `--remote` to break down TOTAL, FAILED and INFLIGHT into remote/total 
pairs: the exchanges that came from a remote
+endpoint, such as Kafka or HTTP, of all the exchanges of the route. A route 
with a remote consumer has only remote
+exchanges, and a route such as `direct:audit` has the remote exchanges of the 
routes that call it. The same works with
+`camel get processor --remote` and `camel top route --remote`, and the JSON of 
these commands has the remote counters
+as `remoteTotal`, `remoteFailed` and `remoteInflight`.
+
 TIP: Run `camel get --help` to see all available sub-commands.
 
 == Top status
diff --git 
a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-get-route.adoc 
b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-get-route.adoc
index 901d238b73f2..7e5f3770b2c4 100644
--- 
a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-get-route.adoc
+++ 
b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-get-route.adoc
@@ -28,6 +28,7 @@ camel get route [options]
 | `--json` | Output in JSON Format |  | boolean
 | `--limit` | Filter routes by limiting to the given number of rows |  | int
 | `--note` | Include note in the ID column (if available) |  | boolean
+| `--remote` | Break down counters into remote/total pairs |  | boolean
 | `--running` | Only include running routes |  | boolean
 | `--short-uri` | List endpoint URI without query parameters (short) |  | 
boolean
 | `--show-group` | Include group column |  | boolean
diff --git 
a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-top-route.adoc 
b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-top-route.adoc
index 8e14f55227dc..889a4ec5d2b0 100644
--- 
a/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-top-route.adoc
+++ 
b/docs/user-manual/modules/ROOT/pages/jbang-commands/camel-jbang-top-route.adoc
@@ -28,6 +28,7 @@ camel top route [options]
 | `--json` | Output in JSON Format |  | boolean
 | `--limit` | Filter routes by limiting to the given number of rows |  | int
 | `--note` | Include note in the ID column (if available) |  | boolean
+| `--remote` | Break down counters into remote/total pairs |  | boolean
 | `--running` | Only include running routes |  | boolean
 | `--short-uri` | List endpoint URI without query parameters (short) |  | 
boolean
 | `--show-group` | Include group column |  | boolean
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json
 
b/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json
index ee4d49be23bb..b26b0f3e4961 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/generated/resources/META-INF/camel-jbang-commands-metadata.json
@@ -15,7 +15,7 @@
     { "name": "eval", "fullName": "eval", "description": "Evaluate Camel 
expressions and scripts", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.EvalCommand", "options": [ { "names": 
"-h,--help", "description": "Display the help and sub-commands", "javaType": 
"boolean", "type": "boolean" } ], "subcommands": [ { "name": "expression", 
"fullName": "eval expression", "description": "Evaluates Camel expression", 
"sourceClass": "org.apache.camel.dsl.jbang.core.commands.action.EvalEx [...]
     { "name": "explain", "fullName": "explain", "description": "Explain what a 
Camel route does using AI\/LLM", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.Explain", "options": [ { "names": 
"--api-key", "description": "API key for authentication. Also reads 
ANTHROPIC_API_KEY, OPENAI_API_KEY, WATSONX_APIKEY, or LLM_API_KEY env vars", 
"javaType": "java.lang.String", "type": "string" }, { "names": "--api-type", 
"description": "API type: 'ollama', 'openai' (OpenAI-compatible), ' [...]
     { "name": "export", "fullName": "export", "description": "Export to other 
runtimes (Camel Main, Spring Boot, or Quarkus)", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.Export", "options": [ { "names": 
"--build-property", "description": "Maven build properties, ex. 
--build-property=prop1=foo", "javaType": "java.util.List", "type": "array" }, { 
"names": "--camel-spring-boot-version", "description": "Camel version to use 
with Spring Boot", "javaType": "java.lang.String", "ty [...]
-    { "name": "get", "fullName": "get", "description": "Get status of Camel 
integrations", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.process.CamelStatus", "options": [ { 
"names": "--watch", "description": "Execute periodically and showing output 
fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": 
"-h,--help", "description": "Display the help and sub-commands", "javaType": 
"boolean", "type": "boolean" } ], "subcommands": [ { "name": "activity", 
"fullName": " [...]
+    { "name": "get", "fullName": "get", "description": "Get status of Camel 
integrations", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.process.CamelStatus", "options": [ { 
"names": "--watch", "description": "Execute periodically and showing output 
fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": 
"-h,--help", "description": "Display the help and sub-commands", "javaType": 
"boolean", "type": "boolean" } ], "subcommands": [ { "name": "activity", 
"fullName": " [...]
     { "name": "harden", "fullName": "harden", "description": "Suggest security 
hardening for Camel routes using AI\/LLM", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.Harden", "options": [ { "names": 
"--api-key", "description": "API key for authentication. Also reads 
OPENAI_API_KEY or LLM_API_KEY env vars", "javaType": "java.lang.String", 
"type": "string" }, { "names": "--api-type", "description": "API type: 'ollama' 
or 'openai' (OpenAI-compatible)", "defaultValue": "ollama", [...]
     { "name": "hawtio", "fullName": "hawtio", "description": "Launch Hawtio 
web console", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.process.Hawtio", "options": [ { 
"names": "--host", "description": "Hostname to bind the Hawtio web console to", 
"defaultValue": "127.0.0.1", "javaType": "java.lang.String", "type": "string" 
}, { "names": "--open-url,--openUrl", "description": "To automatic open Hawtio 
web console in the web browser (without an interactive terminal the default  
[...]
     { "name": "infra", "fullName": "infra", "description": "List and Run 
external services for testing and prototyping", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.infra.InfraCommand", "options": [ { 
"names": "--json", "description": "Output in JSON Format", "javaType": 
"boolean", "type": "boolean" }, { "names": "-h,--help", "description": "Display 
the help and sub-commands", "javaType": "boolean", "type": "boolean" } ], 
"subcommands": [ { "name": "get", "fullName": "infra  [...]
@@ -33,7 +33,7 @@
     { "name": "semantic", "fullName": "semantic", "description": "List 
semantic definitions and expert contracts", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.action.CamelSemantic", "options": [ { 
"names": "--expert", "description": "Show the operations and parameter contract 
of this expert", "javaType": "java.lang.String", "type": "string" }, { "names": 
"--json", "description": "Output a single JSON document", "javaType": 
"boolean", "type": "boolean" }, { "names": "--timeou [...]
     { "name": "shell", "fullName": "shell", "description": "Interactive Camel 
CLI shell.", "sourceClass": "org.apache.camel.dsl.jbang.core.commands.Shell", 
"options": [ { "names": "-h,--help", "description": "Display the help and 
sub-commands", "javaType": "boolean", "type": "boolean" } ] },
     { "name": "stop", "fullName": "stop", "description": "Shuts down running 
Camel integrations", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.process.StopProcess", "options": [ { 
"names": "--kill", "description": "To force killing the process (SIGKILL)", 
"javaType": "boolean", "type": "boolean" }, { "names": "--no-wait", 
"description": "Do not wait for the integration to stop", "javaType": 
"boolean", "type": "boolean" }, { "names": "--timeout", "description": "How 
long to wa [...]
-    { "name": "top", "fullName": "top", "description": "Top status of Camel 
integrations", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.process.CamelTop", "options": [ { 
"names": "--watch", "description": "Execute periodically and showing output 
fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": 
"-h,--help", "description": "Display the help and sub-commands", "javaType": 
"boolean", "type": "boolean" } ], "subcommands": [ { "name": "context", 
"fullName": "top  [...]
+    { "name": "top", "fullName": "top", "description": "Top status of Camel 
integrations", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.process.CamelTop", "options": [ { 
"names": "--watch", "description": "Execute periodically and showing output 
fullscreen", "javaType": "boolean", "type": "boolean" }, { "names": 
"-h,--help", "description": "Display the help and sub-commands", "javaType": 
"boolean", "type": "boolean" } ], "subcommands": [ { "name": "context", 
"fullName": "top  [...]
     { "name": "trace", "fullName": "trace", "description": "Tail message 
traces from running Camel integrations", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.action.CamelTraceAction", "options": 
[ { "names": "--action", "description": "Action to start, stop, clear, list 
status, or dump traces", "defaultValue": "status", "javaType": 
"java.lang.String", "type": "string" }, { "names": "--ago", "description": "Use 
ago instead of yyyy-MM-dd HH:mm:ss in timestamp.", "javaType": "b [...]
     { "name": "transform", "fullName": "transform", "description": "Transform 
message or Camel routes", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.TransformCommand", "options": [ { 
"names": "-h,--help", "description": "Display the help and sub-commands", 
"javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": 
"dataweave", "fullName": "transform dataweave", "description": "Convert 
DataWeave scripts to DataSonnet format", "sourceClass": "org.apache.camel.dsl. 
[...]
     { "name": "update", "fullName": "update", "description": "Update Camel 
project", "sourceClass": 
"org.apache.camel.dsl.jbang.core.commands.update.UpdateCommand", "options": [ { 
"names": "-h,--help", "description": "Display the help and sub-commands", 
"javaType": "boolean", "type": "boolean" } ], "subcommands": [ { "name": 
"list", "fullName": "update list", "description": "List available update 
versions for Camel and its runtime variants", "sourceClass": 
"org.apache.camel.dsl.jbang.cor [...]
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelContextStatus.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelContextStatus.java
index 2f95ab98c862..3677f21a0e37 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelContextStatus.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelContextStatus.java
@@ -194,6 +194,10 @@ public class CamelContextStatus extends 
ProcessWatchCommand {
                     jo.put("total", JsonValues.number(r.total));
                     jo.put("failed", JsonValues.number(r.failed));
                     jo.put("inflight", JsonValues.number(r.inflight));
+                    // the exchanges that came from a remote endpoint
+                    jo.put("remoteTotal", JsonValues.number(r.totalRemote));
+                    jo.put("remoteFailed", JsonValues.number(r.failedRemote));
+                    jo.put("remoteInflight", 
JsonValues.number(r.inflightRemote));
                     jo.put("last", JsonValues.number(r.last));
                     jo.put("sinceLastStarted", 
JsonValues.text(r.sinceLastStarted));
                     jo.put("sinceLastCompleted", 
JsonValues.text(r.sinceLastCompleted));
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelProcessorStatus.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelProcessorStatus.java
index 1b8a23a573f6..943440279ea1 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelProcessorStatus.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelProcessorStatus.java
@@ -334,6 +334,10 @@ public class CamelProcessorStatus extends 
ProcessWatchCommand {
                 jo.put("total", JsonValues.number(r.total));
                 jo.put("failed", JsonValues.number(r.failed));
                 jo.put("inflight", JsonValues.number(r.inflight));
+                // the exchanges that came from a remote endpoint (of the 
routes only)
+                jo.put("remoteTotal", JsonValues.number(r.totalRemote));
+                jo.put("remoteFailed", JsonValues.number(r.failedRemote));
+                jo.put("remoteInflight", JsonValues.number(r.inflightRemote));
                 // processing times in millis
                 jo.put("mean", JsonValues.number(r.mean));
                 jo.put("min", JsonValues.number(r.min));
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelRouteStatus.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelRouteStatus.java
index d8c7f3ce2027..76af869d1fbd 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelRouteStatus.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelRouteStatus.java
@@ -66,6 +66,10 @@ public class CamelRouteStatus extends ProcessWatchCommand {
                         description = "Prefer to display source filename/code 
instead of IDs")
     boolean source;
 
+    @CommandLine.Option(names = { "--remote" },
+                        description = "Break down counters into remote/total 
pairs")
+    boolean remote;
+
     @CommandLine.Option(names = { "--short-uri" },
                         description = "List endpoint URI without query 
parameters (short)")
     boolean shortUri;
@@ -180,6 +184,10 @@ public class CamelRouteStatus extends ProcessWatchCommand {
                     row.total = stats.get("exchangesTotal").toString();
                     row.inflight = stats.get("exchangesInflight").toString();
                     row.failed = stats.get("exchangesFailed").toString();
+                    // the exchanges that came from a remote endpoint (Camel 
4.24 onwards)
+                    row.totalRemote = text(stats.get("remoteExchangesTotal"));
+                    row.failedRemote = 
text(stats.get("remoteExchangesFailed"));
+                    row.inflightRemote = 
text(stats.get("remoteExchangesInflight"));
                     row.mean = stats.get("meanProcessingTime").toString();
                     if ("-1".equals(row.mean)) {
                         row.mean = null;
@@ -337,6 +345,9 @@ public class CamelRouteStatus extends ProcessWatchCommand {
         jo.put("total", JsonValues.number(r.total));
         jo.put("failed", JsonValues.number(r.failed));
         jo.put("inflight", JsonValues.number(r.inflight));
+        jo.put("remoteTotal", JsonValues.number(r.totalRemote));
+        jo.put("remoteFailed", JsonValues.number(r.failedRemote));
+        jo.put("remoteInflight", JsonValues.number(r.inflightRemote));
         // processing times in millis
         jo.put("mean", JsonValues.number(r.mean));
         jo.put("min", JsonValues.number(r.min));
@@ -512,17 +523,30 @@ public class CamelRouteStatus extends ProcessWatchCommand 
{
     }
 
     protected String getTotal(Row r) {
+        if (remote && r.totalRemote != null) {
+            return r.totalRemote + "/" + r.total;
+        }
         return r.total;
     }
 
     protected String getFailed(Row r) {
+        if (remote && r.failedRemote != null) {
+            return r.failedRemote + "/" + r.failed;
+        }
         return r.failed;
     }
 
     protected String getInflight(Row r) {
+        if (remote && r.inflightRemote != null) {
+            return r.inflightRemote + "/" + r.inflight;
+        }
         return r.inflight;
     }
 
+    private static String text(Object value) {
+        return value != null ? value.toString() : null;
+    }
+
     static class Row {
         String pid;
         String name;
@@ -539,8 +563,11 @@ public class CamelRouteStatus extends ProcessWatchCommand {
         String coverage;
         String throughput;
         String total;
+        String totalRemote;
         String failed;
+        String failedRemote;
         String inflight;
+        String inflightRemote;
         String mean;
         String max;
         String min;
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/process/CamelContextStatusTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/process/CamelContextStatusTest.java
index abbab72673bb..5aae966a9c97 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/process/CamelContextStatusTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/process/CamelContextStatusTest.java
@@ -21,6 +21,7 @@ import java.util.stream.Stream;
 import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain;
 import org.apache.camel.util.json.JsonArray;
 import org.apache.camel.util.json.JsonObject;
+import org.apache.camel.util.json.Jsoner;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.MockedStatic;
@@ -145,4 +146,32 @@ class CamelContextStatusTest extends 
ProcessCommandTestSupport {
             assertTrue(output.contains("jsonApp"), "JSON should contain the 
context name");
         }
     }
+
+    @Test
+    void testJsonHasTheRemoteCounters() throws Exception {
+        JsonObject status = buildContextStatus("jsonApp", 5);
+        JsonObject context = status.getMap("context");
+        JsonObject stats = context.getMap("statistics");
+        stats.put("remoteExchangesTotal", 3);
+        stats.put("remoteExchangesFailed", 1);
+        stats.put("remoteExchangesInflight", 0);
+        writeStatusFile(TEST_PID, status);
+
+        CamelContextStatus command = new CamelContextStatus(new 
CamelJBangMain().withPrinter(printer));
+        command.jsonOutput = true;
+
+        try (MockedStatic<ProcessHandle> mocked = 
mockStatic(ProcessHandle.class)) {
+            ProcessHandle ph = mockProcessHandle(TEST_PID);
+            ProcessHandle currentHandle = mockCurrentHandle();
+            mocked.when(ProcessHandle::current).thenReturn(currentHandle);
+            mocked.when(ProcessHandle::allProcesses).thenAnswer(inv -> 
Stream.of(ph));
+
+            assertEquals(0, command.doCall());
+        }
+
+        JsonObject row = Jsoner.deserialize(printer.getOutput(), (JsonArray) 
null).getMap(0);
+        assertEquals(3L, row.getLong("remoteTotal"));
+        assertEquals(1L, row.getLong("remoteFailed"));
+        assertEquals(0L, row.getLong("remoteInflight"));
+    }
 }
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/process/CamelProcessorStatusTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/process/CamelProcessorStatusTest.java
index fd869702d6b0..36b9318ffa82 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/process/CamelProcessorStatusTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/process/CamelProcessorStatusTest.java
@@ -93,6 +93,23 @@ class CamelProcessorStatusTest extends 
ProcessCommandTestSupport {
         assertThat(log.getLong("mean")).isEqualTo(5);
     }
 
+    @Test
+    void remoteBreaksDownTheCountersOfTheRoutes() throws Exception {
+        JsonObject route = route("audit", "direct:audit", "Started", 25, 
processor("audit-log1", "log", 1, 5));
+        JsonObject stats = route.getMap("statistics");
+        stats.put("remoteExchangesTotal", 6);
+        stats.put("remoteExchangesFailed", 0);
+        stats.put("remoteExchangesInflight", 0);
+        writeStatusFile(TEST_PID, integration(route));
+
+        assertThat(call(command("--remote"))).isZero();
+
+        String[] lines = printer.getOutput().split(System.lineSeparator());
+        assertThat(lines[1]).contains("audit", "6/10");
+        // a processor has no remote counters
+        assertThat(lines[2]).contains("log1", " 10 ").doesNotContain("/10");
+    }
+
     @Test
     void disabledProcessor() throws Exception {
         JsonObject log = processor("orders-log1", "log", 1, 5);
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/process/CamelRouteStatusTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/process/CamelRouteStatusTest.java
index 109011a05f9a..40baa36fd3b5 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/process/CamelRouteStatusTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/process/CamelRouteStatusTest.java
@@ -270,6 +270,31 @@ class CamelRouteStatusTest extends 
ProcessCommandTestSupport {
         assertThat(lines[2]).contains("timer").doesNotContain(" x ");
     }
 
+    @Test
+    void remoteBreaksDownTheCountersIntoRemoteAndTotal() throws Exception {
+        JsonObject stats = stats(10, 2, 1, 5);
+        stats.put("remoteExchangesTotal", 6);
+        stats.put("remoteExchangesFailed", 1);
+        stats.put("remoteExchangesInflight", 0);
+        writeStatusFile(TEST_PID, integration("myApp", route("audit", 
"direct:audit", "Started", stats)));
+
+        assertThat(call(command())).isZero();
+        String[] lines = printer.getOutput().split(System.lineSeparator());
+        assertThat(lines[1]).contains(" 10 ").doesNotContain("6/10");
+
+        printer = new StringPrinter();
+        assertThat(call(command("--remote"))).isZero();
+        lines = printer.getOutput().split(System.lineSeparator());
+        assertThat(lines[1]).contains("6/10", "1/2", "0/1");
+
+        printer = new StringPrinter();
+        assertThat(call(command("--json"))).isZero();
+        JsonObject route = Jsoner.deserialize(printer.getOutput(), (JsonArray) 
null).getMap(0);
+        assertThat(route.getLong("remoteTotal")).isEqualTo(6);
+        assertThat(route.getLong("remoteFailed")).isEqualTo(1);
+        assertThat(route.getLong("remoteInflight")).isZero();
+    }
+
     @Test
     void sortByNameOfTheIntegrations() throws Exception {
         writeStatusFile(TEST_PID, integration("zeta", route("z1", "timer:z", 
"Started", stats(0, 0, 0, -1))));

Reply via email to