Technique
Alertes, règles d'enregistrement et SLO
Pour : ingénieurs et SRE · architectesPrérequis : Avoir lu la leçon 4 du parcours sur MetricsQL.
Module 9 : vmalert, règles d’alerte de production
Section intitulée « Module 9 : vmalert, règles d’alerte de production »9.1 Jeu de règles complet
Section intitulée « 9.1 Jeu de règles complet »groups: - name: llm_quality interval: 1m rules:
# Dérive d'un index RAG - alert: RAGIndexDrift expr: | avg by (index_id, pipeline_id) ( avg_over_time(rag_retrieval_score_avg[1h]) ) < 0.70 for: 15m labels: { severity: warning, team: ai-platform } annotations: summary: 'Dérive de l''index RAG {{ $labels.index_id }}' description: | Score de recherche moyen = {{ $value | printf "%.2f" }} < seuil 0.70 depuis 15 min sur le pipeline {{ $labels.pipeline_id }}. Action : vérifier les mises à jour de documents sans réindexation. runbook_url: 'https://wiki.internal/runbooks/rag-index-drift'
# Pression de contexte critique - alert: RAGContextPressureHigh expr: | histogram_quantile(0.95, sum by (le, pipeline_id) ( rate(rag_context_pressure_ratio_bucket[10m]) ) ) > 0.85 for: 5m labels: { severity: warning, team: ai-platform } annotations: summary: 'Pression de contexte P95 élevée : {{ $labels.pipeline_id }}' description: 'P95 = {{ $value | printf "%.2f" }}. Réduire le prompt système ou agrandir la fenêtre de contexte.'
# Taux d'erreur LLM élevé - alert: LLMHighErrorRate expr: | sum by (model, provider) (rate(llm_errors_total[5m])) / sum by (model, provider) (rate(llm_requests_total[5m])) > 0.01 for: 3m labels: { severity: critical, team: ai-platform } annotations: summary: 'Taux d''erreur > 1 % sur {{ $labels.model }} / {{ $labels.provider }}' description: 'Taux actuel : {{ $value | humanizePercentage }}. Vérifier la disponibilité du fournisseur.'
# Dépassement du SLO de latence - alert: LLMLatencySLOBreach expr: | histogram_quantile(0.99, sum by (le, model, pipeline_id) ( rate(llm_request_duration_ms_bucket[5m]) ) ) > 5000 for: 5m labels: { severity: critical, team: ai-platform } annotations: summary: 'SLO de latence P99 dépassé sur {{ $labels.model }}' description: 'P99 = {{ $value | printf "%.0f" }} ms > SLO 5000 ms. Pipeline {{ $labels.pipeline_id }}'
# Saturation de la mémoire GPU - alert: GPUMemorySaturation expr: DCGM_FI_DEV_FB_USED / (DCGM_FI_DEV_FB_USED + DCGM_FI_DEV_FB_FREE) * 100 > 90 for: 2m labels: { severity: warning, team: mlops } annotations: summary: 'Mémoire du GPU {{ $labels.gpu }} saturée ({{ $value | printf "%.0f" }} %)' description: 'Risque d''OOM. Réduire la taille de lot ou la fenêtre de contexte du modèle.'
# Budget LLM quotidien (budget de l'exemple : 100 USD par jour, à remplacer par le vôtre). # llm_cost_usd_total n'existe que si une grille de prix est fournie (module 6.3). - alert: LLMDailyBudgetWarning expr: | sum by (tenant_id) ( increase(llm_cost_usd_total[24h]) ) > 80 labels: { severity: warning, team: billing } annotations: summary: 'Budget LLM à 80 % pour le tenant {{ $labels.tenant_id }}' description: 'Coût sur 24 h = {{ $value | printf "%.2f" }} USD. Seuil : 100 USD par jour.'9.2 Routage Alertmanager par équipe
Section intitulée « 9.2 Routage Alertmanager par équipe »global: slack_api_url: 'https://hooks.slack.com/services/REPLACE_ME'
route: group_by: ['alertname', 'model', 'pipeline_id'] group_wait: 30s repeat_interval: 12h receiver: 'default' routes: - matchers: ['severity="critical"'] receiver: pagerduty - matchers: ['team="ai-platform"'] receiver: slack-ai-platform - matchers: ['team="billing"'] receiver: slack-billing
receivers: - name: 'default' slack_configs: - channel: '#llm-ops-alerts' title: '{{ .CommonAnnotations.summary }}' text: '{{ .CommonAnnotations.description }}' - name: 'slack-ai-platform' slack_configs: - channel: '#ai-platform-alerts' - name: 'slack-billing' slack_configs: - channel: '#billing-alerts' - name: 'pagerduty' pagerduty_configs: - routing_key: 'YOUR_PAGERDUTY_KEY'Module 10 : règles d’enregistrement, pré-agréger les métriques de coût
Section intitulée « Module 10 : règles d’enregistrement, pré-agréger les métriques de coût »Les métriques de coût sont interrogées très souvent par les tableaux de bord. Recalculer increase(llm_cost_usd_total[24h]) à chaque rafraîchissement consomme beaucoup de CPU. Les règles d’enregistrement (recording rules) précalculent ces agrégations en tâche de fond : le tableau de bord lit alors une seule série par combinaison de labels au lieu de recalculer l’agrégation sur toutes les séries brutes. Le gain dépend du nombre de séries et de la fenêtre interrogée ; mesurez-le sur votre instance (c’est l’objet du Lab 4).
groups: - name: llm_recording_rules interval: 1m rules:
- record: llm:cost_usd:increase1h expr: | sum by (model, provider, tenant_id) ( increase(llm_cost_usd_total[1h]) )
- record: llm:cost_usd:increase24h expr: | sum by (model, provider, tenant_id) ( increase(llm_cost_usd_total[24h]) )
- record: llm:error_rate:ratio5m expr: | sum by (model, provider) (rate(llm_errors_total[5m])) / sum by (model, provider) (rate(llm_requests_total[5m]))
- record: llm:request_duration_ms:p99_5m expr: | histogram_quantile(0.99, sum by (le, model, pipeline_id) ( rate(llm_request_duration_ms_bucket[5m]) ) )
- record: llm:ttft_ms:p95_5m expr: | histogram_quantile(0.95, sum by (le, model) (rate(llm_ttft_ms_bucket[5m])) )
- record: rag:retrieval_score:avg30m expr: | avg by (index_id, pipeline_id) ( avg_over_time(rag_retrieval_score_avg[30m]) )
- record: rag:context_pressure:p95_10m expr: | histogram_quantile(0.95, sum by (le, pipeline_id) ( rate(rag_context_pressure_ratio_bucket[10m]) ) )
- record: gpu:memory_utilization:ratio expr: DCGM_FI_DEV_FB_USED / (DCGM_FI_DEV_FB_USED + DCGM_FI_DEV_FB_FREE)Utiliser les règles d’enregistrement dans les alertes et les tableaux de bord
Section intitulée « Utiliser les règles d’enregistrement dans les alertes et les tableaux de bord »Une fois les règles définies, utilisez les séries enregistrées plutôt que la requête complète. Au lieu de :
histogram_quantile(0.99, sum by (le, model, pipeline_id) (rate(llm_request_duration_ms_bucket[5m])))utilisez :
llm:request_duration_ms:p99_5mLa requête est beaucoup plus rapide. Le résultat est équivalent, à la résolution de l’intervalle d’évaluation de la règle près (ici une minute) et avec les labels d’agrégation choisis dans la règle.
Module 11 : SLO et SLA pour les charges LLM
Section intitulée « Module 11 : SLO et SLA pour les charges LLM »Un objectif de niveau de service (Service Level Objective, SLO) traduit une exigence métier en cible mesurable. Pour les LLM, les SLO classiques (disponibilité, latence) restent valables mais ne suffisent pas : ajoutez la qualité et le coût.
11.1 Modèle de SLO LLM en cinq catégories
Section intitulée « 11.1 Modèle de SLO LLM en cinq catégories »| Catégorie | Indicateur (SLI) | SLO (exemple à adapter) | Fenêtre |
|---|---|---|---|
| Disponibilité | 1 - rate(llm_errors_total[5m]) / rate(llm_requests_total[5m]) | 99,5 % | 30 jours |
| Latence interactive | histogram_quantile(0.95, ...llm_ttft_ms...) | < 1 200 ms | 7 jours |
| Latence batch | histogram_quantile(0.99, ...llm_request_duration_ms...) | < 8 000 ms | 30 jours |
| Qualité de recherche | avg(rag_retrieval_score_avg) | > 0,78 | 24 h |
| Consommation par requête | sum(increase(llm_tokens_total[1h])) / sum(increase(llm_requests_total[1h])) | < 2 000 tokens (exemple à adapter) | Mois calendaire |
| Coût par requête (avec une grille de prix) | sum(increase(llm_cost_usd_total[1h])) / sum(increase(llm_requests_total[1h])) | votre cible, dans la devise de la métrique | Mois calendaire |
11.2 Calcul du budget d’erreur
Section intitulée « 11.2 Calcul du budget d’erreur »Le budget d’erreur (error budget) est le complément du SLO à 100 %. Pour une disponibilité de 99,5 % sur 30 jours, le budget d’erreur vaut 0,5 %, soit 3 h 36 min d’indisponibilité tolérée par mois.
# Budget d'erreur consommé sur la fenêtre du SLO (en %)( 1 - ( sum(increase(llm_requests_total[30d])) - sum(increase(llm_errors_total[30d])) ) / sum(increase(llm_requests_total[30d]))) / 0.005 * 10011.3 Alertes sur le taux de consommation (motif Google SRE)
Section intitulée « 11.3 Alertes sur le taux de consommation (motif Google SRE) »Alertez quand le budget d’erreur se consomme trop vite (burn rate). Chaque alerte combine une fenêtre longue et une fenêtre courte : la fenêtre longue confirme la tendance, la fenêtre courte fait retomber l’alerte rapidement une fois le problème corrigé.
- alert: LLMFastBurn expr: | ( sum(rate(llm_errors_total[1h])) / sum(rate(llm_requests_total[1h])) ) > (14.4 * 0.005) and ( sum(rate(llm_errors_total[5m])) / sum(rate(llm_requests_total[5m])) ) > (14.4 * 0.005) for: 2m labels: severity: critical annotations: summary: "Consommation du budget d'erreur 14,4 fois la normale (épuisé en 2 jours environ)"
- alert: LLMSlowBurn expr: | ( sum(rate(llm_errors_total[6h])) / sum(rate(llm_requests_total[6h])) ) > (6 * 0.005) and ( sum(rate(llm_errors_total[30m])) / sum(rate(llm_requests_total[30m])) ) > (6 * 0.005) for: 15m labels: severity: warning annotations: summary: "Consommation du budget d'erreur 6 fois la normale (épuisé en 5 jours)"Révisé le 2 octobre 2026 : prix retirés ; la cible chiffrée de coût par requête est remplacée par une cible en tokens par requête, la cible de coût étant laissée à votre grille de prix.