Observability Pattern
Contexte
Dans les architectures distribuées, les problèmes sont difficiles à diagnostiquer. Un bug peut traverser plusieurs services, bases de données et brokers. Sans observabilité, le debugging devient de la devinette.
L'observabilité repose sur trois piliers :
- Logs — ce qui s'est passé
- Metrics — comment le système se comporte
- Traces — le chemin d'une requête à travers les services
Les trois piliers
Logs
Enregistrement textuel des événements :
2026-01-15 10:30:00 INFO [order-service] Order created: orderId=42, userId=7
2026-01-15 10:30:01 ERROR [payment-service] Payment failed: orderId=42, reason=insufficient_funds
Bonnes pratiques :
- format structuré (JSON) pour le parsing automatique
- inclure un
correlationIdpour relier les logs entre services - niveaux cohérents : ERROR pour les erreurs, WARN pour les situations dégradées, INFO pour les événements métier
Metrics
Mesures numériques agrégées dans le temps :
http_requests_total{method="POST", endpoint="/orders", status="201"} 1523
http_request_duration_seconds{endpoint="/orders", quantile="0.99"} 0.45
jvm_memory_used_bytes{area="heap"} 268435456
Types :
- Counter — valeur qui ne fait qu'augmenter (nombre de requêtes)
- Gauge — valeur qui monte et descend (mémoire utilisée)
- Histogram — distribution des valeurs (latence)
Traces
Suivi du parcours d'une requête à travers les services :
Trace: abc-123
├── order-service POST /orders [120ms]
│ ├── db-query SELECT user [5ms]
│ └── kafka-produce order.created [8ms]
└── payment-service process payment [95ms]
└── db-query INSERT payment [12ms]
Chaque opération est un span. L'ensemble forme une trace.
Stack technique courante
flowchart LR
App[Application] -->|logs| Loki
App -->|metrics| Prometheus
App -->|traces| Tempo
Loki --> Grafana
Prometheus --> Grafana
Tempo --> Grafana
| Pilier | Outil | Rôle |
|---|---|---|
| Logs | Loki / ELK | Collecte et recherche de logs |
| Metrics | Prometheus + Grafana | Collecte et visualisation de métriques |
| Traces | Tempo / Jaeger | Distributed tracing |
| Alerting | Grafana / AlertManager | Notification en cas d'anomalie |
Instrumentation Spring Boot
Actuator + Prometheus
management:
endpoints:
web:
exposure:
include: health, prometheus, info
metrics:
export:
prometheus:
enabled: true
Micrometer pour les métriques custom
@Component
public class OrderMetrics {
private final Counter ordersCreated;
public OrderMetrics(MeterRegistry registry) {
this.ordersCreated = Counter.builder("orders.created.total")
.description("Total orders created")
.register(registry);
}
public void orderCreated() {
ordersCreated.increment();
}
}
Structured logging
<encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
log.info("Order created", kv("orderId", order.getId()), kv("userId", user.getId()));
Health Checks
management:
endpoint:
health:
show-details: always
health:
db:
enabled: true
kafka:
enabled: true
Endpoint /actuator/health retourne l'état de chaque dépendance :
{
"status": "UP",
"components": {
"db": { "status": "UP" },
"kafka": { "status": "UP" },
"diskSpace": { "status": "UP" }
}
}
Alerting
Définir des alertes sur les métriques critiques :
| Alerte | Condition | Sévérité |
|---|---|---|
| Error rate élevé | rate(http_5xx_total[5m]) > 0.05 |
Critical |
| Latence p99 | http_duration_p99 > 2s |
Warning |
| Consumer lag | kafka_consumer_lag > 10000 |
Warning |
| Health down | up == 0 |
Critical |
À retenir
- l'observabilité n'est pas optionnelle en production distribuée
- les trois piliers (logs, metrics, traces) sont complémentaires
- le
correlationIdest indispensable pour tracer une requête entre services - les alertes doivent être définies sur les SLOs, pas sur les métriques brutes
- instrumenter dès le développement, pas après le premier incident