Data & IA

Data observability : vérifier la fraîcheur avant le dashboard

Un chargement récent peut masquer un lot incomplet. Distinguez date métier, ingestion et couverture pour contrôler un dashboard avant son utilisation.

Miljan Stojiljkovic
2 Novembre 2026
9 min
nympharaidataobservabilitequalitebi

À 9 h, le dashboard des ventes affiche un total rassurant. Le chargement s’est terminé à 8 h 55. Pourtant, un magasin manque dans les données du dimanche. Le traitement a bien fonctionné sur ce qu’il a reçu ; il n’a pas prouvé qu’il avait reçu tout ce qui était attendu.

Pour contrôler la fraîcheur des données, il faut préciser jusqu’à quelle période et pour quel périmètre elles doivent être disponibles. La date du dernier chargement ne répond pas à cette question. Elle devient utile lorsqu’on la rapproche d’une échéance métier et d’une preuve de couverture.

Cet article propose une méthode de data observability, ou observabilité des données, appliquée à un dashboard quotidien. Un atelier Python local montre huit situations, dont un rejeu ancien qui paraît récent et un magasin sans vente dont le lot est pourtant complet. Il s’agit de données fictives exécutées localement, sans essai d’un outil BI ni d’une plateforme d’observabilité.

Un dashboard relié à trois lots de données, dont un incomplet. Texte : Données fraîches ? Vérifier le lot complet.

Trois dates qui ne répondent pas à la même question

Une vente possède une date métier : le moment où elle s’est produite. Elle possède aussi une date d’arrivée dans l’entrepôt. Enfin, le pipeline peut publier une borne de couverture : la période qu’il déclare avoir entièrement traitée.

Signal Ce qu’il permet d’observer Ce qu’il ne garantit pas
Dernier événement métier La date la plus récente présente dans les lignes La présence des autres magasins ou des ventes plus anciennes
Dernière ingestion L’arrivée récente d’au moins une ligne La nouveauté de cette ligne, ni la complétude du lot
Borne de couverture par magasin La période déclarée complète par le producteur La qualité de cette déclaration, ni l’exactitude des montants
Actualisation du dashboard La génération récente d’un affichage ou d’un snapshot L’utilisation des bons lots de données

Cette séparation entre temps de l’événement et temps de traitement existe aussi dans les systèmes de streaming. Le guide Apache Beam décrit notamment les données retardataires et les watermarks. Dans notre cas batch, la borne de couverture est un contrat explicite du producteur ; ce n’est pas une garantie automatiquement fournie par une horloge.

Une vente du samedi réinjectée le lundi donne une ingestion récente, tout en laissant les ventes du dimanche manquantes. Inversement, un magasin fermé le dimanche peut ne produire aucun événement récent sans être en panne. Il faut une preuve que l’extraction a été faite et que le résultat vide est attendu.

Partir de la décision commerciale, pas du seuil technique

Prenons une enseigne fictive avec trois magasins : Lille, Lyon et Nantes. Son équipe commerciale utilise à 9 h les ventes de la veille pour préparer les réapprovisionnements. Le contrat retenu pour l’exercice est le suivant :

  • Les trois magasins sont attendus, y compris lorsque l’un déclare zéro vente.
  • Le lot du dimanche couvre la période jusqu’au lundi à minuit, borne exclusive, en Europe/Paris.
  • À partir de 8 h 30, un lot absent ou incomplet doit déclencher une alerte ; à 9 h, le dashboard doit contenir les trois lots.
  • À 9 h, son snapshot doit avoir moins de 15 minutes.

Ces horaires sont des hypothèses pédagogiques. Pour un reporting hebdomadaire ou une caisse qui ferme à une autre heure, il faut les changer. Le lundi après un dimanche fermé et un jour férié demandent aussi un calendrier explicite. Un seuil « moins de 24 heures » ne sait pas décider seul quelle journée devait être livrée.

Le choix du fuseau compte. Le 2 novembre 2026 à minuit Paris correspond au 1er novembre à 23 h UTC. Stocker une chaîne sans fuseau puis la lire comme de l’UTC peut déplacer la période contrôlée. L’atelier utilise des instants avec décalage et le fuseau Europe/Paris ; il refuse un horodatage sans fuseau.

Pourquoi un maximum récent laisse passer un magasin absent

