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 2021/11/05 08:41:53 UTC

[camel] branch main updated: CAMEL-15333: camel-health - Consumers have their own health-check-repo. Make it possible to turn them off, and have similar configuration like routes.

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 e582a52  CAMEL-15333: camel-health - Consumers have their own health-check-repo. Make it possible to turn them off, and have similar configuration like routes.
e582a52 is described below

commit e582a528f446f8c13b7b9b9707948eaf44a69ea3
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Fri Nov 5 09:18:33 2021 +0100

    CAMEL-15333: camel-health - Consumers have their own health-check-repo. Make it possible to turn them off, and have similar configuration like routes.
---
 ...CamelMicroProfileHealthCheckRepositoryTest.java |  2 +
 ...va => CamelMicroProfileHealthConsumerTest.java} | 18 +++--
 ...sumerHealthCheckErrorDisabledConsumerTest.java} | 38 ++++-----
 .../TelegramConsumerHealthCheckErrorTest.java      | 11 +--
 .../TelegramConsumerHealthCheckOkTest.java         |  7 +-
 .../apache/camel/consumers-health-check-repository |  2 +
 .../camel/impl/health/AbstractHealthCheck.java     | 15 +++-
 .../camel/impl/health/ConsumerHealthCheck.java     | 90 ++++++++++++++++++++++
 ...ry.java => ConsumersHealthCheckRepository.java} | 30 ++++----
 .../camel/impl/health/ContextHealthCheck.java      |  3 +-
 .../apache/camel/impl/health/RouteHealthCheck.java | 35 ---------
 .../impl/health/RoutesHealthCheckRepository.java   |  1 +
 .../HealthConfigurationPropertiesConfigurer.java   |  6 ++
 .../camel-main-configuration-metadata.json         |  1 +
 core/camel-main/src/main/docs/main.adoc            |  3 +-
 .../org/apache/camel/main/BaseMainSupport.java     | 24 ++++--
 .../camel/main/HealthConfigurationProperties.java  | 13 ++++
 .../modules/ROOT/pages/health-check.adoc           | 37 +++++++--
 18 files changed, 236 insertions(+), 100 deletions(-)

diff --git a/components/camel-microprofile/camel-microprofile-health/src/test/java/org/apache/camel/microprofile/health/CamelMicroProfileHealthCheckRepositoryTest.java b/components/camel-microprofile/camel-microprofile-health/src/test/java/org/apache/camel/microprofile/health/CamelMicroProfileHealthCheckRepositoryTest.java
index eb93c69..83d1be8 100644
--- a/components/camel-microprofile/camel-microprofile-health/src/test/java/org/apache/camel/microprofile/health/CamelMicroProfileHealthCheckRepositoryTest.java
+++ b/components/camel-microprofile/camel-microprofile-health/src/test/java/org/apache/camel/microprofile/health/CamelMicroProfileHealthCheckRepositoryTest.java
@@ -55,6 +55,7 @@ public class CamelMicroProfileHealthCheckRepositoryTest extends CamelMicroProfil
 
         assertHealthCheckOutput("camel-readiness-checks", Status.UP, checks.getJsonObject(0), jsonObject -> {
             assertEquals(Status.UP.name(), jsonObject.getString("route:healthyRoute"));
+            assertEquals("Started", jsonObject.getString("route.status"));
         });
     }
 
@@ -81,6 +82,7 @@ public class CamelMicroProfileHealthCheckRepositoryTest extends CamelMicroProfil
 
         assertHealthCheckOutput("camel-readiness-checks", Status.DOWN, checks.getJsonObject(0), jsonObject -> {
             assertEquals(Status.DOWN.name(), jsonObject.getString("route:healthyRoute"));
+            assertEquals("Stopped", jsonObject.getString("route.status"));
         });
     }
 
