Aller au contenu

Fondamentaux de l'observabilité

Monitoring vs Observabilité

Aspect Monitoring Observabilité
Approche Vérifier des conditions connues Explorer des problèmes inconnus
Question "Le service est-il up ?" "Pourquoi ce service est-il lent pour cet utilisateur ?"
Données Metriques predefinies, seuils Metriques + logs + traces correles
Alerting Seuils statiques SLO-based, burn rate
Limitation Ne détecte que les problèmes anticipes Permet d'investiguer les problèmes imprevus

Le monitoring est un sous-ensemble de l'observabilité. Un système bien instrumente est observable — on peut poser n'importe quelle question apres coup sans avoir a ajouter de l'instrumentation.

Les 3 piliers

Metriques

Valeurs numeriques agreges dans le temps. Trois types fondamentaux :

Type Usage Exemple
Compteur (counter) Valeur qui ne fait qu'augmenter Nombre total de requêtes HTTP
Jauge (gauge) Valeur instantanee qui monte et descend Utilisation mémoire en octets
Histogramme (histogram) Distribution de valeurs dans des buckets Latence des requêtes (p50, p95, p99)
# Taux de requetes par seconde (derniere 5min)
rate(http_requests_total[5m])

# 99e percentile de latence
histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m]))

# Utilisation CPU
100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

Logs

Événements discrets horodates, idealement structures en JSON :

{
  "timestamp": "2026-04-16T14:23:45.123Z",
  "level": "error",
  "service": "api-gateway",
  "trace_id": "abc123def456",
  "message": "upstream timeout",
  "upstream": "catalog-service:8080",
  "duration_ms": 30012,
  "status_code": 504
}

Logs structures

Toujours emettre des logs en JSON structure. Les logs en texte libre sont difficiles a filtrer et a correler. Utiliser un schema coherent entre tous les services (mêmes noms de champs).

Traces distribuees

Une trace représente le parcours complet d'une requête à travers plusieurs services :

graph TD
    T["Trace abc123def456"]
    T --> GW["api-gateway — 312ms"]
    GW --> Auth["auth-service — 45ms"]
    GW --> Catalog["catalog-service — 250ms"]
    Catalog --> DB["database — 30ms"]
    Catalog --> Cache["cache — 5ms"]

Chaque segment est un span. Les spans sont relies par un trace_id commun et des relations parent/enfant.

Méthode USE

La méthode USE (Brendan Gregg) s'applique à chaque ressource du système :

Lettre Mesure Question
U — Utilization Pourcentage de temps occupe Quel pourcentage de CPU/mémoire/disque est utilisé ?
S — Saturation File d'attente Y a-t-il du travail en attente ? (queue depth, swap)
E — Errors Taux d'erreurs Des erreurs se produisent-elles ? (ECC, disk errors)
# USE pour le CPU d'un noeud
# Utilization
avg by(instance) (rate(node_cpu_seconds_total{mode!="idle"}[5m])) * 100

# Saturation (load average normalise)
node_load1 / count by(instance) (node_cpu_seconds_total{mode="idle"})

# Errors
rate(node_cpu_guest_seconds_total[5m])

Méthode RED

La méthode RED (Tom Wilkie) s'applique à chaque service :

Lettre Mesure Question
R — Rate Requêtes par seconde Combien de requêtes le service traite-t-il ?
E — Errors Taux d'erreurs Quel pourcentage de requêtes échouent ?
D — Duration Latence Combien de temps prend chaque requête ?
# RED pour un service HTTP
# Rate
sum(rate(http_requests_total{service="catalog"}[5m]))

# Errors
sum(rate(http_requests_total{service="catalog", status=~"5.."}[5m]))
/
sum(rate(http_requests_total{service="catalog"}[5m]))

# Duration (p99)
histogram_quantile(0.99,
  sum by(le) (rate(http_request_duration_seconds_bucket{service="catalog"}[5m]))
)

USE vs RED

USE pour les ressources infrastructure (CPU, mémoire, disque, réseau). RED pour les services applicatifs. Les deux méthodes sont complementaires.

SLI, SLO, SLA

Concept Définition Exemple
SLI (Service Level Indicator) Metrique mesuree Pourcentage de requêtes < 200ms
SLO (Service Level Objective) Objectif interne 99.9% des requêtes < 200ms sur 30 jours
SLA (Service Level Agreement) Engagement contractuel 99.5% de disponibilité, pénalités financieres

La relation : SLI alimente le SLO, le SLO est plus strict que le SLA pour conserver une marge.

# SLI : pourcentage de requetes reussies en moins de 200ms
sum(rate(http_request_duration_seconds_bucket{le="0.2", status!~"5.."}[30d]))
/
sum(rate(http_requests_total[30d]))

Lien avec Exploitation

Pour une mise en œuvre operationnelle des SLI/SLO et de l'alerting, voir le tutoriel Exploitation > Superviser et alerter qui detaille les stratégies d'alerte basées sur le burn rate et l'error budget.

OpenTelemetry

OpenTelemetry (OTel) est le standard CNCF pour la collecte de telemetrie. Il unifie la collecte des 3 piliers :

graph TD
    subgraph App["Application"]
        M["OTel SDK (metrics)"]
        L["OTel SDK (logs)"]
        T["OTel SDK (traces)"]
    end
    M --> Collector["OTel Collector<br/>(ou Alloy)"]
    L --> Collector
    T --> Collector
    Collector --> Mimir["Mimir (metriques)"]
    Collector --> Loki["Loki (logs)"]
    Collector --> Tempo["Tempo (traces)"]

Avantages d'OpenTelemetry

  • Vendeur-neutre : instrumenter une fois, envoyer vers n'importe quel backend
  • Auto-instrumentation : bibliotheques pour Java, Python, Go, Node.js, .NET
  • Propagation de contexte : trace_id propage automatiquement entre les services
  • Standard CNCF : adoption massive, pérennité assuree

Structured logging

Les logs doivent suivre un schema structure coherent entre tous les services :

{
  "timestamp": "2026-04-16T14:23:45.123Z",
  "level": "info",
  "service": "catalog-api",
  "version": "1.4.2",
  "trace_id": "abc123def456",
  "span_id": "789ghi",
  "message": "requete traitee",
  "http.method": "GET",
  "http.path": "/api/v1/products",
  "http.status_code": 200,
  "duration_ms": 42
}

Champs obligatoires

Chaque log doit contenir au minimum : timestamp, level, service, message. Pour les services HTTP, ajouter trace_id, http.method, http.status_code, duration_ms.