This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/camel.git
commit cf316012b4c1be43b278f059adffd5b7c4c02f1e Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Fri May 29 13:52:13 2020 +0200 camel-health: also register custom hc repository. And fix camel-spring and add better test. --- .../spring/health/HealthCheckRegistryTest.java | 55 +++++++++++++--------- .../spring/health/HealthCheckRegistryTest.xml | 33 ++++--------- .../core/xml/AbstractCamelContextFactoryBean.java | 14 ++++++ .../MainConfigurationPropertiesConfigurer.java | 10 ++++ .../camel-main-configuration-metadata.json | 2 + .../camel/main/DefaultConfigurationConfigurer.java | 10 ++++ .../camel/management/mbean/ManagedCamelHealth.java | 4 +- 7 files changed, 78 insertions(+), 50 deletions(-) diff --git a/components/camel-spring/src/test/java/org/apache/camel/spring/health/HealthCheckRegistryTest.java b/components/camel-spring/src/test/java/org/apache/camel/spring/health/HealthCheckRegistryTest.java index ad966a9..448bf1f 100644 --- a/components/camel-spring/src/test/java/org/apache/camel/spring/health/HealthCheckRegistryTest.java +++ b/components/camel-spring/src/test/java/org/apache/camel/spring/health/HealthCheckRegistryTest.java @@ -16,15 +16,13 @@ */ package org.apache.camel.spring.health; -import java.util.Collection; -import java.util.Optional; +import java.util.List; +import java.util.stream.Collectors; import org.apache.camel.CamelContext; +import org.apache.camel.CamelContextAware; +import org.apache.camel.health.HealthCheck; import org.apache.camel.health.HealthCheckRegistry; -import org.apache.camel.health.HealthCheckRepository; -import org.apache.camel.impl.health.RegistryRepository; -import org.apache.camel.impl.health.RoutePerformanceCounterEvaluators; -import org.apache.camel.impl.health.RoutesHealthCheckRepository; import org.junit.Assert; import org.junit.Test; import org.springframework.context.support.ClassPathXmlApplicationContext; @@ -34,28 +32,39 @@ import static org.junit.Assert.assertNotNull; public class HealthCheckRegistryTest { @Test - public void testRepositories() { + public void testHealthCheckRoutes() throws Exception { CamelContext context = createContext("org/apache/camel/spring/health/HealthCheckRegistryTest.xml"); - Collection<HealthCheckRepository> repos = HealthCheckRegistry.get(context).getRepositories(); - Assert.assertNotNull(repos); - Assert.assertEquals(2, repos.size()); - Assert.assertTrue(repos.stream().anyMatch(RegistryRepository.class::isInstance)); - Assert.assertTrue(repos.stream().anyMatch(RoutesHealthCheckRepository.class::isInstance)); + HealthCheckRegistry hc = context.getExtension(HealthCheckRegistry.class); + assertNotNull(hc); - Optional<RoutesHealthCheckRepository> repo = repos.stream() - .filter(RoutesHealthCheckRepository.class::isInstance) - .map(RoutesHealthCheckRepository.class::cast) - .findFirst(); + List<HealthCheck> checks = hc.stream().collect(Collectors.toList()); + Assert.assertEquals(2, checks.size()); - Assert.assertTrue(repo.isPresent()); - Assert.assertEquals(2, repo.get().evaluators().count()); - Assert.assertEquals(1, repo.get().evaluators().filter(RoutePerformanceCounterEvaluators.ExchangesFailed.class::isInstance).count()); - Assert.assertEquals(1, repo.get().evaluators().filter(RoutePerformanceCounterEvaluators.LastProcessingTime.class::isInstance).count()); - Assert.assertEquals(1, repo.get().evaluators("route-1").count()); - Assert.assertEquals(1, repo.get().evaluators("route-1").filter(RoutePerformanceCounterEvaluators.ExchangesInflight.class::isInstance).count()); - } + for (HealthCheck check : checks) { + HealthCheck.Result response = check.call(); + + Assert.assertEquals(HealthCheck.State.UP, response.getState()); + Assert.assertFalse(response.getMessage().isPresent()); + Assert.assertFalse(response.getError().isPresent()); + } + context.getRouteController().stopRoute("foo"); + + for (HealthCheck check : checks) { + HealthCheck.Result response = check.call(); + boolean foo = "foo".equals(response.getDetails().get("route.id")); + if (foo) { + Assert.assertEquals(HealthCheck.State.DOWN, response.getState()); + Assert.assertTrue(response.getMessage().isPresent()); + Assert.assertFalse(response.getError().isPresent()); + } else { + Assert.assertEquals(HealthCheck.State.UP, response.getState()); + Assert.assertFalse(response.getMessage().isPresent()); + Assert.assertFalse(response.getError().isPresent()); + } + } + } protected CamelContext createContext(String classpathConfigFile) { ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(classpathConfigFile); diff --git a/components/camel-spring/src/test/resources/org/apache/camel/spring/health/HealthCheckRegistryTest.xml b/components/camel-spring/src/test/resources/org/apache/camel/spring/health/HealthCheckRegistryTest.xml index 879a9df..aa11fb9 100644 --- a/components/camel-spring/src/test/resources/org/apache/camel/spring/health/HealthCheckRegistryTest.xml +++ b/components/camel-spring/src/test/resources/org/apache/camel/spring/health/HealthCheckRegistryTest.xml @@ -25,32 +25,17 @@ http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> - <bean id="hc-repo-routes" class="org.apache.camel.impl.health.RoutesHealthCheckRepository"> - <property name="evaluators"> - <list> - <bean class="org.apache.camel.impl.health.RoutePerformanceCounterEvaluators.ExchangesFailed"> - <constructor-arg value="10"/> - </bean> - <bean class="org.apache.camel.impl.health.RoutePerformanceCounterEvaluators.LastProcessingTime"> - <constructor-arg value="1000"/> - <constructor-arg value="1"/> - </bean> - </list> - </property> - <property name="routesEvaluators"> - <map> - <entry key="route-1"> - <list> - <bean class="org.apache.camel.impl.health.RoutePerformanceCounterEvaluators.ExchangesInflight"> - <constructor-arg value="10"/> - </bean> - </list> - </entry> - </map> - </property> - </bean> + <bean id="hc-repo-routes" class="org.apache.camel.impl.health.RoutesHealthCheckRepository"/> <camelContext xmlns="http://camel.apache.org/schema/spring"> + <route id="foo"> + <from uri="direct:start"/> + <to uri="mock:foo"/> + </route> + <route id="bar"> + <from uri="direct:start2"/> + <to uri="mock:bar"/> + </route> </camelContext> </beans> \ No newline at end of file diff --git a/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java b/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java index 0f854d1..bebafce 100644 --- a/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java +++ b/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java @@ -49,6 +49,7 @@ import org.apache.camel.component.properties.PropertiesComponent; import org.apache.camel.component.properties.PropertiesLocation; import org.apache.camel.component.properties.PropertiesParser; import org.apache.camel.health.HealthCheckRegistry; +import org.apache.camel.health.HealthCheckRepository; import org.apache.camel.impl.engine.DefaultManagementStrategy; import org.apache.camel.impl.transformer.TransformerKey; import org.apache.camel.impl.validator.ValidatorKey; @@ -366,7 +367,20 @@ public abstract class AbstractCamelContextFactoryBean<T extends ModelCamelContex LOG.info("Using HealthCheckRegistry: {}", healthCheckRegistry); getContext().setExtension(HealthCheckRegistry.class, healthCheckRegistry); } else { + // okay attempt to inject this camel context into existing health check (if any) healthCheckRegistry = HealthCheckRegistry.get(getContext()); + if (healthCheckRegistry != null) { + healthCheckRegistry.setCamelContext(getContext()); + } + } + if (healthCheckRegistry != null) { + // Health check repository + Set<HealthCheckRepository> repositories = getContext().getRegistry().findByType(HealthCheckRepository.class); + if (org.apache.camel.util.ObjectHelper.isNotEmpty(repositories)) { + for (HealthCheckRepository repository : repositories) { + healthCheckRegistry.register(repository); + } + } } // UuidGenerator UuidGenerator uuidGenerator = getBeanForType(UuidGenerator.class); diff --git a/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java b/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java index df6f5dd..b7c389d 100644 --- a/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java +++ b/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java @@ -71,6 +71,10 @@ public class MainConfigurationPropertiesConfigurer extends org.apache.camel.supp case "EndpointRuntimeStatisticsEnabled": target.setEndpointRuntimeStatisticsEnabled(property(camelContext, boolean.class, value)); return true; case "fileconfigurations": case "FileConfigurations": target.setFileConfigurations(property(camelContext, java.lang.String.class, value)); return true; + case "healthcheckenabled": + case "HealthCheckEnabled": target.setHealthCheckEnabled(property(camelContext, boolean.class, value)); return true; + case "healthcheckroutesenabled": + case "HealthCheckRoutesEnabled": target.setHealthCheckRoutesEnabled(property(camelContext, boolean.class, value)); return true; case "inflightrepositorybrowseenabled": case "InflightRepositoryBrowseEnabled": target.setInflightRepositoryBrowseEnabled(property(camelContext, boolean.class, value)); return true; case "javaroutesexcludepattern": @@ -214,6 +218,8 @@ public class MainConfigurationPropertiesConfigurer extends org.apache.camel.supp answer.put("EndpointLazyStartProducer", boolean.class); answer.put("EndpointRuntimeStatisticsEnabled", boolean.class); answer.put("FileConfigurations", java.lang.String.class); + answer.put("HealthCheckEnabled", boolean.class); + answer.put("HealthCheckRoutesEnabled", boolean.class); answer.put("InflightRepositoryBrowseEnabled", boolean.class); answer.put("JavaRoutesExcludePattern", java.lang.String.class); answer.put("JavaRoutesIncludePattern", java.lang.String.class); @@ -328,6 +334,10 @@ public class MainConfigurationPropertiesConfigurer extends org.apache.camel.supp case "EndpointRuntimeStatisticsEnabled": return target.isEndpointRuntimeStatisticsEnabled(); case "fileconfigurations": case "FileConfigurations": return target.getFileConfigurations(); + case "healthcheckenabled": + case "HealthCheckEnabled": return target.isHealthCheckEnabled(); + case "healthcheckroutesenabled": + case "HealthCheckRoutesEnabled": return target.isHealthCheckRoutesEnabled(); case "inflightrepositorybrowseenabled": case "InflightRepositoryBrowseEnabled": return target.isInflightRepositoryBrowseEnabled(); case "javaroutesexcludepattern": 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 fcb0e11..fea5222 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 @@ -33,6 +33,8 @@ { "name": "camel.main.endpointLazyStartProducer", "description": "Whether the producer should be started lazy (on the first message). By starting lazy you can use this to allow CamelContext and routes to startup in situations where a producer may otherwise fail during starting and cause the route to fail being started. By deferring this startup to be lazy then the startup failure can be handled during routing messages via Camel's routing error handlers. Beware that when the first mes [...] { "name": "camel.main.endpointRuntimeStatisticsEnabled", "description": "Sets whether endpoint runtime statistics is enabled (gathers runtime usage of each incoming and outgoing endpoints). The default value is false.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean" }, { "name": "camel.main.fileConfigurations", "description": "Directory to load additional configuration files that contains configuration values that takes precedence over any other configuration. This can be used to refer to files that may have secret configuration that has been mounted on the file system for containers. You can specify a pattern to load from sub directories and a name pattern such as \/var\/app\/secret\/.properties, multiple directories can be separated by comma.", " [...] + { "name": "camel.main.healthCheckEnabled", "description": "Whether health check is enabled. Is default enabled.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": true }, + { "name": "camel.main.healthCheckRoutesEnabled", "description": "Whether routes should be included in the health check. By default only the camel context is part of the health check. Enabling routes allows to let routes that are controlled by the routes controller take part of the health check, so if there is problems starting up routes, then they can influence the health check and report its UP or DOWN. Is default disabled.", "sourceType": "org.apache.camel.main.DefaultConfiguration [...] { "name": "camel.main.inflightRepositoryBrowseEnabled", "description": "Sets whether the inflight repository should allow browsing each inflight exchange. This is by default disabled as there is a very slight performance overhead when enabled.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean" }, { "name": "camel.main.javaRoutesExcludePattern", "description": "Used for exclusive filtering component scanning of RouteBuilder classes with Component annotation. The exclusive filtering takes precedence over inclusive filtering. The pattern is using Ant-path style pattern. Multiple patterns can be specified separated by comma. For example to exclude all classes starting with Bar use: **\/Bar* To exclude all routes form a specific package use: com\/mycompany\/bar\/* [...] { "name": "camel.main.javaRoutesIncludePattern", "description": "Used for inclusive filtering component scanning of RouteBuilder classes with Component annotation. The exclusive filtering takes precedence over inclusive filtering. The pattern is using Ant-path style pattern. Multiple patterns can be specified separated by comma. For example to include all classes starting with Foo use: **\/Foo To include all routes form a specific package use: com\/mycompany\/foo\/* To in [...] diff --git a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java index 814865a..6d9b968 100644 --- a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java +++ b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java @@ -29,6 +29,7 @@ import org.apache.camel.TypeConverters; import org.apache.camel.cloud.ServiceRegistry; import org.apache.camel.cluster.CamelClusterService; import org.apache.camel.health.HealthCheckRegistry; +import org.apache.camel.health.HealthCheckRepository; import org.apache.camel.model.Model; import org.apache.camel.processor.interceptor.BacklogTracer; import org.apache.camel.spi.AsyncProcessorAwaitManager; @@ -388,6 +389,15 @@ public final class DefaultConfigurationConfigurer { healthCheckRegistry.setCamelContext(camelContext); } } + if (healthCheckRegistry != null) { + // Health check repository + Set<HealthCheckRepository> repositories = registry.findByType(HealthCheckRepository.class); + if (org.apache.camel.util.ObjectHelper.isNotEmpty(repositories)) { + for (HealthCheckRepository repository : repositories) { + healthCheckRegistry.register(repository); + } + } + } // set the default thread pool profile if defined initThreadPoolProfiles(registry, camelContext); diff --git a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedCamelHealth.java b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedCamelHealth.java index 922bcbe..0959292 100644 --- a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedCamelHealth.java +++ b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedCamelHealth.java @@ -95,9 +95,7 @@ public class ManagedCamelHealth implements ManagedCamelHealthMBean { result.getCheck().getGroup(), result.getState().name(), result.getCheck().getConfiguration().isEnabled(), - result.getCheck().getConfiguration().getInterval() != null - ? result.getCheck().getConfiguration().getInterval().toMillis() - : null, + result.getCheck().getConfiguration().getInterval(), result.getCheck().getConfiguration().getFailureThreshold() } );