Aller au contenu principal

SLO, budgets d'erreur et propagation des traces

Kit sections 11 et 15, exigences OBSE-001, OBSE-005 et OBSE-012. Version anglaise : en/slo.md.

Cibles​

ServiceRoutesDisponibilitéLatence
control_plane_apitoutes les autres routes /v199,5 %95 % des requêtes sous 1 s
model_gateway/v1/gateway/*99,5 %95 % sous 1 s
tool_gateway/v1/tools/*99,5 %95 % sous 1 s
realtime/v1/realtime*99,5 %95 % sous 1 s
workerjobs de python -m eai.worker99 % de jobs réussis

Les cibles de la route sont lues dans la table eai.service_slos (V169, ADR-0157), écrite par PUT /v1/telemetry/slo/targets/{service} (platform_admin seul, corps {availability, latency_seconds, latency_objective, reason?}, audité telemetry.slo.target.update, 404 slo_service_unknown) ; chaque service de la réponse indique target_source: database | settings. Un service sans ligne garde les valeurs par défaut réglées par EAI_SLO_AVAILABILITY_TARGETS, EAI_SLO_LATENCY_TARGETS_SECONDS, EAI_SLO_LATENCY_OBJECTIVE ; la fenêtre est bornée par EAI_SLO_RETENTION_MINUTES (configuration.md). Une valeur invalide est refusée au démarrage en production (eai.security.startup). Les règles Prometheus portent les valeurs par défaut ci-dessus : changer une cible demande de mettre à jour aussi deploy/observability/slo/eai-slo-rules.yaml et ses tests promtool.

Budgets et taux de brûlage​

  • Budget autorisé = (1 - cible) x requêtes de la fenêtre. Budget restant = 1 - mauvaises requêtes / budget autorisé (négatif quand le budget est dépassé).
  • Taux de brûlage = part de mauvaises requêtes / (1 - cible) : 1 consomme exactement le budget sur la période.
  • Mauvaise requête : statut 5xx pour la disponibilité, durée au-dessus du seuil pour la latence.

Alertes de brûlage (multi-fenêtres)​

AlerteConditionSévérité
EaiSloAvailabilityFastBurntaux d'erreur > 14,4 x 0,5 % sur 1 h et 5 min, pendant 2 mincritical
EaiSloAvailabilitySlowBurntaux d'erreur > 6 x 0,5 % sur 6 h et 1 h, pendant 15 minwarning
EaiSloLatencyFastBurnrequêtes lentes > 14,4 x 5 % sur 1 h et 5 min, pendant 2 mincritical
EaiSloWorkerFastBurnjobs en échec > 14,4 x 1 % sur 1 h et 5 min, pendant 2 mincritical

Vérification : promtool check rules deploy/observability/slo/eai-slo-rules.yaml et promtool test rules deploy/observability/slo/tests/eai-slo-rules.test.yaml (tests/test_observability_slo.py).

Écran du portail​

La plateforme ne livre pas de serveur de tableaux de bord (ADR-0169). Les budgets se lisent dans l'écran SLO et budgets d'erreur du portail (/observability/slo, guide), alimenté par la route ci-dessous ; la vue de toute la flotte sur 30 jours vient des règles d'enregistrement eai:* et des alertes de brûlage, lues dans Prometheus et Alertmanager. Un Grafana exploité par le client peut lire les mêmes règles (EAI_GRAFANA_URL).

Route GET /v1/telemetry/slo​

Paramètres : window_minutes (1 à EAI_SLO_RETENTION_MINUTES, défaut 60) et tenant_id (platform_admin seulement). Rôles : platform_admin (toute la plateforme ou un tenant), tenant_admin, auditor et viewer (leur tenant uniquement). Chaque lecture est auditée (telemetry.slo.read). Codes d'erreur : forbidden, tenant_required, slo_scope_forbidden, slo_window_invalid, slo_targets_invalid.

Réponse par service : requests, errors, over_latency_target, latency_target_seconds, puis availability et latency avec target, bad, ratio, budget_remaining et burn_rate.

Source : le middleware HTTP de l'API compte chaque requête servie (gabarit de route, statut, durée, tenant de l'appelant) dans des cases d'une minute gardées en mémoire par réplique. La route donne donc la vue de la réplique interrogée ; la vue de toute la flotte sur 30 jours vient des règles Prometheus, calculées sur les mêmes mesures (eai_http_requests_total, eai_http_request_duration_seconds).

Propagation des traces​

  • HTTP : le span serveur de l'API continue le traceparent reçu ; eai.llm.route, eai.llm.provider_call et eai.tool.invoke sont ses descendants, et l'amont (fournisseur LLM, outil) reçoit le traceparent du span courant.
  • File : scheduler.publish ouvre eai.event.publish et écrit traceparent et tracestate dans les en-têtes de l'événement (NATS ou eai.event_outbox, y compris les réveils des workers média). Le job outbox ouvre eai.event.deliver comme enfant de ce traceparent puis eai.event.dispatch, et les audits écrits pendant la livraison portent le même trace_id.
  • Le worker initialise OpenTelemetry avec les réglages EAI_OTEL_* de l'API et vide l'exportateur à l'arrêt.
  • Preuve : services/control-plane/tests/test_trace_end_to_end.py avec le vrai otelcol-contrib (deploy/observability/tools/fetch-toolchain.sh otelcol).