
Vérifications de santé (`HealthIndicator` personnalisés)
Apprenez à implémenter des HealthIndicator personnalisés pour intégrer l'état de santé de vos propres composants applicatifs à l'endpoint /health de Spring Boot Actuator.
Pourquoi créer des indicateurs de santé personnalisés ?
L'endpoint /actuator/health de Spring Boot Actuator est un outil essentiel pour surveiller l'état de santé global d'une application. Par défaut, il agrège les résultats de plusieurs indicateurs de santé (HealthIndicator) auto-configurés par Spring Boot, vérifiant l'état de composants clés comme la base de données, l'espace disque, les brokers de messages (RabbitMQ, Kafka), etc.
Cependant, l'état de santé de votre application ne dépend pas uniquement de ces composants standards. Vous pouvez avoir des services externes critiques, des caches spécifiques, des files d'attente internes, ou d'autres ressources vitales dont le bon fonctionnement est essentiel. Si l'un de ces composants personnalisés tombe en panne, votre application peut être considérée comme dégradée ou hors service, même si la base de données et l'espace disque sont opérationnels.
C'est là qu'interviennent les HealthIndicator personnalisés. En implémentant cette interface, vous pouvez créer vos propres vérifications de santé pour n'importe quel aspect de votre application et les intégrer de manière transparente à l'endpoint /actuator/health. Cela permet d'obtenir une vision beaucoup plus précise et pertinente de l'état de santé réel de votre application du point de vue métier ou technique spécifique.
Implémenter l'interface `HealthIndicator`
La création d'un indicateur de santé personnalisé est simple. Il suffit d'implémenter l'interface org.springframework.boot.actuate.health.HealthIndicator. Cette interface ne définit qu'une seule méthode : Health health().
La méthode health() doit retourner un objet Health. Cet objet encapsule le résultat de la vérification de santé. Il est construit à l'aide d'un builder et contient principalement deux informations :
- Le statut (
Status) : Indique l'état du composant vérifié. Les statuts prédéfinis les plus courants sontStatus.UP(fonctionnel),Status.DOWN(en panne),Status.OUT_OF_SERVICE(temporairement indisponible), etStatus.UNKNOWN(état indéterminé). Le statut global de l'endpoint/healthest déterminé par une agrégation des statuts de tous les indicateurs (par défaut, si un seul estDOWN, le statut global estDOWN). - Les détails (
details) : Une map (Map) contenant des informations supplémentaires sur l'état du composant. Ces détails sont affichés dans la réponse de/healthlorsque la propriétémanagement.endpoint.health.show-detailsest configurée de manière appropriée (when-authorizedoualways).
Pour que votre implémentation soit découverte et utilisée par Actuator, il suffit généralement de la déclarer comme un bean Spring, par exemple en l'annotant avec @Component.
Exemple : Vérifier un service externe
Imaginons que notre application dépende d'un service externe "Service Météo" accessible via une API REST. Nous voulons créer un HealthIndicator pour vérifier si ce service est joignable et répond correctement.
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
@Component // Déclare ce composant comme un bean Spring
public class ServiceMeteoHealthIndicator implements HealthIndicator {
private final RestTemplate restTemplate;
private final String serviceUrl = "https://api.example-meteo.com/ping"; // URL de test du service
public ServiceMeteoHealthIndicator() {
// Idéalement, injecter un RestTemplate configuré via @Autowired
this.restTemplate = new RestTemplate();
}
@Override
public Health health() {
try {
// Tente d'appeler une URL simple du service externe
restTemplate.getForObject(serviceUrl, String.class);
// Si l'appel réussit sans exception, le service est UP
return Health.up()
.withDetail("service", "Service Météo")
.withDetail("url", serviceUrl)
.build();
} catch (RestClientException e) {
// Si une exception se produit (timeout, erreur 4xx/5xx, etc.), le service est DOWN
return Health.down()
.withDetail("service", "Service Météo")
.withDetail("url", serviceUrl)
.withDetail("error", e.getMessage()) // Ajoute le message d'erreur aux détails
.build();
} catch (Exception e) {
// Gérer d'autres exceptions potentielles
return Health.down(e)
.withDetail("service", "Service Météo")
.withDetail("url", serviceUrl)
.build();
}
}
}
Dans cet exemple :
- La classe implémente
HealthIndicator. - Elle est annotée
@Componentpour être détectée par Spring. - La méthode
health()essaie d'appeler une URL du service externe. - Si l'appel réussit, elle retourne
Health.up()avec des détails informatifs. - Si une
RestClientException(ou autre) survient, elle retourneHealth.down(), incluant le message d'erreur dans les détails pour faciliter le diagnostic. - Le constructeur
Health.down(Exception e)est une alternative qui inclut automatiquement les détails de l'exception.
Intégration dans l'endpoint /health
Une fois votre HealthIndicator personnalisé déclaré comme bean, Actuator l'inclura automatiquement dans l'agrégation de l'endpoint /actuator/health. Le nom du bean (par défaut, le nom de la classe avec la première lettre en minuscule, ici `serviceMeteoHealthIndicator`) est utilisé comme clé dans la réponse JSON, mais sans le suffixe `HealthIndicator`.
Si notre `ServiceMeteoHealthIndicator` retourne UP, et en supposant que show-details est activé, la réponse de /actuator/health pourrait ressembler à ceci :
{
"status": "UP",
"components": {
"db": { /* ... détails base de données ... */ },
"diskSpace": { /* ... détails espace disque ... */ },
"serviceMeteo": { // Note: 'HealthIndicator' est retiré du nom
"status": "UP",
"details": {
"service": "Service Météo",
"url": "https://api.example-meteo.com/ping"
}
}
/* ... autres indicateurs ... */
}
}Si le service météo était en panne, le statut de `serviceMeteo` serait DOWN, des détails d'erreur seraient présents, et le statut global de l'application pourrait passer à DOWN (selon la configuration d'agrégation et les autres indicateurs).
Indicateurs composites et autres considérations
Pour des scénarios plus complexes, vous pouvez regrouper plusieurs indicateurs logiquement liés en implémentant CompositeHealthContributor au lieu de HealthIndicator. Cela permet de créer une structure hiérarchique dans la réponse de l'endpoint /health.
Si vous travaillez avec des applications réactives (Spring WebFlux), vous devriez implémenter l'interface ReactiveHealthIndicator. Sa méthode health() retourne un Mono, s'intégrant naturellement dans les flux réactifs.
Bonnes pratiques pour les Health Indicators :
- Rapidité : Les vérifications de santé doivent être rapides pour ne pas ralentir l'endpoint
/health, qui peut être appelé fréquemment par les systèmes de monitoring. Evitez les opérations longues ou coûteuses. - Robustesse : Gérez correctement les exceptions au sein de la méthode
health()pour toujours retourner un objetHealthvalide, même en cas d'erreur lors de la vérification. - Pertinence des détails : Fournissez des détails utiles pour le diagnostic, mais évitez d'exposer des informations trop sensibles (comme des mots de passe ou des données confidentielles).
- Timeout : Si vous appelez des services externes, configurez des timeouts raisonnables pour éviter que l'indicateur ne bloque indéfiniment.
En ajoutant des HealthIndicator personnalisés, vous enrichissez considérablement la capacité de surveillance de votre application Spring Boot, permettant une détection plus rapide et plus précise des problèmes spécifiques à votre domaine ou à votre infrastructure.