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 cacd79f CAMEL-17626: camel-health - SPI to plugin custom manipulation
of health check
cacd79f is described below
commit cacd79fa02432df7c39228cce3937314ba5c7c45
Author: Claus Ibsen <[email protected]>
AuthorDate: Thu Feb 10 10:31:14 2022 +0100
CAMEL-17626: camel-health - SPI to plugin custom manipulation of health
check
---
.../org/apache/camel/health/HealthCheckHelper.java | 59 ++++---------
...kFilter.java => HealthCheckResultStrategy.java} | 18 ++--
.../health/DefaultHealthCheckRegistryTest.java | 11 ---
.../impl/health/HealthCheckResultStrategyTest.java | 86 +++++++++++++++++++
.../apache/camel/impl/health/HealthCheckTest.java | 5 ++
.../impl/health/ReadinessAndLivenessTest.java | 22 -----
.../camel/impl/health/AbstractHealthCheck.java | 99 +++++++++++++---------
.../impl/health/DefaultHealthCheckRegistry.java | 14 ++-
.../impl/health/HealthCheckRegistryRepository.java | 3 +-
.../modules/ROOT/pages/health-check.adoc | 18 +++-
10 files changed, 208 insertions(+), 127 deletions(-)
diff --git
a/core/camel-api/src/main/java/org/apache/camel/health/HealthCheckHelper.java
b/core/camel-api/src/main/java/org/apache/camel/health/HealthCheckHelper.java
index 1fe0d56..6336c1e 100644
---
a/core/camel-api/src/main/java/org/apache/camel/health/HealthCheckHelper.java
+++
b/core/camel-api/src/main/java/org/apache/camel/health/HealthCheckHelper.java
@@ -22,40 +22,27 @@ import java.util.Comparator;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
+import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.apache.camel.CamelContext;
import org.apache.camel.util.ObjectHelper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
* Helper for invoking {@link HealthCheck}'s.
*
- * The helper will lookup the {@link HealthCheckRegistry} from {@link
CamelContext} and gather all the registered
- * {@link HealthCheck}s and invoke them and gather their responses.
+ * The helper will look up the {@link HealthCheckRegistry} from {@link
CamelContext} and gather all the registered
+ * {@link HealthCheck}s and invoke them and gather their results.
*
- * The helper allows filtering out unwanted health checks using {@link
HealthCheckFilter} or to invoke only readiness or
- * liveness checks.
+ * The helper allows filtering out unwanted health checks using {@link
Predicate<HealthCheck>} or to invoke only
+ * readiness or liveness checks.
*/
public final class HealthCheckHelper {
- private static final Logger LOG =
LoggerFactory.getLogger(HealthCheckHelper.class);
-
private HealthCheckHelper() {
}
/**
- * Get the group of the given check or an empty string if the group is not
set.
- *
- * @param check the health check
- * @return the {@link HealthCheck#getGroup()} or an empty string if
it is <code>null</code>
- */
- public static String getGroup(HealthCheck check) {
- return ObjectHelper.supplyIfEmpty(check.getGroup(), () -> "");
- }
-
- /**
* Invokes the checks and returns a collection of results.
*/
public static Collection<HealthCheck.Result> invoke(CamelContext
camelContext) {
@@ -91,7 +78,7 @@ public final class HealthCheckHelper {
*/
public static Collection<HealthCheck.Result> invoke(
CamelContext camelContext,
- HealthCheckFilter filter) {
+ Predicate<HealthCheck> filter) {
return invoke(camelContext, check -> Collections.emptyMap(), filter);
}
@@ -106,7 +93,7 @@ public final class HealthCheckHelper {
public static Collection<HealthCheck.Result> invoke(
CamelContext camelContext,
Function<HealthCheck, Map<String, Object>> optionsSupplier,
- HealthCheckFilter filter) {
+ Predicate<HealthCheck> filter) {
final HealthCheckRegistry registry =
HealthCheckRegistry.get(camelContext);
@@ -115,59 +102,43 @@ public final class HealthCheckHelper {
// check one by one.
return registry.stream()
.collect(Collectors.groupingBy(HealthCheckHelper::getGroup))
- .entrySet().stream()
- .map(Map.Entry::getValue)
+ .values().stream()
.flatMap(Collection::stream)
.filter(check -> !registry.isExcluded(check) &&
!filter.test(check))
.sorted(Comparator.comparingInt(HealthCheck::getOrder))
.distinct()
.map(check -> check.call(optionsSupplier.apply(check)))
.collect(Collectors.toList());
- } else {
- LOG.debug("No health check source found");
}
return Collections.emptyList();
}
/**
- * Query the status of a check by id. Note that this may result in an
effective invocation of the
- * {@link HealthCheck}.
+ * Invoke a check by id.
*
* @param camelContext the camel context.
* @param id the check id.
* @param options the check options.
* @return an optional {@link HealthCheck.Result}.
*/
- public static Optional<HealthCheck.Result> query(CamelContext
camelContext, String id, Map<String, Object> options) {
+ public static Optional<HealthCheck.Result> invoke(CamelContext
camelContext, String id, Map<String, Object> options) {
final HealthCheckRegistry registry =
HealthCheckRegistry.get(camelContext);
if (registry != null) {
return registry.getCheck(id).map(check -> check.call(options));
- } else {
- LOG.debug("No health check source found");
}
return Optional.empty();
}
/**
- * Invoke a check by id.
+ * Get the group of the given check or an empty string if the group is not
set.
*
- * @param camelContext the camel context.
- * @param id the check id.
- * @param options the check options.
- * @return an optional {@link HealthCheck.Result}.
+ * @param check the health check
+ * @return the {@link HealthCheck#getGroup()} or an empty string if
it is <code>null</code>
*/
- public static Optional<HealthCheck.Result> invoke(CamelContext
camelContext, String id, Map<String, Object> options) {
- final HealthCheckRegistry registry =
HealthCheckRegistry.get(camelContext);
-
- if (registry != null) {
- return registry.getCheck(id).map(check -> check.call(options));
- } else {
- LOG.debug("No health check source found");
- }
-
- return Optional.empty();
+ private static String getGroup(HealthCheck check) {
+ return ObjectHelper.supplyIfEmpty(check.getGroup(), () -> "");
}
}
diff --git
a/core/camel-api/src/main/java/org/apache/camel/health/HealthCheckFilter.java
b/core/camel-api/src/main/java/org/apache/camel/health/HealthCheckResultStrategy.java
similarity index 57%
rename from
core/camel-api/src/main/java/org/apache/camel/health/HealthCheckFilter.java
rename to
core/camel-api/src/main/java/org/apache/camel/health/HealthCheckResultStrategy.java
index 2481104..14bd356 100644
---
a/core/camel-api/src/main/java/org/apache/camel/health/HealthCheckFilter.java
+++
b/core/camel-api/src/main/java/org/apache/camel/health/HealthCheckResultStrategy.java
@@ -16,17 +16,21 @@
*/
package org.apache.camel.health;
+import java.util.Map;
+
/**
- * Health check filter.
+ * A strategy that allows SPI to process {@link HealthCheck} results and
enrich and manipulate the result.
*/
-@FunctionalInterface
-public interface HealthCheckFilter {
+public interface HealthCheckResultStrategy {
/**
- * Determine if the given {@link HealthCheck} has to be filtered out.
+ * Processes and allows manipulation of the result from the {@link
HealthCheck} invocation.
*
- * @param check the check to evaluate.
- * @return true if the given <dode>check</dode> has to be filtered
out.
+ * @param check the invoked health check
+ * @param options optional options when invoked the health check
+ * @param builder the result builder that builds the health check
response, which can be enriched and manipulated by
+ * this strategy.
*/
- boolean test(HealthCheck check);
+ void processResult(HealthCheck check, Map<String, Object> options,
HealthCheckResultBuilder builder);
+
}
diff --git
a/core/camel-core/src/test/java/org/apache/camel/impl/health/DefaultHealthCheckRegistryTest.java
b/core/camel-core/src/test/java/org/apache/camel/impl/health/DefaultHealthCheckRegistryTest.java
index 11c805f..59d7cb2 100644
---
a/core/camel-core/src/test/java/org/apache/camel/impl/health/DefaultHealthCheckRegistryTest.java
+++
b/core/camel-core/src/test/java/org/apache/camel/impl/health/DefaultHealthCheckRegistryTest.java
@@ -202,8 +202,6 @@ public class DefaultHealthCheckRegistryTest {
private static class MyHealthCheck extends AbstractHealthCheck implements
CamelContextAware {
- private CamelContext context;
-
protected MyHealthCheck(String group, String id) {
super(group, id);
}
@@ -213,14 +211,5 @@ public class DefaultHealthCheckRegistryTest {
builder.up();
}
- @Override
- public void setCamelContext(CamelContext camelContext) {
- this.context = camelContext;
- }
-
- @Override
- public CamelContext getCamelContext() {
- return context;
- }
}
}
diff --git
a/core/camel-core/src/test/java/org/apache/camel/impl/health/HealthCheckResultStrategyTest.java
b/core/camel-core/src/test/java/org/apache/camel/impl/health/HealthCheckResultStrategyTest.java
new file mode 100644
index 0000000..1afdc31
--- /dev/null
+++
b/core/camel-core/src/test/java/org/apache/camel/impl/health/HealthCheckResultStrategyTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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.Collection;
+import java.util.Map;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.health.HealthCheck;
+import org.apache.camel.health.HealthCheckHelper;
+import org.apache.camel.health.HealthCheckRegistry;
+import org.apache.camel.health.HealthCheckResultStrategy;
+import org.apache.camel.health.HealthCheckResultBuilder;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class HealthCheckResultStrategyTest extends ContextTestSupport {
+
+ @Override
+ public boolean isUseRouteBuilder() {
+ return false;
+ }
+
+ @Test
+ public void testMyFoo() throws Exception {
+ context.getRegistry().bind("myStrategy", new MyResultStrategy());
+ context.start();
+
+ HealthCheck hc
+ =
context.adapt(ExtendedCamelContext.class).getHealthCheckResolver().resolveHealthCheck("myfoo");
+ Assertions.assertNotNull(hc);
+
+ Assertions.assertEquals("acme", hc.getGroup());
+ Assertions.assertEquals("myfoo", hc.getId());
+
+ HealthCheck.Result r = hc.call();
+
+ Assertions.assertEquals(HealthCheck.State.UP, r.getState());
+ Assertions.assertEquals("I changed this", r.getMessage().get());
+ }
+
+ @Test
+ public void testAddToRegistry() throws Exception {
+ context.getRegistry().bind("myStrategy", new MyResultStrategy());
+ context.start();
+
+ HealthCheck hc
+ =
context.adapt(ExtendedCamelContext.class).getHealthCheckResolver().resolveHealthCheck("myfoo");
+ Assertions.assertNotNull(hc);
+
+ HealthCheckRegistry hcr =
context.getExtension(HealthCheckRegistry.class);
+ hcr.register(hc);
+
+ Collection<HealthCheck.Result> col = HealthCheckHelper.invoke(context);
+ Assertions.assertEquals(1, col.size());
+
+ HealthCheck.Result r = col.iterator().next();
+ Assertions.assertEquals(HealthCheck.State.UP, r.getState());
+ Assertions.assertEquals("I changed this", r.getMessage().get());
+ }
+
+ private static class MyResultStrategy implements HealthCheckResultStrategy
{
+
+ @Override
+ public void processResult(HealthCheck check, Map<String, Object>
options, HealthCheckResultBuilder builder) {
+ builder.up();
+ builder.message("I changed this");
+ }
+ }
+
+}
diff --git
a/core/camel-core/src/test/java/org/apache/camel/impl/health/HealthCheckTest.java
b/core/camel-core/src/test/java/org/apache/camel/impl/health/HealthCheckTest.java
index 4fbeb94..16ad8fc 100644
---
a/core/camel-core/src/test/java/org/apache/camel/impl/health/HealthCheckTest.java
+++
b/core/camel-core/src/test/java/org/apache/camel/impl/health/HealthCheckTest.java
@@ -18,8 +18,10 @@ package org.apache.camel.impl.health;
import java.util.Map;
+import org.apache.camel.CamelContext;
import org.apache.camel.health.HealthCheck;
import org.apache.camel.health.HealthCheckResultBuilder;
+import org.apache.camel.impl.DefaultCamelContext;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -30,7 +32,10 @@ public class HealthCheckTest {
@Test
public void testCheck() throws Exception {
+ CamelContext context = new DefaultCamelContext();
+
MyHealthCheck check = new MyHealthCheck();
+ check.setCamelContext(context);
check.setState(HealthCheck.State.UP);
// disable
check.setEnabled(false);
diff --git
a/core/camel-core/src/test/java/org/apache/camel/impl/health/ReadinessAndLivenessTest.java
b/core/camel-core/src/test/java/org/apache/camel/impl/health/ReadinessAndLivenessTest.java
index cade600..8a44ca1 100644
---
a/core/camel-core/src/test/java/org/apache/camel/impl/health/ReadinessAndLivenessTest.java
+++
b/core/camel-core/src/test/java/org/apache/camel/impl/health/ReadinessAndLivenessTest.java
@@ -71,8 +71,6 @@ public class ReadinessAndLivenessTest {
private static class MyReadyCheck extends AbstractHealthCheck implements
CamelContextAware {
- private CamelContext context;
-
protected MyReadyCheck(String group, String id) {
super(group, id);
}
@@ -87,21 +85,10 @@ public class ReadinessAndLivenessTest {
builder.up();
}
- @Override
- public void setCamelContext(CamelContext camelContext) {
- this.context = camelContext;
- }
-
- @Override
- public CamelContext getCamelContext() {
- return context;
- }
}
private static class MyLiveCheck extends AbstractHealthCheck implements
CamelContextAware {
- private CamelContext context;
-
protected MyLiveCheck(String group, String id) {
super(group, id);
}
@@ -116,14 +103,5 @@ public class ReadinessAndLivenessTest {
builder.down();
}
- @Override
- public void setCamelContext(CamelContext camelContext) {
- this.context = camelContext;
- }
-
- @Override
- public CamelContext getCamelContext() {
- return context;
- }
}
}
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 8b7839a..bb29f64 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
@@ -20,12 +20,14 @@ import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.Map;
+import java.util.Set;
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.HealthCheckResultStrategy;
import org.apache.camel.health.HealthCheckResultBuilder;
import org.apache.camel.util.ObjectHelper;
import org.slf4j.Logger;
@@ -36,7 +38,7 @@ import org.slf4j.LoggerFactory;
*/
public abstract class AbstractHealthCheck implements HealthCheck,
CamelContextAware {
- private static final Logger LOGGER =
LoggerFactory.getLogger(AbstractHealthCheck.class);
+ private static final Logger LOG =
LoggerFactory.getLogger(AbstractHealthCheck.class);
private CamelContext camelContext;
private boolean enabled = true;
@@ -111,56 +113,68 @@ public abstract class AbstractHealthCheck implements
HealthCheck, CamelContextAw
@Override
public Result call(Map<String, Object> options) {
+ HealthCheckResultBuilder builder;
synchronized (lock) {
- final HealthCheckResultBuilder builder =
HealthCheckResultBuilder.on(this);
+ builder = doCall(options);
+ }
+
+ HealthCheckResultStrategy strategy =
customHealthCheckResponseStrategy();
+ if (strategy != null) {
+ strategy.processResult(this, options, builder);
+ }
- // Extract relevant information from meta data.
- int invocationCount = (Integer)
meta.getOrDefault(INVOCATION_COUNT, 0);
- int failureCount = (Integer) meta.getOrDefault(FAILURE_COUNT, 0);
- int successCount = (Integer) meta.getOrDefault(SUCCESS_COUNT, 0);
+ return builder.build();
+ }
- String invocationTime =
ZonedDateTime.now().format(DateTimeFormatter.ISO_ZONED_DATE_TIME);
+ protected HealthCheckResultBuilder doCall(Map<String, Object> options) {
+ final HealthCheckResultBuilder builder =
HealthCheckResultBuilder.on(this);
- // Set common meta-data
- meta.put(INVOCATION_ATTEMPT_TIME, invocationTime);
+ // Extract relevant information from meta data.
+ int invocationCount = (Integer) meta.getOrDefault(INVOCATION_COUNT, 0);
+ int failureCount = (Integer) meta.getOrDefault(FAILURE_COUNT, 0);
+ int successCount = (Integer) meta.getOrDefault(SUCCESS_COUNT, 0);
- if (!isEnabled()) {
- LOGGER.debug("health-check {}/{} disabled", getGroup(),
getId());
+ String invocationTime =
ZonedDateTime.now().format(DateTimeFormatter.ISO_ZONED_DATE_TIME);
- builder.message("Disabled");
- builder.detail(CHECK_ENABLED, false);
+ // Set common meta-data
+ meta.put(INVOCATION_ATTEMPT_TIME, invocationTime);
- return builder.unknown().build();
- }
+ if (!isEnabled()) {
+ LOG.debug("health-check {}/{} disabled", getGroup(), getId());
+ builder.message("Disabled");
+ builder.detail(CHECK_ENABLED, false);
+ builder.unknown();
+ return builder;
+ }
- LOGGER.debug("Invoke health-check {}/{}", getGroup(), getId());
- doCall(builder, options);
+ LOG.debug("Invoke health-check {}/{}", getGroup(), getId());
+ doCall(builder, options);
- // State should be set here
- ObjectHelper.notNull(builder.state(), "Response State");
+ if (builder.state() == null) {
+ builder.unknown();
+ }
- if (builder.state() == State.DOWN) {
- // reset success since it failed
- successCount = 0;
- } else if (builder.state() == State.UP) {
- // reset failure since it ok
- failureCount = 0;
- }
+ if (builder.state() == State.DOWN) {
+ // reset success since it failed
+ successCount = 0;
+ } else if (builder.state() == State.UP) {
+ // reset failure since it ok
+ failureCount = 0;
+ }
- meta.put(INVOCATION_TIME, invocationTime);
- meta.put(INVOCATION_COUNT, ++invocationCount);
- meta.put(FAILURE_COUNT, failureCount);
- meta.put(SUCCESS_COUNT, successCount);
+ meta.put(INVOCATION_TIME, invocationTime);
+ meta.put(INVOCATION_COUNT, ++invocationCount);
+ meta.put(FAILURE_COUNT, failureCount);
+ meta.put(SUCCESS_COUNT, successCount);
- // Copy some meta-data bits to the response attributes so the
- // response caches the health-check state at the time of the
invocation.
- builder.detail(INVOCATION_TIME, meta.get(INVOCATION_TIME));
- builder.detail(INVOCATION_COUNT, meta.get(INVOCATION_COUNT));
- builder.detail(FAILURE_COUNT, meta.get(FAILURE_COUNT));
- builder.detail(SUCCESS_COUNT, meta.get(SUCCESS_COUNT));
+ // Copy some meta-data bits to the response attributes so the
+ // response caches the health-check state at the time of the
invocation.
+ builder.detail(INVOCATION_TIME, meta.get(INVOCATION_TIME));
+ builder.detail(INVOCATION_COUNT, meta.get(INVOCATION_COUNT));
+ builder.detail(FAILURE_COUNT, meta.get(FAILURE_COUNT));
+ builder.detail(SUCCESS_COUNT, meta.get(SUCCESS_COUNT));
- return builder.build();
- }
+ return builder;
}
@Override
@@ -192,4 +206,13 @@ public abstract class AbstractHealthCheck implements
HealthCheck, CamelContextAw
* @see HealthCheck#call(Map)
*/
protected abstract void doCall(HealthCheckResultBuilder builder,
Map<String, Object> options);
+
+ private HealthCheckResultStrategy customHealthCheckResponseStrategy() {
+ Set<HealthCheckResultStrategy> set =
camelContext.getRegistry().findByType(HealthCheckResultStrategy.class);
+ if (set.size() == 1) {
+ return set.iterator().next();
+ }
+ return null;
+ }
+
}
diff --git
a/core/camel-health/src/main/java/org/apache/camel/impl/health/DefaultHealthCheckRegistry.java
b/core/camel-health/src/main/java/org/apache/camel/impl/health/DefaultHealthCheckRegistry.java
index b489d98..0190494 100644
---
a/core/camel-health/src/main/java/org/apache/camel/impl/health/DefaultHealthCheckRegistry.java
+++
b/core/camel-health/src/main/java/org/apache/camel/impl/health/DefaultHealthCheckRegistry.java
@@ -104,7 +104,7 @@ public class DefaultHealthCheckRegistry extends
ServiceSupport implements Health
.filter(repository -> repository instanceof
HealthCheckRegistryRepository)
.findFirst();
- if (!hcr.isPresent()) {
+ if (hcr.isEmpty()) {
register(new HealthCheckRegistryRepository());
}
@@ -184,6 +184,9 @@ public class DefaultHealthCheckRegistry extends
ServiceSupport implements Health
checkIfAccepted(obj);
+ // inject context
+ CamelContextAware.trySetCamelContext(obj, camelContext);
+
if (obj instanceof HealthCheck) {
HealthCheck healthCheck = (HealthCheck) obj;
// do we have this already
@@ -208,6 +211,11 @@ public class DefaultHealthCheckRegistry extends
ServiceSupport implements Health
}
}
+ // ensure the check is started if we are already started (such as
added later)
+ if (isStarted()) {
+ ServiceHelper.startService(obj);
+ }
+
return result;
}
@@ -231,6 +239,10 @@ public class DefaultHealthCheckRegistry extends
ServiceSupport implements Health
}
}
+ if (result) {
+ ServiceHelper.stopService(obj);
+ }
+
return result;
}
diff --git
a/core/camel-health/src/main/java/org/apache/camel/impl/health/HealthCheckRegistryRepository.java
b/core/camel-health/src/main/java/org/apache/camel/impl/health/HealthCheckRegistryRepository.java
index 54210e6..06ff928 100644
---
a/core/camel-health/src/main/java/org/apache/camel/impl/health/HealthCheckRegistryRepository.java
+++
b/core/camel-health/src/main/java/org/apache/camel/impl/health/HealthCheckRegistryRepository.java
@@ -66,7 +66,8 @@ public class HealthCheckRegistryRepository extends
ServiceSupport
public Stream<HealthCheck> stream() {
if (context != null && enabled) {
Set<HealthCheck> set =
this.context.getRegistry().findByType(HealthCheck.class);
- return set.stream().map(this::toHealthCheck);
+ return set.stream()
+ .map(this::toHealthCheck);
} else {
return Stream.empty();
}
diff --git a/docs/user-manual/modules/ROOT/pages/health-check.adoc
b/docs/user-manual/modules/ROOT/pages/health-check.adoc
index 6baa8de..a693b17 100644
--- a/docs/user-manual/modules/ROOT/pages/health-check.adoc
+++ b/docs/user-manual/modules/ROOT/pages/health-check.adoc
@@ -128,6 +128,18 @@ the readiness or liveness checks.
The health checks can also be invoked from JMX.
+== Enriching and controlling health check responses
+
+Each health check that is invoked will gather details about the result using
`HealthCheckResultBuilder`.
+
+To allow enriching and manipulating the result, then you can use
`HealthCheckResultStrategy` to
+plug in a custom bean that can process the result, and change state, add
information, remove unwanted information,
+etc. on the result builder.
+
+The custom bean should be registered to the Camel xref:registry.adoc[Registry]
to be discovered
+by `camel-health`. Only one instance of the bean is allowed.
+
+
== Writing a custom health check
There are a limited number of health checks provided by Camel out of the box,
@@ -169,7 +181,7 @@ public final class MyHealthCheck extends
AbstractHealthCheck {
You can now make _MyHealthCheck_ available to Camel by adding an instance to
(for example Spring application context)
or directly to the Camel xref:registry.adoc[Registry].
-=== Loading custom health checks
+== Loading custom health checks
Camel can discover and load custom health checks from classpath scanning. This
requires
to annotate the custom health checks with `@HealthCheck` annotation on the
class (see above).
@@ -211,7 +223,7 @@ context.setLoadHealthChecks(true);
TIP: The example `main-health` has a custom health check which is loadable.
-==== Loading custom health checks in Camel Quarkus
+=== Loading custom health checks in Camel Quarkus
If you use Camel Quarkus then you can write custom health checks with
xref:components:others:microprofile-health.adoc[MicroProfile Health], which
@@ -222,7 +234,7 @@ Using Camel's own health check APIs does however allow
building health checks
that are usable anywhere you use Camel whether its standalone, spring boot,
quarkus,
or something else.
-=== Writing custom Health Check for Camel components
+== Writing custom Health Check for Camel components
You can implement custom health checks in Camel components (currently only for
consumers).