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 2026/05/14 11:42:01 UTC
(camel) 01/01: CAMEL-23420: TUI monitor improvements
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch camel-tui-improvements
in repository https://gitbox.apache.org/repos/asf/camel.git
commit 4f6cc7630204d5afbde243887d693262ae1e27b5
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu May 14 13:29:28 2026 +0200
CAMEL-23420: TUI monitor improvements
- Remove RELOAD, LAST, THREADS, PLATFORM columns from overview
- Rename CAMEL to VERSION, THRUPUT to MSG/S, UPTIME to AGE, FAILED to FAIL
- Right-align numeric columns in overview, routes, and processors tables
- Add COVER, INFLIGHT, SINCE-LAST, MIN/MAX/MEAN columns to routes tab
- Add MIN/MAX/MEAN column to processors tab (empty when total is 0)
- Add sort to overview tab (pid, name, status, total, fail)
- Add status as sort option in routes tab, default sort by name
- Align processor table columns with routes table
- Add Running as green status color
- Disable mouse capture to allow terminal copy/paste
Co-Authored-By: Claude Opus 4.6 (1M context) <no...@anthropic.com>
Signed-off-by: Claus Ibsen <cl...@gmail.com>
---
.../dsl/jbang/core/commands/tui/CamelMonitor.java | 292 +++++++++++++--------
1 file changed, 189 insertions(+), 103 deletions(-)
diff --git a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelMonitor.java b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelMonitor.java
index f033cb79884a..07f3419d43a2 100644
--- a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelMonitor.java
+++ b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelMonitor.java
@@ -54,13 +54,10 @@ import dev.tamboui.text.CharWidth;
import dev.tamboui.text.Line;
import dev.tamboui.text.Span;
import dev.tamboui.text.Text;
-import dev.tamboui.tui.TuiConfig;
import dev.tamboui.tui.TuiRunner;
import dev.tamboui.tui.event.Event;
import dev.tamboui.tui.event.KeyCode;
import dev.tamboui.tui.event.KeyEvent;
-import dev.tamboui.tui.event.MouseEvent;
-import dev.tamboui.tui.event.MouseEventKind;
import dev.tamboui.tui.event.TickEvent;
import dev.tamboui.widgets.barchart.Bar;
import dev.tamboui.widgets.barchart.BarChart;
@@ -111,13 +108,16 @@ public class CamelMonitor extends CamelCommand {
// Tab indices
private static final int TAB_OVERVIEW = 0;
private static final int TAB_ROUTES = 1;
- private static final int TAB_HEALTH = 2;
+ private static final int TAB_LOG = 2;
private static final int TAB_ENDPOINTS = 3;
- private static final int TAB_LOG = 4;
+ private static final int TAB_HEALTH = 4;
private static final int TAB_TRACE = 5;
+ // Overview sort columns
+ private static final String[] OVERVIEW_SORT_COLUMNS = { "pid", "name", "status", "total", "fail" };
+
// Route sort columns
- private static final String[] ROUTE_SORT_COLUMNS = { "mean", "max", "total", "failed", "name" };
+ private static final String[] ROUTE_SORT_COLUMNS = { "total", "failed", "name", "status" };
@CommandLine.Parameters(description = "Name or pid of running Camel integration", arity = "0..1")
String name = "*";
@@ -145,9 +145,13 @@ public class CamelMonitor extends CamelCommand {
// Track last time a sparkline point was recorded
private final Map<String, Long> previousExchangesTime = new ConcurrentHashMap<>();
+ // Overview sort state
+ private String overviewSort = "name";
+ private int overviewSortIndex = 1;
+
// Route sort state
- private String routeSort = "mean";
- private int routeSortIndex;
+ private String routeSort = "name";
+ private int routeSortIndex = 2;
// Health filter state
private boolean showOnlyDown;
@@ -216,7 +220,7 @@ public class CamelMonitor extends CamelCommand {
// Initial data load (synchronous before TUI starts)
refreshDataSync();
- try (var tui = TuiRunner.create(TuiConfig.builder().mouseCapture(true).build())) {
+ try (var tui = TuiRunner.create()) {
this.runner = tui;
// Intercept Ctrl+C: quit the TUI cleanly instead of letting
// the JVM tear down the classloader while we're still running
@@ -233,18 +237,6 @@ public class CamelMonitor extends CamelCommand {
// ---- Event Handling ----
private boolean handleEvent(Event event, TuiRunner runner) {
- if (event instanceof MouseEvent me) {
- if (showDiagram && tabsState.selected() == TAB_ROUTES) {
- if (me.kind() == MouseEventKind.SCROLL_UP) {
- diagramScroll = Math.max(0, diagramScroll - 3);
- return true;
- }
- if (me.kind() == MouseEventKind.SCROLL_DOWN) {
- diagramScroll += 3;
- return true;
- }
- }
- }
if (event instanceof KeyEvent ke) {
// Global keys
if (ke.isQuit() || ke.isCharIgnoreCase('q') || ke.isCancel()) {
@@ -271,13 +263,13 @@ public class CamelMonitor extends CamelCommand {
return handleTabKey(TAB_ROUTES);
}
if (ke.isChar('3')) {
- return handleTabKey(TAB_HEALTH);
+ return handleTabKey(TAB_LOG);
}
if (ke.isChar('4')) {
return handleTabKey(TAB_ENDPOINTS);
}
if (ke.isChar('5')) {
- return handleTabKey(TAB_LOG);
+ return handleTabKey(TAB_HEALTH);
}
if (ke.isChar('6')) {
return handleTabKey(TAB_TRACE);
@@ -369,6 +361,13 @@ public class CamelMonitor extends CamelCommand {
return true;
}
+ // Overview tab: sort
+ if (tab == TAB_OVERVIEW && ke.isCharIgnoreCase('s')) {
+ overviewSortIndex = (overviewSortIndex + 1) % OVERVIEW_SORT_COLUMNS.length;
+ overviewSort = OVERVIEW_SORT_COLUMNS[overviewSortIndex];
+ return true;
+ }
+
// Routes tab: sort and diagram
if (tab == TAB_ROUTES && ke.isCharIgnoreCase('s')) {
routeSortIndex = (routeSortIndex + 1) % ROUTE_SORT_COLUMNS.length;
@@ -608,9 +607,9 @@ public class CamelMonitor extends CamelCommand {
.titles(
" 1 Overview ",
" 2 Routes" + sel + " ",
- " 3 Health" + sel + " ",
+ " 3 Log" + sel + " ",
" 4 Endpoints" + sel + " ",
- " 5 Log" + sel + " ",
+ " 5 Health" + sel + " ",
" 6 Trace" + sel + " ")
.highlightStyle(Style.EMPTY.fg(Color.rgb(0xF6, 0x91, 0x23)).bold())
.divider(Span.styled(" | ", Style.EMPTY.dim()))
@@ -633,7 +632,8 @@ public class CamelMonitor extends CamelCommand {
// ---- Tab 1: Overview ----
private void renderOverview(Frame frame, Rect area) {
- List<IntegrationInfo> infos = data.get();
+ List<IntegrationInfo> infos = new ArrayList<>(data.get());
+ infos.sort(this::sortOverview);
// Split: table (fill) + sparkline (height 8) if we have data
boolean hasSparkline = !throughputHistory.isEmpty();
@@ -660,9 +660,7 @@ public class CamelMonitor extends CamelCommand {
Cell.from(Span.styled(info.name != null ? info.name : "", dimStyle)),
Cell.from(Span.styled("", dimStyle)),
Cell.from(Span.styled("", dimStyle)),
- Cell.from(Span.styled("", dimStyle)),
Cell.from(Span.styled("\u2716 Stopped", Style.EMPTY.fg(Color.RED).dim())),
- Cell.from(Span.styled("", dimStyle)),
Cell.from(Span.styled(info.ago != null ? info.ago : "", dimStyle)),
Cell.from(Span.styled("", dimStyle)),
Cell.from(Span.styled("", dimStyle)),
@@ -670,21 +668,14 @@ public class CamelMonitor extends CamelCommand {
Cell.from(Span.styled("", dimStyle)),
Cell.from(Span.styled("", dimStyle)),
Cell.from(Span.styled("", dimStyle)),
- Cell.from(Span.styled("", dimStyle)),
- Cell.from(Span.styled("", dimStyle)),
Cell.from(Span.styled("", dimStyle))));
} else {
Style statusStyle = switch (extractState(info.state)) {
- case "Started" -> Style.EMPTY.fg(Color.GREEN);
+ case "Started", "Running" -> Style.EMPTY.fg(Color.GREEN);
case "Stopped" -> Style.EMPTY.fg(Color.RED);
default -> Style.EMPTY.fg(Color.YELLOW);
};
- String platformDisplay = info.platform != null ? info.platform : "";
- if (info.platformVersion != null && !info.platformVersion.isEmpty()) {
- platformDisplay += " " + info.platformVersion;
- }
-
Style failStyle = info.failed > 0 ? Style.EMPTY.fg(Color.RED).bold() : Style.EMPTY;
String sinceLastDisplay = formatSinceLast(info);
@@ -693,41 +684,33 @@ public class CamelMonitor extends CamelCommand {
Cell.from(info.pid),
Cell.from(Span.styled(info.name != null ? info.name : "", Style.EMPTY.fg(Color.CYAN))),
Cell.from(info.camelVersion != null ? info.camelVersion : ""),
- Cell.from(platformDisplay),
Cell.from(info.ready != null ? info.ready : ""),
Cell.from(Span.styled(extractState(info.state), statusStyle)),
- Cell.from(info.reloaded != null ? info.reloaded : ""),
Cell.from(info.ago != null ? info.ago : ""),
Cell.from(info.routeStarted + "/" + info.routeTotal),
- Cell.from(info.throughput != null ? info.throughput : ""),
- Cell.from(String.valueOf(info.exchangesTotal)),
- Cell.from(Span.styled(String.valueOf(info.failed), failStyle)),
- Cell.from(String.valueOf(info.inflight)),
- Cell.from(info.last != null ? info.last : ""),
+ rightCell(info.throughput != null ? info.throughput : "", 8),
+ rightCell(String.valueOf(info.exchangesTotal), 8),
+ rightCell(String.valueOf(info.failed), 6, failStyle),
+ rightCell(String.valueOf(info.inflight), 8),
Cell.from(sinceLastDisplay),
- Cell.from(formatMemory(info.heapMemUsed, info.heapMemMax)),
- Cell.from(formatThreads(info.threadCount, info.peakThreadCount))));
+ Cell.from(formatMemory(info.heapMemUsed, info.heapMemMax))));
}
}
Row header = Row.from(
- Cell.from(Span.styled("PID", Style.EMPTY.bold())),
- Cell.from(Span.styled("NAME", Style.EMPTY.bold())),
- Cell.from(Span.styled("CAMEL", Style.EMPTY.bold())),
- Cell.from(Span.styled("PLATFORM", Style.EMPTY.bold())),
+ Cell.from(Span.styled(overviewSortLabel("PID", "pid"), overviewSortStyle("pid"))),
+ Cell.from(Span.styled(overviewSortLabel("NAME", "name"), overviewSortStyle("name"))),
+ Cell.from(Span.styled("VERSION", Style.EMPTY.bold())),
Cell.from(Span.styled("READY", Style.EMPTY.bold())),
- Cell.from(Span.styled("STATUS", Style.EMPTY.bold())),
- Cell.from(Span.styled("RELOAD", Style.EMPTY.bold())),
+ Cell.from(Span.styled(overviewSortLabel("STATUS", "status"), overviewSortStyle("status"))),
Cell.from(Span.styled("AGE", Style.EMPTY.bold())),
Cell.from(Span.styled("ROUTE", Style.EMPTY.bold())),
- Cell.from(Span.styled("MSG/S", Style.EMPTY.bold())),
- Cell.from(Span.styled("TOTAL", Style.EMPTY.bold())),
- Cell.from(Span.styled("FAIL", Style.EMPTY.bold())),
- Cell.from(Span.styled("INFLIGHT", Style.EMPTY.bold())),
- Cell.from(Span.styled("LAST", Style.EMPTY.bold())),
+ rightCell("MSG/S", 8, Style.EMPTY.bold()),
+ rightCell(overviewSortLabel("TOTAL", "total"), 8, overviewSortStyle("total")),
+ rightCell(overviewSortLabel("FAIL", "fail"), 6, overviewSortStyle("fail")),
+ rightCell("INFLIGHT", 8, Style.EMPTY.bold()),
Cell.from(Span.styled("SINCE-LAST", Style.EMPTY.bold())),
- Cell.from(Span.styled("HEAP", Style.EMPTY.bold())),
- Cell.from(Span.styled("THREADS", Style.EMPTY.bold())));
+ Cell.from(Span.styled("HEAP", Style.EMPTY.bold())));
Table table = Table.builder()
.rows(rows)
@@ -736,20 +719,16 @@ public class CamelMonitor extends CamelCommand {
Constraint.length(8),
Constraint.fill(),
Constraint.length(16),
- Constraint.length(12),
Constraint.length(5),
Constraint.length(10),
- Constraint.length(6),
Constraint.length(8),
Constraint.length(7),
Constraint.length(8),
Constraint.length(8),
Constraint.length(6),
Constraint.length(8),
- Constraint.length(6),
Constraint.length(12),
- Constraint.length(14),
- Constraint.length(10))
+ Constraint.length(14))
.highlightStyle(Style.EMPTY.fg(Color.WHITE).bold().onBlue())
.highlightSpacing(Table.HighlightSpacing.ALWAYS)
.block(Block.builder().borderType(BorderType.ROUNDED).title(" Integrations ").build())
@@ -834,36 +813,49 @@ public class CamelMonitor extends CamelCommand {
? Style.EMPTY.fg(Color.RED).bold()
: Style.EMPTY;
+ String sinceLastRoute = formatSinceLastRoute(route);
+
routeRows.add(Row.from(
Cell.from(Span.styled(route.routeId != null ? route.routeId : "", Style.EMPTY.fg(Color.CYAN))),
Cell.from(route.from != null ? route.from : ""),
Cell.from(Span.styled(route.state != null ? route.state : "", stateStyle)),
Cell.from(route.uptime != null ? route.uptime : ""),
- Cell.from(route.throughput != null ? route.throughput : ""),
- Cell.from(String.valueOf(route.total)),
- Cell.from(Span.styled(String.valueOf(route.failed), failStyle)),
- Cell.from(route.meanTime + "/" + route.maxTime)));
+ Cell.from(route.coverage != null ? route.coverage : ""),
+ rightCell(route.throughput != null ? route.throughput : "", 8),
+ rightCell(String.valueOf(route.total), 8),
+ rightCell(String.valueOf(route.failed), 6, failStyle),
+ rightCell(String.valueOf(route.inflight), 8),
+ rightCell(route.total > 0
+ ? route.minTime + "/" + route.maxTime + "/" + route.meanTime
+ : "", 14),
+ Cell.from(sinceLastRoute)));
}
Table routeTable = Table.builder()
.rows(routeRows)
.header(Row.from(
- Cell.from(Span.styled("ROUTE", Style.EMPTY.bold())),
+ Cell.from(Span.styled(routeSortLabel("ROUTE", "name"), routeSortStyle("name"))),
Cell.from(Span.styled("FROM", Style.EMPTY.bold())),
- Cell.from(Span.styled("STATE", Style.EMPTY.bold())),
- Cell.from(Span.styled("UPTIME", Style.EMPTY.bold())),
- Cell.from(Span.styled("THRUPUT", Style.EMPTY.bold())),
- Cell.from(Span.styled(routeSortLabel("TOTAL", "total"), routeSortStyle("total"))),
- Cell.from(Span.styled(routeSortLabel("FAILED", "failed"), routeSortStyle("failed"))),
- Cell.from(Span.styled(routeSortLabel("MEAN/MAX", "mean"), routeSortStyle("mean")))))
+ Cell.from(Span.styled(routeSortLabel("STATUS", "status"), routeSortStyle("status"))),
+ Cell.from(Span.styled("AGE", Style.EMPTY.bold())),
+ Cell.from(Span.styled("COVER", Style.EMPTY.bold())),
+ rightCell("MSG/S", 8, Style.EMPTY.bold()),
+ rightCell(routeSortLabel("TOTAL", "total"), 8, routeSortStyle("total")),
+ rightCell(routeSortLabel("FAIL", "failed"), 6, routeSortStyle("failed")),
+ rightCell("INFLIGHT", 8, Style.EMPTY.bold()),
+ rightCell("MIN/MAX/MEAN", 14, Style.EMPTY.bold()),
+ Cell.from(Span.styled("SINCE-LAST", Style.EMPTY.bold()))))
.widths(
Constraint.length(12),
Constraint.fill(),
Constraint.length(10),
Constraint.length(8),
- Constraint.length(10),
+ Constraint.length(6),
Constraint.length(8),
Constraint.length(8),
+ Constraint.length(6),
+ Constraint.length(8),
+ Constraint.length(14),
Constraint.length(12))
.highlightStyle(Style.EMPTY.fg(Color.WHITE).bold().onBlue())
.highlightSpacing(Table.HighlightSpacing.ALWAYS)
@@ -894,10 +886,40 @@ public class CamelMonitor extends CamelCommand {
}
}
+ private int sortOverview(IntegrationInfo a, IntegrationInfo b) {
+ if (a.vanishing != b.vanishing) {
+ return a.vanishing ? 1 : -1;
+ }
+ return switch (overviewSort) {
+ case "pid" -> {
+ String pa = a.pid != null ? a.pid : "";
+ String pb = b.pid != null ? b.pid : "";
+ yield pa.compareTo(pb);
+ }
+ case "name" -> {
+ String na = a.name != null ? a.name : "";
+ String nb = b.name != null ? b.name : "";
+ yield na.compareToIgnoreCase(nb);
+ }
+ case "status" -> Integer.compare(a.state, b.state);
+ case "total" -> Long.compare(b.exchangesTotal, a.exchangesTotal);
+ case "fail" -> Long.compare(b.failed, a.failed);
+ default -> 0;
+ };
+ }
+
+ private String overviewSortLabel(String label, String column) {
+ return overviewSort.equals(column) ? label + "▼" : label;
+ }
+
+ private Style overviewSortStyle(String column) {
+ return overviewSort.equals(column)
+ ? Style.EMPTY.fg(Color.YELLOW).bold()
+ : Style.EMPTY.bold();
+ }
+
private int sortRoute(RouteInfo a, RouteInfo b) {
return switch (routeSort) {
- case "mean" -> Long.compare(b.meanTime, a.meanTime);
- case "max" -> Long.compare(b.maxTime, a.maxTime);
case "total" -> Long.compare(b.total, a.total);
case "failed" -> Long.compare(b.failed, a.failed);
case "name" -> {
@@ -905,6 +927,11 @@ public class CamelMonitor extends CamelCommand {
String rb = b.routeId != null ? b.routeId : "";
yield ra.compareToIgnoreCase(rb);
}
+ case "status" -> {
+ String sa = a.state != null ? a.state : "";
+ String sb2 = b.state != null ? b.state : "";
+ yield sa.compareToIgnoreCase(sb2);
+ }
default -> 0;
};
}
@@ -928,13 +955,15 @@ public class CamelMonitor extends CamelCommand {
rows.add(Row.from(
Cell.from(Span.styled(indent + (proc.id != null ? proc.id : ""), nameStyle)),
Cell.from(proc.processor != null ? proc.processor : ""),
- Cell.from(String.valueOf(proc.total)),
- Cell.from(proc.failed > 0
- ? Span.styled(String.valueOf(proc.failed), Style.EMPTY.fg(Color.RED))
- : Span.raw("0")),
- Cell.from(proc.meanTime + "ms"),
- Cell.from(proc.maxTime + "ms"),
- Cell.from(proc.lastTime + "ms")));
+ Cell.from(""), Cell.from(""), Cell.from(""), Cell.from(""),
+ rightCell(String.valueOf(proc.total), 8),
+ rightCell(String.valueOf(proc.failed), 6,
+ proc.failed > 0 ? Style.EMPTY.fg(Color.RED) : Style.EMPTY),
+ Cell.from(""),
+ rightCell(proc.total > 0
+ ? proc.minTime + "/" + proc.maxTime + "/" + proc.meanTime
+ : "", 14),
+ Cell.from("")));
}
Table table = Table.builder()
@@ -942,19 +971,24 @@ public class CamelMonitor extends CamelCommand {
.header(Row.from(
Cell.from(Span.styled("PROCESSOR", Style.EMPTY.bold())),
Cell.from(Span.styled("TYPE", Style.EMPTY.bold())),
- Cell.from(Span.styled("TOTAL", Style.EMPTY.bold())),
- Cell.from(Span.styled("FAILED", Style.EMPTY.bold())),
- Cell.from(Span.styled("MEAN", Style.EMPTY.bold())),
- Cell.from(Span.styled("MAX", Style.EMPTY.bold())),
- Cell.from(Span.styled("LAST", Style.EMPTY.bold()))))
+ Cell.from(""), Cell.from(""), Cell.from(""), Cell.from(""),
+ rightCell("TOTAL", 8, Style.EMPTY.bold()),
+ rightCell("FAIL", 6, Style.EMPTY.bold()),
+ Cell.from(""),
+ rightCell("MIN/MAX/MEAN", 14, Style.EMPTY.bold()),
+ Cell.from("")))
.widths(
+ Constraint.length(12),
Constraint.fill(),
- Constraint.length(15),
+ Constraint.length(10),
Constraint.length(8),
+ Constraint.length(6),
Constraint.length(8),
Constraint.length(8),
+ Constraint.length(6),
Constraint.length(8),
- Constraint.length(8))
+ Constraint.length(14),
+ Constraint.length(12))
.block(Block.builder().borderType(BorderType.ROUNDED)
.title(" Processors [" + route.routeId + "] ").build())
.build();
@@ -986,10 +1020,10 @@ public class CamelMonitor extends CamelCommand {
Cell.from(route.from != null ? route.from : ""),
Cell.from(Span.styled(route.state != null ? route.state : "", stateStyle)),
Cell.from(route.uptime != null ? route.uptime : ""),
- Cell.from(route.throughput != null ? route.throughput : ""),
- Cell.from(String.valueOf(route.total)),
- Cell.from(Span.styled(String.valueOf(route.failed), failStyle)),
- Cell.from(route.meanTime + "/" + route.maxTime)));
+ rightCell(route.throughput != null ? route.throughput : "", 8),
+ rightCell(String.valueOf(route.total), 8),
+ rightCell(String.valueOf(route.failed), 6, failStyle),
+ rightCell(String.valueOf(route.inflight), 8)));
}
Table table = Table.builder()
@@ -997,21 +1031,21 @@ public class CamelMonitor extends CamelCommand {
.header(Row.from(
Cell.from(Span.styled("ROUTE", Style.EMPTY.bold())),
Cell.from(Span.styled("FROM", Style.EMPTY.bold())),
- Cell.from(Span.styled("STATE", Style.EMPTY.bold())),
- Cell.from(Span.styled("UPTIME", Style.EMPTY.bold())),
- Cell.from(Span.styled("THRUPUT", Style.EMPTY.bold())),
- Cell.from(Span.styled("TOTAL", Style.EMPTY.bold())),
- Cell.from(Span.styled("FAILED", Style.EMPTY.bold())),
- Cell.from(Span.styled("MEAN/MAX", Style.EMPTY.bold()))))
+ Cell.from(Span.styled("STATUS", Style.EMPTY.bold())),
+ Cell.from(Span.styled("AGE", Style.EMPTY.bold())),
+ rightCell("MSG/S", 8, Style.EMPTY.bold()),
+ rightCell("TOTAL", 8, Style.EMPTY.bold()),
+ rightCell("FAIL", 6, Style.EMPTY.bold()),
+ rightCell("INFLIGHT", 8, Style.EMPTY.bold())))
.widths(
Constraint.length(12),
Constraint.fill(),
Constraint.length(10),
Constraint.length(8),
- Constraint.length(10),
Constraint.length(8),
Constraint.length(8),
- Constraint.length(12))
+ Constraint.length(6),
+ Constraint.length(8))
.highlightStyle(Style.EMPTY.fg(Color.WHITE).bold().onBlue())
.block(Block.builder().borderType(BorderType.ROUNDED)
.title(" Route [" + info.name + "] ").build())
@@ -2071,6 +2105,7 @@ public class CamelMonitor extends CamelCommand {
if (tab == TAB_OVERVIEW) {
hint(spans, "q", "quit");
hint(spans, "\u2191\u2193", "navigate");
+ hint(spans, "s", "sort");
hint(spans, "Enter", "details");
hint(spans, "1-6", "tabs");
} else if (tab == TAB_ROUTES && showDiagram) {
@@ -2119,6 +2154,34 @@ public class CamelMonitor extends CamelCommand {
frame.renderWidget(Paragraph.from(Line.from(spans)), area);
}
+ private static String formatSinceLastRoute(RouteInfo route) {
+ StringBuilder sb = new StringBuilder();
+ if (route.sinceLastStarted != null) {
+ sb.append(route.sinceLastStarted);
+ }
+ if (route.sinceLastCompleted != null) {
+ if (!sb.isEmpty()) {
+ sb.append('/');
+ }
+ sb.append(route.sinceLastCompleted);
+ }
+ if (route.sinceLastFailed != null) {
+ if (!sb.isEmpty()) {
+ sb.append('/');
+ }
+ sb.append(route.sinceLastFailed);
+ }
+ return sb.toString();
+ }
+
+ private static Cell rightCell(String text, int width) {
+ return Cell.from(String.format("%" + width + "s", text));
+ }
+
+ private static Cell rightCell(String text, int width, Style style) {
+ return Cell.from(Span.styled(String.format("%" + width + "s", text), style));
+ }
+
private static final Style HINT_KEY_STYLE = Style.EMPTY.fg(Color.YELLOW).bold();
private static void hint(List<Span> spans, String key, String label) {
@@ -2543,11 +2606,26 @@ public class CamelMonitor extends CamelCommand {
Map<String, ?> rs = rj.getMap("statistics");
if (rs != null) {
+ ri.coverage = objToString(rs.get("coverage"));
ri.throughput = objToString(rs.get("exchangesThroughput"));
ri.total = objToLong(rs.get("exchangesTotal"));
ri.failed = objToLong(rs.get("exchangesFailed"));
+ ri.inflight = objToLong(rs.get("exchangesInflight"));
ri.meanTime = objToLong(rs.get("meanProcessingTime"));
+ ri.minTime = objToLong(rs.get("minProcessingTime"));
ri.maxTime = objToLong(rs.get("maxProcessingTime"));
+ long tsStarted = objToLong(rs.get("lastCreatedExchangeTimestamp"));
+ if (tsStarted > 0) {
+ ri.sinceLastStarted = TimeUtils.printSince(tsStarted);
+ }
+ long tsCompleted = objToLong(rs.get("lastCompletedExchangeTimestamp"));
+ if (tsCompleted > 0) {
+ ri.sinceLastCompleted = TimeUtils.printSince(tsCompleted);
+ }
+ long tsFailed = objToLong(rs.get("lastFailedExchangeTimestamp"));
+ if (tsFailed > 0) {
+ ri.sinceLastFailed = TimeUtils.printSince(tsFailed);
+ }
}
// Parse processors
@@ -2565,6 +2643,7 @@ public class CamelMonitor extends CamelCommand {
pi.total = objToLong(ps.get("exchangesTotal"));
pi.failed = objToLong(ps.get("exchangesFailed"));
pi.meanTime = objToLong(ps.get("meanProcessingTime"));
+ pi.minTime = objToLong(ps.get("minProcessingTime"));
pi.maxTime = objToLong(ps.get("maxProcessingTime"));
pi.lastTime = objToLong(ps.get("lastProcessingTime"));
}
@@ -2758,10 +2837,16 @@ public class CamelMonitor extends CamelCommand {
String state;
String uptime;
String throughput;
+ String coverage;
long total;
long failed;
+ long inflight;
long meanTime;
+ long minTime;
long maxTime;
+ String sinceLastStarted;
+ String sinceLastCompleted;
+ String sinceLastFailed;
final List<ProcessorInfo> processors = new ArrayList<>();
}
@@ -2772,6 +2857,7 @@ public class CamelMonitor extends CamelCommand {
long total;
long failed;
long meanTime;
+ long minTime;
long maxTime;
long lastTime;
}