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 2024/09/05 14:39:14 UTC
(camel) branch browse created (now 6f164cf9dda)
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a change to branch browse
in repository https://gitbox.apache.org/repos/asf/camel.git
at 6f164cf9dda CAMEL-21178: Add browse jbang command
This branch includes the following new commits:
new 8a982f80082 CAMEL-21178: Add browse dev console
new 603283bf797 CAMEL-21178: Add browse jbang command
new 80a374a25b0 CAMEL-21178: Add browse jbang command
new 6f164cf9dda CAMEL-21178: Add browse jbang command
The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(camel) 02/04: CAMEL-21178: Add browse jbang command
Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch browse
in repository https://gitbox.apache.org/repos/asf/camel.git
commit 603283bf797bde5b80b77793cc1823cb4ba6fb97
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu Sep 5 15:28:50 2024 +0200
CAMEL-21178: Add browse jbang command
---
.../org/apache/camel/catalog/dev-consoles.properties | 1 +
.../org/apache/camel/catalog/dev-consoles/browse.json | 15 +++++++++++++++
.../apache/camel/cli/connector/LocalCliConnector.java | 18 ++++++++++++++++++
3 files changed, 34 insertions(+)
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles.properties b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles.properties
index 0d11272191f..6600db7d46c 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles.properties
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles.properties
@@ -4,6 +4,7 @@ azure-secrets
bean
bean-model
blocked
+browse
circuit-breaker
consumer
context
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles/browse.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles/browse.json
new file mode 100644
index 00000000000..b08c06fde1a
--- /dev/null
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/dev-consoles/browse.json
@@ -0,0 +1,15 @@
+{
+ "console": {
+ "kind": "console",
+ "group": "camel",
+ "name": "browse",
+ "title": "Browse",
+ "description": "Browse pending messages on Camel components",
+ "deprecated": false,
+ "javaType": "org.apache.camel.impl.console.BrowseDevConsole",
+ "groupId": "org.apache.camel",
+ "artifactId": "camel-console",
+ "version": "4.8.0-SNAPSHOT"
+ }
+}
+
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 7ad6ecff054..b88aadc0e05 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
@@ -278,6 +278,8 @@ public class LocalCliConnector extends ServiceSupport implements CliConnector, C
doActionKafkaTask();
} else if ("trace".equals(action)) {
doActionTraceTask(root);
+ } else if ("browse".equals(action)) {
+ doActionBrowseTask(root);
}
} catch (Exception e) {
// ignore
@@ -771,6 +773,22 @@ public class LocalCliConnector extends ServiceSupport implements CliConnector, C
}
}
+ private void doActionBrowseTask(JsonObject root) throws IOException {
+ DevConsole dc = camelContext.getCamelContextExtension().getContextPlugin(DevConsoleRegistry.class)
+ .resolveById("browse");
+ if (dc != null) {
+ String filter = root.getString("filter");
+ String limit = root.getString("limit");
+ String dump = root.getString("dump");
+ JsonObject json
+ = (JsonObject) dc.call(DevConsole.MediaType.JSON, Map.of("filter", filter, "limit", limit, "dump", dump));
+ LOG.trace("Updating output file: {}", outputFile);
+ IOHelper.writeText(json.toJson(), outputFile);
+ } else {
+ IOHelper.writeText("{}", outputFile);
+ }
+ }
+
private void doActionBeanTask(JsonObject root) throws IOException {
String filter = root.getStringOrDefault("filter", "");
String properties = root.getStringOrDefault("properties", "true");
(camel) 04/04: CAMEL-21178: Add browse jbang command
Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch browse
in repository https://gitbox.apache.org/repos/asf/camel.git
commit 6f164cf9dda09a329e46a217c8d67eb1176dd994
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu Sep 5 16:38:56 2024 +0200
CAMEL-21178: Add browse jbang command
---
.../core/commands/action/CamelBrowseAction.java | 46 +++++++++++-----------
.../core/commands/action/MessageTableHelper.java | 3 +-
2 files changed, 24 insertions(+), 25 deletions(-)
diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelBrowseAction.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelBrowseAction.java
index 177b53d2446..0d04a83c661 100644
--- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelBrowseAction.java
+++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelBrowseAction.java
@@ -16,6 +16,12 @@
*/
package org.apache.camel.dsl.jbang.core.commands.action;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
import com.github.freva.asciitable.AsciiTable;
import com.github.freva.asciitable.Column;
import com.github.freva.asciitable.HorizontalAlign;
@@ -29,12 +35,6 @@ import org.apache.camel.util.json.JsonArray;
import org.apache.camel.util.json.JsonObject;
import picocli.CommandLine;
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
-
@CommandLine.Command(name = "browse",
description = "Browse pending messages on endpoints", sortOptions = false)
public class CamelBrowseAction extends ActionBaseCommand {
@@ -59,23 +59,23 @@ public class CamelBrowseAction extends ActionBaseCommand {
String endpoint;
@CommandLine.Option(names = { "--short-uri" },
- description = "List endpoint URI without query parameters (short)")
+ description = "List endpoint URI without query parameters (short)")
boolean shortUri;
@CommandLine.Option(names = { "--wide-uri" },
- description = "List endpoint URI in full details")
+ description = "List endpoint URI in full details")
boolean wideUri;
@CommandLine.Option(names = { "--limit" }, defaultValue = "100",
- description = "Limits the number of messages to dump per endpoint")
+ description = "Limits the number of messages to dump per endpoint")
int limit;
@CommandLine.Option(names = { "--dump" }, defaultValue = "false",
- description = "Whether to include message dumps")
+ description = "Whether to include message dumps")
boolean dump;
@CommandLine.Option(names = { "--sort" }, completionCandidates = UriSizeCompletionCandidates.class,
- description = "Sort by uri, or size", defaultValue = "uri")
+ description = "Sort by uri, or size", defaultValue = "uri")
String sort;
@CommandLine.Option(names = { "--show-exchange-properties" }, defaultValue = "false",
@@ -99,8 +99,6 @@ public class CamelBrowseAction extends ActionBaseCommand {
private volatile long pid;
- private MessageTableHelper tableHelper;
-
public CamelBrowseAction(CamelJBangMain main) {
super(main);
}
@@ -135,12 +133,12 @@ public class CamelBrowseAction extends ActionBaseCommand {
// ignore
}
- List<BrowseRow> rows = new ArrayList<>();
+ List<Row> rows = new ArrayList<>();
JsonObject jo = getJsonObject(outputFile);
if (jo != null) {
root = loadStatus(this.pid);
if (root != null) {
- BrowseRow row = new BrowseRow();
+ Row row = new Row();
row.pid = Long.toString(this.pid);
JsonObject context = (JsonObject) root.get("context");
if (context == null) {
@@ -182,13 +180,13 @@ public class CamelBrowseAction extends ActionBaseCommand {
return 0;
}
- protected void dumpMessages(List<BrowseRow> rows) {
- tableHelper = new MessageTableHelper();
+ protected void dumpMessages(List<Row> rows) {
+ MessageTableHelper tableHelper = new MessageTableHelper();
tableHelper.setPretty(pretty);
tableHelper.setLoggingColor(loggingColor);
tableHelper.setShowExchangeProperties(showExchangeProperties);
- for (BrowseRow row : rows) {
+ for (Row row : rows) {
if (row.messages != null) {
for (int i = 0; i < row.messages.size(); i++) {
JsonObject jo = row.messages.get(i);
@@ -213,7 +211,7 @@ public class CamelBrowseAction extends ActionBaseCommand {
}
}
- protected void tableStatus(List<BrowseRow> rows) {
+ protected void tableStatus(List<Row> rows) {
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)
@@ -226,7 +224,7 @@ public class CamelBrowseAction extends ActionBaseCommand {
new Column().header("SIZE").with(r -> "" + r.size))));
}
- protected int sortRow(BrowseRow o1, BrowseRow o2) {
+ protected int sortRow(Row o1, Row o2) {
String s = sort;
int negate = 1;
if (s.startsWith("-")) {
@@ -243,7 +241,7 @@ public class CamelBrowseAction extends ActionBaseCommand {
}
}
- protected String getEndpointUri(BrowseRow r) {
+ protected String getEndpointUri(Row r) {
String u = r.uri;
if (shortUri) {
int pos = u.indexOf('?');
@@ -254,7 +252,7 @@ public class CamelBrowseAction extends ActionBaseCommand {
return u;
}
- private static class BrowseRow implements Cloneable {
+ private static class Row implements Cloneable {
String pid;
String name;
String ago;
@@ -263,9 +261,9 @@ public class CamelBrowseAction extends ActionBaseCommand {
long size;
List<JsonObject> messages;
- BrowseRow copy() {
+ Row copy() {
try {
- return (BrowseRow) clone();
+ return (Row) clone();
} catch (CloneNotSupportedException e) {
return null;
}
diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/MessageTableHelper.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/MessageTableHelper.java
index cd9d384ceff..69cce88dc95 100644
--- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/MessageTableHelper.java
+++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/MessageTableHelper.java
@@ -141,7 +141,8 @@ public class MessageTableHelper {
eRow = new TableRow("Exchange", root.getString("exchangeType"), exchangePattern, exchangeId);
tab1 = AsciiTable.getTable(AsciiTable.NO_BORDERS, List.of(eRow), Arrays.asList(
new Column().dataAlign(HorizontalAlign.LEFT)
- .minWidth(showExchangeProperties || showExchangeVariables ? 12 : 10).with(TableRow::kindAsString),
+ .minWidth(showExchangeProperties || showExchangeVariables ? 12 : 10)
+ .with(TableRow::kindAsString),
new Column().dataAlign(HorizontalAlign.LEFT).with(TableRow::typeAsString)));
tab1b = AsciiTable.getTable(AsciiTable.NO_BORDERS, List.of(eRow), Arrays.asList(
new Column().dataAlign(HorizontalAlign.CENTER)
(camel) 03/04: CAMEL-21178: Add browse jbang command
Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch browse
in repository https://gitbox.apache.org/repos/asf/camel.git
commit 80a374a25b03559feed6aae966a2823f32edd6cf
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu Sep 5 16:36:46 2024 +0200
CAMEL-21178: Add browse jbang command
---
.../dsl/jbang/core/commands/CamelJBangMain.java | 1 +
.../core/commands/action/ActionBaseCommand.java | 2 +-
.../core/commands/action/CamelBrowseAction.java | 275 +++++++++++++++++++++
.../core/commands/action/MessageTableHelper.java | 22 +-
4 files changed, 289 insertions(+), 11 deletions(-)
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 c7627b3897a..58d7b13e44f 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
@@ -122,6 +122,7 @@ public class CamelJBangMain implements Callable<Integer> {
.addSubcommand("reset-stats", new CommandLine(new CamelResetStatsAction(main)))
.addSubcommand("reload", new CommandLine(new CamelReloadAction(main)))
.addSubcommand("send", new CommandLine(new CamelSendAction(main)))
+ .addSubcommand("browse", new CommandLine(new CamelBrowseAction(main)))
.addSubcommand("stub", new CommandLine(new CamelStubAction(main)))
.addSubcommand("thread-dump", new CommandLine(new CamelThreadDump(main)))
.addSubcommand("logger", new CommandLine(new LoggerAction(main)))
diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/ActionBaseCommand.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/ActionBaseCommand.java
index 6ea515545b9..7520e89cd47 100644
--- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/ActionBaseCommand.java
+++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/ActionBaseCommand.java
@@ -94,7 +94,7 @@ abstract class ActionBaseCommand extends CamelCommand {
static long extractSince(ProcessHandle ph) {
long since = 0;
- if (ph.info().startInstant().isPresent()) {
+ if (ph != null && ph.info().startInstant().isPresent()) {
since = ph.info().startInstant().get().toEpochMilli();
}
return since;
diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelBrowseAction.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelBrowseAction.java
new file mode 100644
index 00000000000..177b53d2446
--- /dev/null
+++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelBrowseAction.java
@@ -0,0 +1,275 @@
+/*
+ * 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.action;
+
+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.dsl.jbang.core.common.ProcessHelper;
+import org.apache.camel.util.FileUtil;
+import org.apache.camel.util.IOHelper;
+import org.apache.camel.util.TimeUtils;
+import org.apache.camel.util.json.JsonArray;
+import org.apache.camel.util.json.JsonObject;
+import picocli.CommandLine;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+@CommandLine.Command(name = "browse",
+ description = "Browse pending messages on endpoints", sortOptions = false)
+public class CamelBrowseAction extends ActionBaseCommand {
+
+ public static class UriSizeCompletionCandidates implements Iterable<String> {
+
+ public UriSizeCompletionCandidates() {
+ }
+
+ @Override
+ public Iterator<String> iterator() {
+ return List.of("uri", "size").iterator();
+ }
+
+ }
+
+ @CommandLine.Parameters(description = "Name or pid of running Camel integration", arity = "0..1")
+ String name = "*";
+
+ @CommandLine.Option(names = { "--endpoint" },
+ description = "Endpoint to browse messages (can be uri, pattern, or refer to a route id)")
+ String endpoint;
+
+ @CommandLine.Option(names = { "--short-uri" },
+ description = "List endpoint URI without query parameters (short)")
+ boolean shortUri;
+
+ @CommandLine.Option(names = { "--wide-uri" },
+ description = "List endpoint URI in full details")
+ boolean wideUri;
+
+ @CommandLine.Option(names = { "--limit" }, defaultValue = "100",
+ description = "Limits the number of messages to dump per endpoint")
+ int limit;
+
+ @CommandLine.Option(names = { "--dump" }, defaultValue = "false",
+ description = "Whether to include message dumps")
+ boolean dump;
+
+ @CommandLine.Option(names = { "--sort" }, completionCandidates = UriSizeCompletionCandidates.class,
+ description = "Sort by uri, or size", defaultValue = "uri")
+ String sort;
+
+ @CommandLine.Option(names = { "--show-exchange-properties" }, defaultValue = "false",
+ description = "Show exchange properties in browsed messages")
+ boolean showExchangeProperties;
+
+ @CommandLine.Option(names = { "--show-headers" }, defaultValue = "true",
+ description = "Show message headers in browsed messages")
+ boolean showHeaders = true;
+
+ @CommandLine.Option(names = { "--show-body" }, defaultValue = "true",
+ description = "Show message body in browsed messages")
+ boolean showBody = true;
+
+ @CommandLine.Option(names = { "--logging-color" }, defaultValue = "true", description = "Use colored logging")
+ boolean loggingColor = true;
+
+ @CommandLine.Option(names = { "--pretty" },
+ description = "Pretty print message body when using JSon or XML format")
+ boolean pretty;
+
+ private volatile long pid;
+
+ private MessageTableHelper tableHelper;
+
+ public CamelBrowseAction(CamelJBangMain main) {
+ super(main);
+ }
+
+ @Override
+ public Integer doCall() throws Exception {
+ List<Long> pids = findPids(name);
+ if (pids.isEmpty()) {
+ return 0;
+ } else if (pids.size() > 1) {
+ printer().println("Name or pid " + name + " matches " + pids.size()
+ + " running Camel integrations. Specify a name or PID that matches exactly one.");
+ return 0;
+ }
+
+ this.pid = pids.get(0);
+
+ // ensure output file is deleted before executing action
+ File outputFile = getOutputFile(Long.toString(pid));
+ FileUtil.deleteFile(outputFile);
+
+ JsonObject root = new JsonObject();
+ root.put("action", "browse");
+ root.put("filter", endpoint == null ? "*" : endpoint);
+ root.put("limit", limit);
+ root.put("dump", dump);
+
+ File f = getActionFile(Long.toString(pid));
+ try {
+ IOHelper.writeText(root.toJson(), f);
+ } catch (Exception e) {
+ // ignore
+ }
+
+ List<BrowseRow> rows = new ArrayList<>();
+ JsonObject jo = getJsonObject(outputFile);
+ if (jo != null) {
+ root = loadStatus(this.pid);
+ if (root != null) {
+ BrowseRow row = new BrowseRow();
+ row.pid = Long.toString(this.pid);
+ JsonObject context = (JsonObject) root.get("context");
+ if (context == null) {
+ return 0;
+ }
+ ProcessHandle ph = ProcessHandle.of(this.pid).orElse(null);
+ row.name = context.getString("name");
+ if ("CamelJBang".equals(row.name)) {
+ row.name = ProcessHelper.extractName(root, ph);
+ }
+ row.uptime = extractSince(ph);
+ row.ago = TimeUtils.printSince(row.uptime);
+ JsonArray arr = jo.getCollection("browse");
+ for (int i = 0; arr != null && i < arr.size(); i++) {
+ JsonObject o = (JsonObject) arr.get(i);
+ row.uri = o.getString("endpointUri");
+ row.size = o.getLong("size");
+ if (dump) {
+ row.messages = o.getCollection("messages");
+ }
+ rows.add(row);
+ row = row.copy();
+ }
+ }
+ }
+
+ // sort rows
+ rows.sort(this::sortRow);
+
+ if (dump) {
+ dumpMessages(rows);
+ } else {
+ tableStatus(rows);
+ }
+
+ // delete output file after use
+ FileUtil.deleteFile(outputFile);
+
+ return 0;
+ }
+
+ protected void dumpMessages(List<BrowseRow> rows) {
+ tableHelper = new MessageTableHelper();
+ tableHelper.setPretty(pretty);
+ tableHelper.setLoggingColor(loggingColor);
+ tableHelper.setShowExchangeProperties(showExchangeProperties);
+
+ for (BrowseRow row : rows) {
+ if (row.messages != null) {
+ for (int i = 0; i < row.messages.size(); i++) {
+ JsonObject jo = row.messages.get(i);
+
+ String exchangeId = jo.getString("exchangeId");
+ JsonObject message = jo.getMap("message");
+ if (!showExchangeProperties && message != null) {
+ message.remove("exchangeProperties");
+ }
+ if (!showHeaders && message != null) {
+ message.remove("headers");
+ }
+ if (!showBody && message != null) {
+ message.remove("body");
+ }
+ JsonObject ep = new JsonObject();
+ ep.put("endpoint", row.uri);
+ String table = tableHelper.getDataAsTable(exchangeId, null, ep, null, message, null);
+ printer().println(table);
+ }
+ }
+ }
+ }
+
+ protected void tableStatus(List<BrowseRow> rows) {
+ 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(40, OverflowBehaviour.ELLIPSIS_RIGHT)
+ .with(r -> r.name),
+ new Column().header("AGE").headerAlign(HorizontalAlign.CENTER).with(r -> r.ago),
+ new Column().header("ENDPOINT").visible(!wideUri).dataAlign(HorizontalAlign.LEFT)
+ .maxWidth(45, OverflowBehaviour.ELLIPSIS_RIGHT)
+ .with(this::getEndpointUri),
+ new Column().header("SIZE").with(r -> "" + r.size))));
+ }
+
+ protected int sortRow(BrowseRow o1, BrowseRow o2) {
+ String s = sort;
+ int negate = 1;
+ if (s.startsWith("-")) {
+ s = s.substring(1);
+ negate = -1;
+ }
+ switch (s) {
+ case "uri":
+ return o1.uri.compareToIgnoreCase(o2.uri) * negate;
+ case "size":
+ return Long.compare(o1.size, o2.size) * negate;
+ default:
+ return 0;
+ }
+ }
+
+ protected String getEndpointUri(BrowseRow r) {
+ String u = r.uri;
+ if (shortUri) {
+ int pos = u.indexOf('?');
+ if (pos > 0) {
+ u = u.substring(0, pos);
+ }
+ }
+ return u;
+ }
+
+ private static class BrowseRow implements Cloneable {
+ String pid;
+ String name;
+ String ago;
+ long uptime;
+ String uri;
+ long size;
+ List<JsonObject> messages;
+
+ BrowseRow copy() {
+ try {
+ return (BrowseRow) clone();
+ } catch (CloneNotSupportedException e) {
+ return null;
+ }
+ }
+ }
+
+}
diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/MessageTableHelper.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/MessageTableHelper.java
index b7fdc7cadeb..cd9d384ceff 100644
--- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/MessageTableHelper.java
+++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/MessageTableHelper.java
@@ -137,16 +137,18 @@ public class MessageTableHelper {
}
if (root != null) {
- eRow = new TableRow("Exchange", root.getString("exchangeType"), exchangePattern, exchangeId);
- tab1 = AsciiTable.getTable(AsciiTable.NO_BORDERS, List.of(eRow), Arrays.asList(
- new Column().dataAlign(HorizontalAlign.LEFT)
- .minWidth(showExchangeProperties || showExchangeVariables ? 12 : 10).with(TableRow::kindAsString),
- new Column().dataAlign(HorizontalAlign.LEFT).with(TableRow::typeAsString)));
- tab1b = AsciiTable.getTable(AsciiTable.NO_BORDERS, List.of(eRow), Arrays.asList(
- new Column().dataAlign(HorizontalAlign.CENTER)
- .minWidth(18).maxWidth(18).with(TableRow::mepAsKey),
- new Column().dataAlign(HorizontalAlign.RIGHT)
- .maxWidth(80).with(TableRow::exchangeIdAsValue)));
+ if (exchangeId != null) {
+ eRow = new TableRow("Exchange", root.getString("exchangeType"), exchangePattern, exchangeId);
+ tab1 = AsciiTable.getTable(AsciiTable.NO_BORDERS, List.of(eRow), Arrays.asList(
+ new Column().dataAlign(HorizontalAlign.LEFT)
+ .minWidth(showExchangeProperties || showExchangeVariables ? 12 : 10).with(TableRow::kindAsString),
+ new Column().dataAlign(HorizontalAlign.LEFT).with(TableRow::typeAsString)));
+ tab1b = AsciiTable.getTable(AsciiTable.NO_BORDERS, List.of(eRow), Arrays.asList(
+ new Column().dataAlign(HorizontalAlign.CENTER)
+ .minWidth(18).maxWidth(18).with(TableRow::mepAsKey),
+ new Column().dataAlign(HorizontalAlign.RIGHT)
+ .maxWidth(80).with(TableRow::exchangeIdAsValue)));
+ }
// exchange variables
JsonArray arr = root.getCollection("exchangeVariables");
if (arr != null) {
(camel) 01/04: CAMEL-21178: Add browse dev console
Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch browse
in repository https://gitbox.apache.org/repos/asf/camel.git
commit 8a982f80082bb08a60853172883297c04d3e6c36
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu Sep 5 15:22:24 2024 +0200
CAMEL-21178: Add browse dev console
---
.../org/apache/camel/dev-console/browse.json | 15 ++
.../services/org/apache/camel/dev-console/browse | 2 +
.../org/apache/camel/dev-consoles.properties | 2 +-
.../camel/impl/console/BrowseDevConsole.java | 159 +++++++++++++++++++++
4 files changed, 177 insertions(+), 1 deletion(-)
diff --git a/core/camel-console/src/generated/resources/META-INF/org/apache/camel/dev-console/browse.json b/core/camel-console/src/generated/resources/META-INF/org/apache/camel/dev-console/browse.json
new file mode 100644
index 00000000000..b08c06fde1a
--- /dev/null
+++ b/core/camel-console/src/generated/resources/META-INF/org/apache/camel/dev-console/browse.json
@@ -0,0 +1,15 @@
+{
+ "console": {
+ "kind": "console",
+ "group": "camel",
+ "name": "browse",
+ "title": "Browse",
+ "description": "Browse pending messages on Camel components",
+ "deprecated": false,
+ "javaType": "org.apache.camel.impl.console.BrowseDevConsole",
+ "groupId": "org.apache.camel",
+ "artifactId": "camel-console",
+ "version": "4.8.0-SNAPSHOT"
+ }
+}
+
diff --git a/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/dev-console/browse b/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/dev-console/browse
new file mode 100644
index 00000000000..5f75731c367
--- /dev/null
+++ b/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/dev-console/browse
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.impl.console.BrowseDevConsole
diff --git a/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/dev-consoles.properties b/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/dev-consoles.properties
index 999c55d935d..1cd0c8b69f4 100644
--- a/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/dev-consoles.properties
+++ b/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/dev-consoles.properties
@@ -1,5 +1,5 @@
# Generated by camel build tools - do NOT edit this file!
-dev-consoles=bean blocked circuit-breaker consumer context debug endpoint event gc health inflight java-security jvm log memory properties reload rest route route-controller route-dump service source startup-recorder thread top trace transformers type-converters variables
+dev-consoles=bean blocked browse circuit-breaker consumer context debug endpoint event gc health inflight java-security jvm log memory properties reload rest route route-controller route-dump service source startup-recorder thread top trace transformers type-converters variables
groupId=org.apache.camel
artifactId=camel-console
version=4.8.0-SNAPSHOT
diff --git a/core/camel-console/src/main/java/org/apache/camel/impl/console/BrowseDevConsole.java b/core/camel-console/src/main/java/org/apache/camel/impl/console/BrowseDevConsole.java
new file mode 100644
index 00000000000..24c134561a3
--- /dev/null
+++ b/core/camel-console/src/main/java/org/apache/camel/impl/console/BrowseDevConsole.java
@@ -0,0 +1,159 @@
+/*
+ * 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 java.util.Collection;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeSet;
+
+import org.apache.camel.Endpoint;
+import org.apache.camel.Exchange;
+import org.apache.camel.spi.BrowsableEndpoint;
+import org.apache.camel.spi.Metadata;
+import org.apache.camel.spi.annotations.DevConsole;
+import org.apache.camel.support.MessageHelper;
+import org.apache.camel.support.PatternHelper;
+import org.apache.camel.support.console.AbstractDevConsole;
+import org.apache.camel.util.json.JsonArray;
+import org.apache.camel.util.json.JsonObject;
+
+@DevConsole(name = "browse", description = "Browse pending messages on Camel components")
+public class BrowseDevConsole extends AbstractDevConsole {
+
+ public BrowseDevConsole() {
+ super("camel", "browse", "Browse", "Browse pending messages on Camel components");
+ }
+
+ /**
+ * Filters the endpoints matching by route id, endpoint url
+ */
+ public static final String FILTER = "filter";
+
+ /**
+ * Limits the number of entries per endpoint
+ */
+ public static final String LIMIT = "limit";
+
+ /**
+ * Whether to include message dumps
+ */
+ public static final String DUMP = "dump";
+
+ @Metadata(defaultValue = "32768",
+ description = "Maximum size of the message body to include in the dump")
+ private int bodyMaxChars = 32 * 1024;
+
+ @Metadata(defaultValue = "100",
+ description = "Maximum number of messages per endpoint to include in the dump")
+ private int limit = 100;
+
+ public int getBodyMaxChars() {
+ return bodyMaxChars;
+ }
+
+ public void setBodyMaxChars(int bodyMaxChars) {
+ this.bodyMaxChars = bodyMaxChars;
+ }
+
+ @Override
+ protected String doCallText(Map<String, Object> options) {
+ StringBuilder sb = new StringBuilder();
+
+ String filter = (String) options.get(FILTER);
+ String lim = (String) options.get(LIMIT);
+ final int max = lim == null ? limit : Integer.parseInt(lim);
+ boolean dump = "true".equals(options.getOrDefault(DUMP, "true"));
+
+ Collection<Endpoint> endpoints = new TreeSet<>(Comparator.comparing(Endpoint::getEndpointUri));
+ endpoints.addAll(getCamelContext().getEndpoints());
+ for (Endpoint endpoint : endpoints) {
+ if (endpoint instanceof BrowsableEndpoint be
+ && (filter == null || PatternHelper.matchPattern(endpoint.getEndpointUri(), filter))) {
+ List<Exchange> list = be.getExchanges();
+ long size = list != null ? list.size() : 0;
+ if (list != null && list.size() > max) {
+ size = list.size();
+ list = list.subList(0, max);
+ }
+ if (list != null) {
+ sb.append("\n");
+ sb.append(String.format("Browse: %s (size: %d)%n", endpoint.getEndpointUri(), size));
+ if (dump) {
+ for (Exchange e : list) {
+ String json = MessageHelper.dumpAsJSon(e.getMessage(), false, false, true, 2, true, true, true,
+ bodyMaxChars, true);
+ sb.append(json);
+ sb.append("\n");
+ }
+ }
+ }
+ }
+ }
+ sb.append("\n");
+
+ return sb.toString();
+ }
+
+ @Override
+ protected JsonObject doCallJson(Map<String, Object> options) {
+ JsonObject root = new JsonObject();
+ JsonArray arr = new JsonArray();
+
+ String filter = (String) options.get(FILTER);
+ String lim = (String) options.get(LIMIT);
+ final int max = lim == null ? limit : Integer.parseInt(lim);
+ boolean dump = "true".equals(options.getOrDefault(DUMP, "true"));
+
+ Collection<Endpoint> endpoints = new TreeSet<>(Comparator.comparing(Endpoint::getEndpointUri));
+ endpoints.addAll(getCamelContext().getEndpoints());
+ for (Endpoint endpoint : endpoints) {
+ if (endpoint instanceof BrowsableEndpoint be
+ && (filter == null || PatternHelper.matchPattern(endpoint.getEndpointUri(), filter))) {
+ List<Exchange> list = be.getExchanges();
+ long size = list != null ? list.size() : 0;
+ if (list != null && list.size() > max) {
+ size = list.size();
+ list = list.subList(0, max);
+ }
+ if (list != null) {
+ JsonObject jo = new JsonObject();
+ jo.put("endpointUri", endpoint.getEndpointUri());
+ jo.put("size", size);
+ arr.add(jo);
+ if (dump) {
+ JsonArray arr2 = new JsonArray();
+ for (Exchange e : list) {
+ arr2.add(MessageHelper.dumpAsJSonObject(e.getMessage(), false, false, true, true, true, true,
+ bodyMaxChars));
+ }
+ if (!arr2.isEmpty()) {
+ jo.put("messages", arr2);
+ }
+ }
+ }
+ }
+ }
+ if (!arr.isEmpty()) {
+ root.put("browse", arr);
+ }
+
+ return root;
+ }
+
+}