Reputation: 6246
I have multiple health check in management.endpoint.health.group (foo, bar)
and I deploy my app within a kubernetes cluster,
What I want is when kube send me liveness request and the state of (foo, bar) is aggregated, at this moment (before replying) I want to run some logic based on this last state.
My Indicators are defined like this
@Component
public class FooHealthIndicator implements HealthIndicator {
@Override
public Health health() {
Health.Builder builder = new Health.Builder();
try {
// some foo specific logic
builder.up();
} catch (Exception exception) {
...
builder.down().withException(exception);
}
return builder.build();
}
the same goes for BarHealthIndicator
Upvotes: 4
Views: 381
Reputation: 202
If I understand your question properly, you have a healthcheck endpoint and when you receive a request for the healthcheck, you want to run some logic based on the last know state of the healthcheck.
Given your code example, you're already dealing with a Spring component, so you have all the tools required to do whatever your requirements are.
The hard part is figuring out what the last state of the application should be, and what to do in an error scenario while getting this information. If the last state is the last state known to this instance of the application then you can utilise your preference of a concurrent collection to store/retrieve this data. If it is the last known to the deployment, you're going to have to go outside of your application to some datastore, preferably a cache in this instance, to retrieve this data. Your exact approach here is going to be dependant on what you have available to you.
After you have that data it's just a manner of getting the fresh data and running your logic on top of it. From here it's a design question of what checks you need to do and how to code to those checks.
Upvotes: 0
Reputation: 515
What you have to do is implementing a component which extends HealthEndpointWebExtension and where you can intercept the group aggregated status :
public class HealthEndpointCustomExtension extends HealthEndpointWebExtension {
private final Map<String,Status> lastStatusByGroup = new HashMap<>();
public HealthEndpointCustomExtension(HealthContributorRegistry registry, HealthEndpointGroups groups, Duration slowIndicatorLoggingThreshold) {
super(registry, groups, slowIndicatorLoggingThreshold);
}
@Override
public WebEndpointResponse<HealthComponent> health(ApiVersion apiVersion, WebServerNamespace serverNamespace, SecurityContext securityContext, boolean showAll, String... path) {
WebEndpointResponse<HealthComponent> response = super.health(apiVersion, serverNamespace, securityContext, showAll, path);
if (path.length > 0) {
String group = path[0];
Status status = response.getBody().getStatus();
Status lastStatus = lastStatusByGroup.put(group, status);
if (lastStatus != null && !lastStatus.equals(status)) {
//..do some logic
}
}
return response;
}
}
Then you just have to declare a bean factory method for this component inside a configuration class :
@Bean
HealthEndpointWebExtension healthEndpointWebExtension(HealthContributorRegistry healthContributorRegistry,
HealthEndpointGroups groups, HealthEndpointProperties properties) {
return new HealthEndpointCustomExtension(healthContributorRegistry, groups,
properties.getLogging().getSlowIndicatorThreshold());
}
Upvotes: 6