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 471a17fc9890a4d19fabc6592184a1c54b689ae6
Author: Claus Ibsen <[email protected]>
AuthorDate: Mon Aug 29 14:20:51 2022 +0200

    CAMEL-18425: camel-cli - Display more information for top commands.
---
 .../GarbageCollectorDevConsoleConfigurer.java      |  49 +++++
 .../impl/console/ThreadDevConsoleConfigurer.java   |  49 +++++
 ...e.camel.impl.console.GarbageCollectorDevConsole |   2 +
 .../org.apache.camel.impl.console.ThreadDevConsole |   2 +
 .../services/org/apache/camel/dev-console/gc       |   2 +
 .../services/org/apache/camel/dev-console/thread   |   2 +
 .../impl/console/GarbageCollectorDevConsole.java   |  73 +++++++
 .../camel/impl/console/ThreadDevConsole.java       | 101 ++++++++++
 .../camel/cli/connector/LocalCliConnector.java     |  84 +++++++-
 .../dsl/jbang/core/commands/CamelJBangMain.java    |  10 +-
 .../core/commands/process/CamelContextTop.java     | 222 +++++++++++++++++++++
 .../{CamelTopStatus.java => CamelRouteTop.java}    |   6 +-
 .../process/{CamelTopStatus.java => CamelTop.java} |  26 +--
 13 files changed, 605 insertions(+), 23 deletions(-)

diff --git 
a/core/camel-console/src/generated/java/org/apache/camel/impl/console/GarbageCollectorDevConsoleConfigurer.java
 
b/core/camel-console/src/generated/java/org/apache/camel/impl/console/GarbageCollectorDevConsoleConfigurer.java
new file mode 100644
index 00000000000..6e11e40485e
--- /dev/null
+++ 
b/core/camel-console/src/generated/java/org/apache/camel/impl/console/GarbageCollectorDevConsoleConfigurer.java
@@ -0,0 +1,49 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.impl.console;
+
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.ExtendedPropertyConfigurerGetter;
+import org.apache.camel.spi.PropertyConfigurerGetter;
+import org.apache.camel.spi.ConfigurerStrategy;
+import org.apache.camel.spi.GeneratedPropertyConfigurer;
+import org.apache.camel.util.CaseInsensitiveMap;
+import org.apache.camel.impl.console.GarbageCollectorDevConsole;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@SuppressWarnings("unchecked")
+public class GarbageCollectorDevConsoleConfigurer extends 
org.apache.camel.support.component.PropertyConfigurerSupport implements 
GeneratedPropertyConfigurer, PropertyConfigurerGetter {
+
+    @Override
+    public boolean configure(CamelContext camelContext, Object obj, String 
name, Object value, boolean ignoreCase) {
+        org.apache.camel.impl.console.GarbageCollectorDevConsole target = 
(org.apache.camel.impl.console.GarbageCollectorDevConsole) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "camelcontext":
+        case "CamelContext": target.setCamelContext(property(camelContext, 
org.apache.camel.CamelContext.class, value)); return true;
+        default: return false;
+        }
+    }
+
+    @Override
+    public Class<?> getOptionType(String name, boolean ignoreCase) {
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "camelcontext":
+        case "CamelContext": return org.apache.camel.CamelContext.class;
+        default: return null;
+        }
+    }
+
+    @Override
+    public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+        org.apache.camel.impl.console.GarbageCollectorDevConsole target = 
(org.apache.camel.impl.console.GarbageCollectorDevConsole) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "camelcontext":
+        case "CamelContext": return target.getCamelContext();
+        default: return null;
+        }
+    }
+}
+
diff --git 
a/core/camel-console/src/generated/java/org/apache/camel/impl/console/ThreadDevConsoleConfigurer.java
 
