Improve liveness/readiness health config
Prior to this commit, the application availability infrastructure would mix the `AvailabilityState`, the `HealthIndicator` and the `HealthGroup` concepts and would not align with the rest. This commit auto-configures the livenessState and readinessState health indicators with the relevant configuration properties. Unlike other indicators, they are not enabled by default but might be in future versions. This also moves the `management.health.probes.enabled` property to `management.endpoint.health.probes.enabled` since "probes" here is not a health indicator but rather a configuration flag for the health endpoint. Finally, the probes auto-configuration is refined to automatically add liveness and readiness indicators for the probes group if they're not already present. Closes gh-22107
This commit is contained in:
parent
cb73558856
commit
fe807d6c0b
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright 2012-2020 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
|
||||
*
|
||||
* https://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.boot.actuate.autoconfigure.availability;
|
||||
|
||||
import org.springframework.boot.actuate.availability.AvailabilityStateHealthIndicator;
|
||||
import org.springframework.boot.actuate.availability.LivenessStateHealthIndicator;
|
||||
import org.springframework.boot.actuate.availability.ReadinessStateHealthIndicator;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.availability.ApplicationAvailability;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for
|
||||
* {@link AvailabilityStateHealthIndicator}.
|
||||
* vailabilityHealthContributorAutoConfigurationTests
|
||||
*
|
||||
* @author Brian Clozel
|
||||
* @since 2.3.2
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@AutoConfigureAfter(ApplicationAvailabilityAutoConfiguration.class)
|
||||
public class AvailabilityHealthContributorAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnProperty(prefix = "management.health.livenessstate", name = "enabled", havingValue = "true")
|
||||
public LivenessStateHealthIndicator livenessStateHealthIndicator(ApplicationAvailability applicationAvailability) {
|
||||
return new LivenessStateHealthIndicator(applicationAvailability);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnProperty(prefix = "management.health.readinessstate", name = "enabled", havingValue = "true")
|
||||
public ReadinessStateHealthIndicator readinessStateHealthIndicator(
|
||||
ApplicationAvailability applicationAvailability) {
|
||||
return new ReadinessStateHealthIndicator(applicationAvailability);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -16,8 +16,6 @@
|
|||
|
||||
package org.springframework.boot.actuate.autoconfigure.availability;
|
||||
|
||||
import org.springframework.boot.actuate.autoconfigure.availability.AvailabilityProbesAutoConfiguration.ProbesCondition;
|
||||
import org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator;
|
||||
import org.springframework.boot.actuate.availability.LivenessStateHealthIndicator;
|
||||
import org.springframework.boot.actuate.availability.ReadinessStateHealthIndicator;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
|
|
@ -44,22 +42,20 @@ import org.springframework.core.type.AnnotatedTypeMetadata;
|
|||
* @since 2.3.0
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Conditional(ProbesCondition.class)
|
||||
@AutoConfigureAfter(ApplicationAvailabilityAutoConfiguration.class)
|
||||
@Conditional(AvailabilityProbesAutoConfiguration.ProbesCondition.class)
|
||||
@AutoConfigureAfter({ AvailabilityHealthContributorAutoConfiguration.class,
|
||||
ApplicationAvailabilityAutoConfiguration.class })
|
||||
public class AvailabilityProbesAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnEnabledHealthIndicator("livenessState")
|
||||
@ConditionalOnMissingBean
|
||||
public LivenessStateHealthIndicator livenessStateHealthIndicator(ApplicationAvailability applicationAvailability) {
|
||||
public LivenessStateHealthIndicator livenessStateProbeIndicator(ApplicationAvailability applicationAvailability) {
|
||||
return new LivenessStateHealthIndicator(applicationAvailability);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnEnabledHealthIndicator("readinessState")
|
||||
@ConditionalOnMissingBean
|
||||
public ReadinessStateHealthIndicator readinessStateHealthIndicator(
|
||||
ApplicationAvailability applicationAvailability) {
|
||||
public ReadinessStateHealthIndicator readinessStateProbeIndicator(ApplicationAvailability applicationAvailability) {
|
||||
return new ReadinessStateHealthIndicator(applicationAvailability);
|
||||
}
|
||||
|
||||
|
|
@ -70,20 +66,27 @@ public class AvailabilityProbesAutoConfiguration {
|
|||
|
||||
/**
|
||||
* {@link SpringBootCondition} to enable or disable probes.
|
||||
* <p>
|
||||
* Probes are enabled if the dedicated configuration property is enabled or if the
|
||||
* Kubernetes cloud environment is detected/enforced.
|
||||
*/
|
||||
static class ProbesCondition extends SpringBootCondition {
|
||||
|
||||
private static final String ENABLED_PROPERTY = "management.health.probes.enabled";
|
||||
private static final String ENABLED_PROPERTY = "management.endpoint.health.probes.enabled";
|
||||
|
||||
private static final String DEPRECATED_ENABLED_PROPERTY = "management.health.probes.enabled";
|
||||
|
||||
@Override
|
||||
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
|
||||
Environment environment = context.getEnvironment();
|
||||
ConditionMessage.Builder message = ConditionMessage.forCondition("Health availability");
|
||||
String enabled = environment.getProperty(ENABLED_PROPERTY);
|
||||
if (enabled != null) {
|
||||
boolean match = !"false".equalsIgnoreCase(enabled);
|
||||
return new ConditionOutcome(match,
|
||||
message.because("'" + ENABLED_PROPERTY + "' set to '" + enabled + "'"));
|
||||
ConditionMessage.Builder message = ConditionMessage.forCondition("Probes availability");
|
||||
ConditionOutcome outcome = onProperty(environment, message, ENABLED_PROPERTY);
|
||||
if (outcome != null) {
|
||||
return outcome;
|
||||
}
|
||||
outcome = onProperty(environment, message, DEPRECATED_ENABLED_PROPERTY);
|
||||
if (outcome != null) {
|
||||
return outcome;
|
||||
}
|
||||
if (CloudPlatform.getActive(environment) == CloudPlatform.KUBERNETES) {
|
||||
return ConditionOutcome.match(message.because("running on Kubernetes"));
|
||||
|
|
@ -91,6 +94,16 @@ public class AvailabilityProbesAutoConfiguration {
|
|||
return ConditionOutcome.noMatch(message.because("not running on a supported cloud platform"));
|
||||
}
|
||||
|
||||
private ConditionOutcome onProperty(Environment environment, ConditionMessage.Builder message,
|
||||
String propertyName) {
|
||||
String enabled = environment.getProperty(propertyName);
|
||||
if (enabled != null) {
|
||||
boolean match = !"false".equalsIgnoreCase(enabled);
|
||||
return new ConditionOutcome(match, message.because("'" + propertyName + "' set to '" + enabled + "'"));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,12 @@
|
|||
"sun.java.command"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "management.endpoint.health.probes.enabled",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "Whether to enable liveness and readiness probes.",
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"name": "management.endpoint.health.show-details",
|
||||
"defaultValue": "never"
|
||||
|
|
@ -168,6 +174,12 @@
|
|||
"description": "Whether to enable LDAP health check.",
|
||||
"defaultValue": true
|
||||
},
|
||||
{
|
||||
"name": "management.health.livenessstate.enabled",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "Whether to enable liveness state health check.",
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"name": "management.health.mail.enabled",
|
||||
"type": "java.lang.Boolean",
|
||||
|
|
@ -196,7 +208,10 @@
|
|||
"name": "management.health.probes.enabled",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "Whether to enable liveness and readiness probes.",
|
||||
"defaultValue": false
|
||||
"defaultValue": false,
|
||||
"deprecation": {
|
||||
"replacement": "management.endpoint.health.probes.enabled"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "management.health.rabbit.enabled",
|
||||
|
|
@ -204,6 +219,12 @@
|
|||
"description": "Whether to enable RabbitMQ health check.",
|
||||
"defaultValue": true
|
||||
},
|
||||
{
|
||||
"name": "management.health.readynessstate.enabled",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "Whether to enable readiness state health check.",
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"name": "management.health.redis.enabled",
|
||||
"type": "java.lang.Boolean",
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
|||
org.springframework.boot.actuate.autoconfigure.amqp.RabbitHealthContributorAutoConfiguration,\
|
||||
org.springframework.boot.actuate.autoconfigure.audit.AuditAutoConfiguration,\
|
||||
org.springframework.boot.actuate.autoconfigure.audit.AuditEventsEndpointAutoConfiguration,\
|
||||
org.springframework.boot.actuate.autoconfigure.availability.AvailabilityHealthContributorAutoConfiguration,\
|
||||
org.springframework.boot.actuate.autoconfigure.availability.AvailabilityProbesAutoConfiguration,\
|
||||
org.springframework.boot.actuate.autoconfigure.beans.BeansEndpointAutoConfiguration,\
|
||||
org.springframework.boot.actuate.autoconfigure.cache.CachesEndpointAutoConfiguration,\
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright 2012-2020 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
|
||||
*
|
||||
* https://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.boot.actuate.autoconfigure.availability;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.actuate.availability.LivenessStateHealthIndicator;
|
||||
import org.springframework.boot.actuate.availability.ReadinessStateHealthIndicator;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration;
|
||||
import org.springframework.boot.availability.ApplicationAvailability;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link AvailabilityHealthContributorAutoConfiguration}
|
||||
*
|
||||
* @author Brian Clozel
|
||||
*/
|
||||
class AvailabilityHealthContributorAutoConfigurationTests {
|
||||
|
||||
private ApplicationContextRunner contextRunner = new ApplicationContextRunner().withConfiguration(AutoConfigurations
|
||||
.of(ApplicationAvailabilityAutoConfiguration.class, AvailabilityHealthContributorAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void probesWhenNotKubernetesAddsNoBeans() {
|
||||
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(ApplicationAvailability.class)
|
||||
.doesNotHaveBean(LivenessStateHealthIndicator.class)
|
||||
.doesNotHaveBean(ReadinessStateHealthIndicator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void livenessIndicatorWhenPropertyEnabledAddsBeans() {
|
||||
this.contextRunner.withPropertyValues("management.health.livenessState.enabled=true")
|
||||
.run((context) -> assertThat(context).hasSingleBean(ApplicationAvailability.class)
|
||||
.hasSingleBean(LivenessStateHealthIndicator.class)
|
||||
.doesNotHaveBean(ReadinessStateHealthIndicator.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void readinessIndicatorWhenPropertyEnabledAddsBeans() {
|
||||
this.contextRunner.withPropertyValues("management.health.readinessState.enabled=true")
|
||||
.run((context) -> assertThat(context).hasSingleBean(ApplicationAvailability.class)
|
||||
.hasSingleBean(ReadinessStateHealthIndicator.class)
|
||||
.doesNotHaveBean(LivenessStateHealthIndicator.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -34,8 +34,9 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
*/
|
||||
class AvailabilityProbesAutoConfigurationTests {
|
||||
|
||||
private ApplicationContextRunner contextRunner = new ApplicationContextRunner().withConfiguration(AutoConfigurations
|
||||
.of(ApplicationAvailabilityAutoConfiguration.class, AvailabilityProbesAutoConfiguration.class));
|
||||
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(ApplicationAvailabilityAutoConfiguration.class,
|
||||
AvailabilityHealthContributorAutoConfiguration.class, AvailabilityProbesAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void probesWhenNotKubernetesAddsNoBeans() {
|
||||
|
|
@ -56,7 +57,7 @@ class AvailabilityProbesAutoConfigurationTests {
|
|||
|
||||
@Test
|
||||
void probesWhenPropertyEnabledAddsBeans() {
|
||||
this.contextRunner.withPropertyValues("management.health.probes.enabled=true")
|
||||
this.contextRunner.withPropertyValues("management.endpoint.health.probes.enabled=true")
|
||||
.run((context) -> assertThat(context).hasSingleBean(ApplicationAvailability.class)
|
||||
.hasSingleBean(LivenessStateHealthIndicator.class)
|
||||
.hasSingleBean(ReadinessStateHealthIndicator.class)
|
||||
|
|
@ -66,7 +67,8 @@ class AvailabilityProbesAutoConfigurationTests {
|
|||
@Test
|
||||
void probesWhenKubernetesAndPropertyDisabledAddsNotBeans() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.main.cloud-platform=kubernetes", "management.health.probes.enabled=false")
|
||||
.withPropertyValues("spring.main.cloud-platform=kubernetes",
|
||||
"management.endpoint.health.probes.enabled=false")
|
||||
.run((context) -> assertThat(context).hasSingleBean(ApplicationAvailability.class)
|
||||
.doesNotHaveBean(LivenessStateHealthIndicator.class)
|
||||
.doesNotHaveBean(ReadinessStateHealthIndicator.class)
|
||||
|
|
|
|||
|
|
@ -712,6 +712,20 @@ The following `HealthIndicators` are auto-configured by Spring Boot when appropr
|
|||
|
||||
TIP: You can disable them all by setting the configprop:management.health.defaults.enabled[] property.
|
||||
|
||||
Additional `HealthIndicators` are available but not enabled by default;
|
||||
developers can use their configuration property to activate them:
|
||||
|
||||
[cols="4,6"]
|
||||
|===
|
||||
| Name | Description
|
||||
|
||||
| {spring-boot-actuator-module-code}/availability/LivenessStateHealthIndicator.java[`LivenessStateHealthIndicator`]
|
||||
| Checks the liveness state of the application.
|
||||
|
||||
| {spring-boot-actuator-module-code}/availability/ReadinessStateHealthIndicator.java[`ReadinessStateHealthIndicator`]
|
||||
| Checks the readiness state of the application.
|
||||
|===
|
||||
|
||||
|
||||
|
||||
==== Writing Custom HealthIndicators
|
||||
|
|
|
|||
Loading…
Reference in New Issue