CI5 : Monitoring et observabilité
Ce cinquième TP marque une étape clé du cours : jusqu’à présent, vous avez construit un système de machine learning fonctionnel et reproductible, capable d’ingérer des données, de calculer des features, d’entraîner un modèle et de servir des prédictions via une API. Dans ce TP, l’objectif est désormais de rendre ce système observable et de lui donner la capacité de détecter des dégradations silencieuses liées à l’évolution des données dans le temps.
Vous allez mettre en place une stack de monitoring complète autour de votre API de prédiction (Prometheus et Grafana), instrumenter le service pour exposer des métriques pertinentes, puis implémenter une détection de drift basée sur Evidently afin de comparer des données de référence et des données récentes. Enfin, vous connecterez cette détection à une logique de décision simulant un déclenchement de réentraînement.
Ce TP est volontairement pragmatique et orienté ingénierie : il ne s’agit pas d’optimiser un modèle, mais de comprendre comment observer un système ML en production, interpréter ses signaux, et poser les bases d’une automatisation robuste.
- Comprendre le rôle de l’observabilité dans un système de machine learning en production.
- Déployer et configurer une stack de monitoring avec Prometheus et Grafana.
- Instrumenter une API FastAPI pour exposer des métriques de trafic et de latence.
- Explorer et interpréter des métriques via l’interface Prometheus et des dashboards Grafana.
- Détecter un drift de données entre deux périodes à l’aide d’Evidently.
- Produire des artefacts de monitoring et de drift exploitables (rapports, métriques).
- Implémenter une logique de décision simulant un déclenchement de réentraînement basé sur le drift.
Démarrer la stack pour l'observabilité
Et en bas du fichier :
- services/grafana/provisioning/datasources/
- services/grafana/provisioning/dashboards/
- services/grafana/provisioning/dashboards/json/
- Lancez docker compose up -d
- Puis vérifiez avec docker compose ps
- Prometheus : http://localhost:9090
- Grafana : http://localhost:3000
- Un court transcript terminal montrant docker compose up -d et/ou docker compose ps.
- Une capture d’écran de la page d’accueil Prometheus.
- Une capture d’écran de l’écran de login ou d’accueil Grafana.
Instrumentation de FastAPI avec de métriques Prometheus
- Un compteur api_requests_total (Counter)
- Un histogramme api_request_latency_seconds (Histogram)
- Un endpoint HTTP /metrics qui renvoie le format Prometheus
Pour vous guider, copiez/collez le squelette ci-dessous dans votre fichier et complétez uniquement les zones marquées TODO et _____.
- Démarrez/re-démarrez l’API
- Exécutez curl http://localhost:8000/metrics
- Appelez /predict quelques fois et re-checkez /metrics
- api_requests_total augmente
- api_request_latency_seconds contient des lignes de buckets
- Une capture d’écran (ou un court extrait copié/collé) de /metrics montrant vos deux métriques et au moins une ligne.
- Une explication en 3–5 lignes : pourquoi un histogramme est plus utile qu’une simple moyenne de latence.
Exploration de Prometheus (Targets, Scrapes, PromQL)
- Allez dans le menu Status puis Targets.
- Repérez le job api (ou le nom défini dans prometheus.yml).
- Vérifiez que l’état est UP et que la dernière scrappe est récente.
- up
- api_requests_total
- rate(api_requests_total[5m])
Exécutez cette requête et observez comment elle évolue lorsque vous générez du trafic :
- rate(api_request_latency_seconds_sum[5m]) / rate(api_request_latency_seconds_count[5m])
Expliquez en une phrase ce que représente cette valeur.
- Une capture d’écran de la page Status → Targets montrant la target de l’API en UP.
- Une capture d’écran d’un graphe Prometheus correspondant à une requête PromQL (par exemple rate(api_requests_total[5m])).
Setup de Grafana Setup et création d'un dashboard minimal
- Ouvrez Grafana : http://localhost:3000
- Allez dans Connections - Data sources (dans le menu à afficher à gauche).
- Ajoutez une datasource Prometheus qui pointe vers http://prometheus:9090.
- Créez un nouveau dashboard dans le menu Dashboards.
- Ajouter Prometheus comme source
- Ajoutez un panel de type Time series (en haut à droite).
- Utilisez une requête PromQL basée sur api_requests_total comme vue à l'exercice précédent. Vous devez la mettre dans le menu en bas à gauche, soit en utilisant le Builder, soit le code brut (à droite de "Run queries").
- Choisissez une fenêtre temporelle glissante (par exemple 5 minutes).
- Cliquez sur "Run queries" pour afficher la métrique.
- Donnez un nom à votre panel
- Cliquez sur Apply en haut à droite pour terminer voter panel
- Créez un nouveau panel (Add, Visualization) de type Time series.
- Utilisez une requête simple basée sur l’histogramme de latence.
- Observez comment la courbe évolue lorsque vous générez du trafic.
- Donnez un nom à votre panel
- Cliquez sur Apply
Une approximation de la latence moyenne est suffisante pour ce TP.
- Appelez l’endpoint /predict environ 50 à 100 fois.
- Regardez les courbes RPS et latence évoluer (vous pouvez rafraichir en haut à droite).
- Configurez un intervalle de rafraîchissement automatique (5s ou 10s en haut à droite).
- Une capture d’écran du dashboard Grafana avec un pic de trafic visible.
- Une capture d’écran de l’éditeur de requête d’un panel.
- Un court texte (5–8 lignes) expliquant ce que ces métriques détectent bien, et ce qu’elles ne permettent pas de détecter (ex: qualité du modèle).
Drift Detection with Evidently (Month_000 vs Month_001)
Vous devez uniquement compléter les zones marquées TODO et _____. Le reste du code doit être recopié tel quel.
- Le script doit charger un dataset “final” (features + label si disponible) pour as_of_ref et as_of_cur.
- Il doit exécuter un rapport Evidently (HTML + JSON) et produire un signal scalaire drift_share.
- Il doit calculer un target drift simple si churn_label est présent.
- Le “réentraînement” doit être simulé : on affiche un message clair, sans lancer de pipeline training.
- Qu’un rapport HTML et un rapport JSON sont créés dans reports/monitoring).
- Que la ligne finale imprimée contient drift_share=... et une décision (RETRAINING_TRIGGERED ou NO_ACTION).
- Qu’il n’y a pas d’erreur de schéma (colonnes différentes entre ref et current).
- Une capture d’écran du rapport Evidently (HTML) ou d’une section clé montrant la comparaison ref vs current.
- Une réponse courte : différence entre covariate drift et target drift dans ce projet.
- Le copier/coller de la ligne de décision finale imprimée par le script.