This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch standby
in repository https://gitbox.apache.org/repos/asf/camel.git

commit d7f0148e17054affa8f5636a9ac38f5b3dae6726
Author: Claus Ibsen <[email protected]>
AuthorDate: Sat Aug 31 17:40:15 2024 +0200

    CAMEL-21150: camel-jbang - Make tracer in standby as default
---
 .../modules/ROOT/pages/camel-jbang.adoc            |  37 +++++-
 .../core/commands/action/CamelTraceAction.java     | 137 ++++++++++++++++++---
 2 files changed, 157 insertions(+), 17 deletions(-)

diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
index da83b483961..1a201c620f6 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
@@ -1611,20 +1611,51 @@ command but only display message tracing information. 
This allows you to see eve
 The `trace` command has many options and can be used to _filter_, _grep_ or 
output on different detail _levels`.
 The _exchange id_ is logged (and grouped by colour), so you can use that to 
correlate the events, when traces are interleaved.
 
-For example if an existing integration is running named chuck, you can trace 
it as follows:
+The trace command will by default list the status of whether tracing is 
enabled or not in the integrations:
 
 [source,bash]
 ----
-camel trace chuck
+camel trace
+ PID   NAME   AGE  STATUS   TOTAL  QUEUE  FILTER  PATTERN
+ 6911  chuck   5s  Standby      0      0
+----
+
+Here we can see that the tracer is in standby mode, and you need to start the 
tracer before Camel will capture messages:
+
+TIP: Camel 4.8 onwards has tracing in standby mode (when using dev profile). 
You can enable tracing on startup by setting the configuration 
`camel.trace.enabled=true` in `application.properties`.
+
+[source,bash]
+----
+camel trace --action=start
 ----
 
-You can also trace all running integrations
+And if you run `camel trace` again you can see the tracer is started:
 
 [source,bash]
 ----
 camel trace
+PID   NAME   AGE   STATUS   TOTAL  QUEUE  FILTER  PATTERN
+6911  chuck  1m5s  Started     16      4
 ----
 
+And to show the traces you need to use the `dump` action as follows:
+
+[source,bash]
+----
+camel trace chuck --action=dump
+----
+
+You can also dump traces from all running integrations:
+
+[source,bash]
+----
+camel trace --action=dump
+----
+
+To stop tracing use `--action=stop`.
+
+And you can also clear the already traced messages with `--action=clear`.
+
 ==== Running Camel integrations in background
 
 The `run` command allows to run Camel in the background with the 
`--background` option.
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelTraceAction.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelTraceAction.java
index cedef90f181..63390605947 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelTraceAction.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelTraceAction.java
@@ -23,6 +23,7 @@ import java.io.LineNumberReader;
 import java.text.SimpleDateFormat;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -35,9 +36,15 @@ import java.util.Set;
 import java.util.concurrent.ArrayBlockingQueue;
 import java.util.regex.Pattern;
 
+import com.github.freva.asciitable.AsciiTable;
+import com.github.freva.asciitable.Column;
+import com.github.freva.asciitable.HorizontalAlign;
+import com.github.freva.asciitable.OverflowBehaviour;
 import org.apache.camel.catalog.impl.TimePatternConverter;
 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.FileUtil;
 import org.apache.camel.util.IOHelper;
 import org.apache.camel.util.StopWatch;
 import org.apache.camel.util.StringHelper;
@@ -75,17 +82,21 @@ public class CamelTraceAction extends ActionBaseCommand {
 
         @Override
         public Iterator<String> iterator() {
-            return List.of("start", "stop", "status").iterator();
+            return List.of("dump", "start", "stop", "status", 
"clear").iterator();
         }
     }
 
     @CommandLine.Parameters(description = "Name or pid of running Camel 
integration. (default selects all)", arity = "0..1")
     String name = "*";
 
-    @CommandLine.Option(names = { "--action" }, completionCandidates = 
ActionCompletionCandidates.class,
-            description = "Action for start, stop, or show status of tracing")
+    @CommandLine.Option(names = { "--action" }, completionCandidates = 
ActionCompletionCandidates.class, defaultValue = "status",
+                        description = "Action to start, stop, clear, list 
status, or dump traces")
     String action;
 
+    @CommandLine.Option(names = { "--sort" }, completionCandidates = 
PidNameAgeCompletionCandidates.class,
+                        description = "Sort by pid, name or age for showing 
status of tracing", defaultValue = "pid")
+    String sort;
+
     @CommandLine.Option(names = { "--timestamp" }, defaultValue = "true",
                         description = "Print timestamp.")
     boolean timestamp = true;
@@ -180,21 +191,30 @@ public class CamelTraceAction extends ActionBaseCommand {
         super(main);
     }
 
-    protected Integer doActionCall() throws Exception {
-        List<Long> pids = findPids(name);
+    @Override
+    public Integer doCall() throws Exception {
+        if ("dump".equals(action)) {
+            return doDumpCall();
+        } else if ("status".equals(action)) {
+            return doStatusCall();
+        }
 
-        if ("status".equals(action)) {
-            // TODO: show table of trace status per pid (like processor status)
-        } else {
-            for (long pid : pids) {
+        List<Long> pids = findPids(name);
+        for (long pid : pids) {
+            if ("clear".equals(action)) {
+                File f = getTraceFile("" + pid);
+                if (f.exists()) {
+                    IOHelper.writeText("{}", f);
+                }
+            } else {
                 JsonObject root = new JsonObject();
                 root.put("action", "trace");
-                File f = getActionFile(Long.toString(pid));
                 if ("start".equals(action)) {
                     root.put("enabled", "true");
                 } else if ("stop".equals(action)) {
                     root.put("enabled", "false");
                 }
+                File f = getActionFile(Long.toString(pid));
                 IOHelper.writeText(root.toJson(), f);
             }
         }
@@ -202,12 +222,88 @@ public class CamelTraceAction extends ActionBaseCommand {
         return 0;
     }
 
-    @Override
-    public Integer doCall() throws Exception {
-        if (action != null) {
-            return doActionCall();
+    protected Integer doStatusCall() {
+        List<StatusRow> rows = new ArrayList<>();
+
+        List<Long> pids = findPids(name);
+        ProcessHandle.allProcesses()
+                .filter(ph -> pids.contains(ph.pid()))
+                .forEach(ph -> {
+                    JsonObject root = loadStatus(ph.pid());
+                    if (root != null) {
+                        StatusRow row = new StatusRow();
+                        JsonObject context = (JsonObject) root.get("context");
+                        if (context == null) {
+                            return;
+                        }
+                        row.name = context.getString("name");
+                        if ("CamelJBang".equals(row.name)) {
+                            row.name = ProcessHelper.extractName(root, ph);
+                        }
+                        row.pid = Long.toString(ph.pid());
+                        row.uptime = extractSince(ph);
+                        row.age = TimeUtils.printSince(row.uptime);
+                        JsonObject jo = root.getMap("trace");
+                        if (jo != null) {
+                            row.enabled = jo.getBoolean("enabled");
+                            row.standby = jo.getBoolean("standby");
+                            row.counter = jo.getLong("counter");
+                            row.queueSize = jo.getLong("queueSize");
+                            row.filter = jo.getString("traceFilter");
+                            row.pattern = jo.getString("tracePattern");
+                        }
+                        rows.add(row);
+                    }
+                });
+
+        // sort rows
+        rows.sort(this::sortStatusRow);
+
+        if (!rows.isEmpty()) {
+            printer().println(AsciiTable.getTable(AsciiTable.NO_BORDERS, rows, 
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("AGE").headerAlign(HorizontalAlign.CENTER).with(r -> r.age),
+                    new Column().header("STATUS").with(this::getTraceStatus),
+                    new Column().header("TOTAL").with(r -> "" + r.counter),
+                    new Column().header("QUEUE").with(r -> "" + r.queueSize),
+                    new Column().header("FILTER").with(r -> r.filter),
+                    new Column().header("PATTERN").with(r -> r.pattern))));
         }
 
+        return 0;
+    }
+
+    private String getTraceStatus(StatusRow r) {
+        if (r.enabled) {
+            return "Started";
+        } else if (r.standby) {
+            return "Standby";
+        }
+        return "Stopped";
+    }
+
+    protected int sortStatusRow(StatusRow o1, StatusRow o2) {
+        String s = sort;
+        int negate = 1;
+        if (s.startsWith("-")) {
+            s = s.substring(1);
+            negate = -1;
+        }
+        switch (s) {
+            case "pid":
+                return Long.compare(Long.parseLong(o1.pid), 
Long.parseLong(o2.pid)) * negate;
+            case "name":
+                return o1.name.compareToIgnoreCase(o2.name) * negate;
+            case "age":
+                return Long.compare(o1.uptime, o2.uptime) * negate;
+            default:
+                return 0;
+        }
+    }
+
+    protected Integer doDumpCall() throws Exception {
         // setup table helper
         tableHelper = new MessageTableHelper();
         tableHelper.setPretty(pretty);
@@ -866,4 +962,17 @@ public class CamelTraceAction extends ActionBaseCommand {
 
     }
 
+    private static class StatusRow {
+        String pid;
+        String name;
+        String age;
+        long uptime;
+        boolean enabled;
+        boolean standby;
+        long counter;
+        long queueSize;
+        String filter;
+        String pattern;
+    }
+
 }

Reply via email to