Supposons que Lille et Lyon soient complets. Une ligne de Lille est arrivée à 8 h 55. Nantes n’a pas livré son lot.

Une requête qui demande seulement max(ingested_at) renvoie 8 h 55. À 9 h, un seuil de 30 minutes passe. Un max(event_at) global peut également passer grâce à une vente tardive de Lyon. Aucun de ces résultats ne prouve que Nantes est couvert.

La première correction consiste à contrôler le périmètre attendu avant de calculer un âge. Une liste des magasins extraite uniquement des lignes reçues échoue aussi : le magasin manquant n’y apparaît jamais. Il faut une liste de référence indépendante, puis une jointure qui conserve les absents.

Le même défaut existe avec des pays, des comptes publicitaires ou des partitions horaires. La bonne granularité correspond à ce qui peut manquer sans interrompre le traitement global. Si un canal peut disparaître seul, un maximum calculé sur tous les canaux masque ce risque.

Ajouter une preuve de lot, puis vérifier sa propagation

Dans l’exercice, chaque magasin publie un manifeste contenant cinq éléments : identifiant de lot, magasin, période couverte, état complet et nombre de lignes attendu. Le contrôle rapproche ce manifeste des lignes réellement reçues.

Le nombre attendu doit venir d’une réconciliation avec la source. Compter les lignes dans la table cible et recopier ce nombre dans le manifeste ne permettrait pas de détecter une perte pendant le transfert. Pour un magasin sans vente, le producteur doit confirmer un lot complet de zéro ligne. L’absence de lot reste une absence de preuve.

Ce contrôle suppose que le manifeste est publié de manière cohérente avec les données. En production, il faut éviter qu’un état « complet » soit visible avant la fin du chargement : transaction commune lorsque c’est possible, ou publication d’une référence de lot validée après écriture. Les reprises doivent conserver des identifiants non ambigus. Deux lots concurrents pour la même période exigent une règle de sélection ; notre atelier les refuse plutôt que d’en choisir un arbitrairement.

Ensuite, il reste à suivre le lot jusqu’au dashboard. Une source complète n’implique pas qu’un modèle transformé ou un cache BI a été rafraîchi. Notre snapshot fictif déclare les identifiants des lots qu’il contient. C’est cette référence que le contrôle vérifie, en plus de l’heure de génération. Dans un outil réel, la preuve peut être une version de dataset, une partition matérialisée ou un journal de rafraîchissement relié au lot.

La décision devient lisible : au moment du contrôle, tous les magasins sont couverts, les comptes concordent, les bons lots atteignent le snapshot et celui-ci est suffisamment récent. ready décrit cette disponibilité actuelle. Il ne certifie pas que la livraison était déjà complète à 8 h 30. Pour mesurer le respect historique de cette heure, il faudrait conserver les heures de fin des lots ou les résultats successifs des contrôles.

Une alerte à 8 h 30 peut donc être suivie d’un retour à ready après une reprise à 8 h 55. Le retour au vert permet d’utiliser les données ; il n’efface pas l’incident de retard. Un nombre de lignes identique ne prouve toujours pas la justesse des montants ou l’absence de doublons. Ces vérifications relèvent d’autres contrôles de qualité.

Exécuter le contrôle et observer ses refus

Téléchargez le script Python et son mode d’emploi. Avec Python 3.9 ou plus récent et une base de fuseaux IANA installée :

python3 controle_fraicheur.py > resultat.json

L’instant est fixé au lundi 2 novembre à 9 h Paris pour rendre le résultat reproductible. Aucune clé, aucun package tiers et aucune connexion ne sont utilisés. Le script génère les données fictives, applique le contrôle puis vérifie les décisions attendues.

Situation exécutée Décision à 9 h Ce que le contrôle apprend
Trois lots complets et présents dans le snapshot ready Données disponibles à 9 h ; ponctualité à 8 h 30 non mesurée
Manifeste de Nantes absent not_ready Le maximum global des autres magasins ne suffit pas
Données de Nantes rejouées récemment, couverture ancienne not_ready Une arrivée récente ne remplace pas la période attendue
Nantes confirme un lot complet de zéro vente ready Zéro ligne et absence de livraison sont deux états différents
Deux lignes annoncées, une reçue pour Nantes not_ready La livraison ne correspond pas au manifeste
Bons lots, snapshot vieux d’une heure not_ready La chaîne BI reste trop ancienne
Horodatage d’événement dans le futur not_ready Une horloge incohérente peut tromper un maximum
Snapshot récent qui omet le lot de Nantes not_ready Rafraîchir l’affichage ne prouve pas sa couverture

