This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch ih in repository https://gitbox.apache.org/repos/asf/camel.git
commit a92e56a67d2b1d4514b6d55d1df38c751cfb9f0f Author: Claus Ibsen <[email protected]> AuthorDate: Sun Nov 23 12:19:26 2025 +0100 CAMEL-22693: Mark up EIP and endpoint headers that are of importance to make tooling, trouble shooting and development easier. --- .../src/main/java/org/apache/camel/NamedNode.java | 12 +++ .../camel/spi/BacklogTracerEventMessage.java | 5 ++ .../impl/debugger/DefaultBacklogDebugger.java | 19 +++-- .../debugger/DefaultBacklogTracerEventMessage.java | 12 ++- .../camel/impl/engine/CamelInternalProcessor.java | 7 +- .../core/commands/action/CamelHistoryAction.java | 88 +++++++++++++++------- .../core/commands/action/MessageTableHelper.java | 11 ++- 7 files changed, 112 insertions(+), 42 deletions(-) diff --git a/core/camel-api/src/main/java/org/apache/camel/NamedNode.java b/core/camel-api/src/main/java/org/apache/camel/NamedNode.java index a9833050f48a..85cdf53a7663 100644 --- a/core/camel-api/src/main/java/org/apache/camel/NamedNode.java +++ b/core/camel-api/src/main/java/org/apache/camel/NamedNode.java @@ -81,4 +81,16 @@ public interface NamedNode extends LineNumberAware { return level; } + default String getParentId() { + NamedNode node = this; + while (node != null && node.getParent() != null) { + boolean shallow = "when".equals(node.getShortName()) || "otherwise".equals(node.getShortName()); + node = node.getParent(); + if (!shallow) { + return node.getId(); + } + } + return null; + } + } diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/BacklogTracerEventMessage.java b/core/camel-api/src/main/java/org/apache/camel/spi/BacklogTracerEventMessage.java index 293493002d33..e53d49d94d80 100644 --- a/core/camel-api/src/main/java/org/apache/camel/spi/BacklogTracerEventMessage.java +++ b/core/camel-api/src/main/java/org/apache/camel/spi/BacklogTracerEventMessage.java @@ -73,6 +73,11 @@ public interface BacklogTracerEventMessage { */ String getToNode(); + /** + * Parent node id for this node + */ + String getToNodeParentId(); + /** * Node short name where the message is being routed to */ diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/debugger/DefaultBacklogDebugger.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/debugger/DefaultBacklogDebugger.java index b36d00242e59..b0d3eecf9998 100644 --- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/debugger/DefaultBacklogDebugger.java +++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/debugger/DefaultBacklogDebugger.java @@ -885,7 +885,7 @@ public final class DefaultBacklogDebugger extends ServiceSupport implements Back (nId, message) -> new DefaultBacklogTracerEventMessage( camelContext, false, false, message.getUid(), message.getTimestamp(), message.getLocation(), message.getRouteId(), - message.getToNode(), message.getToNodeShortName(), message.getToNodeLabel(), message.getToNodeLevel(), + message.getToNode(), message.getToNodeShortName(), message.getToNodeLabel(), message.getToNodeParentId(), message.getToNodeLevel(), message.getExchangeId(), message.getCorrelationExchangeId(), false, false, dumpAsJSonObject(suspendedExchange.getExchange()))); @@ -922,6 +922,7 @@ public final class DefaultBacklogDebugger extends ServiceSupport implements Back // store a copy of the message so we can see that from the debugger long timestamp = System.currentTimeMillis(); String toNode = definition.getId(); + String toNodeParentId = definition.getParentId(); String toNodeShortName = definition.getShortName(); // avoid label is too large String toNodeLabel = StringHelper.limitLength(definition.getLabel(), 50); @@ -936,9 +937,8 @@ public final class DefaultBacklogDebugger extends ServiceSupport implements Back BacklogTracerEventMessage msg = new DefaultBacklogTracerEventMessage( camelContext, - first, false, uid, timestamp, source, routeId, toNode, toNodeShortName, toNodeLabel, level, - exchangeId, - correlationExchangeId, + first, false, uid, timestamp, source, routeId, toNode, toNodeParentId, + toNodeShortName, toNodeLabel, level, exchangeId, correlationExchangeId, false, false, data); suspendedBreakpointMessages.put(nodeId, msg); @@ -1012,6 +1012,7 @@ public final class DefaultBacklogDebugger extends ServiceSupport implements Back // store a copy of the message so we can see that from the debugger long timestamp = System.currentTimeMillis(); String toNode = definition.getId(); + String toNodeParentId = definition.getParentId(); String toNodeShortName = definition.getShortName(); // avoid label is too large String toNodeLabel = StringHelper.limitLength(definition.getLabel(), 50); @@ -1025,7 +1026,8 @@ public final class DefaultBacklogDebugger extends ServiceSupport implements Back BacklogTracerEventMessage msg = new DefaultBacklogTracerEventMessage( camelContext, - false, false, uid, timestamp, source, routeId, toNode, toNodeShortName, toNodeLabel, level, + false, false, uid, timestamp, source, routeId, toNode, toNodeParentId, + toNodeShortName, toNodeLabel, level, exchangeId, correlationExchangeId, false, false, data); suspendedBreakpointMessages.put(toNode, msg); @@ -1122,6 +1124,7 @@ public final class DefaultBacklogDebugger extends ServiceSupport implements Back // create pseudo-last step in single step mode long timestamp = System.currentTimeMillis(); String toNode = CamelContextHelper.getRouteId(definition); + String toNodeParentId = definition.getParentId(); String routeId = route != null ? route.getRouteId() : toNode; String exchangeId = exchange.getExchangeId(); String correlationExchangeId = exchange.getProperty(ExchangePropertyKey.CORRELATION_ID, String.class); @@ -1132,9 +1135,9 @@ public final class DefaultBacklogDebugger extends ServiceSupport implements Back BacklogTracerEventMessage msg = new DefaultBacklogTracerEventMessage( camelContext, - false, true, uid, timestamp, source, routeId, toNode, null, null, level, - exchangeId, correlationExchangeId, - false, false, data); + false, true, uid, timestamp, source, routeId, toNode, toNodeParentId, + null, null, level, exchangeId, correlationExchangeId, + false, false, data); // we want to capture if there was an exception if (cause != null) { msg.setException(cause); diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/debugger/DefaultBacklogTracerEventMessage.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/debugger/DefaultBacklogTracerEventMessage.java index c65c7a5ec812..14c1dd84408d 100644 --- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/debugger/DefaultBacklogTracerEventMessage.java +++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/debugger/DefaultBacklogTracerEventMessage.java @@ -45,6 +45,7 @@ public final class DefaultBacklogTracerEventMessage implements BacklogTracerEven private final String location; private final String routeId; private final String toNode; + private final String toNodeParentId; private final String toNodeShortName; private final String toNodeLabel; private final int toNodeLevel; @@ -69,7 +70,7 @@ public final class DefaultBacklogTracerEventMessage implements BacklogTracerEven private boolean done; public DefaultBacklogTracerEventMessage(CamelContext camelContext, boolean first, boolean last, long uid, long timestamp, - String location, String routeId, String toNode, String toNodeShortName, + String location, String routeId, String toNode, String toNodeParentId, String toNodeShortName, String toNodeLabel, int toNodeLevel, String exchangeId, String correlationExchangeId, boolean rest, boolean template, JsonObject data) { @@ -82,6 +83,7 @@ public final class DefaultBacklogTracerEventMessage implements BacklogTracerEven this.location = location; this.routeId = routeId; this.toNode = toNode; + this.toNodeParentId = toNodeParentId; this.toNodeShortName = toNodeShortName; this.toNodeLabel = toNodeLabel; this.toNodeLevel = toNodeLevel; @@ -146,6 +148,11 @@ public final class DefaultBacklogTracerEventMessage implements BacklogTracerEven return toNode; } + @Override + public String getToNodeParentId() { + return toNodeParentId; + } + @Override public String getToNodeShortName() { return toNodeShortName; @@ -531,6 +538,9 @@ public final class DefaultBacklogTracerEventMessage implements BacklogTracerEven if (toNode != null) { jo.put("nodeId", toNode); } + if (toNodeParentId != null) { + jo.put("nodeParentId", toNodeParentId); + } if (toNodeShortName != null) { jo.put("nodeShortName", toNodeShortName); } diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/CamelInternalProcessor.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/CamelInternalProcessor.java index 3d7f1289800d..77cc3546d467 100644 --- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/CamelInternalProcessor.java +++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/CamelInternalProcessor.java @@ -651,6 +651,7 @@ public class CamelInternalProcessor extends DelegateAsyncProcessor implements In long timestamp = System.currentTimeMillis(); String toNode = processorDefinition.getId(); + String toNodeParentId = processorDefinition.getParentId(); String toNodeShortName = processorDefinition.getShortName(); String toNodeLabel = StringHelper.limitLength(processorDefinition.getLabel(), 50); String exchangeId = exchange.getExchangeId(); @@ -672,7 +673,7 @@ public class CamelInternalProcessor extends DelegateAsyncProcessor implements In final long created = exchange.getClock().getCreated(); DefaultBacklogTracerEventMessage pseudoFirst = new DefaultBacklogTracerEventMessage( camelContext, - true, false, backlogTracer.incrementTraceCounter(), created, source, routeId, null, null, null, + true, false, backlogTracer.incrementTraceCounter(), created, source, routeId, null, null, null, null, level, exchangeId, correlationExchangeId, rest, template, data); if (exchange.getFromEndpoint() instanceof EndpointServiceLocation esl) { @@ -686,7 +687,7 @@ public class CamelInternalProcessor extends DelegateAsyncProcessor implements In String source = LoggerHelper.getLineNumberLoggerName(processorDefinition); DefaultBacklogTracerEventMessage event = new DefaultBacklogTracerEventMessage( camelContext, - false, false, backlogTracer.incrementTraceCounter(), timestamp, source, routeId, toNode, + false, false, backlogTracer.incrementTraceCounter(), timestamp, source, routeId, toNode, toNodeParentId, toNodeShortName, toNodeLabel, level, exchangeId, correlationExchangeId, rest, template, data); backlogTracer.traceEvent(event); @@ -715,7 +716,7 @@ public class CamelInternalProcessor extends DelegateAsyncProcessor implements In backlogTracer.getBodyMaxChars()); DefaultBacklogTracerEventMessage pseudoLast = new DefaultBacklogTracerEventMessage( camelContext, - false, true, backlogTracer.incrementTraceCounter(), created, source, routeId, null, null, null, + false, true, backlogTracer.incrementTraceCounter(), created, source, routeId, null, null, null, null, level, exchangeId, correlationExchangeId, rest, template, data); backlogTracer.traceEvent(pseudoLast); diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelHistoryAction.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelHistoryAction.java index 1646f8dcdf50..9d990961fadd 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelHistoryAction.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelHistoryAction.java @@ -21,18 +21,20 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.StringJoiner; 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.CamelCatalog; +import org.apache.camel.catalog.DefaultCamelCatalog; import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain; +import org.apache.camel.tooling.model.ComponentModel; +import org.apache.camel.tooling.model.EipModel; import org.apache.camel.util.IOHelper; import org.apache.camel.util.StringHelper; import org.apache.camel.util.TimeUtils; @@ -58,11 +60,11 @@ public class CamelHistoryAction extends ActionWatchCommand { description = "Whether to mask endpoint URIs to avoid printing sensitive information such as password or access keys") boolean mask; + private final CamelCatalog camelCatalog = new DefaultCamelCatalog(true); + // TODO: option to max deep level (like trace) // TODO: option to collapse split (to cut very large split) - private final Set<String> usedImportant = new HashSet<>(); - public CamelHistoryAction(CamelJBangMain main) { super(main); } @@ -203,22 +205,15 @@ public class CamelHistoryAction extends ActionWatchCommand { String fs = map.remove("CamelFileLength"); if (fn != null && fs != null) { String line = "File: " + fn + " (" + fs + " bytes)"; - if (usedImportant.add(line)) { - sj.add(line); - } + sj.add(line); } else if (fn != null) { String line = "File: " + fn; - if (usedImportant.add(line)) { - sj.add(line); - } + sj.add(line); } - map.forEach((k,v) -> { + map.forEach((k, v) -> { String line = k + "=" + v; - if (usedImportant.add(line)) { - // avoid duplicates so only show unique - sj.add(k + "=" + v); - } + sj.add(line); }); return sj.toString(); @@ -227,24 +222,63 @@ public class CamelHistoryAction extends ActionWatchCommand { private Map<String, String> extractImportant(Row r) { Map<String, String> answer = new LinkedHashMap<>(); - JsonArray arr = r.message.getCollection("exchangeProperties"); - if (arr != null) { - for (int i = 0; i < arr.size(); i++) { - JsonObject jo = (JsonObject) arr.get(i); - if (jo.getBooleanOrDefault("important", false)) { - answer.put(jo.getString("key"), jo.getString("value")); + // extract important headers for the endpoint + String uri = r.endpoint != null ? r.endpoint.getString("endpoint") : null; + if (uri != null) { + String scheme = StringHelper.before(uri, ":"); + if (scheme != null) { + ComponentModel cm = camelCatalog.componentModel(scheme); + if (cm != null) { + for (var eh : cm.getEndpointHeaders()) { + if (eh.isImportant()) { + JsonArray arr = r.message.getCollection("headers"); + if (arr != null) { + for (int i = 0; i < arr.size(); i++) { + JsonObject jo = (JsonObject) arr.get(i); + String key = jo.getString("key"); + if (key.equals(eh.getName())) { + answer.put(key, jo.getString("value")); + } + } + } + } + } } } } - arr = r.message.getCollection("headers"); - if (arr != null) { - for (int i = 0; i < arr.size(); i++) { - JsonObject jo = (JsonObject) arr.get(i); - if (jo.getBooleanOrDefault("important", false)) { - answer.put(jo.getString("key"), jo.getString("value")); + + // extract important exchange properties for the EIP + String eip = r.nodeShortName; + if (eip != null) { + EipModel em = camelCatalog.eipModel(eip); + if (em != null) { + for (var ep : em.getExchangeProperties()) { + if (ep.isImportant()) { + JsonArray arr = r.message.getCollection("exchangeProperties"); + if (arr != null) { + for (int i = 0; i < arr.size(); i++) { + JsonObject jo = (JsonObject) arr.get(i); + String key = jo.getString("key"); + if (key.equals(ep.getName())) { + answer.put(key, jo.getString("value")); + } + } + } + arr = r.message.getCollection("headers"); + if (arr != null) { + for (int i = 0; i < arr.size(); i++) { + JsonObject jo = (JsonObject) arr.get(i); + String key = jo.getString("key"); + if (key.equals(ep.getName())) { + answer.put(key, jo.getString("value")); + } + } + } + } } } } + return answer; } 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 064af5877800..72422652175f 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 @@ -166,7 +166,9 @@ public class MessageTableHelper { if (arr != null) { for (Object o : arr) { JsonObject jo = (JsonObject) o; - rows.add(new TableRow("Property", jo.getString("type"), jo.getString("key"), jo.get("value"), jo.getBooleanOrDefault("important", false))); + rows.add(new TableRow( + "Property", jo.getString("type"), jo.getString("key"), jo.get("value"), + jo.getBooleanOrDefault("important", false))); } } // internal exchange properties @@ -174,7 +176,9 @@ public class MessageTableHelper { if (arr != null) { for (Object o : arr) { JsonObject jo = (JsonObject) o; - rows.add(new TableRow("Property", jo.getString("type"), jo.getString("key"), jo.get("value"), jo.getBooleanOrDefault("important", false))); + rows.add(new TableRow( + "Property", jo.getString("type"), jo.getString("key"), jo.get("value"), + jo.getBooleanOrDefault("important", false))); } } if (!rows.isEmpty()) { @@ -220,7 +224,8 @@ public class MessageTableHelper { } } } - rows.add(new TableRow("Header", jo.getString("type"), key, value, jo.getBooleanOrDefault("important", false))); + rows.add(new TableRow( + "Header", jo.getString("type"), key, value, jo.getBooleanOrDefault("important", false))); } } if (!rows.isEmpty()) {
