This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch health in repository https://gitbox.apache.org/repos/asf/camel.git
commit a5146f7ce52eb28be31001f21247189fc5a660f5 Author: Claus Ibsen <[email protected]> AuthorDate: Wed Feb 9 11:00:49 2022 +0100 CAMEL-17587: camel-health - Make Health Check API simpler --- .../main/camel-main-configuration-metadata.json | 2 +- .../org/apache/camel/health/HealthCheckHelper.java | 2 +- .../apache/camel/health/HealthCheckRegistry.java | 11 +++- .../health/ConsumersHealthCheckRepository.java | 6 +- .../impl/health/DefaultHealthCheckRegistry.java | 33 ++++++++++- .../impl/health/HealthCheckRegistryRepository.java | 6 +- .../impl/health/RoutesHealthCheckRepository.java | 6 +- .../camel-main-configuration-metadata.json | 2 +- core/camel-main/src/main/docs/main.adoc | 2 +- .../camel/main/HealthConfigurationProperties.java | 6 +- ...ava => MainHealthCheckExcludedPatternTest.java} | 69 ++++++++++++++++++---- 11 files changed, 121 insertions(+), 24 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json index e22879f..1d8e638 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json @@ -134,7 +134,7 @@ { "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.excludePattern", "description": "Pattern to disabled health checks by their ids. Multiple patterns can be separated by comma.", "sourceType": "org.apache.camel.main.HealthConfigurationProperties", "type": "string", "javaType": "java.lang.String" }, + { "name": "camel.health.excludePattern", "description": "Pattern to exclude health checks from being invoked by Camel when checking healths. Multiple patterns can be separated by comma.", "sourceType": "org.apache.camel.main.HealthConfigurationProperties", "type": "string", "javaType": "java.lang.String" }, { "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 }, { "name": "camel.health.routesEnabled", "description": "Whether routes health check is enabled", "sourceType": "org.apache.camel.main.HealthConfigurationProperties", "type": "boolean", "javaType": "java.lang.Boolean", "defaultValue": true }, { "name": "camel.hystrix.allowMaximumSizeToDivergeFromCoreSize", "description": "Allows the configuration for maximumSize to take effect. That value can then be equal to, or higher, than coreSize", "sourceType": "org.apache.camel.main.HystrixConfigurationProperties", "type": "boolean", "javaType": "java.lang.Boolean", "defaultValue": "false", "deprecated": true }, 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 336b7a2..1fe0d56 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 @@ -118,7 +118,7 @@ public final class HealthCheckHelper { .entrySet().stream() .map(Map.Entry::getValue) .flatMap(Collection::stream) - .filter(check -> !filter.test(check)) + .filter(check -> !registry.isExcluded(check) && !filter.test(check)) .sorted(Comparator.comparingInt(HealthCheck::getOrder)) .distinct() .map(check -> check.call(optionsSupplier.apply(check))) diff --git a/core/camel-api/src/main/java/org/apache/camel/health/HealthCheckRegistry.java b/core/camel-api/src/main/java/org/apache/camel/health/HealthCheckRegistry.java index bad246e..8101c04 100644 --- a/core/camel-api/src/main/java/org/apache/camel/health/HealthCheckRegistry.java +++ b/core/camel-api/src/main/java/org/apache/camel/health/HealthCheckRegistry.java @@ -122,13 +122,20 @@ public interface HealthCheckRegistry extends CamelContextAware, StaticService, I void loadHealthChecks(); /** - * Pattern to disabled health checks by their ids. Multiple patterns can be separated by comma. + * Pattern to exclude health checks from being invoked by Camel when checking healths. Multiple patterns can be + * separated by comma. */ String getExcludePattern(); /** - * Pattern to disabled health checks by their ids. Multiple patterns can be separated by comma. + * Pattern to exclude health checks from being invoked by Camel when checking healths. Multiple patterns can be + * separated by comma. */ void setExcludePattern(String excludePattern); + /** + * Whether the given health check has been excluded + */ + boolean isExcluded(HealthCheck healthCheck); + } diff --git a/core/camel-health/src/main/java/org/apache/camel/impl/health/ConsumersHealthCheckRepository.java b/core/camel-health/src/main/java/org/apache/camel/impl/health/ConsumersHealthCheckRepository.java index bcd2bbe..b4244d2 100644 --- a/core/camel-health/src/main/java/org/apache/camel/impl/health/ConsumersHealthCheckRepository.java +++ b/core/camel-health/src/main/java/org/apache/camel/impl/health/ConsumersHealthCheckRepository.java @@ -24,16 +24,20 @@ import org.apache.camel.CamelContext; import org.apache.camel.CamelContextAware; import org.apache.camel.Consumer; import org.apache.camel.DeferredContextBinding; +import org.apache.camel.NonManagedService; import org.apache.camel.Route; +import org.apache.camel.StaticService; import org.apache.camel.health.HealthCheck; import org.apache.camel.health.HealthCheckRepository; +import org.apache.camel.support.service.ServiceSupport; /** * Repository for consumers {@link HealthCheck}s. */ @org.apache.camel.spi.annotations.HealthCheck("consumers-repository") @DeferredContextBinding -public class ConsumersHealthCheckRepository implements CamelContextAware, HealthCheckRepository { +public class ConsumersHealthCheckRepository extends ServiceSupport + implements CamelContextAware, HealthCheckRepository, StaticService, NonManagedService { private final ConcurrentMap<Consumer, HealthCheck> checks; private volatile CamelContext context; 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 fe1d50d..59cb0f4 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 @@ -30,6 +30,8 @@ import org.apache.camel.health.HealthCheck; import org.apache.camel.health.HealthCheckRegistry; import org.apache.camel.health.HealthCheckRepository; import org.apache.camel.health.HealthCheckResolver; +import org.apache.camel.support.PatternHelper; +import org.apache.camel.support.service.ServiceHelper; import org.apache.camel.support.service.ServiceSupport; import org.apache.camel.util.ObjectHelper; import org.apache.camel.util.StopWatch; @@ -113,6 +115,18 @@ public class DefaultHealthCheckRegistry extends ServiceSupport implements Health for (HealthCheckRepository repository : repositories) { CamelContextAware.trySetCamelContext(repository, camelContext); } + + ServiceHelper.initService(repositories, checks); + } + + @Override + protected void doStart() throws Exception { + ServiceHelper.startService(repositories, checks); + } + + @Override + protected void doStop() throws Exception { + ServiceHelper.stopService(repositories, checks); } // ************************************ @@ -170,8 +184,6 @@ public class DefaultHealthCheckRegistry extends ServiceSupport implements Health checkIfAccepted(obj); - // TODO: exclude pattern - if (obj instanceof HealthCheck) { HealthCheck healthCheck = (HealthCheck) obj; // do we have this already @@ -264,6 +276,23 @@ public class DefaultHealthCheckRegistry extends ServiceSupport implements Health } } + @Override + public boolean isExcluded(HealthCheck healthCheck) { + if (excludePattern != null) { + String[] s = excludePattern.split(","); + String id = healthCheck.getId(); + String id2 = null; + // special for route and consumer health checks + if (id.startsWith("route:")) { + id2 = id.substring(6); + } else if (id.startsWith("consumer:")) { + id2 = id.substring(9); + } + return PatternHelper.matchPatterns(id, s) || (id2 != null && PatternHelper.matchPatterns(id2, s)); + } + return false; + } + private void checkIfAccepted(Object obj) { boolean accept = obj instanceof HealthCheck || obj instanceof HealthCheckRepository; if (!accept) { 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 fbb3337..54210e6 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 @@ -21,15 +21,19 @@ import java.util.stream.Stream; import org.apache.camel.CamelContext; import org.apache.camel.CamelContextAware; +import org.apache.camel.NonManagedService; +import org.apache.camel.StaticService; import org.apache.camel.health.HealthCheck; import org.apache.camel.health.HealthCheckRepository; +import org.apache.camel.support.service.ServiceSupport; /** * {@link HealthCheckRepository} that uses the Camel {@link org.apache.camel.spi.Registry}. * * Camel will use this by default, so there is no need to register this manually. */ -public class HealthCheckRegistryRepository implements CamelContextAware, HealthCheckRepository { +public class HealthCheckRegistryRepository extends ServiceSupport + implements CamelContextAware, HealthCheckRepository, StaticService, NonManagedService { private CamelContext context; private boolean enabled = true; 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 3103385..f7cd2fb 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 @@ -23,16 +23,20 @@ import java.util.stream.Stream; import org.apache.camel.CamelContext; import org.apache.camel.CamelContextAware; import org.apache.camel.DeferredContextBinding; +import org.apache.camel.NonManagedService; import org.apache.camel.Route; +import org.apache.camel.StaticService; import org.apache.camel.health.HealthCheck; import org.apache.camel.health.HealthCheckRepository; +import org.apache.camel.support.service.ServiceSupport; /** * Repository for routes {@link HealthCheck}s. */ @org.apache.camel.spi.annotations.HealthCheck("routes-repository") @DeferredContextBinding -public class RoutesHealthCheckRepository implements CamelContextAware, HealthCheckRepository { +public class RoutesHealthCheckRepository extends ServiceSupport + implements CamelContextAware, HealthCheckRepository, StaticService, NonManagedService { private final ConcurrentMap<Route, HealthCheck> checks; private volatile CamelContext context; 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 e22879f..1d8e638 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 @@ -134,7 +134,7 @@ { "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.excludePattern", "description": "Pattern to disabled health checks by their ids. Multiple patterns can be separated by comma.", "sourceType": "org.apache.camel.main.HealthConfigurationProperties", "type": "string", "javaType": "java.lang.String" }, + { "name": "camel.health.excludePattern", "description": "Pattern to exclude health checks from being invoked by Camel when checking healths. Multiple patterns can be separated by comma.", "sourceType": "org.apache.camel.main.HealthConfigurationProperties", "type": "string", "javaType": "java.lang.String" }, { "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 }, { "name": "camel.health.routesEnabled", "description": "Whether routes health check is enabled", "sourceType": "org.apache.camel.main.HealthConfigurationProperties", "type": "boolean", "javaType": "java.lang.Boolean", "defaultValue": true }, { "name": "camel.hystrix.allowMaximumSizeToDivergeFromCoreSize", "description": "Allows the configuration for maximumSize to take effect. That value can then be equal to, or higher, than coreSize", "sourceType": "org.apache.camel.main.HystrixConfigurationProperties", "type": "boolean", "javaType": "java.lang.Boolean", "defaultValue": "false", "deprecated": true }, diff --git a/core/camel-main/src/main/docs/main.adoc b/core/camel-main/src/main/docs/main.adoc index 12af1c8..286680c 100644 --- a/core/camel-main/src/main/docs/main.adoc +++ b/core/camel-main/src/main/docs/main.adoc @@ -158,7 +158,7 @@ The camel.health supports 6 options, which are listed below. | *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.excludePattern* | Pattern to disabled health checks by their ids. Multiple patterns can be separated by comma. | | String +| *camel.health.excludePattern* | Pattern to exclude health checks from being invoked by Camel when checking healths. Multiple patterns can be separated by comma. | | String | *camel.health.registryEnabled* | Whether registry health check is enabled | true | Boolean | *camel.health.routesEnabled* | Whether routes health check is enabled | true | Boolean |=== 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 e2b4fb1..69dc26c 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 @@ -114,7 +114,8 @@ public class HealthConfigurationProperties implements BootstrapCloseable { } /** - * Pattern to disabled health checks by their ids. Multiple patterns can be separated by comma. + * Pattern to exclude health checks from being invoked by Camel when checking healths. Multiple patterns can be + * separated by comma. */ public void setExcludePattern(String excludePattern) { this.excludePattern = excludePattern; @@ -153,7 +154,8 @@ public class HealthConfigurationProperties implements BootstrapCloseable { } /** - * Pattern to exclude health checks by their ids. Multiple patterns can be separated by comma. + * Pattern to exclude health checks from being invoked by Camel when checking healths. Multiple patterns can be + * separated by comma. */ public HealthConfigurationProperties withExcludePattern(String excludePattern) { this.excludePattern = excludePattern; diff --git a/core/camel-main/src/test/java/org/apache/camel/main/MainHealthCheckConfigTest.java b/core/camel-main/src/test/java/org/apache/camel/main/MainHealthCheckExcludedPatternTest.java similarity index 66% rename from core/camel-main/src/test/java/org/apache/camel/main/MainHealthCheckConfigTest.java rename to core/camel-main/src/test/java/org/apache/camel/main/MainHealthCheckExcludedPatternTest.java index 5013656..a541871 100644 --- a/core/camel-main/src/test/java/org/apache/camel/main/MainHealthCheckConfigTest.java +++ b/core/camel-main/src/test/java/org/apache/camel/main/MainHealthCheckExcludedPatternTest.java @@ -19,18 +19,19 @@ package org.apache.camel.main; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; import org.apache.camel.CamelContext; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.health.HealthCheck; +import org.apache.camel.health.HealthCheckHelper; import org.apache.camel.health.HealthCheckRegistry; import org.apache.camel.health.HealthCheckRepository; import org.apache.camel.health.HealthCheckResultBuilder; import org.apache.camel.impl.health.AbstractHealthCheck; import org.apache.camel.impl.health.HealthCheckRegistryRepository; import org.apache.camel.impl.health.RoutesHealthCheckRepository; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -38,13 +39,10 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; -// TODO: exclude pattern - -@Disabled -public class MainHealthCheckConfigTest { +public class MainHealthCheckExcludedPatternTest { @Test - public void testMainRoutesHealthCheckConfiguration() { + public void testMainRoutesHealthCheckExcluded() { Main main = new Main(); main.configure().addRoutesBuilder(new Routes()); main.addInitialProperty("camel.health.routes-enabled", "true"); @@ -66,16 +64,18 @@ public class MainHealthCheckConfigTest { HealthCheck hc = healthCheckRegistry.getCheck("mydirect").get(); assertTrue(hc.isEnabled()); + assertFalse(healthCheckRegistry.isExcluded(hc)); hc = healthCheckRegistry.getCheck("myseda").get(); - assertFalse(hc.isEnabled()); + assertTrue(hc.isEnabled()); + assertTrue(healthCheckRegistry.isExcluded(hc)); } finally { main.stop(); } } @Test - public void testMainBasicHealthCheckConfiguration() { + public void testMainBasicHealthCheckRegistry() { Main main = new Main(); main.configure().addRoutesBuilder(new Routes()); main.addInitialProperty("camel.health.exclude-pattern", "custom"); @@ -85,10 +85,11 @@ public class MainHealthCheckConfigTest { CamelContext camelContext = main.getCamelContext(); assertNotNull(camelContext); + final AtomicBoolean invoked = new AtomicBoolean(); HealthCheck healthCheck = new AbstractHealthCheck("custom") { @Override protected void doCall(HealthCheckResultBuilder builder, Map<String, Object> options) { - // Noop + invoked.set(true); } }; @@ -107,8 +108,54 @@ public class MainHealthCheckConfigTest { List<HealthCheck> healthChecks = registryRepository.stream().collect(Collectors.toList()); assertEquals(1, healthChecks.size()); - HealthCheck hc = healthCheckRegistry.getCheck("custom").get(); - assertTrue(hc.isEnabled()); + assertTrue(healthCheckRegistry.getCheck("custom").isPresent()); + + // custom is excluded + HealthCheckHelper.invoke(camelContext); + assertFalse(invoked.get()); + } finally { + main.stop(); + } + } + + @Test + public void testMainBasicHealthCheckAdded() { + Main main = new Main(); + main.configure().addRoutesBuilder(new Routes()); + main.addInitialProperty("camel.health.exclude-pattern", "custom"); + + main.start(); + try { + CamelContext camelContext = main.getCamelContext(); + assertNotNull(camelContext); + + final AtomicBoolean invoked = new AtomicBoolean(); + HealthCheck healthCheck = new AbstractHealthCheck("custom") { + @Override + protected void doCall(HealthCheckResultBuilder builder, Map<String, Object> options) { + invoked.set(true); + } + }; + + HealthCheckRegistry healthCheckRegistry = camelContext.getExtension(HealthCheckRegistry.class); + assertNotNull(healthCheckRegistry); + + List<HealthCheck> healthChecks = healthCheckRegistry.stream().collect(Collectors.toList()); + int before = healthChecks.size(); + + // register custom health check which should be excluded + boolean added = healthCheckRegistry.register(healthCheck); + assertTrue(added); + + healthChecks = healthCheckRegistry.stream().collect(Collectors.toList()); + int after = healthChecks.size(); + assertEquals(before + 1, after); + + assertTrue(healthCheckRegistry.getCheck("custom").isPresent()); + + // custom is excluded + HealthCheckHelper.invoke(camelContext); + assertFalse(invoked.get()); } finally { main.stop(); }
