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 <[email protected]>
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).