Leonardo Lima
Leonardo Lima

Reputation: 45

Change Actuator aggregated Health Status behavior

I've a project using Springboot 2 with Actuator, and I need change the default behavior for the overall status. Today this status will be "DOWN" if any of the "HealthIndicators" get "DOWN" status. What I need change is add a "required" attribute to the "HealthIndicator" and change the overall status behavior to just return "DOWN" if a "HealthIndicator" is "DOWN" and is "required=true".

To add the required attribute I created a new class CustomAbstractHealthIndicator that extends AbstractHealthIndicator, but do not discovered how add the required when I'm using a composite yet...

And I saw that HealthAggregator was deprecated by the StatusAggregator, but in the StatusAggregator we do not have access to the HealthIndicator object, just the status, so this broke my idea of use the "required" to filter the aggregated status

The health output that I need is something like this:

{
    "status": "UP",
    "components": {
        "myHealthComposite": {
            "required": false,
            "status": "DOWN",
            "components": {
                "myFirstHealthIndicator": {
                    "status": "DOWN",
                    "details": {
                        "required": true,
                        "name": "FristHealthIndicator"
                    }
                },
                "mySecondHealthIndicator": {
                    "status": "UP",
                    "details": {
                        "required": false,
                        "name": "SecondHealthIndicator"
                    }
                }
            }
        },
        "myOtherHealthComposite": {
            "required": false,
            "status": "UP",
            "components": {
                "alphaHealthIndicator": {
                    "status": "DOWN",
                    "details": {
                        "required": false,
                        "name": "alphaHealthIndicator"
                    }
                },
                "gamaHealthIndicator": {
                    "status": "UP",
                    "details": {
                        "required": false,
                        "name": "gamaHealthIndicator"
                    }
                }
            }
        }
    }
}

EDIT 1: I found an example in the "old way"

    private static class MyAggregator extends AbstractHealthAggregator {
        @Override
        protected Status aggregateStatus(List<Status> candidates) {
            Status ret = Status.DOWN;
            for (Status candidate : candidates) {
                if (candidate.equals(Status.UP)) {
                    ret = Status.UP;
                    // as long as one is up, we are up.
                    break;
                }
            }
            return ret;
        }
    }

But the AbstractHealthAggregator has been deprecated

EDIT 2 Studying the Actuator source code, I probably found where I need change to achieve success in change the default Status behavior...

In the abstract class HealthEndpointSupport<C, T>

    protected final CompositeHealth getCompositeHealth(ApiVersion apiVersion, Map<String, HealthComponent> components,
                                                                                               StatusAggregator statusAggregator, boolean showComponents, Set<String> groupNames) {
        Status status = statusAggregator.getAggregateStatus(
                components.values().stream().map(HealthComponent::getStatus).collect(Collectors.toSet()));
        Map<String, HealthComponent> instances = showComponents ? components : null;
        if (groupNames != null) {
            return new SystemHealth(apiVersion, status, instances, groupNames);
        }
        return new CompositeHealth(apiVersion, status, instances);
    }

One solution is to filter the components inside getCompositeHealth, and pass only the Status from the components who have required:true in details....

But I can't just override this class, there are many dependencies that is accessible only from the package, there is any way to change this without making a fork from the project?

I tried to override the StatusAggregator, but it just receive a Set, and I cant access the details from a contributor

Upvotes: 2

Views: 1644

Answers (2)

Leonardo Lima
Leonardo Lima

Reputation: 45

After a lot of research and study I achieved a decision that's not a good idea change de default behavior from the HealthCheck endpoint, maybe this is the reason that I couldn't override without making a custom version

Upvotes: 1

Sai prateek
Sai prateek

Reputation: 11896

If I understand your question correctly, you want a attribute required: true , when health of your service down. You can use detail option of Health class of Spring like this -

@Component
public class MyServiceHEalthStatus implements HealthIndicator {
        
    @Override
    public Health health() {
        if (!isRunningService()) {
            return Health.down().withDetail("Required", "true").build();
        }
        return Health.up().withDetail("Some_Service", "Available").build();
    }

    private Boolean isRunningService() {
        Boolean isRunning = true;
        // Logic Skipped

        return isRunning;
    }
}

Then you should get /Health end point response when service down like this:

{
   "status":"DOWN",
   "details":{
      "your_service":{
         "status":"DOWN",
         "details":{
            "Required":"true"
         }
      }, ...
}
   

Upvotes: 0

Related Questions