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
The following commit(s) were added to refs/heads/main by this push:
new 67f092b88418 CAMEL-23533: ErrorRegistry - enrich captured errors with
additional context (#23558)
67f092b88418 is described below
commit 67f092b8841822987d00348e9a7dfed0f01be1c6
Author: Claus Ibsen <[email protected]>
AuthorDate: Wed May 27 14:45:19 2026 +0200
CAMEL-23533: ErrorRegistry - enrich captured errors with additional context
(#23558)
Co-authored-by: Claude Opus 4.6 <[email protected]>
---
.../apache/camel/spi/BacklogErrorEventMessage.java | 31 +++++++++++
.../camel/impl/engine/DefaultErrorRegistry.java | 64 +++++++++++++++++++++-
.../org/apache/camel/impl/ErrorRegistryTest.java | 6 ++
.../api/management/mbean/CamelOpenMBeanTypes.java | 11 +++-
.../management/mbean/ManagedErrorRegistry.java | 8 ++-
5 files changed, 114 insertions(+), 6 deletions(-)
diff --git
a/core/camel-api/src/main/java/org/apache/camel/spi/BacklogErrorEventMessage.java
b/core/camel-api/src/main/java/org/apache/camel/spi/BacklogErrorEventMessage.java
index 0418c1d15e65..f7d64d643e69 100644
---
a/core/camel-api/src/main/java/org/apache/camel/spi/BacklogErrorEventMessage.java
+++
b/core/camel-api/src/main/java/org/apache/camel/spi/BacklogErrorEventMessage.java
@@ -34,6 +34,37 @@ public interface BacklogErrorEventMessage extends
BacklogEventMessage {
@Nullable
String getRouteGroup();
+ /**
+ * The id of the Step EIP the exchange was inside when the error occurred,
or {@code null} if the exchange was not
+ * inside a Step EIP.
+ *
+ * @since 4.21
+ */
+ @Nullable
+ String getStepId();
+
+ /**
+ * The URI of the route's consumer (from) endpoint where the exchange
originated.
+ *
+ * @since 4.21
+ */
+ @Nullable
+ String getFromEndpointUri();
+
+ /**
+ * The uptime of the route (in milliseconds) at the time the error was
captured.
+ *
+ * @since 4.21
+ */
+ long getRouteUptime();
+
+ /**
+ * The elapsed processing time of the exchange (in milliseconds) from
creation until the error was captured.
+ *
+ * @since 4.21
+ */
+ long getElapsed();
+
/**
* The actual exception that caused the error. This is the live {@link
Throwable} instance, not a serialized copy.
*/
diff --git
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultErrorRegistry.java
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultErrorRegistry.java
index d362482d0ffd..19f88187c31a 100644
---
a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultErrorRegistry.java
+++
b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultErrorRegistry.java
@@ -126,6 +126,27 @@ public class DefaultErrorRegistry extends
EventNotifierSupport implements ErrorR
String toNode = exchange.getExchangeExtension().getHistoryNodeId();
String location =
exchange.getExchangeExtension().getHistoryNodeSource();
+ // capture step id (set by Step EIP)
+ String stepId = exchange.getProperty(ExchangePropertyKey.STEP_ID,
String.class);
+
+ // capture from endpoint URI
+ String fromEndpointUri = null;
+ if (exchange.getFromEndpoint() != null) {
+ fromEndpointUri = exchange.getFromEndpoint().getEndpointUri();
+ }
+
+ // capture route uptime
+ long routeUptime = 0;
+ if (routeId != null) {
+ org.apache.camel.Route r = exchange.getContext().getRoute(routeId);
+ if (r != null) {
+ routeUptime = r.getUptimeMillis();
+ }
+ }
+
+ // capture exchange elapsed time
+ long elapsed = exchange.getClock().elapsed();
+
// capture exchange data snapshot
JsonObject data = MessageHelper.dumpAsJSonObject(
exchange.getMessage(),
@@ -140,7 +161,8 @@ public class DefaultErrorRegistry extends
EventNotifierSupport implements ErrorR
DefaultBacklogErrorEventMessage entry = new
DefaultBacklogErrorEventMessage(
uid, timestamp, location, routeId, fromRouteId, routeGroup,
exchangeId,
- endpointUri, toNode, threadName, data, exception, handled,
messageHistory);
+ endpointUri, toNode, stepId, fromEndpointUri, routeUptime,
elapsed,
+ threadName, data, exception, handled, messageHistory);
entries.addFirst(entry);
evict();
@@ -375,6 +397,10 @@ public class DefaultErrorRegistry extends
EventNotifierSupport implements ErrorR
private final String exchangeId;
private final String endpointUri;
private final String toNode;
+ private final String stepId;
+ private final String fromEndpointUri;
+ private final long routeUptime;
+ private final long elapsed;
private final String threadName;
private final JsonObject data;
private final Throwable exception;
@@ -387,7 +413,9 @@ public class DefaultErrorRegistry extends
EventNotifierSupport implements ErrorR
DefaultBacklogErrorEventMessage(
long uid, long timestamp, String
location, String routeId, String fromRouteId,
String routeGroup,
- String exchangeId, String endpointUri,
String toNode, String threadName,
+ String exchangeId, String endpointUri,
String toNode,
+ String stepId, String fromEndpointUri,
long routeUptime, long elapsed,
+ String threadName,
JsonObject data, Throwable exception,
boolean handled, String[] messageHistory) {
this.uid = uid;
this.timestamp = timestamp;
@@ -398,6 +426,10 @@ public class DefaultErrorRegistry extends
EventNotifierSupport implements ErrorR
this.exchangeId = exchangeId;
this.endpointUri = endpointUri;
this.toNode = toNode;
+ this.stepId = stepId;
+ this.fromEndpointUri = fromEndpointUri;
+ this.routeUptime = routeUptime;
+ this.elapsed = elapsed;
this.threadName = threadName;
this.data = data;
this.exception = exception;
@@ -450,6 +482,26 @@ public class DefaultErrorRegistry extends
EventNotifierSupport implements ErrorR
return toNode;
}
+ @Override
+ public String getStepId() {
+ return stepId;
+ }
+
+ @Override
+ public String getFromEndpointUri() {
+ return fromEndpointUri;
+ }
+
+ @Override
+ public long getRouteUptime() {
+ return routeUptime;
+ }
+
+ @Override
+ public long getElapsed() {
+ return elapsed;
+ }
+
@Override
public String getProcessingThreadName() {
return threadName;
@@ -537,6 +589,14 @@ public class DefaultErrorRegistry extends
EventNotifierSupport implements ErrorR
if (toNode != null) {
jo.put("nodeId", toNode);
}
+ if (stepId != null) {
+ jo.put("stepId", stepId);
+ }
+ if (fromEndpointUri != null) {
+ jo.put("fromEndpointUri", fromEndpointUri);
+ }
+ jo.put("routeUptime", routeUptime);
+ jo.put("elapsed", elapsed);
jo.put("threadName", threadName);
jo.put("handled", handled);
// message data
diff --git
a/core/camel-core/src/test/java/org/apache/camel/impl/ErrorRegistryTest.java
b/core/camel-core/src/test/java/org/apache/camel/impl/ErrorRegistryTest.java
index 38de8560ac2a..864fe500b059 100644
--- a/core/camel-core/src/test/java/org/apache/camel/impl/ErrorRegistryTest.java
+++ b/core/camel-core/src/test/java/org/apache/camel/impl/ErrorRegistryTest.java
@@ -65,6 +65,9 @@ public class ErrorRegistryTest extends ContextTestSupport {
assertTrue(entry.getException() instanceof IllegalArgumentException);
assertTrue(entry.getUid() > 0);
assertNotNull(entry.getProcessingThreadName());
+ assertEquals("direct://start", entry.getFromEndpointUri());
+ assertTrue(entry.getRouteUptime() >= 0, "Route uptime should be
non-negative");
+ assertTrue(entry.getElapsed() >= 0, "Elapsed time should be
non-negative");
}
@Test
@@ -234,6 +237,9 @@ public class ErrorRegistryTest extends ContextTestSupport {
assertNotNull(json.get("exchangeId"));
assertNotNull(json.get("exception"));
assertNotNull(json.get("message"));
+ assertEquals("direct://start", json.get("fromEndpointUri"));
+ assertTrue((long) json.get("routeUptime") >= 0);
+ assertTrue((long) json.get("elapsed") >= 0);
}
@Override
diff --git
a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/CamelOpenMBeanTypes.java
b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/CamelOpenMBeanTypes.java
index 966217eea084..6264b459c8d9 100644
---
a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/CamelOpenMBeanTypes.java
+++
b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/CamelOpenMBeanTypes.java
@@ -386,14 +386,19 @@ public final class CamelOpenMBeanTypes {
return new CompositeType(
"errors", "Errors",
new String[] {
- "exchangeId", "routeId", "routeGroup", "nodeId",
"endpointUri", "timestamp",
+ "exchangeId", "routeId", "routeGroup", "nodeId",
"stepId",
+ "endpointUri", "fromEndpointUri", "timestamp",
+ "routeUptime", "elapsed",
"handled", "exceptionType", "exceptionMessage" },
new String[] {
- "Exchange Id", "Route Id", "Route Group", "Node Id",
"Endpoint Uri", "Timestamp",
+ "Exchange Id", "Route Id", "Route Group", "Node Id",
"Step Id",
+ "Endpoint Uri", "From Endpoint Uri", "Timestamp",
+ "Route Uptime", "Elapsed",
"Handled", "Exception Type", "Exception Message" },
new OpenType[] {
SimpleType.STRING, SimpleType.STRING,
SimpleType.STRING, SimpleType.STRING, SimpleType.STRING,
- SimpleType.STRING,
+ SimpleType.STRING, SimpleType.STRING,
SimpleType.STRING,
+ SimpleType.LONG, SimpleType.LONG,
SimpleType.BOOLEAN, SimpleType.STRING,
SimpleType.STRING });
}
diff --git
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedErrorRegistry.java
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedErrorRegistry.java
index 5f5886b8ba65..3160a08923da 100644
---
a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedErrorRegistry.java
+++
b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedErrorRegistry.java
@@ -160,15 +160,21 @@ public class ManagedErrorRegistry extends ManagedService
implements ManagedError
CompositeData data = new CompositeDataSupport(
ct,
new String[] {
- "exchangeId", "routeId", "routeGroup",
"nodeId", "endpointUri", "timestamp",
+ "exchangeId", "routeId", "routeGroup",
"nodeId", "stepId",
+ "endpointUri", "fromEndpointUri", "timestamp",
+ "routeUptime", "elapsed",
"handled", "exceptionType", "exceptionMessage"
},
new Object[] {
entry.getExchangeId(),
entry.getRouteId(),
entry.getRouteGroup(),
entry.getToNode(),
+ entry.getStepId(),
entry.getEndpointUri(),
+ entry.getFromEndpointUri(),
String.valueOf(entry.getTimestamp()),
+ entry.getRouteUptime(),
+ entry.getElapsed(),
entry.isHandled(),
entry.getExceptionType(),
entry.getExceptionMessage() });