Benutzerdefinierte Endpoint mit Actuator in Spring

Actuator ist eine ganz nützliches Tool bei Überwachung von Microservice. Spring boot nutzt dies ganz gut für Instrumentation und Monitoring. Es kommt aber ab und zu ein Anforderung es zu erweitern. Actuator gibt da so eine Möglichkeit mithilfe von @Endpoint.

Problem: “A” hat eine Externe Abhängigkeit für eine API von “B” und möchte Verfügbarkeit von diese externe API im blick behalten. “A” verwendet Icinga2 für ihre Überwachung und hätte gerne auch diese zum Verfügbarkeit verwendet. “B” gibt keine möglichkeit es zu bewerkstelligen.

Lösungansatz: “A” erstellt eine Endpoint in Actuator welche denn “B” einfache API aufruf macht um zu sehen ob API verfügbr ist. Diese Endpoint könnte denn von Icinga2 Überwacht werden.

Beispiel:

@Component
@Endpoint(id = "Bhealth")
public class BEndpoint {
    private final BHealthCheckService BHealthCheckService;

    @Autowired
    public BEndpoint(BHealthCheckService BHealthCheckService) {
        this.BHealthCheckService = BHealthCheckService;
    }

// default endpoint Parent RequestMapping at /actuator/Bhealth
    @ReadOperation
    public CustomHealth checkAllBApi() {
        CustomHealth health = new CustomHealth();
        Boolean status = false;
        status = BHealthCheckService.checkAllBApisHealth();
        if (status) {
            health.setStatus("UP");
        } else {
            health.setStatus("DOWN");
        }
        return health;
    }
//child endpoint with RequestMapping at /actuator/Bhealth/{apiName}
    @ReadOperation
    public CustomHealth checkIndiviualBApi(@Selector String apiName) {
        CustomHealth health = new CustomHealth();
        Boolean status = false;
        if(apiName.equals("first")) {
            status= BHealthCheckService.checkBApiFirst();
        }
        if(apiName.equals("second")) {
            status= BHealthCheckService.checkBApiSecond();
        }
        if(apiName.equals("third")) {
            status= BHealthCheckService.checkBApiThird();
        }
        if (status) {
            health.setStatus("UP");
        } else {
            health.setStatus("DOWN");
        }
        return health;
    }

    public class CustomHealth {
        private String status;

        public String getStatus() {
            return status;
        }
        public void setStatus(String status) {
            this.status = status;
        }

        @Override
        public String toString() {
            return "CustomHealth{" + "status='" + status + '\'' + '}';
        }
    }
}

In Einstellungen (application.yml) kann man auch für die aufrufe denn ganz einfach Cache erstellen. Man kann da auch time-to-live (Lebenszyklus) ein Cache eingeben. Wichtig ist auch das diese endpoint auch nach außen denn verfügbar gemacht wird für Icinga & co. Application.yml sieht so aus.

management:
  endpoints:
    jmx.exposure.exclude: "*"
    web:
      exposure:
        include: info, health, Bhealth
  endpoint:
    Bhealth:
      cache:
        time-to-live: 100s
    caches:
      enabled: true