Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ The health service is registered with the gRPC server and a `HealthStatusManager

IMPORTANT: The health service resides in the `io.grpc:grpc-services` library which is marked as `optional` by Spring gRPC. You must add this dependency to your application in order for it to be autoconfigured.

NOTE: Server-side gRPC health is enabled by default when the application defines at least one `BindableService`. If no server-side gRPC services are present, health is disabled by default and must be explicitly enabled using `spring.grpc.server.health.enabled=true`.

== Actuator Health
When Spring Boot Actuator is added to your project and the {spring-boot-docs}/actuator/endpoints.html#actuator.endpoints.health[Health endpoint] is available, the framework will automatically periodically update the health status of a configured list of Spring Boot {spring-boot-docs}/actuator/endpoints.html#actuator.endpoints.health.auto-configured-health-indicators[health indicators], including any ({spring-boot-docs}/actuator/endpoints.html#actuator.endpoints.health.writing-custom-health-indicators[custom indicators]).
By default, the aggregate status of the individual indicators is also used to update the overall server status (`""`).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionMessage;
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
Expand Down Expand Up @@ -55,13 +54,14 @@
*
* @author Daniel Theuke (daniel.theuke@heuboe.de)
* @author Chris Bono
* @author Andrey Litvitski
* @since 1.0.0
*/
@AutoConfiguration(before = GrpcServerFactoryAutoConfiguration.class)
@ConditionalOnSpringGrpc
@ConditionalOnClass(HealthStatusManager.class)
@ConditionalOnGrpcServerEnabled("health")
@ConditionalOnBean(BindableService.class)
@Conditional(GrpcServerHealthAutoConfiguration.OnHealthDefaultEnablementCondition.class)
public final class GrpcServerHealthAutoConfiguration {

@Bean(destroyMethod = "enterTerminalState")
Expand Down Expand Up @@ -129,4 +129,25 @@ public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeM

}

static class OnHealthDefaultEnablementCondition extends SpringBootCondition {

@Override
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
String propertyName = "spring.grpc.server.health.enabled";
BindResult<Boolean> enabled = Binder.get(context.getEnvironment()).bind(propertyName, Boolean.class);
if (enabled.isBound()) {
return enabled.get() ? ConditionOutcome.match("Health explicitly enabled")
: ConditionOutcome.noMatch("Health explicitly disabled");
}
if (context.getBeanFactory() == null) {
return ConditionOutcome.noMatch("Context bean factory is null");
}
String[] bindableServices = context.getBeanFactory()
.getBeanNamesForType(BindableService.class, false, false);
return (bindableServices.length > 0) ? ConditionOutcome.match("BindableService found")
: ConditionOutcome.noMatch("No BindableService found and health not explicitly enabled");
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,19 @@ void whenServerEnabledPropertySetTrueThenAutoConfigurationIsNotSkipped() {
.run((context) -> assertThat(context).hasSingleBean(GrpcServerHealthAutoConfiguration.class));
}

@Test
void whenNoBindableServiceAndHealthPropertyNotSetDoesNotAutoConfigureBeans() {
new ApplicationContextRunner().withConfiguration(AutoConfigurations.of(GrpcServerHealthAutoConfiguration.class))
.run((context) -> assertThat(context).doesNotHaveBean(GrpcServerHealthAutoConfiguration.class));
}

@Test
void whenNoBindableServiceAndHealthPropertyTrueAutoConfiguresBeans() {
new ApplicationContextRunner().withConfiguration(AutoConfigurations.of(GrpcServerHealthAutoConfiguration.class))
.withPropertyValues("spring.grpc.server.health.enabled=true")
.run((context) -> assertThat(context).hasSingleBean(GrpcServerHealthAutoConfiguration.class));
}

@Disabled("Will be tested in an integration test once the Actuator adapter is implemented")
@Test
void enterTerminalStateIsCalledWhenStatusManagerIsStopped() {
Expand Down
Loading