b/core/camel-console/src/generated/java/org/apache/camel/impl/console/ThreadDevConsoleConfigurer.java
new file mode 100644
index 00000000000..6df6dd7ab60
--- /dev/null
+++ 
b/core/camel-console/src/generated/java/org/apache/camel/impl/console/ThreadDevConsoleConfigurer.java
@@ -0,0 +1,49 @@
+/* Generated by camel build tools - do NOT edit this file! */
+package org.apache.camel.impl.console;
+
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.ExtendedPropertyConfigurerGetter;
+import org.apache.camel.spi.PropertyConfigurerGetter;
+import org.apache.camel.spi.ConfigurerStrategy;
+import org.apache.camel.spi.GeneratedPropertyConfigurer;
+import org.apache.camel.util.CaseInsensitiveMap;
+import org.apache.camel.impl.console.ThreadDevConsole;
+
+/**
+ * Generated by camel build tools - do NOT edit this file!
+ */
+@SuppressWarnings("unchecked")
+public class ThreadDevConsoleConfigurer extends 
org.apache.camel.support.component.PropertyConfigurerSupport implements 
GeneratedPropertyConfigurer, PropertyConfigurerGetter {
+
+    @Override
+    public boolean configure(CamelContext camelContext, Object obj, String 
name, Object value, boolean ignoreCase) {
+        org.apache.camel.impl.console.ThreadDevConsole target = 
(org.apache.camel.impl.console.ThreadDevConsole) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "camelcontext":
+        case "CamelContext": target.setCamelContext(property(camelContext, 
org.apache.camel.CamelContext.class, value)); return true;
+        default: return false;
+        }
+    }
+
+    @Override
+    public Class<?> getOptionType(String name, boolean ignoreCase) {
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "camelcontext":
+        case "CamelContext": return org.apache.camel.CamelContext.class;
+        default: return null;
+        }
+    }
+
+    @Override
+    public Object getOptionValue(Object obj, String name, boolean ignoreCase) {
+        org.apache.camel.impl.console.ThreadDevConsole target = 
(org.apache.camel.impl.console.ThreadDevConsole) obj;
+        switch (ignoreCase ? name.toLowerCase() : name) {
+        case "camelcontext":
+        case "CamelContext": return target.getCamelContext();
+        default: return null;
+        }
+    }
+}
+
diff --git 
a/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.impl.console.GarbageCollectorDevConsole
 
b/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.impl.console.GarbageCollectorDevConsole
new file mode 100644
index 00000000000..da5eb35d631
--- /dev/null
+++ 
b/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.impl.console.GarbageCollectorDevConsole
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.impl.console.GarbageCollectorDevConsoleConfigurer
diff --git 
a/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.impl.console.ThreadDevConsole
 
b/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.impl.console.ThreadDevConsole
new file mode 100644
index 00000000000..6aff17f333c
--- /dev/null
+++ 
b/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/configurer/org.apache.camel.impl.console.ThreadDevConsole
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.impl.console.ThreadDevConsoleConfigurer
diff --git 
a/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/dev-console/gc
 
b/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/dev-console/gc
new file mode 100644
index 00000000000..b3f7a71ee18
--- /dev/null
+++ 
b/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/dev-console/gc
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.impl.console.GarbageCollectorDevConsole
diff --git 
a/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/dev-console/thread
 
b/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/dev-console/thread
new file mode 100644
index 00000000000..e34acd483f6
--- /dev/null
+++ 
b/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/dev-console/thread
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.impl.console.ThreadDevConsole
diff --git 
a/core/camel-console/src/main/java/org/apache/camel/impl/console/GarbageCollectorDevConsole.java
 
