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 634e2a0ac675 camel-jbang (tui) - Fix throughput chart y-axis showing 
scaled values
634e2a0ac675 is described below

commit 634e2a0ac675e8c2cbb9d28a3d55bf3c4564f065
Author: Claus Ibsen <[email protected]>
AuthorDate: Wed Aug 12 21:16:26 2026 +0200

    camel-jbang (tui) - Fix throughput chart y-axis showing scaled values
    
    The throughput data is stored as rate * 100 for sub-1.0 precision, so
    7 msg/s was displayed as 700 on the y-axis. Now the chart data is
    divided by THROUGHPUT_SCALE before rendering so the y-axis matches
    the actual msg/s rate shown in the title.
    
    camel-jbang (tui) - Add EWMA smoothing to endpoint throughput charts
    
    Apply a 10-second exponential weighted moving average to endpoint
    throughput rates to eliminate the picket-fence pattern at low message
    rates (e.g. timer=1000ms producing 1 msg/s). Also use rounding instead
    of truncation when scaling chart values so near-threshold rates display
    as filled bars instead of gaps.
    
    Co-Authored-By: Claude Opus 4.6 <[email protected]>
    Signed-off-by: Claus Ibsen <[email protected]>
---
 .../camel/dsl/jbang/core/commands/tui/FlowHelper.java       |  5 +++++
 .../camel/dsl/jbang/core/commands/tui/MetricsCollector.java | 13 +++++++++++++
 2 files changed, 18 insertions(+)

diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/FlowHelper.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/FlowHelper.java
index 3246c16ae52c..d4764cb204c6 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/FlowHelper.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/FlowHelper.java
@@ -117,6 +117,11 @@ final class FlowHelper {
         }
         long curIn = inArr[renderPoints - 1];
         long curOut = outArr[renderPoints - 1];
+        // scale down from internal precision (rate * THROUGHPUT_SCALE) to 
actual msg/s for y-axis
+        for (int i = 0; i < renderPoints; i++) {
+            inArr[i] = Math.round((double) inArr[i] / 
MetricsCollector.THROUGHPUT_SCALE);
+            outArr[i] = Math.round((double) outArr[i] / 
MetricsCollector.THROUGHPUT_SCALE);
+        }
 
         List<Span> titleSpans = new ArrayList<>();
         if (chartLabel != null) {
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/MetricsCollector.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/MetricsCollector.java
index 63767d61489d..0df55e2b752e 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/MetricsCollector.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/MetricsCollector.java
@@ -36,6 +36,8 @@ class MetricsCollector {
     static final long HEAP_SAMPLE_INTERVAL_MS = 5000;
     // Throughput values are stored scaled by this factor so sub-1.0 msg/s 
rates are preserved as longs
     static final long THROUGHPUT_SCALE = 100;
+    // EWMA decay for endpoint throughput smoothing (10-second window)
+    private static final double EWMA_ALPHA = 1.0 - Math.exp(-1.0 / 10.0);
 
     // Throughput history per PID (one point per second)
     private final Map<String, LinkedList<Long>> throughputHistory = new 
ConcurrentHashMap<>();
@@ -88,6 +90,9 @@ class MetricsCollector {
     private final Map<String, LinkedList<Long>> serviceOutSizeHistory = new 
ConcurrentHashMap<>();
     private final Map<String, Long> previousServiceSizeTime = new 
ConcurrentHashMap<>();
 
+    // EWMA state for endpoint throughput smoothing — keyed same as the 
history maps
+    private final Map<String, long[]> ewmaState = new ConcurrentHashMap<>();
+
     // Circuit breaker throughput history per PID/cbId
     private final Map<String, LinkedList<Long>> cbSuccessHistory = new 
ConcurrentHashMap<>();
     private final Map<String, LinkedList<Long>> cbFailHistory = new 
ConcurrentHashMap<>();
@@ -386,6 +391,14 @@ class MetricsCollector {
             Long lastTime = prevTimeMap.get(pid);
             if (lastTime == null || now - lastTime >= 1000) {
                 prevTimeMap.put(pid, now);
+                // apply EWMA smoothing to reduce jitter at low rates
+                String ewmaKey = System.identityHashCode(inHistMap) + "|" + 
pid;
+                long[] prev = ewmaState.get(ewmaKey);
+                if (prev != null) {
+                    inRate = Math.round(EWMA_ALPHA * inRate + (1.0 - 
EWMA_ALPHA) * prev[0]);
+                    outRate = Math.round(EWMA_ALPHA * outRate + (1.0 - 
EWMA_ALPHA) * prev[1]);
+                }
+                ewmaState.put(ewmaKey, new long[] { Math.max(0, inRate), 
Math.max(0, outRate) });
                 addToHistory(inHistMap, pid, Math.max(0, inRate), 
MAX_ENDPOINT_CHART_POINTS);
                 addToHistory(outHistMap, pid, Math.max(0, outRate), 
MAX_ENDPOINT_CHART_POINTS);
             }

Reply via email to