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 2023/11/29 14:29:35 UTC

(camel) branch main updated: consumer dev console (#12258)

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 58f49acc41b consumer dev console (#12258)
58f49acc41b is described below

commit 58f49acc41bd84bd0981b72048add1cddacca864
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Nov 29 15:29:27 2023 +0100

    consumer dev console (#12258)
    
    * CAMEL-20164: camel-core - Dev console for consumer
    
    * CAMEL-20164: camel-core - Dev console for consumer
    
    * CAMEL-20164: camel-timer: Expose more stats of its running state.
    
    * CAMEL-20164: camel-timer: Expose more stats of its running state.
    
    * CAMEL-20164: camel-quartz: Add dev console.
---
 .../org/apache/camel/catalog/components/timer.json |   3 +-
 .../services/org/apache/camel/dev-console/quartz   |   2 +
 .../camel/component/quartz/QuartzConsole.java      | 202 +++++++++++++++++++
 .../camel/component/quartz/QuartzEndpoint.java     |   1 -
 .../QuartzCronRouteWithStartDateEndDateTest.java   |   1 +
 .../component/timer/TimerEndpointConfigurer.java   |   6 +
 .../component/timer/TimerEndpointUriFactory.java   |   3 +-
 .../org/apache/camel/component/timer/timer.json    |   3 +-
 .../camel/component/timer/TimerConsumer.java       | 132 ++++++++++---
 .../camel/component/timer/TimerEndpoint.java       |  14 ++
 .../services/org/apache/camel/dev-console/consumer |   2 +
 .../camel/impl/console/ConsumerDevConsole.java     | 215 +++++++++++++++++++++
 .../camel/api/management/ManagedCamelContext.java  |  22 +++
 .../mbean/ManagedSchedulePollConsumerMBean.java    |  32 +++
 .../camel/management/ManagedCamelContextImpl.java  |  24 +++
 .../mbean/ManagedScheduledPollConsumer.java        |  51 +++++
 .../camel/support/ScheduledPollConsumer.java       |  14 +-
 .../dsl/JettyHttp11EndpointBuilderFactory.java     | 115 +++++++++++
 .../endpoint/dsl/TimerEndpointBuilderFactory.java  |  35 ++++
 19 files changed, 842 insertions(+), 35 deletions(-)

diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/timer.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/timer.json
index 17a8126b749..f0b0c46d430 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/timer.json
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/components/timer.json
@@ -44,6 +44,7 @@
     "pattern": { "index": 10, "kind": "parameter", "displayName": "Pattern", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Allows you to specify a custom Date pattern to use for setting the time option using URI syntax." },
     "synchronous": { "index": 11, "kind": "parameter", "displayName": "Synchronous", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether synchronous processing should be strictly used" },
     "time": { "index": 12, "kind": "parameter", "displayName": "Time", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.util.Date", "deprecated": false, "autowired": false, "secret": false, "description": "A java.util.Date the first event should be generated. If using the URI, the pattern expected is: yyyy-MM-dd HH:mm:ss or yyyy-MM-dd'T'HH:mm:ss." },
-    "timer": { "index": 13, "kind": "parameter", "displayName": "Timer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Timer", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom Timer" }
+    "timer": { "index": 13, "kind": "parameter", "displayName": "Timer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Timer", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom Timer" },
+    "runLoggingLevel": { "index": 14, "kind": "parameter", "displayName": "Run Logging Level", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "org.apache.camel.LoggingLevel", "enum": [ "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "TRACE", "description": "The consumer logs a start\/complete log line when it polls. This option allows you to configure the l [...]
   }
 }
diff --git a/components/camel-quartz/src/generated/resources/META-INF/services/org/apache/camel/dev-console/quartz b/components/camel-quartz/src/generated/resources/META-INF/services/org/apache/camel/dev-console/quartz
new file mode 100644
index 00000000000..ee877d2bf69
--- /dev/null
+++ b/components/camel-quartz/src/generated/resources/META-INF/services/org/apache/camel/dev-console/quartz
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.component.quartz.QuartzConsole
diff --git a/components/camel-quartz/src/main/java/org/apache/camel/component/quartz/QuartzConsole.java b/components/camel-quartz/src/main/java/org/apache/camel/component/quartz/QuartzConsole.java
new file mode 100644
index 00000000000..3fdbcfcf97c
--- /dev/null
+++ b/components/camel-quartz/src/main/java/org/apache/camel/component/quartz/QuartzConsole.java
@@ -0,0 +1,202 @@
+/*
+ * 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.component.quartz;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.camel.spi.annotations.DevConsole;
+import org.apache.camel.support.console.AbstractDevConsole;
+import org.apache.camel.util.json.JsonArray;
+import org.apache.camel.util.json.JsonObject;
+import org.quartz.JobExecutionContext;
+import org.quartz.Scheduler;
+import org.quartz.SchedulerMetaData;
+
+@DevConsole("quartz")
+public class QuartzConsole extends AbstractDevConsole {
+
+    public QuartzConsole() {
+        super("camel", "quartz", "Quartz", "Quartz Scheduler");
+    }
+
+    @Override
+    protected String doCallText(Map<String, Object> options) {
+        StringBuilder sb = new StringBuilder();
+
+        QuartzComponent quartz = getCamelContext().getComponent("quartz", QuartzComponent.class);
+        if (quartz != null) {
+            Scheduler scheduler = quartz.getScheduler();
+            try {
+                sb.append(String.format("    Scheduler Name: %s\n", scheduler.getSchedulerName()));
+                sb.append(String.format("    Scheduler Id: %s\n", scheduler.getSchedulerInstanceId()));
+                SchedulerMetaData meta = scheduler.getMetaData();
+                if (meta != null) {
+                    sb.append(String.format("    Quartz Version: %s\n", meta.getVersion()));
+                    String since = SimpleDateFormat.getDateTimeInstance().format(meta.getRunningSince());
+                    sb.append(String.format("    Running Since: %s\n", since));
+                    sb.append(String.format("    Total Counter: %s\n", meta.getNumberOfJobsExecuted()));
+                    sb.append(String.format("    Started: %s\n", meta.isStarted()));
+                    sb.append(String.format("    Shutdown: %s\n", meta.isShutdown()));
+                    sb.append(String.format("    In Standby Mode: %s\n", meta.isInStandbyMode()));
+                    sb.append(String.format("    Thread Pool Class: %s\n", meta.getThreadPoolClass().getName()));
+                    sb.append(String.format("    Thread Pool Size: %d\n", meta.getThreadPoolSize()));
+                    sb.append(String.format("    Job Store Class: %s\n", meta.getJobStoreClass().getName()));
+                    sb.append(String.format("    Job Store Clustered: %s\n", meta.isJobStoreClustered()));
+                    sb.append(String.format("    Job Store Supports Persistence: %s\n", meta.isJobStoreSupportsPersistence()));
+                }
+
+                List<JobExecutionContext> jobs = scheduler.getCurrentlyExecutingJobs();
+                sb.append(String.format("    Currently Executing Jobs: %d\n", jobs.size()));
+                if (!jobs.isEmpty()) {
+                    sb.append("\n");
+                    sb.append("Jobs:\n");
+                    sb.append("\n");
+                    for (JobExecutionContext job : jobs) {
+                        sb.append(String.format("        Job Id: %s\n", job.getFireInstanceId()));
+
+                        String type = (String) job.getJobDetail().getJobDataMap().get(QuartzConstants.QUARTZ_TRIGGER_TYPE);
+                        sb.append(String.format("        Trigger Type: %s\n", type));
+                        String cron = (String) job.getJobDetail().getJobDataMap()
+                                .get(QuartzConstants.QUARTZ_TRIGGER_CRON_EXPRESSION);
+                        if (cron != null) {
+                            sb.append(String.format("        Cron: %s\n", cron));
+                        }
+                        String routeId = (String) job.getJobDetail().getJobDataMap().get("routeId");
+                        if (routeId != null) {
+                            sb.append(String.format("        Route Id: %s\n", routeId));
+                        }
+                        String uri = (String) job.getJobDetail().getJobDataMap().get(QuartzConstants.QUARTZ_ENDPOINT_URI);
+                        if (cron != null) {
+                            sb.append(String.format("        Endpoint Uri: %s\n", uri));
+                        }
+                        Date d = job.getTrigger().getPreviousFireTime();
+                        if (d != null) {
+                            sb.append(String.format("        Prev Fire Time: %s\n",
+                                    SimpleDateFormat.getDateTimeInstance().format(d)));
+                        }
+                        d = job.getFireTime();
+                        if (d != null) {
+                            sb.append(
+                                    String.format("        Fire Time: %s\n", SimpleDateFormat.getDateTimeInstance().format(d)));
+                        }
+                        d = job.getTrigger().getNextFireTime();
+                        if (d != null) {
+                            sb.append(String.format("        Next Fire Time: %s\n",
+                                    SimpleDateFormat.getDateTimeInstance().format(d)));
+                        }
+                        d = job.getTrigger().getFinalFireTime();
+                        if (d != null) {
+                            sb.append(String.format("        Final Fire Time: %s\n",
+                                    SimpleDateFormat.getDateTimeInstance().format(d)));
+                        }
+                        sb.append(String.format("        Recovering: %s\n", job.isRecovering()));
+                        sb.append(String.format("        Refire Count: %s\n", job.getRefireCount()));
+                        sb.append(String.format("        Misfire Instruction: %s\n", job.getTrigger().getMisfireInstruction()));
+
+                        sb.append("\n");
+                    }
+                }
+            } catch (Exception e) {
+                // ignore
+            }
+        }
+
+        return sb.toString();
+    }
+
+    @Override
+    protected Map<String, Object> doCallJson(Map<String, Object> options) {
+        JsonObject root = new JsonObject();
+
+        QuartzComponent quartz = getCamelContext().getComponent("quartz", QuartzComponent.class);
+        if (quartz != null) {
+            Scheduler scheduler = quartz.getScheduler();
+            try {
+                root.put("schedulerName", scheduler.getSchedulerName());
+                root.put("schedulerInstanceId", scheduler.getSchedulerInstanceId());
+                SchedulerMetaData meta = scheduler.getMetaData();
+                if (meta != null) {
+                    root.put("quartzVersion", meta.getVersion());
+                    root.put("runningSince", meta.getRunningSince().getTime());
+                    root.put("totalCounter", meta.getNumberOfJobsExecuted());
+                    root.put("started", meta.isStarted());
+                    root.put("shutdown", meta.isShutdown());
+                    root.put("inStandbyMode", meta.isInStandbyMode());
+                    root.put("threadPoolClass", meta.getThreadPoolClass().getName());
+                    root.put("threadPoolSize", meta.getThreadPoolSize());
+                    root.put("jpbStoreClass", meta.getJobStoreClass().getName());
+                    root.put("jpbStoreClustered", meta.isJobStoreClustered());
+                    root.put("jpbStoreSupportsPersistence", meta.isJobStoreSupportsPersistence());
+                }
+
+                List<JobExecutionContext> jobs = scheduler.getCurrentlyExecutingJobs();
+                root.put("currentExecutingJobs", jobs.size());
+                if (!jobs.isEmpty()) {
+                    JsonArray arr = new JsonArray();
+                    root.put("jobs", arr);
+                    for (JobExecutionContext job : jobs) {
+                        JsonObject jo = new JsonObject();
+                        jo.put("jobId", job.getFireInstanceId());
+
+                        String type = (String) job.getJobDetail().getJobDataMap().get(QuartzConstants.QUARTZ_TRIGGER_TYPE);
+                        jo.put("triggerType", type);
+                        String cron = (String) job.getJobDetail().getJobDataMap()
+                                .get(QuartzConstants.QUARTZ_TRIGGER_CRON_EXPRESSION);
+                        if (cron != null) {
+                            jo.put("cron", cron);
+                        }
+                        String routeId = (String) job.getJobDetail().getJobDataMap().get("routeId");
+                        if (routeId != null) {
+                            jo.put("routeId", routeId);
+                        }
+                        String uri = (String) job.getJobDetail().getJobDataMap().get(QuartzConstants.QUARTZ_ENDPOINT_URI);
+                        if (cron != null) {
+                            jo.put("uri", uri);
+                        }
+                        Date d = job.getTrigger().getPreviousFireTime();
+                        if (d != null) {
+                            jo.put("prevFireTime", d.getTime());
+                        }
+                        d = job.getFireTime();
+                        if (d != null) {
+                            jo.put("fireTime", d.getTime());
+                        }
+                        d = job.getTrigger().getNextFireTime();
+                        if (d != null) {
+                            jo.put("nextFireTime", d.getTime());
+                        }
+                        d = job.getTrigger().getFinalFireTime();
+                        if (d != null) {
+                            jo.put("finalFireTime", d.getTime());
+                        }
+                        jo.put("recovering", job.isRecovering());
+                        jo.put("refireCount", job.getRefireCount());
+                        jo.put("misfireInstruction", job.getTrigger().getMisfireInstruction());
+                        arr.add(jo);
+                    }
+                }
+            } catch (Exception e) {
+                // ignore
+            }
+        }
+
+        return root;
+    }
+}
diff --git a/components/camel-quartz/src/main/java/org/apache/camel/component/quartz/QuartzEndpoint.java b/components/camel-quartz/src/main/java/org/apache/camel/component/quartz/QuartzEndpoint.java
index 667ca8c4fad..645ea0b752b 100644
--- a/components/camel-quartz/src/main/java/org/apache/camel/component/quartz/QuartzEndpoint.java
+++ b/components/camel-quartz/src/main/java/org/apache/camel/component/quartz/QuartzEndpoint.java
@@ -16,7 +16,6 @@
  */
 package org.apache.camel.component.quartz;
 
-import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.HashMap;
diff --git a/components/camel-quartz/src/test/java/org/apache/camel/component/quartz/QuartzCronRouteWithStartDateEndDateTest.java b/components/camel-quartz/src/test/java/org/apache/camel/component/quartz/QuartzCronRouteWithStartDateEndDateTest.java
index b39084a2073..daadcb126d5 100644
--- a/components/camel-quartz/src/test/java/org/apache/camel/component/quartz/QuartzCronRouteWithStartDateEndDateTest.java
+++ b/components/camel-quartz/src/test/java/org/apache/camel/component/quartz/QuartzCronRouteWithStartDateEndDateTest.java
@@ -21,6 +21,7 @@ import java.util.Calendar;
 import java.util.Date;
 import java.util.TimeZone;
 import java.util.concurrent.TimeUnit;
+
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
 import org.hamcrest.CoreMatchers;
diff --git a/components/camel-timer/src/generated/java/org/apache/camel/component/timer/TimerEndpointConfigurer.java b/components/camel-timer/src/generated/java/org/apache/camel/component/timer/TimerEndpointConfigurer.java
index fcae1f7e3b8..80f46a49a49 100644
--- a/components/camel-timer/src/generated/java/org/apache/camel/component/timer/TimerEndpointConfigurer.java
+++ b/components/camel-timer/src/generated/java/org/apache/camel/component/timer/TimerEndpointConfigurer.java
@@ -37,6 +37,8 @@ public class TimerEndpointConfigurer extends PropertyConfigurerSupport implement
         case "period": target.setPeriod(property(camelContext, java.time.Duration.class, value).toMillis()); return true;
         case "repeatcount":
         case "repeatCount": target.setRepeatCount(property(camelContext, long.class, value)); return true;
+        case "runlogginglevel":
+        case "runLoggingLevel": target.setRunLoggingLevel(property(camelContext, org.apache.camel.LoggingLevel.class, value)); return true;
         case "synchronous": target.setSynchronous(property(camelContext, boolean.class, value)); return true;
         case "time": target.setTime(property(camelContext, java.util.Date.class, value)); return true;
         case "timer": target.setTimer(property(camelContext, java.util.Timer.class, value)); return true;
@@ -63,6 +65,8 @@ public class TimerEndpointConfigurer extends PropertyConfigurerSupport implement
         case "period": return long.class;
         case "repeatcount":
         case "repeatCount": return long.class;
+        case "runlogginglevel":
+        case "runLoggingLevel": return org.apache.camel.LoggingLevel.class;
         case "synchronous": return boolean.class;
         case "time": return java.util.Date.class;
         case "timer": return java.util.Timer.class;
@@ -90,6 +94,8 @@ public class TimerEndpointConfigurer extends PropertyConfigurerSupport implement
         case "period": return target.getPeriod();
         case "repeatcount":
         case "repeatCount": return target.getRepeatCount();
+        case "runlogginglevel":
+        case "runLoggingLevel": return target.getRunLoggingLevel();
         case "synchronous": return target.isSynchronous();
         case "time": return target.getTime();
         case "timer": return target.getTimer();
diff --git a/components/camel-timer/src/generated/java/org/apache/camel/component/timer/TimerEndpointUriFactory.java b/components/camel-timer/src/generated/java/org/apache/camel/component/timer/TimerEndpointUriFactory.java
index fcf247658c8..5e5edd2402f 100644
--- a/components/camel-timer/src/generated/java/org/apache/camel/component/timer/TimerEndpointUriFactory.java
+++ b/components/camel-timer/src/generated/java/org/apache/camel/component/timer/TimerEndpointUriFactory.java
@@ -21,7 +21,7 @@ public class TimerEndpointUriFactory extends org.apache.camel.support.component.
     private static final Set<String> SECRET_PROPERTY_NAMES;
     private static final Set<String> MULTI_VALUE_PREFIXES;
     static {
-        Set<String> props = new HashSet<>(14);
+        Set<String> props = new HashSet<>(15);
         props.add("bridgeErrorHandler");
         props.add("daemon");
         props.add("delay");
@@ -32,6 +32,7 @@ public class TimerEndpointUriFactory extends org.apache.camel.support.component.
         props.add("pattern");
         props.add("period");
         props.add("repeatCount");
+        props.add("runLoggingLevel");
         props.add("synchronous");
         props.add("time");
         props.add("timer");
diff --git a/components/camel-timer/src/generated/resources/org/apache/camel/component/timer/timer.json b/components/camel-timer/src/generated/resources/org/apache/camel/component/timer/timer.json
index 17a8126b749..f0b0c46d430 100644
--- a/components/camel-timer/src/generated/resources/org/apache/camel/component/timer/timer.json
+++ b/components/camel-timer/src/generated/resources/org/apache/camel/component/timer/timer.json
@@ -44,6 +44,7 @@
     "pattern": { "index": 10, "kind": "parameter", "displayName": "Pattern", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Allows you to specify a custom Date pattern to use for setting the time option using URI syntax." },
     "synchronous": { "index": 11, "kind": "parameter", "displayName": "Synchronous", "group": "advanced", "label": "advanced", "required": false, "type": "boolean", "javaType": "boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether synchronous processing should be strictly used" },
     "time": { "index": 12, "kind": "parameter", "displayName": "Time", "group": "advanced", "label": "advanced", "required": false, "type": "string", "javaType": "java.util.Date", "deprecated": false, "autowired": false, "secret": false, "description": "A java.util.Date the first event should be generated. If using the URI, the pattern expected is: yyyy-MM-dd HH:mm:ss or yyyy-MM-dd'T'HH:mm:ss." },
-    "timer": { "index": 13, "kind": "parameter", "displayName": "Timer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Timer", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom Timer" }
+    "timer": { "index": 13, "kind": "parameter", "displayName": "Timer", "group": "advanced", "label": "advanced", "required": false, "type": "object", "javaType": "java.util.Timer", "deprecated": false, "autowired": false, "secret": false, "description": "To use a custom Timer" },
+    "runLoggingLevel": { "index": 14, "kind": "parameter", "displayName": "Run Logging Level", "group": "scheduler", "label": "consumer,scheduler", "required": false, "type": "object", "javaType": "org.apache.camel.LoggingLevel", "enum": [ "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF" ], "deprecated": false, "autowired": false, "secret": false, "defaultValue": "TRACE", "description": "The consumer logs a start\/complete log line when it polls. This option allows you to configure the l [...]
   }
 }
diff --git a/components/camel-timer/src/main/java/org/apache/camel/component/timer/TimerConsumer.java b/components/camel-timer/src/main/java/org/apache/camel/component/timer/TimerConsumer.java
index d1545eb1bad..396909eb1ad 100644
--- a/components/camel-timer/src/main/java/org/apache/camel/component/timer/TimerConsumer.java
+++ b/components/camel-timer/src/main/java/org/apache/camel/component/timer/TimerConsumer.java
@@ -25,9 +25,12 @@ import java.util.concurrent.atomic.AtomicLong;
 import org.apache.camel.AsyncCallback;
 import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
+import org.apache.camel.LoggingLevel;
 import org.apache.camel.Processor;
 import org.apache.camel.StartupListener;
 import org.apache.camel.Suspendable;
+import org.apache.camel.api.management.ManagedAttribute;
+import org.apache.camel.api.management.ManagedResource;
 import org.apache.camel.support.DefaultConsumer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -35,6 +38,7 @@ import org.slf4j.LoggerFactory;
 /**
  * The timer consumer.
  */
+@ManagedResource(description = "Managed TimerConsumer")
 public class TimerConsumer extends DefaultConsumer implements StartupListener, Suspendable {
 
     private static final Logger LOG = LoggerFactory.getLogger(TimerConsumer.class);
@@ -42,6 +46,8 @@ public class TimerConsumer extends DefaultConsumer implements StartupListener, S
     private volatile TimerTask task;
     private volatile boolean configured;
     private ExecutorService executorService;
+    private final AtomicLong counter = new AtomicLong();
+    private volatile boolean polling;
 
     public TimerConsumer(TimerEndpoint endpoint, Processor processor) {
         super(endpoint, processor);
@@ -53,13 +59,56 @@ public class TimerConsumer extends DefaultConsumer implements StartupListener, S
         return (TimerEndpoint) super.getEndpoint();
     }
 
+    /**
+     * Total number of polls run
+     */
+    @ManagedAttribute(description = "Total number of polls run")
+    public long getCounter() {
+        return counter.get();
+    }
+
+    /**
+     * Whether polling is currently in progress
+     */
+    @ManagedAttribute(description = "Whether polling is currently in progress")
+    public boolean isPolling() {
+        return polling;
+    }
+
+    @ManagedAttribute(description = "Timer Name")
+    public String getTimerName() {
+        return getEndpoint().getTimerName();
+    }
+
+    @ManagedAttribute(description = "Timer FixedRate")
+    public boolean isFixedRate() {
+        return getEndpoint().isFixedRate();
+    }
+
+    @ManagedAttribute(description = "Timer Delay")
+    public long getDelay() {
+        return getEndpoint().getDelay();
+    }
+
+    @ManagedAttribute(description = "Timer Period")
+    public long getPeriod() {
+        return getEndpoint().getPeriod();
+    }
+
+    @ManagedAttribute(description = "Repeat Count")
+    public long getRepeatCount() {
+        return getEndpoint().getRepeatCount();
+    }
+
+    @ManagedAttribute(description = "The consumer logs a start/complete log line when it polls. This option allows you to configure the logging level for that.")
+    public String getRunLoggingLevel() {
+        return getEndpoint().getRunLoggingLevel().name();
+    }
+
     @Override
     public void doInit() throws Exception {
         if (endpoint.getDelay() >= 0) {
             task = new TimerTask() {
-                // counter
-                private final AtomicLong counter = new AtomicLong();
-
                 @Override
                 public void run() {
                     if (!isTaskRunAllowed()) {
@@ -68,25 +117,57 @@ public class TimerConsumer extends DefaultConsumer implements StartupListener, S
                         return;
                     }
 
+                    // log starting
+                    LoggingLevel runLoggingLevel = getEndpoint().getRunLoggingLevel();
+                    if (LoggingLevel.ERROR == runLoggingLevel) {
+                        LOG.error("Timer task started on:   {}", getEndpoint());
+                    } else if (LoggingLevel.WARN == runLoggingLevel) {
+                        LOG.warn("Timer task started on:   {}", getEndpoint());
+                    } else if (LoggingLevel.INFO == runLoggingLevel) {
+                        LOG.info("Timer task started on:   {}", getEndpoint());
+                    } else if (LoggingLevel.DEBUG == runLoggingLevel) {
+                        LOG.debug("Timer task started on:   {}", getEndpoint());
+                    } else {
+                        LOG.trace("Timer task started on:   {}", getEndpoint());
+                    }
+
                     try {
-                        long count = counter.incrementAndGet();
-
-                        boolean fire = endpoint.getRepeatCount() <= 0 || count <= endpoint.getRepeatCount();
-                        if (fire) {
-                            sendTimerExchange(count);
-                        } else {
-                            // no need to fire anymore as we exceeded repeat
-                            // count
-                            LOG.debug("Cancelling {} timer as repeat count limit reached after {} counts.",
-                                    endpoint.getTimerName(), endpoint.getRepeatCount());
-                            cancel();
-                        }
+                        polling = true;
+                        doRun();
                     } catch (Exception e) {
-                        // catch all to avoid the JVM closing the thread and not
-                        // firing again
                         LOG.warn(
                                 "Error processing exchange. This exception will be ignored, to let the timer be able to trigger again.",
                                 e);
+                    } finally {
+                        polling = false;
+                    }
+
+                    // log completed
+                    if (LoggingLevel.ERROR == runLoggingLevel) {
+                        LOG.error("Timer task completed on: {}", getEndpoint());
+                    } else if (LoggingLevel.WARN == runLoggingLevel) {
+                        LOG.warn("Timer task completed on: {}", getEndpoint());
+                    } else if (LoggingLevel.INFO == runLoggingLevel) {
+                        LOG.info("Timer task completed on: {}", getEndpoint());
+                    } else if (LoggingLevel.DEBUG == runLoggingLevel) {
+                        LOG.debug("Timer task completed on: {}", getEndpoint());
+                    } else {
+                        LOG.trace("Timer task completed on: {}", getEndpoint());
+                    }
+                }
+
+                protected void doRun() {
+                    long count = counter.incrementAndGet();
+
+                    boolean fire = endpoint.getRepeatCount() <= 0 || count <= endpoint.getRepeatCount();
+                    if (fire) {
+                        sendTimerExchange(count);
+                    } else {
+                        // no need to fire anymore as we exceeded repeat
+                        // count
+                        LOG.debug("Cancelling {} timer as repeat count limit reached after {} counts.",
+                                endpoint.getTimerName(), endpoint.getRepeatCount());
+                        cancel();
                     }
                 }
             };
@@ -99,8 +180,7 @@ public class TimerConsumer extends DefaultConsumer implements StartupListener, S
 
         if (endpoint.getDelay() >= 0) {
             // only configure task if CamelContext already started, otherwise
-            // the StartupListener
-            // is configuring the task later
+            // the StartupListener is configuring the task later
             if (task != null && !configured && endpoint.getCamelContext().getStatus().isStarted()) {
                 Timer timer = endpoint.getTimer(this);
                 configureTask(task, timer);
@@ -111,11 +191,15 @@ public class TimerConsumer extends DefaultConsumer implements StartupListener, S
                     endpoint.getEndpointUri());
 
             executorService.execute(() -> {
-                final AtomicLong counter = new AtomicLong();
-                long count = counter.incrementAndGet();
-                while ((endpoint.getRepeatCount() <= 0 || count <= endpoint.getRepeatCount()) && isRunAllowed()) {
-                    sendTimerExchange(count);
-                    count = counter.incrementAndGet();
+                polling = true;
+                try {
+                    long count = counter.incrementAndGet();
+                    while ((endpoint.getRepeatCount() <= 0 || count <= endpoint.getRepeatCount()) && isRunAllowed()) {
+                        sendTimerExchange(count);
+                        count = counter.incrementAndGet();
+                    }
+                } finally {
+                    polling = false;
                 }
             });
         }
diff --git a/components/camel-timer/src/main/java/org/apache/camel/component/timer/TimerEndpoint.java b/components/camel-timer/src/main/java/org/apache/camel/component/timer/TimerEndpoint.java
index 97dfaacbd4a..4361f351ea2 100644
--- a/components/camel-timer/src/main/java/org/apache/camel/component/timer/TimerEndpoint.java
+++ b/components/camel-timer/src/main/java/org/apache/camel/component/timer/TimerEndpoint.java
@@ -22,6 +22,7 @@ import java.util.Timer;
 import org.apache.camel.Category;
 import org.apache.camel.Component;
 import org.apache.camel.Consumer;
+import org.apache.camel.LoggingLevel;
 import org.apache.camel.MultipleConsumersSupport;
 import org.apache.camel.Processor;
 import org.apache.camel.Producer;
@@ -53,6 +54,9 @@ public class TimerEndpoint extends DefaultEndpoint implements MultipleConsumersS
     private long delay = 1000;
     @UriParam
     private long repeatCount;
+    @UriParam(defaultValue = "TRACE", label = "consumer,scheduler",
+              description = "The consumer logs a start/complete log line when it polls. This option allows you to configure the logging level for that.")
+    private LoggingLevel runLoggingLevel = LoggingLevel.TRACE;
     @UriParam
     private boolean fixedRate;
     @UriParam(defaultValue = "true", label = "advanced")
@@ -176,6 +180,16 @@ public class TimerEndpoint extends DefaultEndpoint implements MultipleConsumersS
         this.fixedRate = fixedRate;
     }
 
+    @ManagedAttribute(description = "The consumer logs a start/complete log line when it polls. This option allows you to configure the logging level for that.")
+    public LoggingLevel getRunLoggingLevel() {
+        return runLoggingLevel;
+    }
+
+    @ManagedAttribute(description = "The consumer logs a start/complete log line when it polls. This option allows you to configure the logging level for that.")
+    public void setRunLoggingLevel(LoggingLevel runLoggingLevel) {
+        this.runLoggingLevel = runLoggingLevel;
+    }
+
     @ManagedAttribute(description = "Timer Period")
     public long getPeriod() {
         return period;
diff --git a/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/dev-console/consumer b/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/dev-console/consumer
new file mode 100644
index 00000000000..aeb2b3da695
--- /dev/null
+++ b/core/camel-console/src/generated/resources/META-INF/services/org/apache/camel/dev-console/consumer
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.impl.console.ConsumerDevConsole
diff --git a/core/camel-console/src/main/java/org/apache/camel/impl/console/ConsumerDevConsole.java b/core/camel-console/src/main/java/org/apache/camel/impl/console/ConsumerDevConsole.java
new file mode 100644
index 00000000000..8d94953b527
--- /dev/null
+++ b/core/camel-console/src/main/java/org/apache/camel/impl/console/ConsumerDevConsole.java
@@ -0,0 +1,215 @@
+/*
+ * 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.lang.management.ManagementFactory;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+import org.apache.camel.Route;
+import org.apache.camel.api.management.ManagedCamelContext;
+import org.apache.camel.api.management.mbean.ManagedConsumerMBean;
+import org.apache.camel.api.management.mbean.ManagedSchedulePollConsumerMBean;
+import org.apache.camel.spi.annotations.DevConsole;
+import org.apache.camel.support.console.AbstractDevConsole;
+import org.apache.camel.util.json.JsonObject;
+
+@DevConsole("consumer")
+public class ConsumerDevConsole extends AbstractDevConsole {
+
+    public ConsumerDevConsole() {
+        super("camel", "consumer", "Consumers", "Display information about Camel consumers");
+    }
+
+    @Override
+    protected String doCallText(Map<String, Object> options) {
+        StringBuilder sb = new StringBuilder();
+
+        ManagedCamelContext mcc = getCamelContext().getCamelContextExtension().getContextPlugin(ManagedCamelContext.class);
+        if (mcc != null) {
+            for (Route route : getCamelContext().getRoutes()) {
+                String id = route.getId();
+                ManagedConsumerMBean mc = mcc.getManagedConsumer(id);
+                if (mc != null) {
+                    Integer inflight = mc.getInflightExchanges();
+                    if (inflight == null) {
+                        inflight = 0;
+                    }
+
+                    if (!sb.isEmpty()) {
+                        sb.append("\n");
+                    }
+                    sb.append(String.format("\n    Id: %s", id));
+                    sb.append(String.format("\n    From: %s", mc.getEndpointUri()));
+                    sb.append(String.format("\n    State: %s", mc.getState()));
+                    sb.append(String.format("\n    Class: %s", mc.getServiceType()));
+                    sb.append(String.format("\n    Inflight: %d", inflight));
+                    if (mcc instanceof ManagedSchedulePollConsumerMBean mpc) {
+                        sb.append(String.format("\n    Polling: %s", mpc.isPolling()));
+                        sb.append(String.format("\n    First Poll Done: %s", mpc.isFirstPollDone()));
+                        sb.append(String.format("\n    Scheduler Started: %s", mpc.isSchedulerStarted()));
+                        sb.append(String.format("\n    Scheduler Class: %s", mpc.getSchedulerClassName()));
+                        sb.append(String.format("\n    Repeat Count: %s", mpc.getRepeatCount()));
+                        sb.append(String.format("\n    Fixed Delay: %s", mpc.isUseFixedDelay()));
+                        sb.append(String.format("\n    Greedy: %s", mpc.isGreedy()));
+                        sb.append(String.format("\n    Running Logging Level: %s", mpc.getRunningLoggingLevel()));
+                        sb.append(String.format("\n    Send Empty Message When Idle: %s", mpc.isSendEmptyMessageWhenIdle()));
+                        sb.append(String.format("\n    Counter(total: %d success: %d error: %d)",
+                                mpc.getCounter(), mpc.getSuccessCounter(), mpc.getErrorCounter()));
+                        sb.append(String.format("\n    Delay(initial: %d delay: %d unit: %s)",
+                                mpc.getInitialDelay(), mpc.getDelay(), mpc.getTimeUnit()));
+                        sb.append(String.format(
+                                "\n    Backoff(counter: %d multiplier: %d errorThreshold: %d, idleThreshold: %d )",
+                                mpc.getBackoffCounter(), mpc.getBackoffMultiplier(), mpc.getBackoffErrorThreshold(),
+                                mpc.getBackoffIdleThreshold()));
+                    }
+                    if ("TimerConsumer".equals(mc.getServiceType())) {
+                        // need to use JMX to gather details for camel-timer consumer
+                        try {
+                            MBeanServer ms = ManagementFactory.getPlatformMBeanServer();
+                            ObjectName on = getCamelContext().getManagementStrategy().getManagementObjectNameStrategy()
+                                    .getObjectNameForConsumer(getCamelContext(),
+                                            route.getConsumer());
+                            if (ms.isRegistered(on)) {
+                                String timerName = (String) ms.getAttribute(on, "TimerName");
+                                Long counter = (Long) ms.getAttribute(on, "Counter");
+                                Boolean polling = (Boolean) ms.getAttribute(on, "Polling");
+                                Boolean fixedRate = (Boolean) ms.getAttribute(on, "FixedRate");
+                                Long delay = (Long) ms.getAttribute(on, "Delay");
+                                Long period = (Long) ms.getAttribute(on, "Period");
+                                Long repeatCount = (Long) ms.getAttribute(on, "RepeatCount");
+                                String runLoggingLevel = (String) ms.getAttribute(on, "RunLoggingLevel");
+
+                                sb.append(String.format("\n    Timer Name: %s", timerName));
+                                sb.append(String.format("\n    Polling: %s", polling));
+                                sb.append(String.format("\n    Fixed Rate: %s", fixedRate));
+                                if (delay != null) {
+                                    sb.append(String.format("\n    Delay: %s", delay));
+                                }
+                                if (period != null) {
+                                    sb.append(String.format("\n    Period: %s", period));
+                                }
+                                if (repeatCount != null) {
+                                    sb.append(String.format("\n    Repeat Count: %s", repeatCount));
+                                }
+                                sb.append(String.format("\n    Running Logging Level: %s", runLoggingLevel));
+                                sb.append(String.format("\n    Counter(total: %s)", counter));
+
+                            }
+                        } catch (Exception e) {
+                            // ignore
+                        }
+                    }
+                }
+            }
+        }
+
+        return sb.toString();
+    }
+
+    @Override
+    protected JsonObject doCallJson(Map<String, Object> options) {
+        final JsonObject root = new JsonObject();
+        final List<JsonObject> list = new ArrayList<>();
+        root.put("consumers", list);
+
+        ManagedCamelContext mcc = getCamelContext().getCamelContextExtension().getContextPlugin(ManagedCamelContext.class);
+        if (mcc != null) {
+            for (Route route : getCamelContext().getRoutes()) {
+                String id = route.getId();
+                ManagedConsumerMBean mc = mcc.getManagedConsumer(id);
+                if (mc != null) {
+                    JsonObject jo = new JsonObject();
+                    Integer inflight = mc.getInflightExchanges();
+                    if (inflight == null) {
+                        inflight = 0;
+                    }
+
+                    jo.put("id", id);
+                    jo.put("from", mc.getEndpointUri());
+                    jo.put("state", mc.getState());
+                    jo.put("class", mc.getServiceType());
+                    jo.put("inflight", inflight);
+                    if (mcc instanceof ManagedSchedulePollConsumerMBean mpc) {
+                        jo.put("polling", mpc.isPolling());
+                        jo.put("firstPollDone", mpc.isFirstPollDone());
+                        jo.put("schedulerStarted", mpc.isSchedulerStarted());
+                        jo.put("schedulerClass", mpc.getSchedulerClassName());
+                        jo.put("repeatCount", mpc.getRepeatCount());
+                        jo.put("fixedDelay", mpc.isUseFixedDelay());
+                        jo.put("initialDelay", mpc.getInitialDelay());
+                        jo.put("delay", mpc.getDelay());
+                        jo.put("timeUnit", mpc.getTimeUnit());
+                        jo.put("greedy", mpc.isGreedy());
+                        jo.put("runningLoggingLevel", mpc.getRunningLoggingLevel());
+                        jo.put("totalCounter", mpc.getCounter());
+                        jo.put("errorCounter", mpc.getErrorCounter());
+                        jo.put("successCounter", mpc.getSuccessCounter());
+                        jo.put("backoffCounter", mpc.getBackoffCounter());
+                        jo.put("backoffMultiplier", mpc.getBackoffMultiplier());
+                        jo.put("backoffErrorThreshold", mpc.getBackoffErrorThreshold());
+                        jo.put("backoffIdleThreshold", mpc.getBackoffIdleThreshold());
+                    }
+                    if ("TimerConsumer".equals(mc.getServiceType())) {
+                        // need to use JMX to gather details for camel-timer consumer
+                        try {
+                            MBeanServer ms = ManagementFactory.getPlatformMBeanServer();
+                            ObjectName on = getCamelContext().getManagementStrategy().getManagementObjectNameStrategy()
+                                    .getObjectNameForConsumer(getCamelContext(),
+                                            route.getConsumer());
+                            if (ms.isRegistered(on)) {
+                                String timerName = (String) ms.getAttribute(on, "TimerName");
+                                Long counter = (Long) ms.getAttribute(on, "Counter");
+                                Boolean polling = (Boolean) ms.getAttribute(on, "Polling");
+                                Boolean fixedRate = (Boolean) ms.getAttribute(on, "FixedRate");
+                                Long delay = (Long) ms.getAttribute(on, "Delay");
+                                Long period = (Long) ms.getAttribute(on, "Period");
+                                Long repeatCount = (Long) ms.getAttribute(on, "RepeatCount");
+                                String runLoggingLevel = (String) ms.getAttribute(on, "RunLoggingLevel");
+
+                                jo.put("timerName", timerName);
+                                jo.put("polling", polling);
+                                jo.put("fixedRate", fixedRate);
+                                if (delay != null) {
+                                    jo.put("delay", delay);
+                                }
+                                if (period != null) {
+                                    jo.put("period", period);
+                                }
+                                if (repeatCount != null) {
+                                    jo.put("repeatCount", repeatCount);
+                                }
+                                jo.put("runningLoggingLevel", runLoggingLevel);
+                                jo.put("totalCounter", counter);
+                            }
+                        } catch (Exception e) {
+                            // ignore
+                        }
+                    }
+                    list.add(jo);
+                }
+            }
+        }
+
+        return root;
+    }
+
+}
diff --git a/core/camel-management-api/src/main/java/org/apache/camel/api/management/ManagedCamelContext.java b/core/camel-management-api/src/main/java/org/apache/camel/api/management/ManagedCamelContext.java
index ebb1d4592be..d8a11acd886 100644
--- a/core/camel-management-api/src/main/java/org/apache/camel/api/management/ManagedCamelContext.java
+++ b/core/camel-management-api/src/main/java/org/apache/camel/api/management/ManagedCamelContext.java
@@ -17,6 +17,7 @@
 package org.apache.camel.api.management;
 
 import org.apache.camel.api.management.mbean.ManagedCamelContextMBean;
+import org.apache.camel.api.management.mbean.ManagedConsumerMBean;
 import org.apache.camel.api.management.mbean.ManagedProcessorMBean;
 import org.apache.camel.api.management.mbean.ManagedRouteMBean;
 import org.apache.camel.api.management.mbean.ManagedStepMBean;
@@ -78,4 +79,25 @@ public interface ManagedCamelContext {
      */
     <T extends ManagedRouteMBean> T getManagedRoute(String routeId, Class<T> type);
 
+    /**
+     * Gets the managed consumer client api from any of the routes which with the given route id
+     *
+     * @param  id route id having the consumer
+     * @return    the consumer or <tt>null</tt> if not found
+     */
+    default ManagedConsumerMBean getManagedConsumer(String id) {
+        return getManagedConsumer(id, ManagedConsumerMBean.class);
+    }
+
+    /**
+     * Gets the managed consumer client api from any of the routes which with the given route id
+     *
+     * @param  id                       route id having the consumer
+     * @param  type                     the managed consumer type from the {@link org.apache.camel.api.management.mbean}
+     *                                  package.
+     * @return                          the consumer or <tt>null</tt> if not found
+     * @throws IllegalArgumentException if the type is not compliant
+     */
+    <T extends ManagedConsumerMBean> T getManagedConsumer(String id, Class<T> type);
+
 }
diff --git a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedSchedulePollConsumerMBean.java b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedSchedulePollConsumerMBean.java
index 908a5a13037..77aa84b89f7 100644
--- a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedSchedulePollConsumerMBean.java
+++ b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedSchedulePollConsumerMBean.java
@@ -39,6 +39,24 @@ public interface ManagedSchedulePollConsumerMBean extends ManagedConsumerMBean {
     @ManagedAttribute(description = "Scheduled Fixed Delay")
     void setUseFixedDelay(boolean useFixedDelay);
 
+    @ManagedAttribute(description = "Scheduled Greedy")
+    boolean isGreedy();
+
+    @ManagedAttribute(description = "Scheduled Greedy")
+    void setGreedy(boolean greedy);
+
+    @ManagedAttribute(description = "If the polling consumer did not poll any files, you can enable this option to send an empty message (no body) instead")
+    boolean isSendEmptyMessageWhenIdle();
+
+    @ManagedAttribute(description = "If the polling consumer did not poll any files, you can enable this option to send an empty message (no body) instead")
+    void setSendEmptyMessageWhenIdle(boolean sendEmptyMessageWhenIdle);
+
+    @ManagedAttribute(description = "The consumer logs a start/complete log line when it polls. This option allows you to configure the logging level for that.")
+    String getRunningLoggingLevel();
+
+    @ManagedAttribute(description = "The consumer logs a start/complete log line when it polls. This option allows you to configure the logging level for that.")
+    void setRunningLoggingLevel(String runningLoggingLevel);
+
     @ManagedAttribute(description = "Scheduled TimeUnit")
     String getTimeUnit();
 
@@ -72,4 +90,18 @@ public interface ManagedSchedulePollConsumerMBean extends ManagedConsumerMBean {
     @ManagedAttribute(description = "Repeat count")
     long getRepeatCount();
 
+    @ManagedAttribute(description = "Whether a first pool attempt has been done (also if the consumer has been restarted)")
+    boolean isFirstPollDone();
+
+    @ManagedAttribute(description = "Total number of polls run")
+    long getCounter();
+
+    @ManagedAttribute(description = "Error counter. If the counter is > 0 that means the consumer failed polling for the last N number of times."
+                                    + " When the consumer is successfully again, then the error counter resets to zero.")
+    long getErrorCounter();
+
+    @ManagedAttribute(description = "Success counter. If the success is > 0 that means the consumer succeeded polling for the last N number of times."
+                                    + " When the consumer is failing again, then the success counter resets to zero.")
+    long getSuccessCounter();
+
 }
diff --git a/core/camel-management/src/main/java/org/apache/camel/management/ManagedCamelContextImpl.java b/core/camel-management/src/main/java/org/apache/camel/management/ManagedCamelContextImpl.java
index 99df07c2198..59ec9fac7d4 100644
--- a/core/camel-management/src/main/java/org/apache/camel/management/ManagedCamelContextImpl.java
+++ b/core/camel-management/src/main/java/org/apache/camel/management/ManagedCamelContextImpl.java
@@ -20,11 +20,13 @@ import javax.management.MalformedObjectNameException;
 import javax.management.ObjectName;
 
 import org.apache.camel.CamelContext;
+import org.apache.camel.Consumer;
 import org.apache.camel.Processor;
 import org.apache.camel.Route;
 import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.api.management.ManagedCamelContext;
 import org.apache.camel.api.management.mbean.ManagedCamelContextMBean;
+import org.apache.camel.api.management.mbean.ManagedConsumerMBean;
 import org.apache.camel.api.management.mbean.ManagedProcessorMBean;
 import org.apache.camel.api.management.mbean.ManagedRouteMBean;
 import org.apache.camel.api.management.mbean.ManagedStepMBean;
@@ -118,6 +120,28 @@ public class ManagedCamelContextImpl implements ManagedCamelContext {
         return null;
     }
 
+    @Override
+    public <T extends ManagedConsumerMBean> T getManagedConsumer(String id, Class<T> type) {
+        // jmx must be enabled
+        if (getManagementStrategy().getManagementAgent() == null) {
+            return null;
+        }
+
+        Route route = camelContext.getRoute(id);
+        if (route != null) {
+            try {
+                Consumer consumer = route.getConsumer();
+                ObjectName on = getManagementStrategy().getManagementObjectNameStrategy().getObjectNameForConsumer(camelContext,
+                        consumer);
+                return getManagementStrategy().getManagementAgent().newProxyClient(on, type);
+            } catch (MalformedObjectNameException e) {
+                throw RuntimeCamelException.wrapRuntimeCamelException(e);
+            }
+        }
+
+        return null;
+    }
+
     @Override
     public ManagedCamelContextMBean getManagedCamelContext() {
         // jmx must be enabled
diff --git a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedScheduledPollConsumer.java b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedScheduledPollConsumer.java
index 5d69ec0be75..7c39603de50 100644
--- a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedScheduledPollConsumer.java
+++ b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedScheduledPollConsumer.java
@@ -19,6 +19,7 @@ package org.apache.camel.management.mbean;
 import java.util.concurrent.TimeUnit;
 
 import org.apache.camel.CamelContext;
+import org.apache.camel.LoggingLevel;
 import org.apache.camel.api.management.ManagedResource;
 import org.apache.camel.api.management.mbean.ManagedSchedulePollConsumerMBean;
 import org.apache.camel.support.ScheduledPollConsumer;
@@ -67,6 +68,36 @@ public class ManagedScheduledPollConsumer extends ManagedConsumer implements Man
         getConsumer().setUseFixedDelay(useFixedDelay);
     }
 
+    @Override
+    public boolean isGreedy() {
+        return getConsumer().isGreedy();
+    }
+
+    @Override
+    public void setGreedy(boolean greedy) {
+        getConsumer().setGreedy(greedy);
+    }
+
+    @Override
+    public boolean isSendEmptyMessageWhenIdle() {
+        return getConsumer().isSendEmptyMessageWhenIdle();
+    }
+
+    @Override
+    public void setSendEmptyMessageWhenIdle(boolean sendEmptyMessageWhenIdle) {
+        getConsumer().setSendEmptyMessageWhenIdle(sendEmptyMessageWhenIdle);
+    }
+
+    @Override
+    public String getRunningLoggingLevel() {
+        return getConsumer().getRunLoggingLevel().name();
+    }
+
+    @Override
+    public void setRunningLoggingLevel(String runningLoggingLevel) {
+        getConsumer().setRunLoggingLevel(LoggingLevel.valueOf(runningLoggingLevel));
+    }
+
     @Override
     public String getTimeUnit() {
         return getConsumer().getTimeUnit().name();
@@ -121,4 +152,24 @@ public class ManagedScheduledPollConsumer extends ManagedConsumer implements Man
     public long getRepeatCount() {
         return getConsumer().getRepeatCount();
     }
+
+    @Override
+    public boolean isFirstPollDone() {
+        return getConsumer().isFirstPollDone();
+    }
+
+    @Override
+    public long getCounter() {
+        return getConsumer().getCounter();
+    }
+
+    @Override
+    public long getErrorCounter() {
+        return getConsumer().getErrorCounter();
+    }
+
+    @Override
+    public long getSuccessCounter() {
+        return getConsumer().getSuccessCounter();
+    }
 }
diff --git a/core/camel-support/src/main/java/org/apache/camel/support/ScheduledPollConsumer.java b/core/camel-support/src/main/java/org/apache/camel/support/ScheduledPollConsumer.java
index ffcfa3384ff..86337c9979c 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/ScheduledPollConsumer.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/ScheduledPollConsumer.java
@@ -452,16 +452,13 @@ public abstract class ScheduledPollConsumer extends DefaultConsumer
         this.scheduledExecutorService = scheduledExecutorService;
     }
 
-    // Implementation methods
-    // -------------------------------------------------------------------------
-
     /**
      * Gets the error counter. If the counter is > 0 that means the consumer failed polling for the last N number of
      * times. When the consumer is successfully again, then the error counter resets to zero.
      *
      * @see #getSuccessCounter()
      */
-    protected long getErrorCounter() {
+    public long getErrorCounter() {
         return errorCounter;
     }
 
@@ -471,24 +468,27 @@ public abstract class ScheduledPollConsumer extends DefaultConsumer
      *
      * @see #getErrorCounter()
      */
-    protected long getSuccessCounter() {
+    public long getSuccessCounter() {
         return successCounter;
     }
 
     /**
      * Gets the total number of polls run.
      */
-    protected long getCounter() {
+    public long getCounter() {
         return counter.get();
     }
 
     /**
      * Whether a first pool attempt has been done (also if the consumer has been restarted)
      */
-    protected boolean isFirstPollDone() {
+    public boolean isFirstPollDone() {
         return firstPollDone;
     }
 
+    // Implementation methods
+    // -------------------------------------------------------------------------
+
     /**
      * Gets the last caused error (exception) for the last poll that failed. When the consumer is successfully again,
      * then the error resets to null.
diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/JettyHttp11EndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/JettyHttp11EndpointBuilderFactory.java
index 30cedbea383..22c9b97f548 100644
--- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/JettyHttp11EndpointBuilderFactory.java
+++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/JettyHttp11EndpointBuilderFactory.java
@@ -934,6 +934,58 @@ public interface JettyHttp11EndpointBuilderFactory {
             doSetProperty("exchangePattern", exchangePattern);
             return this;
         }
+        /**
+         * The size threshold after which files will be written to disk for
+         * multipart/form-data requests. By default the files are not written to
+         * disk.
+         * 
+         * The option is a: &lt;code&gt;java.lang.Integer&lt;/code&gt; type.
+         * 
+         * Group: consumer (advanced)
+         * 
+         * @param fileSizeThreshold the value to set
+         * @return the dsl builder
+         */
+        default AdvancedJettyHttp11EndpointBuilder fileSizeThreshold(
+                Integer fileSizeThreshold) {
+            doSetProperty("fileSizeThreshold", fileSizeThreshold);
+            return this;
+        }
+        /**
+         * The size threshold after which files will be written to disk for
+         * multipart/form-data requests. By default the files are not written to
+         * disk.
+         * 
+         * The option will be converted to a
+         * &lt;code&gt;java.lang.Integer&lt;/code&gt; type.
+         * 
+         * Group: consumer (advanced)
+         * 
+         * @param fileSizeThreshold the value to set
+         * @return the dsl builder
+         */
+        default AdvancedJettyHttp11EndpointBuilder fileSizeThreshold(
+                String fileSizeThreshold) {
+            doSetProperty("fileSizeThreshold", fileSizeThreshold);
+            return this;
+        }
+        /**
+         * The directory location where files will be store for
+         * multipart/form-data requests. By default the files are written in the
+         * system temporary folder.
+         * 
+         * The option is a: &lt;code&gt;java.lang.String&lt;/code&gt; type.
+         * 
+         * Group: consumer (advanced)
+         * 
+         * @param filesLocation the value to set
+         * @return the dsl builder
+         */
+        default AdvancedJettyHttp11EndpointBuilder filesLocation(
+                String filesLocation) {
+            doSetProperty("filesLocation", filesLocation);
+            return this;
+        }
         /**
          * Configuration of the filter init parameters. These parameters will be
          * applied to the filter list before starting the jetty server.
@@ -1198,6 +1250,69 @@ public interface JettyHttp11EndpointBuilderFactory {
             doSetProperty("mapHttpMessageHeaders", mapHttpMessageHeaders);
             return this;
         }
+        /**
+         * The maximum size allowed for uploaded files. -1 means no limit.
+         * 
+         * The option is a: &lt;code&gt;java.lang.Long&lt;/code&gt; type.
+         * 
+         * Group: consumer (advanced)
+         * 
+         * @param maxFileSize the value to set
+         * @return the dsl builder
+         */
+        default AdvancedJettyHttp11EndpointBuilder maxFileSize(Long maxFileSize) {
+            doSetProperty("maxFileSize", maxFileSize);
+            return this;
+        }
+        /**
+         * The maximum size allowed for uploaded files. -1 means no limit.
+         * 
+         * The option will be converted to a
+         * &lt;code&gt;java.lang.Long&lt;/code&gt; type.
+         * 
+         * Group: consumer (advanced)
+         * 
+         * @param maxFileSize the value to set
+         * @return the dsl builder
+         */
+        default AdvancedJettyHttp11EndpointBuilder maxFileSize(
+                String maxFileSize) {
+            doSetProperty("maxFileSize", maxFileSize);
+            return this;
+        }
+        /**
+         * The maximum size allowed for multipart/form-data requests. -1 means
+         * no limit.
+         * 
+         * The option is a: &lt;code&gt;java.lang.Long&lt;/code&gt; type.
+         * 
+         * Group: consumer (advanced)
+         * 
+         * @param maxRequestSize the value to set
+         * @return the dsl builder
+         */
+        default AdvancedJettyHttp11EndpointBuilder maxRequestSize(
+                Long maxRequestSize) {
+            doSetProperty("maxRequestSize", maxRequestSize);
+            return this;
+        }
+        /**
+         * The maximum size allowed for multipart/form-data requests. -1 means
+         * no limit.
+         * 
+         * The option will be converted to a
+         * &lt;code&gt;java.lang.Long&lt;/code&gt; type.
+         * 
+         * Group: consumer (advanced)
+         * 
+         * @param maxRequestSize the value to set
+         * @return the dsl builder
+         */
+        default AdvancedJettyHttp11EndpointBuilder maxRequestSize(
+                String maxRequestSize) {
+            doSetProperty("maxRequestSize", maxRequestSize);
+            return this;
+        }
         /**
          * Allows using a custom multipart filter. Note: setting
          * multipartFilterRef forces the value of enableMultipartFilter to true.
diff --git a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/TimerEndpointBuilderFactory.java b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/TimerEndpointBuilderFactory.java
index d521d42800c..782c82c4ce3 100644
--- a/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/TimerEndpointBuilderFactory.java
+++ b/dsl/camel-endpointdsl/src/generated/java/org/apache/camel/builder/endpoint/dsl/TimerEndpointBuilderFactory.java
@@ -199,6 +199,41 @@ public interface TimerEndpointBuilderFactory {
             doSetProperty("repeatCount", repeatCount);
             return this;
         }
+        /**
+         * The consumer logs a start/complete log line when it polls. This
+         * option allows you to configure the logging level for that.
+         * 
+         * The option is a:
+         * &lt;code&gt;org.apache.camel.LoggingLevel&lt;/code&gt; type.
+         * 
+         * Default: TRACE
+         * Group: scheduler
+         * 
+         * @param runLoggingLevel the value to set
+         * @return the dsl builder
+         */
+        default TimerEndpointBuilder runLoggingLevel(
+                org.apache.camel.LoggingLevel runLoggingLevel) {
+            doSetProperty("runLoggingLevel", runLoggingLevel);
+            return this;
+        }
+        /**
+         * The consumer logs a start/complete log line when it polls. This
+         * option allows you to configure the logging level for that.
+         * 
+         * The option will be converted to a
+         * &lt;code&gt;org.apache.camel.LoggingLevel&lt;/code&gt; type.
+         * 
+         * Default: TRACE
+         * Group: scheduler
+         * 
+         * @param runLoggingLevel the value to set
+         * @return the dsl builder
+         */
+        default TimerEndpointBuilder runLoggingLevel(String runLoggingLevel) {
+            doSetProperty("runLoggingLevel", runLoggingLevel);
+            return this;
+        }
     }
 
     /**