You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2022/09/09 08:17:59 UTC

[camel] 01/03: CAMEL-18488: camel-management - Statistic for current throughput

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

commit 037de46fcca244c1b386aea1a2636408f9fd2896
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Fri Sep 9 09:31:37 2022 +0200

    CAMEL-18488: camel-management - Statistic for current throughput
---
 .../camel/impl/console/ContextDevConsole.java      | 11 ++++
 .../apache/camel/impl/console/RouteDevConsole.java | 11 ++++
 .../management/mbean/ManagedCamelContextMBean.java |  3 +
 .../api/management/mbean/ManagedRouteMBean.java    |  3 +
 .../camel/management/mbean/LoadThroughput.java     | 64 ++++++++++++++++++++++
 .../management/mbean/ManagedCamelContext.java      | 13 +++++
 .../camel/management/mbean/ManagedRoute.java       | 13 +++++
 .../main/java/org/apache/camel/util/StopWatch.java | 13 ++++-
 .../core/commands/process/CamelContextStatus.java  | 14 +++++
 .../core/commands/process/CamelRouteStatus.java    | 14 +++++
 10 files changed, 157 insertions(+), 2 deletions(-)

diff --git a/core/camel-console/src/main/java/org/apache/camel/impl/console/ContextDevConsole.java b/core/camel-console/src/main/java/org/apache/camel/impl/console/ContextDevConsole.java
index 0f1cafa1196..b93b346a317 100644
--- a/core/camel-console/src/main/java/org/apache/camel/impl/console/ContextDevConsole.java
+++ b/core/camel-console/src/main/java/org/apache/camel/impl/console/ContextDevConsole.java
@@ -129,6 +129,10 @@ public class ContextDevConsole extends AbstractDevConsole {
                     stats.put("load05", load5);
                     stats.put("load15", load15);
                 }
+                String thp = getThroughput(mb);
+                if (!thp.isEmpty()) {
+                    stats.put("exchangesThroughput", thp);
+                }
                 stats.put("exchangesTotal", mb.getExchangesTotal());
                 stats.put("exchangesFailed", mb.getExchangesFailed());
                 stats.put("exchangesInflight", mb.getExchangesInflight());
@@ -179,4 +183,11 @@ public class ContextDevConsole extends AbstractDevConsole {
         return s;
     }
 
+    private String getThroughput(ManagedCamelContextMBean mb) {
+        String s = mb.getThroughput();
+        // lets use dot as separator
+        s = s.replace(',', '.');
+        return s;
+    }
+
 }
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 7be50248e07..0a31a67f147 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
@@ -121,6 +121,10 @@ public class RouteDevConsole extends AbstractDevConsole {
                 stats.put("load05", load5);
                 stats.put("load15", load15);
             }
+            String thp = getThroughput(mrb);
+            if (!thp.isEmpty()) {
+                stats.put("exchangesThroughput", thp);
+            }
             stats.put("exchangesTotal", mrb.getExchangesTotal());
             stats.put("exchangesFailed", mrb.getExchangesFailed());
             stats.put("exchangesInflight", mrb.getExchangesInflight());
@@ -207,4 +211,11 @@ public class RouteDevConsole extends AbstractDevConsole {
         return s;
     }
 
+    private String getThroughput(ManagedRouteMBean mrb) {
+        String s = mrb.getThroughput();
+        // lets use dot as separator
+        s = s.replace(',', '.');
+        return s;
+    }
+
 }
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 75c2fa1a022..d5924f3ed79 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
@@ -123,6 +123,9 @@ public interface ManagedCamelContextMBean extends ManagedPerformanceCounterMBean
     @ManagedAttribute(description = "Average load over the last fifteen minutes")
     String getLoad15();
 
