How to aggregate health indicators in Spring boot

徘徊边缘 提交于 2021-01-23 05:41:12

问题


I've added Actuator support for my Spring 2.0.4 application using this Baeldung article. In section 4.4 it talks about

A handy feature of health indicators is that we can aggregate them as part of a hierarchy

but it doesn't go into any discussion of how to do this aggregation. Nor have I been able to find any documentation on how to do this.

Question Do any of you know of a tutorial, example or other documentation on creating such an aggregation?

More Info I have a service in my application which relies on several sub-components. The service itself is only considered down if all these sub-components are down. So long as one is up then the service is up. Currently using the normal HealthIndicator mechanism if one of the sub-components is down it marks the server as down.

It seems I would want to use the CompositeHealthIndicator but it's not clear how I create the child HealthIndicators without the system picking them up. The caveat is that each of these sub-components uses the @Scheduled annotation, my understanding is that in order for that to work the class must use the @Component annotation(or some such) which will cause it to be created and sucked up into the application health.

Clarification I have added actuators and the health URL comes up as this:

{"status":"UP","details":{"MyServ1":{"status":"UP","details":{"Latency":...}},"MyServ2":{"status":"UP","details":{"Latency":...}},"diskSpace":{"status":"UP","details":{"total":...,"free":...,"threshold":...}}}}

but if 'MyServ1' or 'MySrv2' are down the overall status is down, but I only want that to happen if 'diskSpace' is down OR 'MyServ1' and 'MyServ2' is down.

It would appear that CompositeHealthIndicator would be the appropriate class for this, it is just unclear how I create the children health indicators for it (just use new)?

Thanks in advance


回答1:


Aggregating the statuses from each health indicator into a single overall status is done by an implementation of org.springframework.boot.actuate.health.HealthAggregator. Spring Boot auto-configures an instance of OrderedHealthAggregator. If you provide your own bean that implements HealthAggregator the auto-configured aggregator will back off in favour of your custom implementation.

The aggregator's aggregate method is called with a Map<String, Status> where the keys are the names of the health indicators and the values are their statuses. Knowing the names of your sub-components' health indicators should allow you to perform custom aggregation for them.




回答2:


I came up with a solution, I posted a simple demonstration on GitHub. I have no idea if this is the correct way to do this or not but it seems to be working...

Example Spring Application




回答3:


I was struggling with this issue, and here is my solution. https://github.com/mohamed-taman/Spring-Actuator-health-aggregator

This demo based on the old spring version way of doing Health aggregation and latest spring boot versions 2.3.0.M4. The new idea I have developed based on new APIs in favor of old deprecated ones.

It will give you something like this:

{
   "status":"DOWN",
   "components":{
      "Core System Microservices":{
         "status":"DOWN",
         "components":{
            "Product Service":{
               "status":"UP"
            },
            "Recommendation Service":{
               "status":"DOWN",
               "details":{
                  "error":"java.lang.IllegalStateException: Not working"
               }
            },
            "Review Service":{
               "status":"UP"
            }
         }
      },
      "diskSpace":{
         "status":"UP",
         "details":{
            "total":255382777856,
            "free":86618931200,
            "threshold":10485760,
            "exists":true
         }
      },
      "ping":{
         "status":"UP"
      }
   }
}

I hope this helps you.




回答4:


Well, Spring just rolled out some strange functionality. Here is how you use it!

Construct a couple healthchecks using a new "ReactiveHealthIndicator" class extension.

@Component("myindicator1")
public class CriticalAppHealthIndicator implements ReactiveHealthIndicator {

    @Override
    public Mono<Health> health() {

        return Mono.just(Health.up().build()); // obviously yours will do more..
    }
}

Second one:

@Component("myindicator2")
public class OptionalAppHealthIndicator implements ReactiveHealthIndicator {

    @Override
    public Mono<Health> health() {

        return Mono.just(Health.outOfService().build()); // obviously yours will do more..
    }
}

Now you can add a grouping. Modify your application.properties, or in this example your application.yml to add the "management.endpoint.health.group.{yourgroup}.include" key with a value of comma-delimited bean names.

management:
  endpoint:
    health:
      show-details: always
      # Include custom actuator grouping for any custom health checks with the "my-indicators" qualifier
      group:
        my-indicators:
          include: myindicator1,myindicator2

Now.. this is where it gets a bit strange. Now if you hit your health endpoint:

GET: {base}/health?detail=true

Your response will look like this:

{
  "status" : "DOWN",
  "components" : {
    "indicator2" : {
      "status" : "UP",
    },
    "indicator2" : {
      "status" : "DOWN",
    }
  },
  "groups" : [ "my-indicators" ]
}

Which doesn't actually group the two together like other dependencies are (ex: "db" for any spring-data hibernate groupings of data connections.)

However you can now navigate to:

GET: {base}/health/my-indicators

In order to see just the grouping you've setup.

PLEASE post if you figure out how to get a grouping in the parent endpoint - simply /health.

From what I can gather its setup this way so that groupings could be made dynamically based off of where you're deployed. E.G: Kubernetes..

It is beyond my understanding why they wouldn't apply a grouping at the top-level or give a setting to use a grouping as a default at the base /health level - when no other groupings exist. Making multiple requests to see a group isn't really convenient at-all if you're using postman or CURL. A front end dev could spend a bunch of time with this to make collapsible categories custom front-end, but this is also fraught with problems as the actuator endpoints don't strongly-type their response objects enough to make them work with any OpenAPI 3.0 code generator so today you'll have to disable actuator from being included in the swagger if you want to run any code generation..

References:

  • https://spring.io/blog/2019/10/16/spring-boot-2-2-0#health-indicator-groups
  • https://docs.spring.io/spring-boot/docs/2.2.0.RELEASE/reference/html//production-ready-features.html#health-groups

Seems to me the Spring Team was a bit lazy with documentation for all of this grouping nonsense.



来源:https://stackoverflow.com/questions/51861320/how-to-aggregate-health-indicators-in-spring-boot

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!