diff --git a/docs/src/main/asciidoc/spring-cloud-commons.adoc b/docs/src/main/asciidoc/spring-cloud-commons.adoc index 38fdab00..b9921306 100644 --- a/docs/src/main/asciidoc/spring-cloud-commons.adoc +++ b/docs/src/main/asciidoc/spring-cloud-commons.adoc @@ -317,6 +317,10 @@ Commons provides the `@EnableDiscoveryClient` annotation. This looks for impleme By default, implementations of `DiscoveryClient` will auto-register the local Spring Boot server with the remote discovery server. This can be disabled by setting `autoRegister=false` in `@EnableDiscoveryClient`. +==== Health Indicator + +Commons creates a Spring Boot `HealthIndicator` that `DiscoveryClient` implementations can participate in by implementing `DiscoveryHealthIndicator`. To disable the composite `HealthIndicator` set `spring.cloud.discovery.client.composite-indicator.enabled=false`. A generic `HealthIndicator` based on `DiscoveryClient` is auto-configured (`DiscoveryClientHealthIndicator). To disable it, set `spring.cloud.discovery.client.health-indicator.enabled=false`. To disable the description field of the `DiscoveryClientHealthIndicator` set `spring.cloud.discovery.client.health-indicator.include-description=false`, otherwise it can bubble up as the `description` of the rolled up `HealthIndicator`. + === ServiceRegistry Commons now provides a `ServiceRegistry` interface which provides methods like `register(Registration)` and `deregister(Registration)` which allow you to provide custom registered services. `Registration` is a marker interface. diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/CommonsClientAutoConfiguration.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/CommonsClientAutoConfiguration.java index 53abf1e8..b2b346a0 100644 --- a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/CommonsClientAutoConfiguration.java +++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/CommonsClientAutoConfiguration.java @@ -28,10 +28,12 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.client.actuator.FeaturesEndpoint; import org.springframework.cloud.client.actuator.HasFeatures; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.client.discovery.health.DiscoveryClientHealthIndicator; +import org.springframework.cloud.client.discovery.health.DiscoveryClientHealthIndicatorProperties; import org.springframework.cloud.client.discovery.health.DiscoveryCompositeHealthIndicator; import org.springframework.cloud.client.discovery.health.DiscoveryHealthIndicator; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; @@ -48,6 +50,7 @@ import org.springframework.context.annotation.Configuration; public class CommonsClientAutoConfiguration { @Configuration + @EnableConfigurationProperties(DiscoveryClientHealthIndicatorProperties.class) @ConditionalOnClass(HealthIndicator.class) @ConditionalOnBean(DiscoveryClient.class) @ConditionalOnProperty(value = "spring.cloud.discovery.enabled", matchIfMissing = true) @@ -55,8 +58,8 @@ public class CommonsClientAutoConfiguration { @Bean @ConditionalOnProperty(value = "spring.cloud.discovery.client.health-indicator.enabled", matchIfMissing = true) public DiscoveryClientHealthIndicator discoveryClientHealthIndicator( - DiscoveryClient discoveryClient) { - return new DiscoveryClientHealthIndicator(discoveryClient); + DiscoveryClient discoveryClient, DiscoveryClientHealthIndicatorProperties properties) { + return new DiscoveryClientHealthIndicator(discoveryClient, properties); } @Bean diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/health/DiscoveryClientHealthIndicator.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/health/DiscoveryClientHealthIndicator.java index 0c0304ef..75ec4a2b 100644 --- a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/health/DiscoveryClientHealthIndicator.java +++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/health/DiscoveryClientHealthIndicator.java @@ -39,10 +39,17 @@ public class DiscoveryClientHealthIndicator implements DiscoveryHealthIndicator, private int order = Ordered.HIGHEST_PRECEDENCE; - private DiscoveryClient discoveryClient; + private final DiscoveryClient discoveryClient; + private final DiscoveryClientHealthIndicatorProperties properties; + @Deprecated public DiscoveryClientHealthIndicator(DiscoveryClient discoveryClient) { + this(discoveryClient, new DiscoveryClientHealthIndicatorProperties()); + } + + public DiscoveryClientHealthIndicator(DiscoveryClient discoveryClient, DiscoveryClientHealthIndicatorProperties properties) { this.discoveryClient = discoveryClient; + this.properties = properties; } @Override @@ -59,7 +66,8 @@ public class DiscoveryClientHealthIndicator implements DiscoveryHealthIndicator, if (this.discoveryInitialized.get()) { try { List services = this.discoveryClient.getServices(); - builder.status(new Status("UP", this.discoveryClient.description())) + String description = (this.properties.isIncludeDescription()) ? this.discoveryClient.description() : ""; + builder.status(new Status("UP", description)) .withDetail("services", services); } catch (Exception e) { diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/health/DiscoveryClientHealthIndicatorProperties.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/health/DiscoveryClientHealthIndicatorProperties.java new file mode 100644 index 00000000..fed6ddf1 --- /dev/null +++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/discovery/health/DiscoveryClientHealthIndicatorProperties.java @@ -0,0 +1,40 @@ +package org.springframework.cloud.client.discovery.health; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * @author Spencer Gibb + */ +@ConfigurationProperties("spring.cloud.discovery.client.health-indicator") +public class DiscoveryClientHealthIndicatorProperties { + + private boolean enabled = true; + + //TODO: change to false in 2.0.0 + private boolean includeDescription = true; + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public boolean isIncludeDescription() { + return includeDescription; + } + + public void setIncludeDescription(boolean includeDescription) { + this.includeDescription = includeDescription; + } + + @Override + public String toString() { + final StringBuffer sb = new StringBuffer("DiscoveryClientHealthIndicatorProperties{"); + sb.append("enabled=").append(enabled); + sb.append(", includeDescription=").append(includeDescription); + sb.append('}'); + return sb.toString(); + } +} diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/serviceregistry/AutoServiceRegistrationProperties.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/serviceregistry/AutoServiceRegistrationProperties.java index d489afe8..a43c68ad 100644 --- a/spring-cloud-commons/src/main/java/org/springframework/cloud/client/serviceregistry/AutoServiceRegistrationProperties.java +++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/client/serviceregistry/AutoServiceRegistrationProperties.java @@ -11,6 +11,17 @@ public class AutoServiceRegistrationProperties { /** If Auto-Service Registration is enabled, default to true. */ private boolean enabled = true; + /** Whether to register the management as a service, defaults to true */ + private boolean registerManagement = true; + + public boolean shouldRegisterManagement() { + return registerManagement; + } + + public void setRegisterManagement(boolean registerManagement) { + this.registerManagement = registerManagement; + } + /** Should startup fail if there is no AutoServiceRegistration, default to false. */ private boolean failFast = false; diff --git a/spring-cloud-commons/src/test/java/org/springframework/cloud/client/discovery/health/DiscoveryClientHealthIndicatorTests.java b/spring-cloud-commons/src/test/java/org/springframework/cloud/client/discovery/health/DiscoveryClientHealthIndicatorTests.java new file mode 100644 index 00000000..5a8113af --- /dev/null +++ b/spring-cloud-commons/src/test/java/org/springframework/cloud/client/discovery/health/DiscoveryClientHealthIndicatorTests.java @@ -0,0 +1,109 @@ +/* + * Copyright 2013-2015 the original author or authors. + * + * Licensed 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.springframework.cloud.client.discovery.health; + +import java.util.Arrays; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.health.Health; +import org.springframework.boot.actuate.health.HealthAggregator; +import org.springframework.boot.actuate.health.OrderedHealthAggregator; +import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cloud.client.CommonsClientAutoConfiguration; +import org.springframework.cloud.client.discovery.DiscoveryClient; +import org.springframework.cloud.client.discovery.event.InstanceRegisteredEvent; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; + +/** + * @author Spencer Gibb + */ +@RunWith(SpringRunner.class) +@SpringBootTest(classes = { DiscoveryClientHealthIndicatorTests.Config.class, + CommonsClientAutoConfiguration.class }, properties = "spring.cloud.discovery.client.health-indicator.include-description:false") +public class DiscoveryClientHealthIndicatorTests { + + @Autowired + private DiscoveryCompositeHealthIndicator healthIndicator; + + @Autowired + private DiscoveryClientHealthIndicator clientHealthIndicator; + + @Configuration + @EnableConfigurationProperties + public static class Config { + @Bean + public HealthAggregator healthAggregator() { + return new OrderedHealthAggregator(); + } + + @Bean + public DiscoveryClient discoveryClient() { + DiscoveryClient mock = mock(DiscoveryClient.class); + given(mock.description()).willReturn("TestDiscoveryClient"); + given(mock.getServices()).willReturn(Arrays.asList("TestService1")); + return mock; + } + + @Bean + public DiscoveryHealthIndicator discoveryHealthIndicator() { + return new DiscoveryHealthIndicator() { + @Override + public String getName() { + return "testDiscoveryHealthIndicator"; + } + + @Override + public Health health() { + return new Health.Builder().unknown().build(); + } + }; + } + } + + @Test + public void testHealthIndicatorDescriptionDisabled() { + assertNotNull("healthIndicator was null", this.healthIndicator); + Health health = this.healthIndicator.health(); + assertHealth(health, Status.UNKNOWN); + + clientHealthIndicator.onApplicationEvent(new InstanceRegisteredEvent<>(this, null)); + + health = this.healthIndicator.health(); + Status status = assertHealth(health, Status.UP); + assertEquals("status description was wrong", "", + status.getDescription()); + } + + private Status assertHealth(Health health, Status expected) { + assertNotNull("health was null", health); + Status status = health.getStatus(); + assertNotNull("status was null", status); + assertEquals("status code was wrong", expected.getCode(), status.getCode()); + return status; + } +} diff --git a/spring-cloud-commons/src/test/java/org/springframework/cloud/client/discovery/health/DiscoveryCompositeHealthIndicatorTests.java b/spring-cloud-commons/src/test/java/org/springframework/cloud/client/discovery/health/DiscoveryCompositeHealthIndicatorTests.java index e35bbe82..b1eb25df 100644 --- a/spring-cloud-commons/src/test/java/org/springframework/cloud/client/discovery/health/DiscoveryCompositeHealthIndicatorTests.java +++ b/spring-cloud-commons/src/test/java/org/springframework/cloud/client/discovery/health/DiscoveryCompositeHealthIndicatorTests.java @@ -16,42 +16,41 @@ package org.springframework.cloud.client.discovery.health; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.mock; - import java.util.Arrays; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.SpringApplication; import org.springframework.boot.actuate.health.Health; import org.springframework.boot.actuate.health.HealthAggregator; import org.springframework.boot.actuate.health.OrderedHealthAggregator; import org.springframework.boot.actuate.health.Status; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.cloud.client.CommonsClientAutoConfiguration; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.client.discovery.event.InstanceRegisteredEvent; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; + /** * @author Spencer Gibb */ @RunWith(SpringRunner.class) -@ContextConfiguration(classes = { DiscoveryCompositeHealthIndicatorTests.Config.class, +@SpringBootTest(classes = { DiscoveryCompositeHealthIndicatorTests.Config.class, CommonsClientAutoConfiguration.class }) public class DiscoveryCompositeHealthIndicatorTests { @Autowired - DiscoveryCompositeHealthIndicator healthIndicator; + private DiscoveryCompositeHealthIndicator healthIndicator; @Autowired - DiscoveryClientHealthIndicator clientHealthIndicator; + private DiscoveryClientHealthIndicator clientHealthIndicator; @Configuration public static class Config { @@ -90,11 +89,11 @@ public class DiscoveryCompositeHealthIndicatorTests { Health health = this.healthIndicator.health(); assertHealth(health, Status.UNKNOWN); - clientHealthIndicator.onApplicationEvent(new InstanceRegisteredEvent(this, null)); + clientHealthIndicator.onApplicationEvent(new InstanceRegisteredEvent<>(this, null)); health = this.healthIndicator.health(); Status status = assertHealth(health, Status.UP); - assertEquals("status desciption was wrong", "TestDiscoveryClient", + assertEquals("status description was wrong", "TestDiscoveryClient", status.getDescription()); } @@ -105,9 +104,5 @@ public class DiscoveryCompositeHealthIndicatorTests { assertEquals("status code was wrong", expected.getCode(), status.getCode()); return status; } - - public static void main(String[] args) { - SpringApplication.run(new Class[]{Config.class,CommonsClientAutoConfiguration.class}, new String[] {"--debug", "--spring.main.webEnvironment=false"}); - } }