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 2175171ac52 CAMEL-20972: camel-jbang - Be able to see route error message and stacktrace 2175171ac52 is described below commit 2175171ac5238040eaf096aa2a505de105ca8d3c Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Thu Jul 11 20:42:32 2024 +0200 CAMEL-20972: camel-jbang - Be able to see route error message and stacktrace --- .../apache/camel/impl/console/RouteDevConsole.java | 34 +++++++++++ .../core/commands/process/CamelRouteStatus.java | 67 +++++++++++++++++++++- 2 files changed, 99 insertions(+), 2 deletions(-) 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 59d022b5440..0624230c452 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 @@ -16,8 +16,11 @@ */ package org.apache.camel.impl.console; +import java.io.PrintWriter; +import java.io.StringWriter; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.List; @@ -92,6 +95,20 @@ public class RouteDevConsole extends AbstractDevConsole { sb.append(String.format("\n Source: %s", mrb.getSourceLocation())); } sb.append(String.format("\n State: %s", mrb.getState())); + if (mrb.getLastError() != null) { + String phase = StringHelper.capitalize(mrb.getLastError().getPhase().name().toLowerCase()); + sb.append(String.format("\n Error Phase: %s", phase)); + Throwable cause = mrb.getLastError().getException(); + if (cause != null) { + sb.append(String.format("\n Error Message: %s", cause.getMessage())); + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + cause.printStackTrace(pw); + sb.append("\n\n"); + sb.append(sw); + sb.append("\n\n"); + } + } sb.append(String.format("\n Uptime: %s", mrb.getUptime())); String coverage = calculateRouteCoverage(mrb, true); if (coverage != null) { @@ -240,6 +257,23 @@ public class RouteDevConsole extends AbstractDevConsole { } jo.put("state", mrb.getState()); jo.put("uptime", mrb.getUptime()); + if (mrb.getLastError() != null) { + String phase = StringHelper.capitalize(mrb.getLastError().getPhase().name().toLowerCase()); + JsonObject eo = new JsonObject(); + eo.put("phase", phase); + Throwable cause = mrb.getLastError().getException(); + if (cause != null) { + eo.put("message", cause.getMessage()); + JsonArray arr2 = new JsonArray(); + StringWriter writer = new StringWriter(); + cause.printStackTrace(new PrintWriter(writer)); + writer.flush(); + String trace = writer.toString(); + eo.put("stackTrace", arr2); + Collections.addAll(arr2, trace.split("\n")); + } + jo.put("lastError", eo); + } JsonObject stats = new JsonObject(); String coverage = calculateRouteCoverage(mrb, false); if (coverage != null) { 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 ac3eb7464f4..b2941c3b0ac 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 @@ -21,6 +21,7 @@ import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; import com.github.freva.asciitable.AsciiTable; import com.github.freva.asciitable.Column; @@ -29,6 +30,7 @@ import com.github.freva.asciitable.OverflowBehaviour; import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain; import org.apache.camel.dsl.jbang.core.common.PidNameAgeCompletionCandidates; import org.apache.camel.dsl.jbang.core.common.ProcessHelper; +import org.apache.camel.util.StringHelper; import org.apache.camel.util.TimeUtils; import org.apache.camel.util.json.JsonArray; import org.apache.camel.util.json.JsonObject; @@ -66,6 +68,10 @@ public class CamelRouteStatus extends ProcessWatchCommand { description = "Filter routes that must be slower than the given time (ms)") long mean; + @CommandLine.Option(names = { "--error" }, + description = "Shows detailed information for routes that has error status") + boolean error; + public CamelRouteStatus(CamelJBangMain main) { super(main); } @@ -106,6 +112,12 @@ public class CamelRouteStatus extends ProcessWatchCommand { row.state = o.getString("state"); row.age = o.getString("uptime"); row.uptime = row.age != null ? TimeUtils.toMilliSeconds(row.age) : 0; + JsonObject eo = (JsonObject) o.get("lastError"); + if (eo != null) { + row.lastErrorPhase = eo.getString("phase"); + row.lastErrorMessage = eo.getString("message"); + row.stackTrace = eo.getCollection("stackTrace"); + } Map<String, ?> stats = o.getMap("statistics"); if (stats != null) { Object load = stats.get("load01"); @@ -180,7 +192,16 @@ public class CamelRouteStatus extends ProcessWatchCommand { rows.sort(this::sortRow); if (!rows.isEmpty()) { - printTable(rows, remoteVisible.get()); + if (error) { + for (Row r : rows) { + boolean error = r.lastErrorPhase != null; + if (error) { + printErrorTable(r, remoteVisible.get()); + } + } + } else { + printTable(rows, remoteVisible.get()); + } } return 0; @@ -200,7 +221,7 @@ public class CamelRouteStatus extends ProcessWatchCommand { .dataAlign(HorizontalAlign.CENTER) .with(this::getRemote), new Column().header("STATUS").headerAlign(HorizontalAlign.CENTER) - .with(r -> r.state), + .with(this::getStatus), new Column().header("AGE").headerAlign(HorizontalAlign.CENTER).with(r -> r.age), new Column().header("COVER").with(this::getCoverage), new Column().header("MSG/S").with(this::getThroughput), @@ -215,6 +236,38 @@ public class CamelRouteStatus extends ProcessWatchCommand { new Column().header("SINCE-LAST").with(this::getSinceLast)))); } + protected void printErrorTable(Row er, boolean remoteVisible) { + printer().println(AsciiTable.getTable(AsciiTable.NO_BORDERS, List.of(er), Arrays.asList( + new Column().header("PID").headerAlign(HorizontalAlign.CENTER).with(r -> r.pid), + new Column().header("NAME").dataAlign(HorizontalAlign.LEFT).maxWidth(30, OverflowBehaviour.ELLIPSIS_RIGHT) + .with(r -> r.name), + new Column().header("ID").dataAlign(HorizontalAlign.LEFT).maxWidth(20, OverflowBehaviour.ELLIPSIS_RIGHT) + .with(this::getId), + new Column().header("FROM").visible(!wideUri).dataAlign(HorizontalAlign.LEFT) + .maxWidth(45, OverflowBehaviour.ELLIPSIS_RIGHT) + .with(this::getFrom), + new Column().header("REMOTE").visible(remoteVisible).headerAlign(HorizontalAlign.CENTER) + .dataAlign(HorizontalAlign.CENTER) + .with(this::getRemote), + new Column().header("STATUS").headerAlign(HorizontalAlign.CENTER) + .with(this::getStatus), + new Column().header("PHASE").headerAlign(HorizontalAlign.CENTER) + .with(r -> r.lastErrorPhase), + new Column().header("MESSAGE").dataAlign(HorizontalAlign.LEFT) + .maxWidth(80, OverflowBehaviour.NEWLINE) + .with(r -> r.lastErrorMessage)))); + if (!er.stackTrace.isEmpty()) { + printer().println(); + printer().println(StringHelper.fillChars('-', 120)); + printer().println(StringHelper.padString(1, 55) + "STACK-TRACE"); + printer().println(StringHelper.fillChars('-', 120)); + for (String line : er.stackTrace) { + printer().println(String.format("\t%s", line)); + } + printer().println(); + } + } + protected int sortRow(Row o1, Row o2) { String s = sort; int negate = 1; @@ -272,6 +325,13 @@ public class CamelRouteStatus extends ProcessWatchCommand { return r.remote ? "x" : ""; } + protected String getStatus(Row r) { + if (r.lastErrorPhase != null) { + return "Error"; + } + return r.state; + } + protected String getId(Row r) { if (source && r.source != null) { return sourceLocLine(r.source); @@ -318,6 +378,9 @@ public class CamelRouteStatus extends ProcessWatchCommand { String load01; String load05; String load15; + String lastErrorPhase; + String lastErrorMessage; + List<String> stackTrace; } }