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 2022/06/28 08:48:11 UTC

[camel] branch main updated: CAMEL-18150: Add option to enable timestamps in camel events to know exactly when they fired.

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 0b146125e4b CAMEL-18150: Add option to enable timestamps in camel events to know exactly when they fired.
0b146125e4b is described below

commit 0b146125e4b9f4de26ca389e4eb049b0417684aa
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Tue Jun 28 10:47:55 2022 +0200

    CAMEL-18150: Add option to enable timestamps in camel events to know exactly when they fired.
---
 .../main/java/org/apache/camel/spi/CamelEvent.java |   8 +
 .../java/org/apache/camel/spi/EventFactory.java    |  10 +
 .../camel/impl/event/AbstractContextEvent.java     |  11 +
 .../camel/impl/event/AbstractExchangeEvent.java    |  12 ++
 .../camel/impl/event/AbstractRouteEvent.java       |  12 ++
 .../camel/impl/event/DefaultEventFactory.java      | 237 +++++++++++++++++----
 .../impl/event/ServiceStartupFailureEvent.java     |  11 +
 .../camel/impl/event/ServiceStopFailureEvent.java  |  11 +
 .../event/CamelEventsTimestampEnabledTest.java     |  89 ++++++++
 .../MainConfigurationPropertiesConfigurer.java     |   6 +
 .../camel-main-configuration-metadata.json         |   1 +
 core/camel-main/src/main/docs/main.adoc            |   3 +-
 .../camel/main/DefaultConfigurationConfigurer.java |   6 +-
 .../camel/main/DefaultConfigurationProperties.java |  24 +++
 14 files changed, 400 insertions(+), 41 deletions(-)

diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/CamelEvent.java b/core/camel-api/src/main/java/org/apache/camel/spi/CamelEvent.java
index 68ec4355080..69ddfa91a0f 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/CamelEvent.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/CamelEvent.java
@@ -72,6 +72,14 @@ public interface CamelEvent {
 
     Object getSource();
 
+    /**
+     * Timestamp for each event, when the event occurred. By default, the timestamp is not included and this method
+     * returns 0.
+     */
+    long getTimestamp();
+
+    void setTimestamp(long timestamp);
+
     /**
      * This interface is implemented by all events that contain an exception and is used to retrieve the exception in a
      * universal way.
diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/EventFactory.java b/core/camel-api/src/main/java/org/apache/camel/spi/EventFactory.java
index a92bcd7f785..08e86d11dcf 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/EventFactory.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/EventFactory.java
@@ -29,6 +29,16 @@ import org.apache.camel.Route;
  */
 public interface EventFactory {
 
+    /**
+     * Whether to include timestamp for each event, when the event occurred. This is by default false.
+     */
+    boolean isTimestampEnabled();
+
+    /**
+     * Whether to include timestamp for each event, when the event occurred.
+     */
+    void setTimestampEnabled(boolean timestampEnabled);
+
     /**
      * Creates an {@link CamelEvent} for Camel is initializing.
      *
diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/event/AbstractContextEvent.java b/core/camel-base/src/main/java/org/apache/camel/impl/event/AbstractContextEvent.java
index 4d9dd398d0f..f647f0e594d 100644
--- a/core/camel-base/src/main/java/org/apache/camel/impl/event/AbstractContextEvent.java
+++ b/core/camel-base/src/main/java/org/apache/camel/impl/event/AbstractContextEvent.java
@@ -27,6 +27,7 @@ import org.apache.camel.spi.CamelEvent.CamelContextEvent;
 public abstract class AbstractContextEvent extends EventObject implements CamelContextEvent {
     private static final long serialVersionUID = 1L;
     private CamelContext context;
+    private long timestamp;
 
     public AbstractContextEvent(CamelContext source) {
         super(source);
@@ -37,4 +38,14 @@ public abstract class AbstractContextEvent extends EventObject implements CamelC
     public CamelContext getContext() {
         return context;
     }
+
+    @Override
+    public long getTimestamp() {
+        return timestamp;
+    }
+
+    @Override
+    public void setTimestamp(long timestamp) {
+        this.timestamp = timestamp;
+    }
 }
diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/event/AbstractExchangeEvent.java b/core/camel-base/src/main/java/org/apache/camel/impl/event/AbstractExchangeEvent.java
index 2384efdc826..a0af40ab19a 100644
--- a/core/camel-base/src/main/java/org/apache/camel/impl/event/AbstractExchangeEvent.java
+++ b/core/camel-base/src/main/java/org/apache/camel/impl/event/AbstractExchangeEvent.java
@@ -27,6 +27,7 @@ import org.apache.camel.spi.CamelEvent.ExchangeEvent;
 public abstract class AbstractExchangeEvent extends EventObject implements ExchangeEvent {
     private static final long serialVersionUID = 1L;
     private final Exchange exchange;
+    private long timestamp;
 
     public AbstractExchangeEvent(Exchange source) {
         super(source);
@@ -37,4 +38,15 @@ public abstract class AbstractExchangeEvent extends EventObject implements Excha
     public Exchange getExchange() {
         return exchange;
     }
+
+    @Override
+    public long getTimestamp() {
+        return timestamp;
+    }
+
+    @Override
+    public void setTimestamp(long timestamp) {
+        this.timestamp = timestamp;
+    }
+
 }
diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/event/AbstractRouteEvent.java b/core/camel-base/src/main/java/org/apache/camel/impl/event/AbstractRouteEvent.java
index 179ac378fac..45254091ae3 100644
--- a/core/camel-base/src/main/java/org/apache/camel/impl/event/AbstractRouteEvent.java
+++ b/core/camel-base/src/main/java/org/apache/camel/impl/event/AbstractRouteEvent.java
@@ -28,6 +28,7 @@ import org.apache.camel.spi.CamelEvent.RouteEvent;
 public abstract class AbstractRouteEvent extends EventObject implements RouteEvent {
     private static final long serialVersionUID = 1L;
     private Route route;
+    private long timestamp;
 
     public AbstractRouteEvent(Route source) {
         super(source);
@@ -38,4 +39,15 @@ public abstract class AbstractRouteEvent extends EventObject implements RouteEve
     public Route getRoute() {
         return route;
     }
+
+    @Override
+    public long getTimestamp() {
+        return timestamp;
+    }
+
+    @Override
+    public void setTimestamp(long timestamp) {
+        this.timestamp = timestamp;
+    }
+
 }
diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/event/DefaultEventFactory.java b/core/camel-base/src/main/java/org/apache/camel/impl/event/DefaultEventFactory.java
index c54a1cc0524..df048ec95ba 100644
--- a/core/camel-base/src/main/java/org/apache/camel/impl/event/DefaultEventFactory.java
+++ b/core/camel-base/src/main/java/org/apache/camel/impl/event/DefaultEventFactory.java
@@ -30,124 +30,235 @@ import org.apache.camel.spi.EventFactory;
  */
 public class DefaultEventFactory implements EventFactory {
 
+    private boolean timestampEnabled;
+
+    @Override
+    public boolean isTimestampEnabled() {
+        return timestampEnabled;
+    }
+
+    @Override
+    public void setTimestampEnabled(boolean timestampEnabled) {
+        this.timestampEnabled = timestampEnabled;
+    }
+
     @Override
     public CamelEvent createCamelContextInitializingEvent(CamelContext context) {
-        return new CamelContextInitializingEvent(context);
+        CamelEvent answer = new CamelContextInitializingEvent(context);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 
     @Override
     public CamelEvent createCamelContextInitializedEvent(CamelContext context) {
-        return new CamelContextInitializedEvent(context);
+        CamelEvent answer = new CamelContextInitializedEvent(context);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 
     @Override
     public CamelEvent createCamelContextStartingEvent(CamelContext context) {
-        return new CamelContextStartingEvent(context);
+        CamelEvent answer = new CamelContextStartingEvent(context);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 
     @Override
     public CamelEvent createCamelContextStartedEvent(CamelContext context) {
-        return new CamelContextStartedEvent(context);
+        CamelEvent answer = new CamelContextStartedEvent(context);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 
     @Override
     public CamelEvent createCamelContextStoppingEvent(CamelContext context) {
-        return new CamelContextStoppingEvent(context);
+        CamelEvent answer = new CamelContextStoppingEvent(context);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 
     @Override
     public CamelEvent createCamelContextStoppedEvent(CamelContext context) {
-        return new CamelContextStoppedEvent(context);
+        CamelEvent answer = new CamelContextStoppedEvent(context);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 
     @Override
     public CamelEvent createCamelContextRoutesStartingEvent(CamelContext context) {
-        return new CamelContextRoutesStartingEvent(context);
+        CamelEvent answer = new CamelContextRoutesStartingEvent(context);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 
     @Override
     public CamelEvent createCamelContextRoutesStartedEvent(CamelContext context) {
-        return new CamelContextRoutesStartedEvent(context);
+        CamelEvent answer = new CamelContextRoutesStartedEvent(context);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 
     @Override
     public CamelEvent createCamelContextRoutesStoppingEvent(CamelContext context) {
-        return new CamelContextRoutesStoppingEvent(context);
+        CamelEvent answer = new CamelContextRoutesStoppingEvent(context);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 
     @Override
     public CamelEvent createCamelContextRoutesStoppedEvent(CamelContext context) {
-        return new CamelContextRoutesStoppedEvent(context);
+        CamelEvent answer = new CamelContextRoutesStoppedEvent(context);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 
     @Override
     public CamelEvent createCamelContextStartupFailureEvent(CamelContext context, Throwable cause) {
-        return new CamelContextStartupFailureEvent(context, cause);
+        CamelEvent answer = new CamelContextStartupFailureEvent(context, cause);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 
     @Override
     public CamelEvent createCamelContextStopFailureEvent(CamelContext context, Throwable cause) {
-        return new CamelContextStopFailureEvent(context, cause);
+        CamelEvent answer = new CamelContextStopFailureEvent(context, cause);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 
     @Override
     public CamelEvent createServiceStartupFailureEvent(CamelContext context, Object service, Throwable cause) {
-        return new ServiceStartupFailureEvent(context, service, cause);
+        CamelEvent answer = new ServiceStartupFailureEvent(context, service, cause);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 
     @Override
     public CamelEvent createServiceStopFailureEvent(CamelContext context, Object service, Throwable cause) {
-        return new ServiceStopFailureEvent(context, service, cause);
+        CamelEvent answer = new ServiceStopFailureEvent(context, service, cause);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 
     @Override
     public CamelEvent createRouteStartingEvent(Route route) {
-        return new RouteStartingEvent(route);
+        CamelEvent answer = new RouteStartingEvent(route);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 
     @Override
     public CamelEvent createRouteStartedEvent(Route route) {
-        return new RouteStartedEvent(route);
+        CamelEvent answer = new RouteStartedEvent(route);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 
     @Override
     public CamelEvent createRouteStoppingEvent(Route route) {
-        return new RouteStoppingEvent(route);
+        CamelEvent answer = new RouteStoppingEvent(route);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 
     @Override
     public CamelEvent createRouteStoppedEvent(Route route) {
-        return new RouteStoppedEvent(route);
+        CamelEvent answer = new RouteStoppedEvent(route);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
+
     }
 
     @Override
     public CamelEvent createRouteAddedEvent(Route route) {
-        return new RouteAddedEvent(route);
+        CamelEvent answer = new RouteAddedEvent(route);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
+
     }
 
     @Override
     public CamelEvent createRouteRemovedEvent(Route route) {
-        return new RouteRemovedEvent(route);
+        CamelEvent answer = new RouteRemovedEvent(route);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
+
     }
 
     @Override
     public CamelEvent createRouteReloaded(Route route, int index, int total) {
-        return new RouteReloadedEvent(route, index, total);
+        CamelEvent answer = new RouteReloadedEvent(route, index, total);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 
     @Override
     public CamelEvent createExchangeCreatedEvent(Exchange exchange) {
-        return new ExchangeCreatedEvent(exchange);
+        CamelEvent answer = new ExchangeCreatedEvent(exchange);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 
     @Override
     public CamelEvent createExchangeCompletedEvent(Exchange exchange) {
-        return new ExchangeCompletedEvent(exchange);
+        CamelEvent answer = new ExchangeCompletedEvent(exchange);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 
     @Override
     public CamelEvent createExchangeFailedEvent(Exchange exchange) {
-        return new ExchangeFailedEvent(exchange);
+        CamelEvent answer = new ExchangeFailedEvent(exchange);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 
     @Override
@@ -158,7 +269,11 @@ public class DefaultEventFactory implements EventFactory {
         if (handler instanceof DelegateProcessor) {
             handler = ((DelegateProcessor) handler).getProcessor();
         }
-        return new ExchangeFailureHandlingEvent(exchange, handler, deadLetterChannel, deadLetterUri);
+        CamelEvent answer = new ExchangeFailureHandlingEvent(exchange, handler, deadLetterChannel, deadLetterUri);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 
     @Override
@@ -170,61 +285,109 @@ public class DefaultEventFactory implements EventFactory {
         if (handler instanceof DelegateProcessor) {
             handler = ((DelegateProcessor) handler).getProcessor();
         }
-        return new ExchangeFailureHandledEvent(exchange, handler, deadLetterChannel, deadLetterUri);
+        CamelEvent answer = new ExchangeFailureHandledEvent(exchange, handler, deadLetterChannel, deadLetterUri);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 
     @Override
     public CamelEvent createExchangeRedeliveryEvent(Exchange exchange, int attempt) {
-        return new ExchangeRedeliveryEvent(exchange, attempt);
+        CamelEvent answer = new ExchangeRedeliveryEvent(exchange, attempt);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 
     @Override
     public CamelEvent createExchangeSendingEvent(Exchange exchange, Endpoint endpoint) {
-        return new ExchangeSendingEvent(exchange, endpoint);
+        CamelEvent answer = new ExchangeSendingEvent(exchange, endpoint);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 
     @Override
     public CamelEvent createExchangeSentEvent(Exchange exchange, Endpoint endpoint, long timeTaken) {
-        return new ExchangeSentEvent(exchange, endpoint, timeTaken);
+        CamelEvent answer = new ExchangeSentEvent(exchange, endpoint, timeTaken);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 
     @Override
     public CamelEvent createStepStartedEvent(Exchange exchange, String stepId) {
-        return new StepStartedEvent(exchange, stepId);
+        CamelEvent answer = new StepStartedEvent(exchange, stepId);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 
     @Override
     public CamelEvent createStepCompletedEvent(Exchange exchange, String stepId) {
-        return new StepCompletedEvent(exchange, stepId);
+        CamelEvent answer = new StepCompletedEvent(exchange, stepId);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 
     @Override
     public CamelEvent createStepFailedEvent(Exchange exchange, String stepId) {
-        return new StepFailedEvent(exchange, stepId);
+        CamelEvent answer = new StepFailedEvent(exchange, stepId);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 
     @Override
     public CamelEvent createCamelContextSuspendingEvent(CamelContext context) {
-        return new CamelContextSuspendingEvent(context);
+        CamelEvent answer = new CamelContextSuspendingEvent(context);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 
     @Override
     public CamelEvent createCamelContextSuspendedEvent(CamelContext context) {
-        return new CamelContextSuspendedEvent(context);
+        CamelEvent answer = new CamelContextSuspendedEvent(context);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 
     @Override
     public CamelEvent createCamelContextResumingEvent(CamelContext context) {
-        return new CamelContextResumingEvent(context);
+        CamelEvent answer = new CamelContextResumingEvent(context);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 
     @Override
     public CamelEvent createCamelContextResumedEvent(CamelContext context) {
-        return new CamelContextResumedEvent(context);
+        CamelEvent answer = new CamelContextResumedEvent(context);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 
     @Override
     public CamelEvent createCamelContextResumeFailureEvent(CamelContext context, Throwable cause) {
-        return new CamelContextResumeFailureEvent(context, cause);
+        CamelEvent answer = new CamelContextResumeFailureEvent(context, cause);
+        if (timestampEnabled) {
+            answer.setTimestamp(System.currentTimeMillis());
+        }
+        return answer;
     }
 }
diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/event/ServiceStartupFailureEvent.java b/core/camel-base/src/main/java/org/apache/camel/impl/event/ServiceStartupFailureEvent.java
index 3095ccf8441..71a254620fc 100644
--- a/core/camel-base/src/main/java/org/apache/camel/impl/event/ServiceStartupFailureEvent.java
+++ b/core/camel-base/src/main/java/org/apache/camel/impl/event/ServiceStartupFailureEvent.java
@@ -27,6 +27,7 @@ public class ServiceStartupFailureEvent extends EventObject implements CamelEven
     private CamelContext context;
     private Object service;
     private Throwable cause;
+    private long timestamp;
 
     public ServiceStartupFailureEvent(CamelContext context, Object service, Throwable cause) {
         super(service);
@@ -49,6 +50,16 @@ public class ServiceStartupFailureEvent extends EventObject implements CamelEven
         return cause;
     }
 
+    @Override
+    public long getTimestamp() {
+        return timestamp;
+    }
+
+    @Override
+    public void setTimestamp(long timestamp) {
+        this.timestamp = timestamp;
+    }
+
     @Override
     public String toString() {
         return "Service startup failure: " + service + " due to " + cause.getMessage();
diff --git a/core/camel-base/src/main/java/org/apache/camel/impl/event/ServiceStopFailureEvent.java b/core/camel-base/src/main/java/org/apache/camel/impl/event/ServiceStopFailureEvent.java
index f904b99a245..4056ff9a3bf 100644
--- a/core/camel-base/src/main/java/org/apache/camel/impl/event/ServiceStopFailureEvent.java
+++ b/core/camel-base/src/main/java/org/apache/camel/impl/event/ServiceStopFailureEvent.java
@@ -27,6 +27,7 @@ public class ServiceStopFailureEvent extends EventObject implements CamelEvent.S
     private CamelContext context;
     private Object service;
     private Throwable cause;
+    private long timestamp;
 
     public ServiceStopFailureEvent(CamelContext context, Object service, Throwable cause) {
         super(service);
@@ -49,6 +50,16 @@ public class ServiceStopFailureEvent extends EventObject implements CamelEvent.S
         return cause;
     }
 
+    @Override
+    public long getTimestamp() {
+        return timestamp;
+    }
+
+    @Override
+    public void setTimestamp(long timestamp) {
+        this.timestamp = timestamp;
+    }
+
     @Override
     public String toString() {
         return "Service stop failure: " + service + " due to " + cause.getMessage();
diff --git a/core/camel-core/src/test/java/org/apache/camel/impl/event/CamelEventsTimestampEnabledTest.java b/core/camel-core/src/test/java/org/apache/camel/impl/event/CamelEventsTimestampEnabledTest.java
new file mode 100644
index 00000000000..248bc571327
--- /dev/null
+++ b/core/camel-core/src/test/java/org/apache/camel/impl/event/CamelEventsTimestampEnabledTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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.event;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.spi.CamelEvent;
+import org.apache.camel.support.EventNotifierSupport;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class CamelEventsTimestampEnabledTest extends ContextTestSupport {
+
+    private static List<CamelEvent> events = new ArrayList<>();
+
+    @Override
+    @BeforeEach
+    public void setUp() throws Exception {
+        events.clear();
+        super.setUp();
+    }
+
+    @Override
+    protected CamelContext createCamelContext() throws Exception {
+        DefaultCamelContext context = new DefaultCamelContext(createRegistry());
+        // enable timestamp
+        context.getManagementStrategy().getEventFactory().setTimestampEnabled(true);
+        context.getManagementStrategy().addEventNotifier(new EventNotifierSupport() {
+            public void notify(CamelEvent event) throws Exception {
+                events.add(event);
+            }
+
+            @Override
+            protected void doBuild() throws Exception {
+                setIgnoreExchangeEvents(true);
+                setIgnoreRouteEvents(true);
+            }
+        });
+        return context;
+    }
+
+    @Test
+    public void testTimestamp() throws Exception {
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(1);
+
+        template.sendBody("direct:start", "Hello World");
+
+        assertMockEndpointsSatisfied();
+
+        context.stop();
+
+        Assertions.assertEquals(10, events.size());
+        events.forEach(e -> {
+            Assertions.assertTrue(e.getTimestamp() > 0, "should include timestamp");
+        });
+    }
+
+    @Override
+    protected RouteBuilder createRouteBuilder() throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:start").to("mock:result");
+            }
+        };
+    }
+}
diff --git a/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java b/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java
index fd03a1a7ac8..0e4c713c17c 100644
--- a/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java
+++ b/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java
@@ -49,6 +49,8 @@ public class MainConfigurationPropertiesConfigurer extends org.apache.camel.supp
         case "BeanIntrospectionLoggingLevel": target.setBeanIntrospectionLoggingLevel(property(camelContext, org.apache.camel.LoggingLevel.class, value)); return true;
         case "beanpostprocessorenabled":
         case "BeanPostProcessorEnabled": target.setBeanPostProcessorEnabled(property(camelContext, boolean.class, value)); return true;
+        case "cameleventstimestampenabled":
+        case "CamelEventsTimestampEnabled": target.setCamelEventsTimestampEnabled(property(camelContext, boolean.class, value)); return true;
         case "caseinsensitiveheaders":
         case "CaseInsensitiveHeaders": target.setCaseInsensitiveHeaders(property(camelContext, boolean.class, value)); return true;
         case "configurationclasses":
@@ -284,6 +286,8 @@ public class MainConfigurationPropertiesConfigurer extends org.apache.camel.supp
         case "BeanIntrospectionLoggingLevel": return org.apache.camel.LoggingLevel.class;
         case "beanpostprocessorenabled":
         case "BeanPostProcessorEnabled": return boolean.class;
+        case "cameleventstimestampenabled":
+        case "CamelEventsTimestampEnabled": return boolean.class;
         case "caseinsensitiveheaders":
         case "CaseInsensitiveHeaders": return boolean.class;
         case "configurationclasses":
@@ -520,6 +524,8 @@ public class MainConfigurationPropertiesConfigurer extends org.apache.camel.supp
         case "BeanIntrospectionLoggingLevel": return target.getBeanIntrospectionLoggingLevel();
         case "beanpostprocessorenabled":
         case "BeanPostProcessorEnabled": return target.isBeanPostProcessorEnabled();
+        case "cameleventstimestampenabled":
+        case "CamelEventsTimestampEnabled": return target.isCamelEventsTimestampEnabled();
         case "caseinsensitiveheaders":
         case "CaseInsensitiveHeaders": return target.isCaseInsensitiveHeaders();
         case "configurationclasses":
diff --git a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
index 2376528636f..e03737a1400 100644
--- a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
+++ b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json
@@ -26,6 +26,7 @@
     { "name": "camel.main.beanIntrospectionExtendedStatistics", "description": "Sets whether bean introspection uses extended statistics. The default is false.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": "false" },
     { "name": "camel.main.beanIntrospectionLoggingLevel", "description": "Sets the logging level used by bean introspection, logging activity of its usage. The default is TRACE.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "object", "javaType": "org.apache.camel.LoggingLevel", "enum": [ "ERROR", "WARN", "INFO", "DEBUG", "TRACE", "OFF" ] },
     { "name": "camel.main.beanPostProcessorEnabled", "description": "Can be used to turn off bean post processing. Be careful to turn this off, as this means that beans that use Camel annotations such as org.apache.camel.EndpointInject , org.apache.camel.ProducerTemplate , org.apache.camel.Produce , org.apache.camel.Consume etc will not be injected and in use. Turning this off should only be done if you are sure you do not use any of these Camel features. Not all runtimes allow turning t [...]
+    { "name": "camel.main.camelEventsTimestampEnabled", "description": "Whether to include timestamps for all emitted Camel Events. Enabling this allows to know fine-grained at what time each event was emitted, which can be used for reporting to report exactly the time of the events. This is by default false to avoid the overhead of including this information.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": [...]
     { "name": "camel.main.caseInsensitiveHeaders", "description": "Whether to use case sensitive or insensitive headers. Important: When using case sensitive (this is set to false). Then the map is case sensitive which means headers such as content-type and Content-Type are two different keys which can be a problem for some protocols such as HTTP based, which rely on case insensitive headers. However case sensitive implementations can yield faster performance. Therefore use case sensitiv [...]
     { "name": "camel.main.configurationClasses", "description": "Sets classes names that will be used to configure the camel context as example by providing custom beans through org.apache.camel.BindToRegistry annotation.", "sourceType": "org.apache.camel.main.MainConfigurationProperties", "type": "string", "javaType": "java.lang.String" },
     { "name": "camel.main.configurations", "description": "Sets the configuration objects used to configure the camel context.", "sourceType": "org.apache.camel.main.MainConfigurationProperties", "type": "object", "javaType": "java.util.List" },
diff --git a/core/camel-main/src/main/docs/main.adoc b/core/camel-main/src/main/docs/main.adoc
index 6bbd722441a..370d927237e 100644
--- a/core/camel-main/src/main/docs/main.adoc
+++ b/core/camel-main/src/main/docs/main.adoc
@@ -18,7 +18,7 @@ The following tables lists all the options:
 
 // main options: START
 === Camel Main configurations
-The camel.main supports 114 options, which are listed below.
+The camel.main supports 115 options, which are listed below.
 
 [width="100%",cols="2,5,^1,2",options="header"]
 |===
@@ -37,6 +37,7 @@ The camel.main supports 114 options, which are listed below.
 | *camel.main.beanIntrospection{zwsp}ExtendedStatistics* | Sets whether bean introspection uses extended statistics. The default is false. | false | boolean
 | *camel.main.beanIntrospection{zwsp}LoggingLevel* | Sets the logging level used by bean introspection, logging activity of its usage. The default is TRACE. |  | LoggingLevel
 | *camel.main.beanPostProcessor{zwsp}Enabled* | Can be used to turn off bean post processing. Be careful to turn this off, as this means that beans that use Camel annotations such as org.apache.camel.EndpointInject , org.apache.camel.ProducerTemplate , org.apache.camel.Produce , org.apache.camel.Consume etc will not be injected and in use. Turning this off should only be done if you are sure you do not use any of these Camel features. Not all runtimes allow turning this off (such as came [...]
+| *camel.main.camelEvents{zwsp}TimestampEnabled* | Whether to include timestamps for all emitted Camel Events. Enabling this allows to know fine-grained at what time each event was emitted, which can be used for reporting to report exactly the time of the events. This is by default false to avoid the overhead of including this information. | false | boolean
 | *camel.main.caseInsensitive{zwsp}Headers* | Whether to use case sensitive or insensitive headers. Important: When using case sensitive (this is set to false). Then the map is case sensitive which means headers such as content-type and Content-Type are two different keys which can be a problem for some protocols such as HTTP based, which rely on case insensitive headers. However case sensitive implementations can yield faster performance. Therefore use case sensitive implementation with [...]
 | *camel.main.configuration{zwsp}Classes* | Sets classes names that will be used to configure the camel context as example by providing custom beans through org.apache.camel.BindToRegistry annotation. |  | String
 | *camel.main.configurations* | Sets the configuration objects used to configure the camel context. |  | List
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java
index 24f82e2ee5c..4f9871ebe72 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java
@@ -253,6 +253,9 @@ public final class DefaultConfigurationConfigurer {
             camelContext.getManagementStrategy().getManagementAgent()
                     .setManagementNamePattern(config.getJmxManagementNamePattern());
         }
+        if (config.isCamelEventsTimestampEnabled()) {
+            camelContext.getManagementStrategy().getEventFactory().setTimestampEnabled(true);
+        }
 
         // global options
         if (config.getGlobalOptions() != null) {
@@ -547,19 +550,16 @@ public final class DefaultConfigurationConfigurer {
             }
         }
         // vaults
-        // TODO: add more vault providers here
         AwsVaultConfiguration aws = getSingleBeanOfType(registry, AwsVaultConfiguration.class);
         if (aws != null) {
             VaultConfiguration vault = camelContext.getVaultConfiguration();
             vault.setAwsVaultConfiguration(aws);
         }
-
         GcpVaultConfiguration gcp = getSingleBeanOfType(registry, GcpVaultConfiguration.class);
         if (gcp != null) {
             VaultConfiguration vault = camelContext.getVaultConfiguration();
             vault.setGcpVaultConfiguration(gcp);
         }
-
         AzureVaultConfiguration azure = getSingleBeanOfType(registry, AzureVaultConfiguration.class);
         if (gcp != null) {
             VaultConfiguration vault = camelContext.getVaultConfiguration();
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationProperties.java
index ce84bb39628..11d7ddb25af 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationProperties.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationProperties.java
@@ -94,6 +94,7 @@ public abstract class DefaultConfigurationProperties<T> {
     @Metadata(defaultValue = "Default")
     private ManagementStatisticsLevel jmxManagementStatisticsLevel = ManagementStatisticsLevel.Default;
     private String jmxManagementNamePattern = "#name#";
+    private boolean camelEventsTimestampEnabled;
     private boolean useMdcLogging;
     private String mdcLoggingKeysPattern;
     private String threadNamePattern;
@@ -902,6 +903,19 @@ public abstract class DefaultConfigurationProperties<T> {
         this.jmxManagementNamePattern = jmxManagementNamePattern;
     }
 
+    public boolean isCamelEventsTimestampEnabled() {
+        return camelEventsTimestampEnabled;
+    }
+
+    /**
+     * Whether to include timestamps for all emitted Camel Events. Enabling this allows to know fine-grained at what
+     * time each event was emitted, which can be used for reporting to report exactly the time of the events. This is by
+     * default false to avoid the overhead of including this information.
+     */
+    public void setCamelEventsTimestampEnabled(boolean camelEventsTimestampEnabled) {
+        this.camelEventsTimestampEnabled = camelEventsTimestampEnabled;
+    }
+
     public boolean isUseMdcLogging() {
         return useMdcLogging;
     }
@@ -2063,6 +2077,16 @@ public abstract class DefaultConfigurationProperties<T> {
         return (T) this;
     }
 
+    /**
+     * Whether to include timestamps for all emitted Camel Events. Enabling this allows to know fine-grained at what
+     * time each event was emitted, which can be used for reporting to report exactly the time of the events. This is by
+     * default false to avoid the overhead of including this information.
+     */
+    public T withCamelEventsTimestampEnabled(boolean camelEventsTimestampEnabled) {
+        this.camelEventsTimestampEnabled = camelEventsTimestampEnabled;
+        return (T) this;
+    }
+
     /**
      * To turn on MDC logging
      */