1. Les métriques nécessaires #
Compter les bons et les mauvais événements.
Instrumentation #
Un SLI de type ratio demande deux compteurs : le total des événements et les mauvais (ou les bons). Pour une API HTTP, un compteur par code de statut et un histogramme de durée suffisent :
http_requests_total{service="checkout", route="/pay", code="200"}
http_requests_total{service="checkout", route="/pay", code="503"}
http_request_duration_seconds_bucket{service="checkout", le="0.1"}
http_request_duration_seconds_bucket{service="checkout", le="0.3"}
http_request_duration_seconds_count{service="checkout"}Bonne Pratique : Placez la mesure au plus près de l'utilisateur : métriques du load balancer ou de l'ingress plutôt que de l'application, pour compter aussi les requêtes qui n'atteignent jamais le code.
2. Les requêtes de SLI #
Disponibilité et latence.
Disponibilité #
# Taux d'erreur sur 5 minutes
sum(rate(http_requests_total{service="checkout", code=~"5.."}[5m]))
/
sum(rate(http_requests_total{service="checkout"}[5m]))Latence #
# Part des requêtes servies en plus de 300 ms (le seuil doit être un bucket existant)
1 - (
sum(rate(http_request_duration_seconds_bucket{service="checkout", le="0.3"}[5m]))
/
sum(rate(http_request_duration_seconds_count{service="checkout"}[5m]))
)Erreur Courante : Le seuil de latence doit correspondre exactement à une borne de bucket (le="0.3"). Sinon, ajoutez ce bucket à l'histogramme ou utilisez les histogrammes natifs de Prometheus.3. Règles d'enregistrement #
Pré-calculer pour plusieurs fenêtres.
Multi-fenêtres #
Les alertes de burn rate ont besoin du taux d'erreur sur plusieurs fenêtres (5 min, 30 min, 1 h, 2 h, 6 h, 1 j, 3 j). On les pré-calcule :
groups:
- name: slo-checkout
rules:
- record: slo:sli_error:ratio_rate5m
expr: |
sum(rate(http_requests_total{service="checkout", code=~"5.."}[5m]))
/ sum(rate(http_requests_total{service="checkout"}[5m]))
labels: { slo: checkout-availability }
- record: slo:sli_error:ratio_rate1h
expr: |
sum(rate(http_requests_total{service="checkout", code=~"5.."}[1h]))
/ sum(rate(http_requests_total{service="checkout"}[1h]))
labels: { slo: checkout-availability }
# ... 30m, 2h, 6h, 1d, 3d
- record: slo:error_budget_remaining:ratio
expr: |
1 - (
sum_over_time(slo:sli_error:ratio_rate5m{slo="checkout-availability"}[30d])
/ count_over_time(slo:sli_error:ratio_rate5m{slo="checkout-availability"}[30d])
) / (1 - 0.999)À savoir : Écrire ces règles à la main est fastidieux et source d'erreurs : c'est exactement ce que génèrent Sloth et Pyrra à partir d'une description de quelques lignes.