diff --git a/components/camel-microprofile/camel-microprofile-health/src/test/java/org/apache/camel/microprofile/health/CamelMicroProfileHealthCheckRepositoryTest.java b/components/camel-microprofile/camel-microprofile-health/src/test/java/org/apache/camel/microprofile/health/CamelMicroProfileHealthConsumerTest.java
similarity index 84%
copy from components/camel-microprofile/camel-microprofile-health/src/test/java/org/apache/camel/microprofile/health/CamelMicroProfileHealthCheckRepositoryTest.java
copy to components/camel-microprofile/camel-microprofile-health/src/test/java/org/apache/camel/microprofile/health/CamelMicroProfileHealthConsumerTest.java
index eb93c69..6928bccf 100644
--- a/components/camel-microprofile/camel-microprofile-health/src/test/java/org/apache/camel/microprofile/health/CamelMicroProfileHealthCheckRepositoryTest.java
+++ b/components/camel-microprofile/camel-microprofile-health/src/test/java/org/apache/camel/microprofile/health/CamelMicroProfileHealthConsumerTest.java
@@ -29,13 +29,13 @@ import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
-public class CamelMicroProfileHealthCheckRepositoryTest extends CamelMicroProfileHealthTestSupport {
+public class CamelMicroProfileHealthConsumerTest extends CamelMicroProfileHealthTestSupport {
 
     @Test
     public void testCamelHealthRepositoryUpStatus() {
         HealthCheckRegistry healthCheckRegistry = HealthCheckRegistry.get(context);
-        // enable routes health check
-        Object hc = healthCheckRegistry.resolveById("routes");
+        // enable consumers health check
+        Object hc = healthCheckRegistry.resolveById("consumers");
         healthCheckRegistry.register(hc);
 
         CamelMicroProfileReadinessCheck readinessCheck = new CamelMicroProfileReadinessCheck();
@@ -54,15 +54,17 @@ public class CamelMicroProfileHealthCheckRepositoryTest extends CamelMicroProfil
         Assertions.assertEquals("healthyRoute", checks.getJsonObject(0).getJsonObject("data").getString("route.id"));
 
         assertHealthCheckOutput("camel-readiness-checks", Status.UP, checks.getJsonObject(0), jsonObject -> {
-            assertEquals(Status.UP.name(), jsonObject.getString("route:healthyRoute"));
+            assertEquals(Status.UP.name(), jsonObject.getString("consumer:healthyRoute"));
+            assertEquals("healthyRoute", jsonObject.getString("route.id"));
+            assertEquals("Started", jsonObject.getString("route.status"));
         });
     }
 
     @Test
     public void testCamelHealthRepositoryDownStatus() throws Exception {
         HealthCheckRegistry healthCheckRegistry = HealthCheckRegistry.get(context);
-        // enable routes health check
-        Object hc = healthCheckRegistry.resolveById("routes");
+        // enable consumers health check
+        Object hc = healthCheckRegistry.resolveById("consumers");
         healthCheckRegistry.register(hc);
 
         CamelMicroProfileReadinessCheck readinessCheck = new CamelMicroProfileReadinessCheck();
@@ -80,7 +82,9 @@ public class CamelMicroProfileHealthCheckRepositoryTest extends CamelMicroProfil
         assertEquals(1, checks.size());
 
         assertHealthCheckOutput("camel-readiness-checks", Status.DOWN, checks.getJsonObject(0), jsonObject -> {
-            assertEquals(Status.DOWN.name(), jsonObject.getString("route:healthyRoute"));
+            assertEquals(Status.DOWN.name(), jsonObject.getString("consumer:healthyRoute"));
+            assertEquals("healthyRoute", jsonObject.getString("route.id"));
+            assertEquals("Stopped", jsonObject.getString("route.status"));
         });
     }
 
diff --git a/components/camel-telegram/src/test/java/org/apache/camel/component/telegram/TelegramConsumerHealthCheckErrorTest.java b/components/camel-telegram/src/test/java/org/apache/camel/component/telegram/TelegramConsumerHealthCheckErrorDisabledConsumerTest.java
similarity index 74%
copy from components/camel-telegram/src/test/java/org/apache/camel/component/telegram/TelegramConsumerHealthCheckErrorTest.java
copy to components/camel-telegram/src/test/java/org/apache/camel/component/telegram/TelegramConsumerHealthCheckErrorDisabledConsumerTest.java
index 885e61b..1544d99 100644
--- a/components/camel-telegram/src/test/java/org/apache/camel/component/telegram/TelegramConsumerHealthCheckErrorTest.java
+++ b/components/camel-telegram/src/test/java/org/apache/camel/component/telegram/TelegramConsumerHealthCheckErrorDisabledConsumerTest.java
@@ -33,7 +33,7 @@ import org.awaitility.Awaitility;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
-public class TelegramConsumerHealthCheckErrorTest extends TelegramTestSupport {
+public class TelegramConsumerHealthCheckErrorDisabledConsumerTest extends TelegramTestSupport {
 
     @EndpointInject("mock:telegram")
     private MockEndpoint endpoint;
@@ -46,7 +46,15 @@ public class TelegramConsumerHealthCheckErrorTest extends TelegramTestSupport {
         HealthCheckRegistry hcr = context.getExtension(HealthCheckRegistry.class);
         HealthCheckRepository repo = hcr.getRepository("routes").orElse((HealthCheckRepository) hcr.resolveById("routes"));
         // add some slack so the check should fail 5 times in a row to be DOWN
-        repo.addConfiguration("telegram", HealthCheckConfiguration.builder().failureThreshold(5).build());
+        repo.addConfiguration("*", HealthCheckConfiguration.builder().failureThreshold(5).build());
+        repo.setEnabled(true);
+        hcr.register(repo);
+        // enabling consumers health check is a bit cumbersome via low-level Java code
+        repo = hcr.getRepository("consumers").orElse((HealthCheckRepository) hcr.resolveById("consumers"));
+        // add some slack so the check should fail 5 times in a row to be DOWN
+        repo.addConfiguration("consumer:telegram", HealthCheckConfiguration.builder().failureThreshold(5).build());
+        // turn off all consumer health checks
+        repo.addConfiguration("consumer:*", HealthCheckConfiguration.builder().enabled(false).build());
         repo.setEnabled(true);
         hcr.register(repo);
 
@@ -58,34 +66,22 @@ public class TelegramConsumerHealthCheckErrorTest extends TelegramTestSupport {
         HealthCheckRegistry hcr = context.getExtension(HealthCheckRegistry.class);
         HealthCheckRepository repo = hcr.getRepository("routes").get();
 
-        // should not be DOWN from the start
+        // should not be UP from the start as routes can be started
         boolean down = repo.stream().anyMatch(h -> h.call().getState().equals(HealthCheck.State.DOWN));
         Assertions.assertFalse(down, "None health-check should be DOWN");
 
-        // wait until HC is DOWN
+        // wait until HC is UP
         Awaitility.waitAtMost(5, TimeUnit.SECONDS).until(
-                () -> repo.stream().anyMatch(h -> h.call().getState().equals(HealthCheck.State.DOWN)));
+                () -> repo.stream().anyMatch(h -> h.call().getState().equals(HealthCheck.State.UP)));
 
         // if we grab the health check by id, we can also check it afterwards
         HealthCheck hc = hcr.getCheck("telegram").get();
         HealthCheck.Result rc = hc.call();
 
-        // and get the detailed error message (and exception)
-        Assertions.assertEquals(HealthCheck.State.DOWN, rc.getState());
-        String msg = rc.getMessage().get();
-        long count = (long) rc.getDetails().get(HealthCheck.FAILURE_ERROR_COUNT);
-        if (count == 0) {
-            Assertions.assertEquals("Consumer has not yet polled route: telegram (telegram://bots)", msg);
-        } else {
-            Assertions.assertEquals("Consumer failed polling " + count + " times route: telegram (telegram://bots)", msg);
-        }
-        Assertions.assertEquals("telegram://bots?authorizationToken=mock-token",
-                rc.getDetails().get(HealthCheck.FAILURE_ENDPOINT_URI));
-
-        if (rc.getError().isPresent()) {
-            Throwable e = rc.getError().get();
-            Assertions.assertTrue(e.getMessage().contains("401 Unauthorized"));
-        }
+        // so routes health check just check the status of the route which is started (UP)
+        // but the telegram consumer is not healthy as it keeps getting 401 errors
+        // to detect this we needed the consumer health check which has been disabled
+        Assertions.assertEquals(HealthCheck.State.UP, rc.getState());
     }
 
     @Override
diff --git a/components/camel-telegram/src/test/java/org/apache/camel/component/telegram/TelegramConsumerHealthCheckErrorTest.java b/components/camel-telegram/src/test/java/org/apache/camel/component/telegram/TelegramConsumerHealthCheckErrorTest.java
index 885e61b..b7a4892 100644
--- a/components/camel-telegram/src/test/java/org/apache/camel/component/telegram/TelegramConsumerHealthCheckErrorTest.java
+++ b/components/camel-telegram/src/test/java/org/apache/camel/component/telegram/TelegramConsumerHealthCheckErrorTest.java
@@ -42,11 +42,12 @@ public class TelegramConsumerHealthCheckErrorTest extends TelegramTestSupport {
     protected CamelContext createCamelContext() throws Exception {
         CamelContext context = super.createCamelContext();
 
-        // enabling routes health check is a bit cumbersome via low-level Java code
+        // enabling consumers health check is a bit cumbersome via low-level Java code
         HealthCheckRegistry hcr = context.getExtension(HealthCheckRegistry.class);
-        HealthCheckRepository repo = hcr.getRepository("routes").orElse((HealthCheckRepository) hcr.resolveById("routes"));
+        HealthCheckRepository repo
+                = hcr.getRepository("consumers").orElse((HealthCheckRepository) hcr.resolveById("consumers"));
         // add some slack so the check should fail 5 times in a row to be DOWN
-        repo.addConfiguration("telegram", HealthCheckConfiguration.builder().failureThreshold(5).build());
+        repo.addConfiguration("consumer:telegram", HealthCheckConfiguration.builder().failureThreshold(5).build());
         repo.setEnabled(true);
         hcr.register(repo);
 
@@ -56,7 +57,7 @@ public class TelegramConsumerHealthCheckErrorTest extends TelegramTestSupport {
     @Test
     public void testReceptionOfTwoMessages() throws Exception {
         HealthCheckRegistry hcr = context.getExtension(HealthCheckRegistry.class);
-        HealthCheckRepository repo = hcr.getRepository("routes").get();
+        HealthCheckRepository repo = hcr.getRepository("consumers").get();
 
         // should not be DOWN from the start
         boolean down = repo.stream().anyMatch(h -> h.call().getState().equals(HealthCheck.State.DOWN));
@@ -67,7 +68,7 @@ public class TelegramConsumerHealthCheckErrorTest extends TelegramTestSupport {
                 () -> repo.stream().anyMatch(h -> h.call().getState().equals(HealthCheck.State.DOWN)));
 
         // if we grab the health check by id, we can also check it afterwards
-        HealthCheck hc = hcr.getCheck("telegram").get();
+        HealthCheck hc = hcr.getCheck("consumer:telegram").get();
         HealthCheck.Result rc = hc.call();
 
         // and get the detailed error message (and exception)
diff --git a/components/camel-telegram/src/test/java/org/apache/camel/component/telegram/TelegramConsumerHealthCheckOkTest.java b/components/camel-telegram/src/test/java/org/apache/camel/component/telegram/TelegramConsumerHealthCheckOkTest.java
index b68db20..526b843 100644
--- a/components/camel-telegram/src/test/java/org/apache/camel/component/telegram/TelegramConsumerHealthCheckOkTest.java
+++ b/components/camel-telegram/src/test/java/org/apache/camel/component/telegram/TelegramConsumerHealthCheckOkTest.java
@@ -40,9 +40,10 @@ public class TelegramConsumerHealthCheckOkTest extends TelegramTestSupport {
     protected CamelContext createCamelContext() throws Exception {
         CamelContext context = super.createCamelContext();
 
-        // enabling routes health check is a bit cumbersome via low-level Java code
+        // enabling consumers health check is a bit cumbersome via low-level Java code
         HealthCheckRegistry hcr = context.getExtension(HealthCheckRegistry.class);
-        HealthCheckRepository repo = hcr.getRepository("routes").orElse((HealthCheckRepository) hcr.resolveById("routes"));
+        HealthCheckRepository repo
+                = hcr.getRepository("consumers").orElse((HealthCheckRepository) hcr.resolveById("consumers"));
         repo.setEnabled(true);
         hcr.register(repo);
 
@@ -52,7 +53,7 @@ public class TelegramConsumerHealthCheckOkTest extends TelegramTestSupport {
     @Test
     public void testReceptionOfTwoMessages() throws Exception {
         HealthCheckRegistry hcr = context.getExtension(HealthCheckRegistry.class);
-        HealthCheckRepository repo = hcr.getRepository("routes").get();
+        HealthCheckRepository repo = hcr.getRepository("consumers").get();
 
         endpoint.expectedMinimumMessageCount(2);
         endpoint.expectedBodiesReceived("message1", "message2");
diff --git a/core/camel-health/src/generated/resources/META-INF/services/org/apache/camel/consumers-health-check-repository b/core/camel-health/src/generated/resources/META-INF/services/org/apache/camel/consumers-health-check-repository
new file mode 100644
index 0000000..fc36fe3
--- /dev/null
+++ b/core/camel-health/src/generated/resources/META-INF/services/org/apache/camel/consumers-health-check-repository
@@ -0,0 +1,2 @@
+# Generated by camel build tools - do NOT edit this file!
+class=org.apache.camel.impl.health.ConsumersHealthCheckRepository
diff --git a/core/camel-health/src/main/java/org/apache/camel/impl/health/AbstractHealthCheck.java b/core/camel-health/src/main/java/org/apache/camel/impl/health/AbstractHealthCheck.java
index 24fdd64..4e70c7e 100644
--- a/core/camel-health/src/main/java/org/apache/camel/impl/health/AbstractHealthCheck.java
+++ b/core/camel-health/src/main/java/org/apache/camel/impl/health/AbstractHealthCheck.java
@@ -24,6 +24,8 @@ import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
 import org.apache.camel.health.HealthCheck;
 import org.apache.camel.health.HealthCheckConfiguration;
 import org.apache.camel.health.HealthCheckResultBuilder;
@@ -34,10 +36,11 @@ import org.slf4j.LoggerFactory;
 /**
  * Base implementation for {@link HealthCheck}.
  */
-public abstract class AbstractHealthCheck implements HealthCheck {
+public abstract class AbstractHealthCheck implements HealthCheck, CamelContextAware {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(AbstractHealthCheck.class);
 
+    private CamelContext camelContext;
     private final Object lock;
     private final String group;
     private final String id;
@@ -73,6 +76,16 @@ public abstract class AbstractHealthCheck implements HealthCheck {
     }
 
     @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    @Override
     public String getId() {
         return id;
     }
diff --git a/core/camel-health/src/main/java/org/apache/camel/impl/health/ConsumerHealthCheck.java b/core/camel-health/src/main/java/org/apache/camel/impl/health/ConsumerHealthCheck.java
new file mode 100644
index 0000000..6f56c76
--- /dev/null
+++ b/core/camel-health/src/main/java/org/apache/camel/impl/health/ConsumerHealthCheck.java
@@ -0,0 +1,90 @@
+/*
+ * 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.health;
+
+import java.util.Map;
+
+import org.apache.camel.Consumer;
+import org.apache.camel.ServiceStatus;
+import org.apache.camel.health.HealthCheck;
+import org.apache.camel.health.HealthCheckAware;
+import org.apache.camel.health.HealthCheckResultBuilder;
+import org.apache.camel.support.service.ServiceSupport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * {@link HealthCheck} for a given consumer.
+ */
+public class ConsumerHealthCheck extends AbstractHealthCheck {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(ConsumerHealthCheck.class);
+
+    private final Consumer consumer;
+    private final String routeId;
+
+    public ConsumerHealthCheck(Consumer consumer, String id) {
+        super("camel", id);
+        this.consumer = consumer;
+        this.routeId = id.replace("consumer:", "");
+    }
+
+    @Override
+    public boolean isLiveness() {
+        // this check is only for readiness
+        return false;
+    }
+
+    @Override
+    protected void doCall(HealthCheckResultBuilder builder, Map<String, Object> options) {
+        final ServiceStatus status = getCamelContext().getRouteController().getRouteStatus(routeId);
+        builder.detail("route.id", routeId);
+        builder.detail("route.status", status.name());
+        builder.detail("route.context.name", getCamelContext().getName());
+
+        if (consumer instanceof HealthCheckAware) {
+            // health check is optional
+            HealthCheck hc = ((HealthCheckAware) consumer).getHealthCheck();
+            if (hc != null) {
+                if (LOGGER.isTraceEnabled()) {
+                    LOGGER.trace("Calling HealthCheck on consumer route: {}", routeId);
+                }
+                Result result = hc.call();
+                if (LOGGER.isDebugEnabled()) {
+                    LOGGER.debug("HealthCheck consumer route: {} -> {}", routeId, result.getState());
+                }
+
+                builder.state(result.getState());
+                if (result.getMessage().isPresent()) {
+                    builder.message(result.getMessage().get());
+                }
+                if (result.getError().isPresent()) {
+                    builder.error(result.getError().get());
+                }
+                builder.details(result.getDetails());
+                return;
+            }
+        }
+
+        // consumer has no fine-grained health-check so check whether is started
+        boolean started = true;
+        if (consumer instanceof ServiceSupport) {
+            started = ((ServiceSupport) consumer).isStarted();
+        }
+        builder.state(started ? State.UP : State.DOWN);
+    }
+}
diff --git a/core/camel-health/src/main/java/org/apache/camel/impl/health/RoutesHealthCheckRepository.java b/core/camel-health/src/main/java/org/apache/camel/impl/health/ConsumersHealthCheckRepository.java
similarity index 80%
copy from core/camel-health/src/main/java/org/apache/camel/impl/health/RoutesHealthCheckRepository.java
copy to core/camel-health/src/main/java/org/apache/camel/impl/health/ConsumersHealthCheckRepository.java
index f7b9912..6ec18f2 100644
--- a/core/camel-health/src/main/java/org/apache/camel/impl/health/RoutesHealthCheckRepository.java
+++ b/core/camel-health/src/main/java/org/apache/camel/impl/health/ConsumersHealthCheckRepository.java
@@ -24,6 +24,7 @@ import java.util.stream.Stream;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.CamelContextAware;
+import org.apache.camel.Consumer;
 import org.apache.camel.DeferredContextBinding;
 import org.apache.camel.Route;
 import org.apache.camel.health.HealthCheck;
@@ -33,18 +34,18 @@ import org.apache.camel.spi.annotations.JdkService;
 import org.apache.camel.support.PatternHelper;
 
 /**
- * Repository for routes {@link HealthCheck}s.
+ * Repository for consumers {@link HealthCheck}s.
  */
-@JdkService("routes-health-check-repository")
+@JdkService("consumers-health-check-repository")
 @DeferredContextBinding
-public class RoutesHealthCheckRepository implements CamelContextAware, HealthCheckRepository {
-    private final ConcurrentMap<Route, HealthCheck> checks;
+public class ConsumersHealthCheckRepository implements CamelContextAware, HealthCheckRepository {
+    private final ConcurrentMap<Consumer, HealthCheck> checks;
     private volatile CamelContext context;
     private Map<String, HealthCheckConfiguration> configurations;
     private HealthCheckConfiguration fallbackConfiguration;
     private boolean enabled = true;
 
-    public RoutesHealthCheckRepository() {
+    public ConsumersHealthCheckRepository() {
         this.checks = new ConcurrentHashMap<>();
     }
 
@@ -55,7 +56,7 @@ public class RoutesHealthCheckRepository implements CamelContextAware, HealthChe
 
     @Override
     public String getId() {
-        return "routes";
+        return "consumers";
     }
 
     @Override
@@ -112,7 +113,7 @@ public class RoutesHealthCheckRepository implements CamelContextAware, HealthChe
                 ? this.context.getRoutes()
                         .stream()
                         .filter(route -> route.getId() != null)
-                        .map(this::toRouteHealthCheck)
+                        .map(this::toConsumerHealthCheck)
                 : Stream.empty();
     }
 
@@ -120,14 +121,17 @@ public class RoutesHealthCheckRepository implements CamelContextAware, HealthChe
     // Helpers
     // *****************************
 
-    private HealthCheck toRouteHealthCheck(Route route) {
-        return checks.computeIfAbsent(route, r -> {
-            RouteHealthCheck rhc = new RouteHealthCheck(route);
-            HealthCheckConfiguration hcc = matchConfiguration(route.getRouteId());
+    private HealthCheck toConsumerHealthCheck(Route route) {
+        return checks.computeIfAbsent(route.getConsumer(), r -> {
+            // must prefix id with consumer: to not clash with route
+            String id = "consumer:" + route.getRouteId();
+            ConsumerHealthCheck chc = new ConsumerHealthCheck(route.getConsumer(), id);
+            CamelContextAware.trySetCamelContext(chc, route.getCamelContext());
+            HealthCheckConfiguration hcc = matchConfiguration(id);
             if (hcc != null) {
-                rhc.setConfiguration(hcc);
+                chc.setConfiguration(hcc);
             }
-            return rhc;
+            return chc;
         });
     }
 
diff --git a/core/camel-health/src/main/java/org/apache/camel/impl/health/ContextHealthCheck.java b/core/camel-health/src/main/java/org/apache/camel/impl/health/ContextHealthCheck.java
index fe99b98..b2f9f71 100644
--- a/core/camel-health/src/main/java/org/apache/camel/impl/health/ContextHealthCheck.java
+++ b/core/camel-health/src/main/java/org/apache/camel/impl/health/ContextHealthCheck.java
@@ -19,7 +19,6 @@ package org.apache.camel.impl.health;
 import java.util.Map;
 
 import org.apache.camel.CamelContext;
-import org.apache.camel.CamelContextAware;
 import org.apache.camel.health.HealthCheckResultBuilder;
 import org.apache.camel.spi.annotations.JdkService;
 
@@ -28,7 +27,7 @@ import org.apache.camel.spi.annotations.JdkService;
  * not.
  */
 @JdkService("context-health-check")
-public final class ContextHealthCheck extends AbstractHealthCheck implements CamelContextAware {
+public final class ContextHealthCheck extends AbstractHealthCheck {
     private CamelContext camelContext;
 
     public ContextHealthCheck() {
diff --git a/core/camel-health/src/main/java/org/apache/camel/impl/health/RouteHealthCheck.java b/core/camel-health/src/main/java/org/apache/camel/impl/health/RouteHealthCheck.java
index e925c1d..44cde6b 100644
--- a/core/camel-health/src/main/java/org/apache/camel/impl/health/RouteHealthCheck.java
+++ b/core/camel-health/src/main/java/org/apache/camel/impl/health/RouteHealthCheck.java
@@ -19,22 +19,15 @@ package org.apache.camel.impl.health;
 import java.util.Map;
 
 import org.apache.camel.CamelContext;
-import org.apache.camel.Consumer;
 import org.apache.camel.Route;
 import org.apache.camel.ServiceStatus;
-import org.apache.camel.health.HealthCheck;
-import org.apache.camel.health.HealthCheckAware;
 import org.apache.camel.health.HealthCheckResultBuilder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * {@link org.apache.camel.health.HealthCheck} for a given route.
  */
 public class RouteHealthCheck extends AbstractHealthCheck {
 
-    private static final Logger LOGGER = LoggerFactory.getLogger(RouteHealthCheck.class);
-
     private final Route route;
 
     public RouteHealthCheck(Route route) {
@@ -82,34 +75,6 @@ public class RouteHealthCheck extends AbstractHealthCheck {
                     }
                 }
             }
-
-            // check fine-grained consumer health check if we are up as the route may be up and running
-            // but the consumer can be un-healthy
-            if (State.UP.equals(builder.state())) {
-                Consumer consumer = route.getConsumer();
-                if (consumer instanceof HealthCheckAware) {
-                    // health check is optional
-                    HealthCheck hc = ((HealthCheckAware) consumer).getHealthCheck();
-                    if (hc != null) {
-                        if (LOGGER.isTraceEnabled()) {
-                            LOGGER.trace("Calling HealthCheck on consumer route: {}", route.getId());
-                        }
-                        Result result = hc.call();
-                        if (LOGGER.isDebugEnabled()) {
-                            LOGGER.debug("HealthCheck consumer route: {} -> {}", route.getId(), result.getState());
-                        }
-
-                        builder.state(result.getState());
-                        if (result.getMessage().isPresent()) {
-                            builder.message(result.getMessage().get());
-                        }
-                        if (result.getError().isPresent()) {
-                            builder.error(result.getError().get());
-                        }
-                        builder.details(result.getDetails());
-                    }
-                }
-            }
         }
     }
 }
diff --git a/core/camel-health/src/main/java/org/apache/camel/impl/health/RoutesHealthCheckRepository.java b/core/camel-health/src/main/java/org/apache/camel/impl/health/RoutesHealthCheckRepository.java
index f7b9912..da9e794 100644
--- a/core/camel-health/src/main/java/org/apache/camel/impl/health/RoutesHealthCheckRepository.java
+++ b/core/camel-health/src/main/java/org/apache/camel/impl/health/RoutesHealthCheckRepository.java
@@ -123,6 +123,7 @@ public class RoutesHealthCheckRepository implements CamelContextAware, HealthChe
     private HealthCheck toRouteHealthCheck(Route route) {
         return checks.computeIfAbsent(route, r -> {
             RouteHealthCheck rhc = new RouteHealthCheck(route);
+            CamelContextAware.trySetCamelContext(rhc, route.getCamelContext());
             HealthCheckConfiguration hcc = matchConfiguration(route.getRouteId());
             if (hcc != null) {
                 rhc.setConfiguration(hcc);
diff --git a/core/camel-main/src/generated/java/org/apache/camel/main/HealthConfigurationPropertiesConfigurer.java b/core/camel-main/src/generated/java/org/apache/camel/main/HealthConfigurationPropertiesConfigurer.java
index 906d623..e44bf31 100644
--- a/core/camel-main/src/generated/java/org/apache/camel/main/HealthConfigurationPropertiesConfigurer.java
+++ b/core/camel-main/src/generated/java/org/apache/camel/main/HealthConfigurationPropertiesConfigurer.java
@@ -23,6 +23,8 @@ public class HealthConfigurationPropertiesConfigurer extends org.apache.camel.su
         switch (ignoreCase ? name.toLowerCase() : name) {
         case "config":
         case "Config": target.setConfig(property(camelContext, java.util.Map.class, value)); return true;
+        case "consumersenabled":
+        case "ConsumersEnabled": target.setConsumersEnabled(property(camelContext, java.lang.Boolean.class, value)); return true;
         case "contextenabled":
         case "ContextEnabled": target.setContextEnabled(property(camelContext, java.lang.Boolean.class, value)); return true;
         case "enabled":
@@ -40,6 +42,8 @@ public class HealthConfigurationPropertiesConfigurer extends org.apache.camel.su
         switch (ignoreCase ? name.toLowerCase() : name) {
         case "config":
         case "Config": return java.util.Map.class;
+        case "consumersenabled":
+        case "ConsumersEnabled": return java.lang.Boolean.class;
         case "contextenabled":
         case "ContextEnabled": return java.lang.Boolean.class;
         case "enabled":
@@ -58,6 +62,8 @@ public class HealthConfigurationPropertiesConfigurer extends org.apache.camel.su
         switch (ignoreCase ? name.toLowerCase() : name) {
         case "config":
         case "Config": return target.getConfig();
+        case "consumersenabled":
+        case "ConsumersEnabled": return target.getConsumersEnabled();
         case "contextenabled":
         case "ContextEnabled": return target.getContextEnabled();
         case "enabled":
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 ab4da55..58c12b9 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
@@ -119,6 +119,7 @@
     { "name": "camel.faulttolerance.timeoutPoolSize", "description": "Configures the pool size of the thread pool when timeout is enabled. Default value is 10.", "sourceType": "org.apache.camel.main.FaultToleranceConfigurationProperties", "type": "integer", "javaType": "java.lang.Integer", "defaultValue": 10 },
     { "name": "camel.faulttolerance.timeoutScheduledExecutorServiceRef", "description": "References to a custom thread pool to use when timeout is enabled", "sourceType": "org.apache.camel.main.FaultToleranceConfigurationProperties", "type": "string", "javaType": "java.lang.String" },
     { "name": "camel.health.config", "description": "Set additional HealthConfigurationProperties for fine grained configuration of health checks.", "sourceType": "org.apache.camel.main.HealthConfigurationProperties", "type": "object", "javaType": "java.util.Map" },
+    { "name": "camel.health.consumersEnabled", "description": "Whether consumers health check is enabled", "sourceType": "org.apache.camel.main.HealthConfigurationProperties", "type": "boolean", "javaType": "java.lang.Boolean", "defaultValue": true },
     { "name": "camel.health.contextEnabled", "description": "Whether context health check is enabled", "sourceType": "org.apache.camel.main.HealthConfigurationProperties", "type": "boolean", "javaType": "java.lang.Boolean", "defaultValue": true },
     { "name": "camel.health.enabled", "description": "Whether health check is enabled globally", "sourceType": "org.apache.camel.main.HealthConfigurationProperties", "type": "boolean", "javaType": "java.lang.Boolean", "defaultValue": true },
     { "name": "camel.health.registryEnabled", "description": "Whether registry health check is enabled", "sourceType": "org.apache.camel.main.HealthConfigurationProperties", "type": "boolean", "javaType": "java.lang.Boolean", "defaultValue": true },
diff --git a/core/camel-main/src/main/docs/main.adoc b/core/camel-main/src/main/docs/main.adoc
index 341a352..32e17a9 100644
--- a/core/camel-main/src/main/docs/main.adoc
+++ b/core/camel-main/src/main/docs/main.adoc
@@ -140,12 +140,13 @@ The camel.threadpool supports 8 options, which are listed below.
 |===
 
 === Camel Health Check configurations
-The camel.health supports 5 options, which are listed below.
+The camel.health supports 6 options, which are listed below.
 
 [width="100%",cols="2,5,^1,2",options="header"]
 |===
 | Name | Description | Default | Type
 | *camel.health.config* | Set additional HealthConfigurationProperties for fine grained configuration of health checks. |  | Map
+| *camel.health.consumersEnabled* | Whether consumers health check is enabled | true | Boolean
 | *camel.health.contextEnabled* | Whether context health check is enabled | true | Boolean
 | *camel.health.enabled* | Whether health check is enabled globally | true | Boolean
 | *camel.health.registryEnabled* | Whether registry health check is enabled | true | Boolean
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
index b7e4782..e98ebd5 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
@@ -969,7 +969,7 @@ public abstract class BaseMainSupport extends BaseService {
                 hcr.register(hc);
             }
         }
-        // routes is enabled by default
+        // routes are enabled by default
         if (hcr.isEnabled() && (!health.getConfig().containsKey("routes") || health.getRoutesEnabled() != null)) {
             HealthCheckRepository hc = hcr.getRepository("routes").orElse((HealthCheckRepository) hcr.resolveById("routes"));
             if (hc != null) {
@@ -979,13 +979,27 @@ public abstract class BaseMainSupport extends BaseService {
                 hcr.register(hc);
             }
         }
-        // registry is enabled by default
+        // consumers are enabled by default
+        if (hcr.isEnabled() && (!health.getConfig().containsKey("consumers") || health.getRegistryEnabled() != null)) {
+            HealthCheckRepository hc
+                    = hcr.getRepository("consumers").orElse((HealthCheckRepository) hcr.resolveById("consumers"));
+            if (hc != null) {
+                if (health.getConsumersEnabled() != null) {
+                    hc.setEnabled(health.getConsumersEnabled());
+                }
+                hcr.register(hc);
+            }
+        }
+        // registry are enabled by default
         if (hcr.isEnabled() && (!health.getConfig().containsKey("registry") || health.getRegistryEnabled() != null)) {
-            hcr.getRepository("registry").ifPresent(h -> {
+            HealthCheckRepository hc
+                    = hcr.getRepository("registry").orElse((HealthCheckRepository) hcr.resolveById("registry"));
+            if (hc != null) {
                 if (health.getRegistryEnabled() != null) {
-                    h.setEnabled(health.getRegistryEnabled());
+                    hc.setEnabled(health.getRegistryEnabled());
                 }
-            });
+                hcr.register(hc);
+            }
         }
 
         // configure health checks configurations
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/HealthConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/HealthConfigurationProperties.java
index b652291..6c403fa 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/HealthConfigurationProperties.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/HealthConfigurationProperties.java
@@ -38,6 +38,8 @@ public class HealthConfigurationProperties implements BootstrapCloseable {
     @Metadata(defaultValue = "true")
     private Boolean routesEnabled;
     @Metadata(defaultValue = "true")
+    private Boolean consumersEnabled;
+    @Metadata(defaultValue = "true")
     private Boolean registryEnabled;
     private Map<String, HealthCheckConfigurationProperties> config = new HashMap<>();
 
@@ -89,6 +91,17 @@ public class HealthConfigurationProperties implements BootstrapCloseable {
         this.routesEnabled = routesEnabled;
     }
 
+    public Boolean getConsumersEnabled() {
+        return consumersEnabled;
+    }
+
+    /**
+     * Whether consumers health check is enabled
+     */
+    public void setConsumersEnabled(Boolean consumersEnabled) {
+        this.consumersEnabled = consumersEnabled;
+    }
+
     public Boolean getRegistryEnabled() {
         return registryEnabled;
     }
diff --git a/docs/user-manual/modules/ROOT/pages/health-check.adoc b/docs/user-manual/modules/ROOT/pages/health-check.adoc
index 948d0a6..db219e0 100644
--- a/docs/user-manual/modules/ROOT/pages/health-check.adoc
+++ b/docs/user-manual/modules/ROOT/pages/health-check.adoc
@@ -12,19 +12,19 @@ Camel provides support to probe the state of an integration via a pluggable Heal
 
 Camel provides the following health checks out of the box:
 
-- context - A `HealthCheck` which performs check whether the `CamelContext` is started. This can be used for readiness checks; to know when Camel is fully started and ready to handle traffic.
+- _context_ - A `HealthCheck` which performs check whether the `CamelContext` is started. This can be used for readiness checks; to know when Camel is fully started and ready to handle traffic.
 - routes - A `HealthCheckRegistry` which discovers all the available routes in `CamelContext` and checks whether they are all started.
   This can be used for readiness checks; to know when Camel is fully started and ready to handle traffic.
   Combining with the supervised `RouteController` this allows to perform readiness check for routes that are under supervising,
   such as troublesome routes that may not start up the first time, and are retried to be started in the background with backoff delays.
-- consumer (scheduled polling consumer) - A `ScheduledPollConsumerHealthCheck` which automatic integrates with the *routes* health check
-  which enables fine-grained checks for the route input. This means if the consumer is failing to poll new messages
+- _consumers_ A `HealthCheckRegistry` which discovers all the consumers from all the routes in `CamelContext`
+  enabling fine-grained checks for the route input. This means if the consumer is failing to poll new messages
   then the health check can detect this and report as un-healthy. Note that the consumer will be DOWN during its initialization and until at least
   one poll run has been executed, to know whether that poll was a success or not. And if the poll was a success
   then the consumer is UP. This is on purpose to avoid having the health check to be initially UP
   and then after first poll run then DOWN again because the consumer cannot poll from external system;
   which causes the health check to be _flaky_.
-- registry - A `HealthCheckRegistry` which discovers all the available custom `HealthCheck` instances in the `Registry`.
+- _registry_ - A `HealthCheckRegistry` which discovers all the available custom `HealthCheck` instances in the `Registry`.
 
 == IDs
 
@@ -33,8 +33,8 @@ With the suffix `-health-check` or `-health-check-repository`. When looking up o
 
 For example `context-health-check` is the ID but can also be used by its shorthand `context`.
 
-The ID of the `ScheduledPollConsumerHealthCheck` is the route id with `route:` as prefix, eg if the route
-is named foo, then the ID is `route:foo`.
+The ID of the consumer health checks is the route id with `consumer:` as prefix, i.e. if the route
+is named foo, then the ID is `consumer:foo`.
 
 == Readiness and Liveness
 
@@ -78,7 +78,7 @@ By default, this is not in use, and the first successful check will result in UP
 Camel supports via `camel-main` to configure health-checks from configuration files. This is possible for runtimes that leverage `camel-main`
 such as Camel on Spring Boot, or Camel K.
 
-Camel will automatically enable `context`, `routes` and `registry` health-checks if `camel-health` is detected on the classpath.
+Camel will automatically enable `context`, `routes`, `consumers`, and `registry` health-checks if `camel-health` is detected on the classpath.
 They are all enabled by default. However, you can configure them, for example to turn it off:
 
 [source,properties]
@@ -90,6 +90,7 @@ They are all enabled by default. However, you can configure them, for example to
 # for example to only use context health-check
 camel.health.contextEnabled=true
 camel.health.routesEnabled=false
+camel.health.consumersEnabled=false
 camel.health.registryEnabled=false
 ----
 
@@ -119,6 +120,28 @@ camel.health.config[*].success-threshold=3
 camel.health.config[*].failure-threshold=10
 ----
 
+=== Turning off consumer level health-checks
+
+If routes health check is enabled then they will execute consumer health-checks as well
+as part of an aggregated response.
+
+The consumer checks can be turned off, to only use the route level checks (status of the route)
+
+[source,properties]
+----
+camel.health.consumersEnabled=false
+----
+
+You can also turn off individual consumers by prefixing the ID with `consumer:` such as:
+
+[source,properties]
+----
+camel.health.config[consumer:kafka*].enabled=false
+----
+
+which will turn off checks for all consumers on routes that starts with `kafka` in the route ID.
+
+
 == JMX management
 
 The health check is manageable via JMX (requires `camel-management` JAR on the classpath).