Spring Boot Actuator : monitoring production avec Micrometer et Prometheus
Guide complet Spring Boot Actuator pour le monitoring en production. Configuration Micrometer, métriques Prometheus, endpoints personnalisés et alerting.

Spring Boot Actuator transforme le monitoring des applications Java en fournissant des endpoints prêts à l'emploi pour la santé, les métriques et le diagnostic. Combiné avec Micrometer et Prometheus, il offre une solution complète d'observabilité pour les environnements de production.
Actuator expose automatiquement plus de 50 métriques JVM et applicatives. Micrometer sert de façade pour publier ces métriques vers Prometheus, Grafana, Datadog ou tout autre système de monitoring.
Configuration de base avec Spring Boot 3
Dépendances Maven requises
L'intégration d'Actuator avec Prometheus nécessite trois dépendances principales. Le starter Actuator active les endpoints, Micrometer fournit l'abstraction des métriques, et le registry Prometheus formate les données pour le scraping.
<!-- pom.xml -->
<!-- Configuration Actuator + Micrometer + Prometheus -->
<dependencies>
<!-- Spring Boot Actuator - endpoints de monitoring -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Micrometer Registry Prometheus -->
<!-- Expose les métriques au format Prometheus -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
<!-- AOP pour les métriques @Timed et @Counted -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
</dependencies>Ces dépendances suffisent pour exposer un endpoint /actuator/prometheus que Prometheus peut scraper périodiquement.
Configuration des endpoints Actuator
Par défaut, seuls les endpoints health et info sont exposés via HTTP. La configuration explicite contrôle quels endpoints restent accessibles en production.
# application.yml
# Configuration Actuator pour la production
management:
endpoints:
web:
exposure:
# Endpoints exposés via HTTP
# health, info, prometheus sont les minimums pour le monitoring
include: health,info,prometheus,metrics,env,loggers
base-path: /actuator
# Désactive les endpoints non utilisés pour réduire la surface d'attaque
enabled-by-default: false
endpoint:
# Active individuellement chaque endpoint nécessaire
health:
enabled: true
show-details: when-authorized
show-components: when-authorized
info:
enabled: true
prometheus:
enabled: true
metrics:
enabled: true
env:
enabled: true
# Masque les valeurs sensibles
show-values: when-authorized
loggers:
enabled: trueL'option show-details: when-authorized affiche les détails de santé uniquement aux utilisateurs authentifiés avec le rôle approprié.
// Sécurisation des endpoints Actuator
package com.example.monitoring.config;
import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class ActuatorSecurityConfig {
@Bean
SecurityFilterChain actuatorSecurityFilterChain(HttpSecurity http) throws Exception {
return http
.securityMatcher(EndpointRequest.toAnyEndpoint())
.authorizeHttpRequests(auth -> auth
// Health et info publics pour les load balancers
.requestMatchers(EndpointRequest.to("health", "info")).permitAll()
// Prometheus accessible depuis le réseau interne
.requestMatchers(EndpointRequest.to("prometheus")).hasIpAddress("10.0.0.0/8")
// Autres endpoints réservés aux admins
.anyRequest().hasRole("ACTUATOR_ADMIN")
)
.httpBasic(basic -> {})
.build();
}
}Cette configuration autorise l'accès public aux endpoints de base tout en protégeant les endpoints sensibles.
Métriques personnalisées avec Micrometer
Compteurs et jauges applicatives
Micrometer fournit plusieurs types de métriques adaptés à différents cas d'usage. Les compteurs mesurent les événements cumulatifs, les jauges les valeurs instantanées, et les timers la durée des opérations.
// Service de métriques métier personnalisées
package com.example.monitoring.metrics;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import org.springframework.stereotype.Service;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;
@Service
public class OrderMetricsService {
// Compteur de commandes créées avec tag de statut
private final Counter ordersCreatedCounter;
// Timer pour mesurer la durée de traitement
private final Timer orderProcessingTimer;
// Valeur atomique pour la jauge des commandes en cours
private final AtomicInteger pendingOrdersCount = new AtomicInteger(0);
public OrderMetricsService(MeterRegistry registry) {
// Compteur avec tags pour filtrer dans Prometheus
this.ordersCreatedCounter = Counter.builder("orders.created.total")
.description("Nombre total de commandes créées")
.tag("application", "order-service")
.register(registry);
// Timer avec histogramme pour les percentiles
this.orderProcessingTimer = Timer.builder("orders.processing.duration")
.description("Durée de traitement des commandes")
.publishPercentiles(0.5, 0.95, 0.99)
.publishPercentileHistogram()
.register(registry);
// Jauge liée à une valeur atomique
// Se met à jour automatiquement à chaque scraping
Gauge.builder("orders.pending.count", pendingOrdersCount, AtomicInteger::get)
.description("Nombre de commandes en attente de traitement")
.register(registry);
}
public void recordOrderCreated() {
ordersCreatedCounter.increment();
pendingOrdersCount.incrementAndGet();
}
public void recordOrderProcessed(Runnable processingLogic) {
// Mesure automatiquement la durée d'exécution
orderProcessingTimer.record(processingLogic);
pendingOrdersCount.decrementAndGet();
}
public <T> T recordOrderProcessedWithResult(Supplier<T> processingLogic) {
return orderProcessingTimer.record(processingLogic);
}
}L'utilisation de tags permet de filtrer et agréger les métriques dans Prometheus avec des requêtes PromQL précises.
Annotations @Timed et @Counted
Pour éviter le code boilerplate, Micrometer propose des annotations AOP qui instrumentent automatiquement les méthodes.
// Instrumentation automatique avec annotations
package com.example.monitoring.service;
import io.micrometer.core.annotation.Counted;
import io.micrometer.core.annotation.Timed;
import org.springframework.stereotype.Service;
@Service
public class PaymentService {
// @Timed crée automatiquement un Timer
// Mesure chaque appel et publie count, sum, max
@Timed(
value = "payment.process.duration",
description = "Durée de traitement des paiements",
percentiles = {0.5, 0.95, 0.99},
histogram = true
)
public PaymentResult processPayment(PaymentRequest request) {
// Logique de paiement
validatePayment(request);
return executePayment(request);
}
// @Counted incrémente un compteur à chaque appel
// Utile pour les événements discrets
@Counted(
value = "payment.refunds.total",
description = "Nombre total de remboursements"
)
public void refundPayment(String transactionId) {
// Logique de remboursement
}
// Combinaison des deux annotations
@Timed(value = "payment.validation.duration")
@Counted(value = "payment.validation.total")
private void validatePayment(PaymentRequest request) {
// Validation du paiement
}
}// Configuration requise pour activer @Timed
package com.example.monitoring.config;
import io.micrometer.core.aop.CountedAspect;
import io.micrometer.core.aop.TimedAspect;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class TimedAspectConfig {
// Aspect nécessaire pour que @Timed fonctionne
@Bean
TimedAspect timedAspect(MeterRegistry registry) {
return new TimedAspect(registry);
}
// Aspect pour @Counted
@Bean
CountedAspect countedAspect(MeterRegistry registry) {
return new CountedAspect(registry);
}
}Les annotations @Timed et @Counted ne fonctionnent que sur les beans Spring et les appels externes. Les appels internes à une même classe contournent le proxy AOP et ne sont pas instrumentés.
Prêt à réussir tes entretiens Spring Boot ?
Entraîne-toi avec nos simulateurs interactifs, fiches express et tests techniques.
Endpoints de santé personnalisés
Health Indicators métier
Les Health Indicators permettent de vérifier l'état de dépendances externes et de composants métier critiques. Spring Boot fournit des indicateurs par défaut pour la base de données, Redis, et d'autres services courants.
// Indicateur de santé pour la gateway de paiement
package com.example.monitoring.health;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClient;
import java.time.Duration;
import java.time.Instant;
@Component
public class PaymentGatewayHealthIndicator implements HealthIndicator {
private final RestClient restClient;
private final String gatewayHealthUrl;
public PaymentGatewayHealthIndicator(RestClient.Builder restClientBuilder) {
this.restClient = restClientBuilder.build();
this.gatewayHealthUrl = "https://api.payment-gateway.com/health";
}
@Override
public Health health() {
Instant start = Instant.now();
try {
// Appel au endpoint de santé de la gateway
var response = restClient.get()
.uri(gatewayHealthUrl)
.retrieve()
.toBodilessEntity();
Duration responseTime = Duration.between(start, Instant.now());
if (response.getStatusCode().is2xxSuccessful()) {
return Health.up()
.withDetail("responseTime", responseTime.toMillis() + "ms")
.withDetail("statusCode", response.getStatusCode().value())
.build();
} else {
return Health.down()
.withDetail("statusCode", response.getStatusCode().value())
.withDetail("reason", "Unexpected status code")
.build();
}
} catch (Exception e) {
Duration responseTime = Duration.between(start, Instant.now());
return Health.down()
.withDetail("error", e.getClass().getSimpleName())
.withDetail("message", e.getMessage())
.withDetail("responseTime", responseTime.toMillis() + "ms")
.build();
}
}
}Cet indicateur apparaît automatiquement dans /actuator/health sous le nom paymentGateway.
Health Groups pour Kubernetes
Les groupes de santé permettent de créer des endpoints distincts pour les probes Kubernetes liveness et readiness.
# application.yml
# Configuration des groupes de santé pour Kubernetes
management:
endpoint:
health:
group:
# Liveness probe - l'application est-elle vivante ?
liveness:
include: livenessState
show-details: always
# Readiness probe - l'application peut-elle recevoir du trafic ?
readiness:
include: readinessState,db,redis,paymentGateway
show-details: always
# Probe personnalisée pour les dépendances critiques
critical:
include: db,paymentGateway
show-details: when-authorized
health:
# Active les états Kubernetes
livenessstate:
enabled: true
readinessstate:
enabled: true// Configuration programmatique des groupes
package com.example.monitoring.config;
import org.springframework.boot.actuate.availability.LivenessStateHealthIndicator;
import org.springframework.boot.actuate.availability.ReadinessStateHealthIndicator;
import org.springframework.boot.availability.ApplicationAvailability;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class KubernetesHealthConfig {
@Bean
LivenessStateHealthIndicator livenessStateHealthIndicator(
ApplicationAvailability availability) {
return new LivenessStateHealthIndicator(availability);
}
@Bean
ReadinessStateHealthIndicator readinessStateHealthIndicator(
ApplicationAvailability availability) {
return new ReadinessStateHealthIndicator(availability);
}
}Les probes Kubernetes pointent alors vers les endpoints dédiés :
# kubernetes-deployment.yml
# Configuration des probes Kubernetes
spec:
containers:
- name: order-service
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
failureThreshold: 3Intégration Prometheus et Grafana
Configuration du scraping Prometheus
Prometheus collecte les métriques en interrogeant périodiquement l'endpoint /actuator/prometheus. La configuration définit les cibles à scraper.
# prometheus.yml
# Configuration Prometheus pour Spring Boot
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'spring-boot-apps'
metrics_path: '/actuator/prometheus'
scrape_interval: 10s
static_configs:
- targets:
- 'order-service:8080'
- 'payment-service:8080'
- 'inventory-service:8080'
# Relabeling pour ajouter des métadonnées
relabel_configs:
- source_labels: [__address__]
target_label: instance
regex: '([^:]+):\d+'
replacement: '${1}'
# Service discovery Kubernetes
- job_name: 'kubernetes-pods'
kubernetes_sd_configs:
- role: pod
relabel_configs:
# Scrape uniquement les pods avec l'annotation
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: true
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__
regex: (.+)Métriques JVM exposées par défaut
Actuator avec Micrometer expose automatiquement des métriques JVM détaillées. Voici les plus importantes pour le monitoring.
# Requêtes PromQL pour le monitoring JVM
# Utilisation mémoire heap
jvm_memory_used_bytes{area="heap"}
# Pourcentage mémoire utilisée
jvm_memory_used_bytes{area="heap"} / jvm_memory_max_bytes{area="heap"} * 100
# Threads actifs
jvm_threads_live_threads
# Garbage collection - temps passé
rate(jvm_gc_pause_seconds_sum[5m])
# Nombre de GC par minute
rate(jvm_gc_pause_seconds_count[1m]) * 60
# CPU utilisé par la JVM
process_cpu_usage
# Connexions base de données actives
hikaricp_connections_active
# Pool de connexions - utilisation
hikaricp_connections_active / hikaricp_connections_max * 100// Métriques JVM additionnelles
package com.example.monitoring.metrics;
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.binder.MeterBinder;
import org.springframework.stereotype.Component;
import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
@Component
public class CustomJvmMetrics implements MeterBinder {
@Override
public void bindTo(MeterRegistry registry) {
OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
// Load average système
Gauge.builder("system.load.average", osBean, OperatingSystemMXBean::getSystemLoadAverage)
.description("System load average over 1 minute")
.register(registry);
// Nombre de processeurs disponibles
Gauge.builder("system.cpu.count", osBean, OperatingSystemMXBean::getAvailableProcessors)
.description("Number of available processors")
.register(registry);
// Uptime de l'application
Gauge.builder("application.uptime.seconds",
ManagementFactory.getRuntimeMXBean(),
bean -> bean.getUptime() / 1000.0)
.description("Application uptime in seconds")
.register(registry);
}
}Dashboard Grafana prêt à l'emploi
Grafana propose des dashboards préconfigurés pour Spring Boot. Le dashboard ID 12900 offre une vue complète des métriques Actuator.
{
"annotations": {
"list": []
},
"panels": [
{
"title": "Request Rate",
"type": "graph",
"targets": [
{
"expr": "rate(http_server_requests_seconds_count{application=\"$application\"}[5m])",
"legendFormat": "{{method}} {{uri}} - {{status}}"
}
]
},
{
"title": "Response Time P99",
"type": "graph",
"targets": [
{
"expr": "histogram_quantile(0.99, rate(http_server_requests_seconds_bucket{application=\"$application\"}[5m]))",
"legendFormat": "{{method}} {{uri}}"
}
]
},
{
"title": "Error Rate",
"type": "singlestat",
"targets": [
{
"expr": "sum(rate(http_server_requests_seconds_count{application=\"$application\",status=~\"5..\"}[5m])) / sum(rate(http_server_requests_seconds_count{application=\"$application\"}[5m])) * 100"
}
]
}
]
}Pour importer un dashboard : Grafana → Dashboards → Import → ID 12900 (Spring Boot Statistics) ou 4701 (JVM Micrometer). Ces dashboards fonctionnent directement avec les métriques Actuator standard.
Alerting avec Prometheus
Règles d'alerte essentielles
Les règles d'alerte Prometheus déclenchent des notifications lorsque les métriques dépassent des seuils critiques.
# alerting-rules.yml
# Règles d'alerte pour applications Spring Boot
groups:
- name: spring-boot-alerts
rules:
# Alerte si l'application est down
- alert: ApplicationDown
expr: up{job="spring-boot-apps"} == 0
for: 1m
labels:
severity: critical
annotations:
summary: "Application {{ $labels.instance }} is down"
description: "{{ $labels.instance }} has been down for more than 1 minute"
# Alerte sur le taux d'erreurs HTTP
- alert: HighErrorRate
expr: |
sum(rate(http_server_requests_seconds_count{status=~"5.."}[5m])) by (application)
/
sum(rate(http_server_requests_seconds_count[5m])) by (application)
> 0.05
for: 5m
labels:
severity: warning
annotations:
summary: "High error rate on {{ $labels.application }}"
description: "Error rate is {{ $value | humanizePercentage }}"
# Alerte sur la latence P99
- alert: HighLatency
expr: |
histogram_quantile(0.99,
rate(http_server_requests_seconds_bucket[5m])
) > 2
for: 5m
labels:
severity: warning
annotations:
summary: "High latency detected"
description: "P99 latency is {{ $value | humanizeDuration }}"
# Alerte mémoire heap
- alert: HighHeapUsage
expr: |
jvm_memory_used_bytes{area="heap"}
/ jvm_memory_max_bytes{area="heap"}
> 0.85
for: 5m
labels:
severity: warning
annotations:
summary: "High heap memory usage on {{ $labels.instance }}"
description: "Heap usage is at {{ $value | humanizePercentage }}"
# Alerte connexions base de données épuisées
- alert: DatabaseConnectionPoolExhausted
expr: |
hikaricp_connections_active
/ hikaricp_connections_max
> 0.9
for: 2m
labels:
severity: critical
annotations:
summary: "Database connection pool nearly exhausted"
description: "{{ $value | humanizePercentage }} of connections in use"
# Alerte GC excessif
- alert: HighGCPause
expr: |
rate(jvm_gc_pause_seconds_sum[5m])
/ rate(jvm_gc_pause_seconds_count[5m])
> 0.5
for: 5m
labels:
severity: warning
annotations:
summary: "High GC pause time"
description: "Average GC pause is {{ $value | humanizeDuration }}"Ces alertes couvrent les problèmes les plus courants en production : disponibilité, performance, et ressources.
Métriques HTTP et base de données
Instrumentation automatique des requêtes HTTP
Spring Boot 3 instrumente automatiquement toutes les requêtes HTTP entrantes avec des métriques détaillées.
# application.yml
# Configuration des métriques HTTP
management:
metrics:
distribution:
# Active les histogrammes pour les percentiles
percentiles-histogram:
http.server.requests: true
percentiles:
http.server.requests: 0.5, 0.75, 0.95, 0.99
# Définit les buckets SLA
slo:
http.server.requests: 100ms, 500ms, 1s, 2s
tags:
# Tags globaux ajoutés à toutes les métriques
application: ${spring.application.name}
environment: ${spring.profiles.active:default}// Personnalisation des tags HTTP
package com.example.monitoring.config;
import io.micrometer.core.instrument.Tag;
import org.springframework.boot.actuate.metrics.web.servlet.WebMvcTagsContributor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerMapping;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.util.Collections;
@Configuration
public class WebMvcMetricsConfig {
@Bean
WebMvcTagsContributor customTagsContributor() {
return (request, response, handler, exception) -> {
// Ajoute des tags personnalisés aux métriques HTTP
String userId = request.getHeader("X-User-Id");
String tenantId = request.getHeader("X-Tenant-Id");
return java.util.List.of(
Tag.of("user.type", userId != null ? "authenticated" : "anonymous"),
Tag.of("tenant", tenantId != null ? tenantId : "default")
);
};
}
}Métriques HikariCP et requêtes SQL
Les métriques du pool de connexions HikariCP sont exposées automatiquement. Pour les requêtes SQL, une configuration supplémentaire permet de tracer la durée des queries.
# application.yml
# Configuration HikariCP avec métriques
spring:
datasource:
hikari:
pool-name: OrderServicePool
maximum-pool-size: 20
minimum-idle: 5
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000
# Active les métriques détaillées
register-mbeans: true// Métriques supplémentaires pour les requêtes SQL
package com.example.monitoring.config;
import io.micrometer.core.instrument.MeterRegistry;
import net.ttddyy.dsproxy.listener.logging.SLF4JLogLevel;
import net.ttddyy.dsproxy.support.ProxyDataSourceBuilder;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
@Configuration
public class DataSourceMetricsConfig {
@Bean
@Primary
DataSource metricsDataSource(
DataSourceProperties properties,
MeterRegistry registry) {
// DataSource original
DataSource originalDataSource = properties
.initializeDataSourceBuilder()
.build();
// Proxy avec métriques
return ProxyDataSourceBuilder.create(originalDataSource)
.name("order-service-db")
.listener(new MicrometerQueryMetricsListener(registry))
.logQueryBySlf4j(SLF4JLogLevel.DEBUG)
.build();
}
}// Listener pour les métriques de requêtes SQL
package com.example.monitoring.metrics;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import net.ttddyy.dsproxy.ExecutionInfo;
import net.ttddyy.dsproxy.QueryInfo;
import net.ttddyy.dsproxy.listener.QueryExecutionListener;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class MicrometerQueryMetricsListener implements QueryExecutionListener {
private final Timer queryTimer;
public MicrometerQueryMetricsListener(MeterRegistry registry) {
this.queryTimer = Timer.builder("sql.query.duration")
.description("Durée d'exécution des requêtes SQL")
.publishPercentiles(0.5, 0.95, 0.99)
.register(registry);
}
@Override
public void beforeQuery(ExecutionInfo execInfo, List<QueryInfo> queryInfoList) {
// Avant l'exécution
}
@Override
public void afterQuery(ExecutionInfo execInfo, List<QueryInfo> queryInfoList) {
// Enregistre la durée de chaque requête
long elapsedTime = execInfo.getElapsedTime();
queryTimer.record(elapsedTime, TimeUnit.MILLISECONDS);
}
}Bonnes pratiques pour la production
Cardinalité des métriques
Une cardinalité excessive dégrade les performances de Prometheus. Chaque combinaison unique de tags crée une série temporelle distincte.
// ❌ À ÉVITER - Cardinalité explosive
package com.example.monitoring.antipattern;
@Service
public class AntiPatternHighCardinality {
private final MeterRegistry registry;
// ❌ MAUVAIS : userId crée une série par utilisateur
public void trackUserAction(String userId, String action) {
Counter.builder("user.actions")
.tag("userId", userId) // Millions de valeurs possibles !
.tag("action", action)
.register(registry)
.increment();
}
}// ✅ Cardinalité contrôlée
package com.example.monitoring.bestpractice;
@Service
public class GoodPracticeCardinality {
private final MeterRegistry registry;
// ✅ BON : Catégorie utilisateur au lieu d'ID
public void trackUserAction(User user, String action) {
Counter.builder("user.actions")
.tag("userType", user.getSubscriptionType()) // FREE, PREMIUM, ENTERPRISE
.tag("action", action)
.register(registry)
.increment();
}
// ✅ BON : Regroupement par plage
public void trackResponseTime(long responseTimeMs) {
String bucket = categorizeResponseTime(responseTimeMs);
Counter.builder("response.time.bucket")
.tag("bucket", bucket) // fast, normal, slow, very_slow
.register(registry)
.increment();
}
private String categorizeResponseTime(long ms) {
if (ms < 100) return "fast";
if (ms < 500) return "normal";
if (ms < 2000) return "slow";
return "very_slow";
}
}Configuration production-ready
# application-production.yml
# Configuration optimisée pour la production
management:
endpoints:
web:
exposure:
include: health,info,prometheus
endpoint:
health:
show-details: when-authorized
probes:
enabled: true
metrics:
export:
prometheus:
enabled: true
step: 30s
distribution:
percentiles-histogram:
http.server.requests: true
minimum-expected-value:
http.server.requests: 1ms
maximum-expected-value:
http.server.requests: 30s
tags:
application: ${spring.application.name}
environment: production
version: ${app.version:unknown}
server:
# Port séparé pour les endpoints de management
port: 9090
# Désactive les endpoints non essentiels en production
endpoint:
env:
enabled: false
beans:
enabled: false
configprops:
enabled: false
mappings:
enabled: falseConclusion
Spring Boot Actuator combiné avec Micrometer et Prometheus offre une solution de monitoring complète :
✅ Configuration minimale : endpoints prêts à l'emploi avec Spring Boot Starter
✅ Métriques JVM automatiques : mémoire, threads, GC, CPU sans code additionnel
✅ Métriques personnalisées : Counter, Gauge, Timer avec annotations @Timed/@Counted
✅ Health Indicators : vérification des dépendances externes et états Kubernetes
✅ Intégration Prometheus : format standard pour le scraping et l'alerting
✅ Sécurité intégrée : contrôle d'accès aux endpoints sensibles
✅ Dashboards Grafana : visualisation immédiate avec dashboards préconfigurés
✅ Alerting : règles PromQL pour détecter les anomalies en production
Cette stack d'observabilité forme la base indispensable pour opérer des applications Spring Boot en production avec confiance.
Passe à la pratique !
Teste tes connaissances avec nos simulateurs d'entretien et tests techniques.
Tags
Partager
Articles similaires

Spring Boot logging en 2026 : logs structurés pour la production avec Logback et JSON
Guide complet des logs structurés Spring Boot. Configuration Logback JSON, MDC pour le tracing, best practices production et intégration ELK Stack.

Spring Kafka : architecture event-driven avec consumers résilients
Guide complet Spring Kafka pour architectures event-driven. Configuration, consumers résilients, retry policies, dead letter queues et patterns de production pour applications distribuées.

Spring GraphQL en entretien : resolvers, DataLoaders et gestion du problème N+1
Préparez vos entretiens Spring GraphQL avec ce guide complet. Resolvers, DataLoaders, gestion N+1, mutations et bonnes pratiques pour réussir vos questions techniques.