+    @ManagedAttribute(description = "Throughput message/second")
+    String getThroughput();
+
     @ManagedAttribute(description = "Whether breadcrumbs is in use")
     boolean isUseBreadcrumb();
 
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 83867af9540..72b00aa6a43 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
@@ -88,6 +88,9 @@ public interface ManagedRouteMBean extends ManagedPerformanceCounterMBean {
     @ManagedAttribute(description = "Average load over the last fifteen minutes")
     String getLoad15();
 
+    @ManagedAttribute(description = "Throughput message/second")
+    String getThroughput();
+
     @ManagedOperation(description = "Start route")
     void start() throws Exception;
 
diff --git a/core/camel-management/src/main/java/org/apache/camel/management/mbean/LoadThroughput.java b/core/camel-management/src/main/java/org/apache/camel/management/mbean/LoadThroughput.java
new file mode 100644
index 00000000000..546f00d7bae
--- /dev/null
+++ b/core/camel-management/src/main/java/org/apache/camel/management/mbean/LoadThroughput.java
@@ -0,0 +1,64 @@
+/*
+ * 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.mbean;
+
+import org.apache.camel.util.StopWatch;
+
+/**
+ * Holds the load throughput messages/second
+ */
+public final class LoadThroughput {
+
+    private final StopWatch watch = new StopWatch(false);
+    private long last;
+    private double thp = Double.NaN;
+
+    /**
+     * Update the load statistics
+     *
+     * @param currentReading the current reading
+     */
+    public void update(long currentReading) {
+        if (watch.taken() == 0) {
+            watch.restart();
+            thp = 0;
+        } else {
+            long time = watch.takenAndRestart();
+            if (time > 0) {
+                long delta = currentReading - last;
+                if (delta > 0) {
+                    thp = (1000 / time) * delta;
+                } else {
+                    thp = 0;
+                }
+            } else {
+                thp = 0;
+            }
+        }
+        last = currentReading;
+    }
+
+    public double getThroughput() {
+        return thp;
+    }
+
+    @Override
+    public String toString() {
+        return "" + thp;
+    }
+
+}
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 44a0c7d1701..15a7a0c9974 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
@@ -58,6 +58,7 @@ public class ManagedCamelContext extends ManagedPerformanceCounter implements Ti
 
     private final CamelContext context;
     private final LoadTriplet load = new LoadTriplet();
+    private final LoadThroughput thp = new LoadThroughput();
     private final String jmxDomain;
 
     public ManagedCamelContext(CamelContext context) {
@@ -256,6 +257,17 @@ public class ManagedCamelContext extends ManagedPerformanceCounter implements Ti
         }
     }
 
+    @Override
+    public String getThroughput() {
+        double d = thp.getThroughput();
+        if (Double.isNaN(d)) {
+            // empty string if load statistics is disabled
+            return "";
+        } else {
+            return String.format("%.2f", d);
+        }
+    }
+
     @Override
     public boolean isUseBreadcrumb() {
         return context.isUseBreadcrumb();
@@ -289,6 +301,7 @@ public class ManagedCamelContext extends ManagedPerformanceCounter implements Ti
     @Override
     public void onTimer() {
         load.update(getInflightExchanges());
+        thp.update(getExchangesTotal());
     }
 
     @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 ec490f49bb6..6b1ad0db16c 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
@@ -77,6 +77,7 @@ public class ManagedRoute extends ManagedPerformanceCounter implements TimerList
     protected final String sourceLocationShort;
     protected final CamelContext context;
     private final LoadTriplet load = new LoadTriplet();
+    private final LoadThroughput thp = new LoadThroughput();
     private final String jmxDomain;
 
     public ManagedRoute(CamelContext context, Route route) {
@@ -277,9 +278,21 @@ public class ManagedRoute extends ManagedPerformanceCounter implements TimerList
         }
     }
 
+    @Override
+    public String getThroughput() {
+        double d = thp.getThroughput();
+        if (Double.isNaN(d)) {
+            // empty string if load statistics is disabled
+            return "";
+        } else {
+            return String.format("%.2f", d);
+        }
+    }
+
     @Override
     public void onTimer() {
         load.update(getInflightExchanges());
+        thp.update(getExchangesTotal());
     }
 
     @Override