La sortie JSON conserve les motifs et les deux maxima. Dans les scénarios « magasin absent » et « rejeu ancien », l’ingestion reste récente ; la décision échoue grâce à la preuve de lot. Le champ delivery_deadline_met reste null : aucune preuve de ponctualité historique n’est calculée. Deux contrôles supplémentaires vérifient l’état awaiting avant l’heure d’alerte sur une situation sans date future, et le refus des dates sans fuseau.

Pour adapter la méthode, commencez par remplacer les trois magasins et la borne fixe par votre périmètre attendu et votre calendrier métier. Branchez ensuite de vraies preuves de livraison. Ne déduisez pas la complétude de la seule réussite de ce script : ici, son producteur et son snapshot sont simulés.

Raccorder ce contrôle aux outils déjà présents

Si l’équipe utilise dbt, elle dispose de contrôles de fraîcheur avec seuils d’avertissement et d’erreur. La documentation actuelle distingue la commande dbt freshness de dbt v2, qui peut contrôler sources et modèles configurés, de dbt source freshness, conservée pour les sources. Il faut donc lire la version du projet avant de reprendre un exemple de configuration. Configuration freshness de dbt.

Le timestamp surveillé doit avoir un sens connu : arrivée d’une ligne, métadonnée du stockage ou expression dédiée. Même un contrôle correctement configuré reste limité par le signal qu’il interroge. S’il examine un maximum global, il ne reconstitue pas notre contrat par magasin.

La place du contrôle dans le job compte également. La documentation de la plateforme dbt précise que dbt build n’inclut pas automatiquement les contrôles de fraîcheur des sources. Elle distingue aussi la case de configuration qui exécute ce contrôle sans arrêter les étapes suivantes et une commande ajoutée comme étape dont l’échec interrompt la suite. Vérifiez le comportement applicable à votre environnement avant d’en faire un verrou de publication. Source freshness dans les jobs dbt.

Un ordonnanceur peut donc continuer de surveiller les exécutions, tandis qu’un contrôle de couverture décide si le dataset peut être consommé. Une plateforme d’observabilité plus large devient pertinente lorsque les dépendances, les périmètres et le diagnostic sont difficiles à maintenir. Son intérêt doit se mesurer sur les incidents détectés avant utilisation, les alertes actionnables et l’effort d’exploitation. L’atelier ne compare ni tarifs ni performances de ces plateformes.

Préparer la réaction avant d’activer l’alerte

Pour notre dashboard, un refus à 9 h conduit à conserver le dernier état validé en affichant sa période réelle, ou à suspendre la décision commerciale. Le choix dépend de l’usage. Une ancienne valeur clairement datée peut convenir à une tendance hebdomadaire ; elle peut être inacceptable pour un réapprovisionnement quotidien.

L’alerte doit nommer le magasin, la période attendue, la dernière preuve de couverture, l’état du snapshot et le responsable de la reprise. Après correction, rejouez le contrôle jusqu’au consommateur final, pas seulement jusqu’à la table source. Le guide de lineage aide à identifier ces consommateurs ; le guide de CI SQL traite les contrôles sur les transformations.

Commencez avec un seul indicateur utilisé à heure fixe. Faites tourner le contrôle en observation, relevez les faux refus et les absences réellement détectées, puis décidez avec le métier du comportement à adopter. Vous aurez alors un contrat testable : quelle période est disponible, pour quel périmètre, avec quelle preuve, avant quelle décision.

Ressource gratuite

Checklist Audit IA 90 jours pour PME

Cadrage des process, données, cas d'usage, garde-fous RGPD/AI Act, quick wins, roadmap : 6 blocs et 28 points de contrôle, utilisables en autonomie. Reçue par email, sans séquence commerciale derrière.

Recevoir la checklist

Appliquer cette méthode à vos process

Votre équipe Data & IA externalisée, de 2 à 5 jours par semaine. L'atelier de cadrage inclus produit votre feuille de route priorisée par impact.