b/core/camel-console/src/main/java/org/apache/camel/impl/console/GarbageCollectorDevConsole.java
new file mode 100644
index 00000000000..9e2bdc6ee3a
--- /dev/null
+++ 
b/core/camel-console/src/main/java/org/apache/camel/impl/console/GarbageCollectorDevConsole.java
@@ -0,0 +1,73 @@
+/*
+ * 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.impl.console;
+
+import org.apache.camel.spi.Configurer;
+import org.apache.camel.spi.annotations.DevConsole;
+import org.apache.camel.util.json.JsonArray;
+import org.apache.camel.util.json.JsonObject;
+
+import java.lang.management.GarbageCollectorMXBean;
+import java.lang.management.ManagementFactory;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import static org.apache.camel.util.UnitUtils.printUnitFromBytesDot;
+
+@DevConsole("gc")
+@Configurer(bootstrap = true)
+public class GarbageCollectorDevConsole extends AbstractDevConsole {
+
+    public GarbageCollectorDevConsole() {
+        super("jvm", "gc", "Garbage Collector", "Displays Garbage Collector 
information");
+    }
+
+    @Override
+    protected String doCallText(Map<String, Object> options) {
+        StringBuilder sb = new StringBuilder();
+
+        List<GarbageCollectorMXBean> gcs = 
ManagementFactory.getGarbageCollectorMXBeans();
+        if (gcs != null && !gcs.isEmpty()) {
+            for (GarbageCollectorMXBean gc : gcs) {
+                sb.append(String.format("\n    %s: %s (%s ms)", gc.getName(), 
gc.getCollectionCount(), gc.getCollectionTime()));
+            }
+        }
+
+        return sb.toString();
+    }
+
+    @Override
+    protected JsonObject doCallJson(Map<String, Object> options) {
+        JsonObject root = new JsonObject();
+        JsonArray arr = new JsonArray();
+        root.put("garbageCollectors", arr);
+
+        List<GarbageCollectorMXBean> gcs = 
ManagementFactory.getGarbageCollectorMXBeans();
+        if (gcs != null && !gcs.isEmpty()) {
+            for (GarbageCollectorMXBean gc : gcs) {
+                JsonObject jo = new JsonObject();
+                arr.add(jo);
+                jo.put("name", gc.getName());
+                jo.put("collectionCount", gc.getCollectionCount());
+                jo.put("collectionTime", gc.getCollectionTime());
+                jo.put("memoryPoolNames", String.join(",", 
Arrays.asList(gc.getMemoryPoolNames())));
+            }
+        }
+        return root;
+    }
+}
diff --git 
a/core/camel-console/src/main/java/org/apache/camel/impl/console/ThreadDevConsole.java
 
b/core/camel-console/src/main/java/org/apache/camel/impl/console/ThreadDevConsole.java
new file mode 100644
index 00000000000..ed98ea22724
--- /dev/null
+++ 
b/core/camel-console/src/main/java/org/apache/camel/impl/console/ThreadDevConsole.java
@@ -0,0 +1,101 @@
+/*
+ * 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.impl.console;
+
+import org.apache.camel.spi.Configurer;
+import org.apache.camel.spi.annotations.DevConsole;
+import org.apache.camel.util.json.JsonArray;
+import org.apache.camel.util.json.JsonObject;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
+import java.util.Arrays;
+import java.util.Map;
+
+@DevConsole("thread")
+@Configurer(bootstrap = true)
+public class ThreadDevConsole extends AbstractDevConsole {
+
+    public ThreadDevConsole() {
+        super("jvm", "thread", "Thread", "Displays Threads information");
+    }
+
+    @Override
+    protected String doCallText(Map<String, Object> options) {
+        StringBuilder sb = new StringBuilder();
+
+        ThreadMXBean tb = ManagementFactory.getThreadMXBean();
+        if (tb != null) {
+            sb.append(String.format("Threads: %s\n", tb.getThreadCount()));
+            sb.append(String.format("Daemon Threads: %s\n", 
tb.getDaemonThreadCount()));
+            sb.append(String.format("Total Started Threads: %s\n", 
tb.getTotalStartedThreadCount()));
+            sb.append(String.format("Peak Threads: %s\n", 
tb.getPeakThreadCount()));
+
+            long[] ids = tb.getAllThreadIds();
+            Arrays.sort(ids);
+            for (long id : ids) {
+                ThreadInfo ti = tb.getThreadInfo(id);
+                if (ti != null) {
+                    String lock = ti.getLockName() != null ? "locked: " + 
ti.getLockName() : "";
+                    sb.append(String.format("\n    Thread %s: %s (%s) %s", id, 
ti.getThreadName(), ti.getThreadState(), lock));
+                }
+            }
+        }
+
+        return sb.toString();
+    }
+
+    @Override
+    protected JsonObject doCallJson(Map<String, Object> options) {
+        JsonObject root = new JsonObject();
+
+        ThreadMXBean tb = ManagementFactory.getThreadMXBean();
+        if (tb != null) {
+            root.put("threadCount", tb.getThreadCount());
+            root.put("daemonThreadCount", tb.getDaemonThreadCount());
+            root.put("totalStartedThreadCount", 
tb.getTotalStartedThreadCount());
+            root.put("peakThreadCount", tb.getPeakThreadCount());
+
+            JsonArray arr = new JsonArray();
+            root.put("threads", arr);
+
+            long[] ids = tb.getAllThreadIds();
+            Arrays.sort(ids);
+            for (long id : ids) {
+                ThreadInfo ti = tb.getThreadInfo(id);
+                if (ti != null) {
+                    JsonObject jo = new JsonObject();
+                    jo.put("id", ti.getThreadId());
+                    jo.put("name", ti.getThreadName());
+                    jo.put("state", ti.getThreadState());
+                    jo.put("blockedCount", ti.getBlockedCount());
+                    jo.put("blockedTime", ti.getBlockedTime());
+                    jo.put("waitedCount", ti.getWaitedCount());
+                    jo.put("waitedTime", ti.getWaitedTime());
+                    if (ti.getLockName() != null) {
+                        jo.put("lockName", ti.getLockName());
+                    }
+                    arr.add(jo);
+                }
+            }
+        }
+
+        return root;
+    }
+
+}
diff --git 
a/dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/LocalCliConnector.java
 
b/dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/LocalCliConnector.java
index d51a7f79a27..f26d00b5afd 100644
--- 
a/dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/LocalCliConnector.java
+++ 
b/dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/LocalCliConnector.java
@@ -17,7 +17,14 @@
 package org.apache.camel.cli.connector;
 
 import java.io.File;
+import java.lang.management.ClassLoadingMXBean;
+import java.lang.management.GarbageCollectorMXBean;
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryMXBean;
+import java.lang.management.RuntimeMXBean;
+import java.lang.management.ThreadMXBean;
 import java.util.Collection;
+import java.util.List;
 import java.util.Locale;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -168,11 +175,15 @@ public class LocalCliConnector extends ServiceSupport 
implements CliConnector, C
             ProcessHandle.current().info().user().ifPresent(u -> 
rc.put("user", u));
             rc.put("platform", platform);
             if (platformVersion != null) {
-                rc.put("version", platformVersion);
+                rc.put("platformVersion", platformVersion);
             }
             if (mainClass != null) {
                 rc.put("mainClass", mainClass);
             }
+            RuntimeMXBean mb = ManagementFactory.getRuntimeMXBean();
+            if (mb != null) {
+                rc.put("javaVersion", mb.getVmVersion());
+            }
             root.put("runtime", rc);
 
             // collect details via console
@@ -190,6 +201,23 @@ public class LocalCliConnector extends ServiceSupport 
implements CliConnector, C
                     root.put("routes", json2.get("routes"));
                 }
             }
+            // various details
+            JsonObject mem = collectMemory();
+            if (mem != null) {
+                root.put("memory", mem);
+            }
+            JsonObject cl = collectClassLoading();
+            if (cl != null) {
+                root.put("classLoading", cl);
+            }
+            JsonObject threads = collectThreads();
+            if (threads != null) {
+                root.put("threads", threads);
+            }
+            JsonObject gc = collectGC();
+            if (gc != null) {
+                root.put("gc", gc);
+            }
             // and health-check readiness
             Collection<HealthCheck.Result> res = 
HealthCheckHelper.invokeReadiness(camelContext);
             for (var r : res) {
@@ -213,6 +241,60 @@ public class LocalCliConnector extends ServiceSupport 
implements CliConnector, C
         }
     }
 
+    private JsonObject collectMemory() {
+        MemoryMXBean mb = ManagementFactory.getMemoryMXBean();
+        if (mb != null) {
+            JsonObject root = new JsonObject();
+            root.put("heapMemoryUsed", mb.getHeapMemoryUsage().getUsed());
+            root.put("heapMemoryCommitted", 
mb.getHeapMemoryUsage().getCommitted());
+            root.put("heapMemoryMax", mb.getHeapMemoryUsage().getMax());
+            root.put("nonHeapMemoryUsed", 
mb.getNonHeapMemoryUsage().getUsed());
+            root.put("nonHeapMemoryCommitted", 
mb.getNonHeapMemoryUsage().getCommitted());
+            return root;
+        }
+        return null;
+    }
+
+    private JsonObject collectClassLoading() {
+        ClassLoadingMXBean cb = ManagementFactory.getClassLoadingMXBean();
+        if (cb != null) {
+            JsonObject root = new JsonObject();
+            root.put("loadedClassCount", cb.getLoadedClassCount());
+            root.put("unloadedClassCount", cb.getUnloadedClassCount());
+            root.put("totalLoadedClassCount", cb.getTotalLoadedClassCount());
+            return root;
+        }
+        return null;
+    }
+
+    private JsonObject collectThreads() {
+        ThreadMXBean tb = ManagementFactory.getThreadMXBean();
+        if (tb != null) {
+            JsonObject root = new JsonObject();
+            root.put("threadCount", tb.getThreadCount());
+            root.put("peakThreadCount", tb.getPeakThreadCount());
+            return root;
+        }
+        return null;
+    }
+
+    private JsonObject collectGC() {
+        List<GarbageCollectorMXBean> gcs = 
ManagementFactory.getGarbageCollectorMXBeans();
+        if (gcs != null && !gcs.isEmpty()) {
+            JsonObject root = new JsonObject();
+            long count = 0;
+            long time = 0;
+            for (GarbageCollectorMXBean gc : gcs) {
+                count += gc.getCollectionCount();
+                time += gc.getCollectionTime();
+            }
+            root.put("collectionCount", count);
+            root.put("collectionTime", time);
+            return root;
+        }
+        return null;
+    }
+
     @Override
     protected void doStop() throws Exception {
         // cleanup
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java
index e19a4f0f55f..32448d38b62 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java
@@ -21,9 +21,11 @@ import java.util.concurrent.Callable;
 import org.apache.camel.catalog.CamelCatalog;
 import org.apache.camel.catalog.DefaultCamelCatalog;
 import org.apache.camel.dsl.jbang.core.commands.process.CamelContextStatus;
+import org.apache.camel.dsl.jbang.core.commands.process.CamelContextTop;
 import org.apache.camel.dsl.jbang.core.commands.process.CamelRouteStatus;
+import org.apache.camel.dsl.jbang.core.commands.process.CamelRouteTop;
 import org.apache.camel.dsl.jbang.core.commands.process.CamelStatus;
-import org.apache.camel.dsl.jbang.core.commands.process.CamelTopStatus;
+import org.apache.camel.dsl.jbang.core.commands.process.CamelTop;
 import org.apache.camel.dsl.jbang.core.commands.process.Hawtio;
 import org.apache.camel.dsl.jbang.core.commands.process.Jolokia;
 import org.apache.camel.dsl.jbang.core.commands.process.ListProcess;
@@ -44,8 +46,10 @@ public class CamelJBangMain implements Callable<Integer> {
                 .addSubcommand("stop", new CommandLine(new StopProcess(main)))
                 .addSubcommand("get", new CommandLine(new CamelStatus(main))
                         .addSubcommand("context", new CommandLine(new 
CamelContextStatus(main)))
-                        .addSubcommand("route", new CommandLine(new 
CamelRouteStatus(main)))
-                        .addSubcommand("top", new CommandLine(new 
CamelTopStatus(main))))
+                        .addSubcommand("route", new CommandLine(new 
CamelRouteStatus(main))))
+                .addSubcommand("top", new CommandLine(new CamelTop(main))
+                        .addSubcommand("context", new CommandLine(new 
CamelContextTop(main)))
+                        .addSubcommand("route", new CommandLine(new 
CamelRouteTop(main))))
                 .addSubcommand("generate", new CommandLine(new 
CodeGenerator(main))
                         .addSubcommand("rest", new CommandLine(new 
CodeRestGenerator(main))))
                 .addSubcommand("jolokia", new CommandLine(new Jolokia(main)))
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelContextTop.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelContextTop.java
new file mode 100644
index 00000000000..2c51d4acfa5
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelContextTop.java
@@ -0,0 +1,222 @@
+/*
+ * 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.dsl.jbang.core.commands.process;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+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.dsl.jbang.core.commands.CamelJBangMain;
+import org.apache.camel.util.TimeUtils;
+import org.apache.camel.util.json.JsonObject;
+import picocli.CommandLine;
+import picocli.CommandLine.Command;
+
+@Command(name = "integration", aliases = { "int", "integration", 
"integrations", "context" },
+         description = "Top status of Camel integrations")
+public class CamelContextTop extends ProcessBaseCommand {
+
+    @CommandLine.Parameters(description = "Name or pid of running Camel 
integration", arity = "0..1")
+    String name = "*";
+
+    @CommandLine.Option(names = { "--sort" },
+                        description = "Sort by pid, name, mem, or age", 
defaultValue = "mem")
+    String sort;
+
+    public CamelContextTop(CamelJBangMain main) {
+        super(main);
+    }
+
+    @Override
+    public Integer call() throws Exception {
+        List<Row> rows = new ArrayList<>();
+
+        List<Long> pids = findPids(name);
+        ProcessHandle.allProcesses()
+                .filter(ph -> pids.contains(ph.pid()))
+                .forEach(ph -> {
+                    JsonObject root = loadStatus(ph.pid());
+                    // there must be a status file for the running Camel 
integration
+                    if (root != null) {
+                        Row row = new Row();
+                        rows.add(row);
+                        row.name = extractName(root, ph);
+                        row.pid = "" + ph.pid();
+                        row.uptime = extractSince(ph);
+                        row.ago = TimeUtils.printSince(row.uptime);
+                        JsonObject runtime = (JsonObject) root.get("runtime");
+                        row.platform = extractPlatform(ph, runtime);
+                        row.platformVersion = runtime != null ? 
runtime.getString("platformVersion") : null;
+                        row.javaVersion = runtime != null ? 
runtime.getString("javaVersion") : null;
+                        JsonObject context = (JsonObject) root.get("context");
+                        row.state = context.getInteger("phase");
+                        row.camelVersion = context.getString("version");
+
+                        JsonObject mem = (JsonObject) root.get("memory");
+                        if (mem != null) {
+                            row.heapMemUsed = mem.getLong("heapMemoryUsed");
+                            row.heapMemCommitted = 
mem.getLong("heapMemoryCommitted");
+                            row.heapMemMax = mem.getLong("heapMemoryMax");
+                            row.nonHeapMemUsed = 
mem.getLong("nonHeapMemoryUsed");
+                            row.nonHeapMemCommitted = 
mem.getLong("nonHeapMemoryCommitted");
+                        }
+                        JsonObject threads = (JsonObject) root.get("threads");
+                        if (threads != null) {
+                            row.threadCount = 
threads.getInteger("threadCount");
+                            row.peakThreadCount = 
threads.getInteger("peakThreadCount");
+                        }
+                        JsonObject cl = (JsonObject) root.get("classLoading");
+                        if (cl != null) {
+                            row.loadedClassCount = 
cl.getInteger("loadedClassCount");
+                            row.totalLoadedClassCount = 
cl.getLong("totalLoadedClassCount");
+                        }
+                        JsonObject gc = (JsonObject) root.get("gc");
+                        if (gc != null) {
+                            row.gcCount = gc.getLong("collectionCount");
+                            row.gcTime = gc.getLong("collectionTime");
+                        }
+                    }
+                });
+
+        // sort rows
+        rows.sort(this::sortRow);
+
+        if (!rows.isEmpty()) {
+            System.out.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)
+                            .with(r -> r.name),
+                    new 
Column().header("JAVA").dataAlign(HorizontalAlign.LEFT).with(this::getJavaVersion),
+                    new 
Column().header("CAMEL").dataAlign(HorizontalAlign.LEFT).with(r -> 
r.camelVersion),
+                    new 
Column().header("PLATFORM").dataAlign(HorizontalAlign.LEFT).with(this::getPlatform),
+                    new 
Column().header("STATUS").headerAlign(HorizontalAlign.CENTER)
+                            .with(r -> extractState(r.state)),
+                    new 
Column().header("AGE").headerAlign(HorizontalAlign.CENTER).with(r -> r.ago),
+                    new 
Column().header("HEAP").headerAlign(HorizontalAlign.CENTER).with(this::getHeapMemory),
+                    new 
Column().header("NON-HEAP").headerAlign(HorizontalAlign.CENTER).with(this::getNonHeapMemory),
+                    new 
Column().header("GC").headerAlign(HorizontalAlign.CENTER).with(this::getGC),
+                    new 
Column().header("THREADS").headerAlign(HorizontalAlign.CENTER).with(this::getThreads),
+                    new 
Column().header("CLASSES").headerAlign(HorizontalAlign.CENTER).with(this::getClassLoading))));
+        }
+
+        return 0;
+    }
+
+    private String extractPlatform(ProcessHandle ph, JsonObject runtime) {
+        String answer = runtime != null ? runtime.getString("platform") : null;
+        if ("Camel".equals(answer)) {
+            // generic camel, we need to check if we run in JBang
+            String cl = ph.info().commandLine().orElse("");
+            if (cl.contains("main.CamelJBang run")) {
+                answer = "JBang";
+            }
+        }
+        return answer;
+    }
+
+    protected int sortRow(Row o1, Row o2) {
+        switch (sort) {
+            case "pid":
+                return Long.compare(Long.parseLong(o1.pid), 
Long.parseLong(o2.pid));
+            case "name":
+                return o1.name.compareToIgnoreCase(o2.name);
+            case "mem":
+                return Long.compare(o1.heapMemUsed, o2.heapMemUsed) * -1; // 
we want the biggest first
+            case "age":
+                return Long.compare(o1.uptime, o2.uptime);
+            default:
+                return 0;
+        }
+    }
+
+    private String getPlatform(Row r) {
+        if (r.platformVersion != null) {
+            return r.platform + " v" + r.platformVersion;
+        } else {
+            return r.platform;
+        }
+    }
+
+    private String getHeapMemory(Row r) {
+        return asMegaBytesOneDigit(r.heapMemUsed) + "/" + 
asMegaBytesOneDigit(r.heapMemCommitted) + "/"
+               + asMegaBytesOneDigit(r.heapMemMax) + " MB";
+    }
+
+    private String getNonHeapMemory(Row r) {
+        return asMegaBytesOneDigit(r.nonHeapMemUsed) + "/" + 
asMegaBytesOneDigit(r.nonHeapMemCommitted) + " MB";
+    }
+
+    private String getThreads(Row r) {
+        return r.threadCount + "/" + r.peakThreadCount;
+    }
+
+    private String getClassLoading(Row r) {
+        return r.loadedClassCount + "/" + r.totalLoadedClassCount;
+    }
+
+    private String getGC(Row r) {
+        if (r.gcTime <= 0) {
+            return "";
+        } else {
+            return r.gcTime + "ms (" + r.gcCount + ")";
+        }
+    }
+
+    private String getJavaVersion(Row r) {
+        String v = r.javaVersion;
+        for (int i = 0; i < v.length(); i++) {
+            char ch = v.charAt(i);
+            if (Character.isDigit(ch) || ch == '.') {
+                continue;
+            }
+            return v.substring(0, i);
+        }
+        return v;
+    }
+
+    private static long asMegaBytesOneDigit(long bytes) {
+        return bytes / 1000 / 1000;
+    }
+
+    private static class Row {
+        String pid;
+        String platform;
+        String platformVersion;
+        String camelVersion;
+        String javaVersion;
+        String name;
+        int state;
+        String ago;
+        long uptime;
+        long heapMemUsed;
+        long heapMemCommitted;
+        long heapMemMax;
+        long nonHeapMemUsed;
+        long nonHeapMemCommitted;
+        int threadCount;
+        int peakThreadCount;
+        int loadedClassCount;
+        long totalLoadedClassCount;
+        long gcCount;
+        long gcTime;
+    }
+
+}
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelTopStatus.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelRouteTop.java
similarity index 89%
copy from 
dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelTopStatus.java
copy to 
dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelRouteTop.java
index 44d6e8a17ea..afef2e6bb1c 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelTopStatus.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelRouteTop.java
@@ -19,10 +19,10 @@ package org.apache.camel.dsl.jbang.core.commands.process;
 import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain;
 import picocli.CommandLine.Command;
 
-@Command(name = "top", description = "Top performing routes")
-public class CamelTopStatus extends CamelRouteStatus {
+@Command(name = "route", description = "Top performing routes")
+public class CamelRouteTop extends CamelRouteStatus {
 
-    public CamelTopStatus(CamelJBangMain main) {
+    public CamelRouteTop(CamelJBangMain main) {
         super(main);
     }
 
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelTopStatus.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelTop.java
similarity index 62%
rename from 
dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelTopStatus.java
rename to 
dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelTop.java
index 44d6e8a17ea..93c56715adf 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelTopStatus.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelTop.java
@@ -16,28 +16,22 @@
  */
 package org.apache.camel.dsl.jbang.core.commands.process;
 
+import org.apache.camel.dsl.jbang.core.commands.CamelCommand;
 import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain;
-import picocli.CommandLine.Command;
+import picocli.CommandLine;
 
-@Command(name = "top", description = "Top performing routes")
-public class CamelTopStatus extends CamelRouteStatus {
[email protected](name = "top",
+                     description = "Top status of Camel integrations (use 
--help to see sub commands)")
+public class CamelTop extends CamelCommand {
 
-    public CamelTopStatus(CamelJBangMain main) {
+    public CamelTop(CamelJBangMain main) {
         super(main);
     }
 
     @Override
-    protected int sortRow(Row o1, Row o2) {
-        // sort for highest mean value as we want the slowest in the top
-        long m1 = o1.mean != null ? Long.parseLong(o1.mean) : 0;
-        long m2 = o2.mean != null ? Long.parseLong(o2.mean) : 0;
-        if (m1 < m2) {
-            return 1;
-        } else if (m1 > m2) {
-            return -1;
-        } else {
-            return 0;
-        }
+    public Integer call() throws Exception {
+        // default to top the integrations
+        new CommandLine(new CamelRouteTop(getMain())).execute();
+        return 0;
     }
-
 }

Reply via email to