diff --git a/core/camel-util/src/main/java/org/apache/camel/util/StopWatch.java b/core/camel-util/src/main/java/org/apache/camel/util/StopWatch.java
index 71d6625e31b..9615d4094a7 100644
--- a/core/camel-util/src/main/java/org/apache/camel/util/StopWatch.java
+++ b/core/camel-util/src/main/java/org/apache/camel/util/StopWatch.java
@@ -67,13 +67,22 @@ public final class StopWatch {
     public long taken() {
         if (start > 0) {
             long delta = System.nanoTime() - start;
-
             return Duration.ofNanos(delta).toMillis();
         }
-
         return 0;
     }
 
+    /**
+     * Returns the time taken in millis and restarts the timer.
+     *
+     * @return time in millis, or <tt>0</tt> if not started yet.
+     */
+    public long takenAndRestart() {
+        long answer = taken();
+        restart();
+        return answer;
+    }
+
     /**
      * Utility method to provide the elapsed time using milliseconds since epoch. This serves as an alternative for the
      * former constructor based on a Date argument. This should be used only when converting old code that relies on
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 09bd9bdcb49..33c719c8b9d 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
@@ -74,6 +74,10 @@ public class CamelContextStatus extends ProcessBaseCommand {
                         row.camelVersion = context.getString("version");
                         Map<String, ?> stats = context.getMap("statistics");
                         if (stats != null) {
+                            Object thp = stats.get("exchangesThroughput");
+                            if (thp != null) {
+                                row.throughput = thp.toString();
+                            }
                             row.total = stats.get("exchangesTotal").toString();
                             row.inflight = stats.get("exchangesInflight").toString();
                             row.failed = stats.get("exchangesFailed").toString();
@@ -129,6 +133,7 @@ public class CamelContextStatus extends ProcessBaseCommand {
                             .with(r -> r.reloaded),
                     new Column().header("AGE").headerAlign(HorizontalAlign.CENTER).with(r -> r.ago),
                     new Column().header("ROUTE").with(this::getRoutes),
+                    new Column().header("MSG/S").with(this::getThroughput),
                     new Column().header("TOTAL").with(r -> r.total),
                     new Column().header("FAIL").with(r -> r.failed),
                     new Column().header("INFLIGHT").with(r -> r.inflight),
@@ -178,6 +183,14 @@ public class CamelContextStatus extends ProcessBaseCommand {
         return s1 + "/" + s2 + "/" + s3;
     }
 
+    private String getThroughput(Row r) {
+        String s = r.throughput;
+        if ("0.00".equals(s) || s.isEmpty()) {
+            s = "-";
+        }
+        return s;
+    }
+
     private String getRoutes(Row r) {
         return r.routeStarted + "/" + r.routeTotal;
     }
@@ -195,6 +208,7 @@ public class CamelContextStatus extends ProcessBaseCommand {
         String reloaded;
         String ago;
         long uptime;
+        String throughput;
         String total;
         String failed;
         String inflight;
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 90c7140bc37..f77cce19600 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
@@ -94,6 +94,10 @@ public class CamelRouteStatus extends ProcessBaseCommand {
                                 if (load != null) {
                                     row.load15 = load.toString();
                                 }
+                                Object thp = stats.get("exchangesThroughput");
+                                if (thp != null) {
+                                    row.throughput = thp.toString();
+                                }
                                 row.total = stats.get("exchangesTotal").toString();
                                 row.inflight = stats.get("exchangesInflight").toString();
                                 row.failed = stats.get("exchangesFailed").toString();
@@ -153,6 +157,7 @@ public class CamelRouteStatus extends ProcessBaseCommand {
                 new Column().header("STATUS").headerAlign(HorizontalAlign.CENTER)
                         .with(r -> r.state),
                 new Column().header("AGE").headerAlign(HorizontalAlign.CENTER).with(r -> r.age),
+                new Column().header("MSG/S").with(this::getThroughput),
                 new Column().header("TOTAL").with(r -> r.total),
                 new Column().header("FAIL").with(r -> r.failed),
                 new Column().header("INFLIGHT").with(r -> r.inflight),
@@ -182,6 +187,14 @@ public class CamelRouteStatus extends ProcessBaseCommand {
         }
     }
 
+    private String getThroughput(Row r) {
+        String s = r.throughput;
+        if ("0.00".equals(s) || s.isEmpty()) {
+            s = "-";
+        }
+        return s;
+    }
+
     static class Row {
         String pid;
         String name;
@@ -191,6 +204,7 @@ public class CamelRouteStatus extends ProcessBaseCommand {
         String source;
         String state;
         String age;
+        String throughput;
         String total;
         String failed;
         String inflight;