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()) {

Reply via email to