Aller au contenu
medium

Gouvernance de l'observabilité : coûts, rétention et sécurité

28 min de lecture

Collecter des traces, des métriques et des logs, c’est essentiel. Mais sans gouvernance, les volumes explosent, les coûts deviennent incontrôlables, et des données sensibles finissent dans des dashboards accessibles à tous. La gouvernance de l’observabilité, c’est l’ensemble des règles qui répondent à quatre questions : combien de temps garder les données, combien ça coûte, qui voit quoi, et comment on nomme les choses. Ce guide vous donne les leviers concrets pour construire un système d’observabilité durable et maîtrisé.

  • Les coûts réels : pourquoi l’observabilité coûte cher et la formule pour l’estimer
  • La rétention : combien de temps garder métriques, logs et traces — et pourquoi c’est différent pour chaque signal
  • Les politiques par environnement : ce qui change entre dev, staging et production
  • La cardinalité : comment une mauvaise combinaison de labels peut faire exploser votre base Prometheus — et comment la budgétiser
  • La sécurité des données : PII, secrets, RGPD — ce qui ne doit jamais se retrouver dans vos pipelines, avec des exemples de masquage
  • L’accès et le multi-tenant : RBAC, organisations, datasources — qui voit quoi dans Grafana
  • Les conventions d’équipe : nommage des métriques, niveaux de log, labels obligatoires — le socle commun qui évite le chaos
  • Le RACI : qui décide quoi en matière de gouvernance

L’observabilité suit une loi simple : plus vous collectez, plus longtemps vous conservez, plus souvent vous interrogez — plus ça coûte. Et les volumes croissent naturellement avec l’infrastructure : chaque nouveau service, chaque nouveau pod, chaque nouveau label génère des données supplémentaires.

Le coût de votre observabilité est le produit de trois facteurs :

Volume × Rétention × Requêtage = Coût

  • Volume : la quantité de données ingérées par jour (Go de logs, nombre de séries temporelles, nombre de spans)
  • Rétention : la durée de conservation (7 jours, 30 jours, 1 an)
  • Requêtage : la fréquence et la complexité des requêtes sur ces données

Le requêtage est le facteur le moins visible mais souvent le plus coûteux dans les systèmes managés. Trois exemples concrets :

  • Alerting toutes les 30 secondes : chaque règle d’alerte évalue une requête à chaque intervalle — 50 règles à 30 s = 144 000 requêtes/jour
  • Dashboards surchargés : un dashboard avec 50 panneaux, ouvert par 10 personnes, auto-rafraîchi toutes les 15 s, génère des milliers de requêtes par heure
  • Range queries non bornées : une requête PromQL sur 30 jours de données avec une résolution fine (step 15 s) charge des millions de points en mémoire

Chacun de ces trois facteurs est un levier d’optimisation. Réduire la rétention de 30 à 15 jours divise le stockage par deux. Passer le scrape interval de 15 à 30 secondes divise le volume de métriques par deux. Filtrer les logs DEBUG en production réduit le volume de 50 à 80 %.

Les trois signaux n’ont pas les mêmes profils de coût :

SignalVolume relatifCoût principalLevier d’optimisation
LogsLe plus volumineux (1-10 Go/jour par application sous trafic)Stockage + indexationFiltrage (niveaux, sampling), rétention courte
MétriquesCompact individuellement, mais la cardinalité (nombre de séries) fait toutMémoire + stockage TSDBContrôle des labels, agrégation, relabeling
TracesVariable (dépend du sampling)Stockage + indexation (span par span)Taux de sampling (head-based ou tail-based)

La rétention est le levier le plus direct sur les coûts. Mais toutes les données n’ont pas la même durée de vie utile. La règle : garder longtemps ce qui sert au capacity planning, garder court ce qui sert au diagnostic.

SignalRétention courte (diagnostic)Rétention longue (tendance)Pourquoi cette différence
Métriques15 jours (résolution complète)1-2 ans (agrégées / downsampled)Le diagnostic nécessite la résolution fine ; les tendances long terme acceptent un point par heure
Logs7-30 jours selon le niveau90 jours pour WARN/ERROR (audit)Un log DEBUG de la semaine dernière n’a plus de valeur ; un log ERROR peut être requis pour un audit
Traces7-15 joursRarement au-delà (volumétrie trop élevée)Les traces servent au diagnostic immédiat, pas à l’analyse historique

Le downsampling : garder les tendances sans le coût

Section intitulée « Le downsampling : garder les tendances sans le coût »

Pour les métriques, la technique du downsampling permet de conserver l’historique long terme à moindre coût. Le principe : au-delà d’un seuil (par exemple 15 jours), les points sont agrégés — au lieu d’un point toutes les 15 secondes, vous gardez un point par heure (min, max, moyenne).

Thanos implémente nativement le downsampling via sa compaction, avec trois niveaux de résolution (brute, 5 minutes, 1 heure). Pour les autres systèmes compatibles Prometheus (Cortex, Mimir), les mécanismes varient : Mimir utilise la compaction par blocs et les recording rules pour obtenir un résultat similaire, mais le terme “downsampling” n’est pas toujours employé de la même façon.

Résultat pratique : vous gardez 2 ans de tendances dans un espace de stockage comparable à 2 semaines de données brutes.

Pour les logs et les traces, le tiering de stockage complète le downsampling :

NiveauStockageAccèsUsage
HotSSD / stockage rapideMillisecondes7-15 derniers jours
WarmHDD / stockage standardSecondes15-90 jours
ColdObject storage (S3, MinIO)MinutesAu-delà de 90 jours (archive)

Le passage hot → warm → cold peut être automatisé (ILM dans Elasticsearch, rétention par blocs dans Loki/Tempo). Le stockage cold en object storage coûte typiquement 10× moins que le stockage hot.

Exemple de politique ILM type :

DonnéeHotWarmColdSuppression
Logs DEBUG3 jours3 jours
Logs INFO7 jours23 jours30 jours
Logs WARN/ERROR15 jours75 jours275 jours365 jours
Traces (sampled)7 jours8 jours15 jours
Métriques (brutes)15 jours15 jours (puis downsampled)
Métriques (downsampled)350 jours1 an+2 ans

La gouvernance n’est pas la même en développement et en production. Un environnement de dev a besoin de visibilité maximale pour le debugging, mais ne nécessite ni rétention longue ni protection PII stricte. La production, c’est l’inverse.

CritèreDevStagingProduction
Rétention logs3-7 jours7-15 jours15-90 jours (selon niveau)
Rétention métriques7 jours15 jours15 jours brut + downsampling long terme
Rétention traces3 jours7 jours7-15 jours
Niveaux de logDEBUG activéINFO + DEBUG cibléINFO minimum, WARN/ERROR pour diagnostic
Sampling traces100 % (tout tracer)50-100 %1-10 % (head-based) ou tail-based (erreurs)
Protection PIIOptionnelle (données fictives)Obligatoire (données proches prod)Stricte (masquage, audit, RGPD)
Accès (RBAC)Large (toute l’équipe Editor)Restreint (équipe + QA)Strict (Viewer par défaut, Editor ciblé)
AlertingDésactivé ou minimalActif (tests de seuils)Pleinement opérationnel

La cardinalité est le nombre total de séries temporelles distinctes dans votre base. Chaque combinaison unique de nom de métrique + labels crée une série distincte. C’est le facteur qui fait le plus souvent exploser les coûts et les performances des systèmes de métriques.

Prenons une métrique simple :

http_requests_total{method="GET", status="200", service="api"}

Trois labels, des valeurs bornées → quelques dizaines de séries. Ajoutez un label user_id avec 100 000 utilisateurs :

http_requests_total{method="GET", status="200", service="api", user_id="usr_12345"}

Vous passez de quelques dizaines à des centaines de milliers de séries. Multipliez par le nombre de méthodes HTTP, de codes de statut, de services, et le nombre de séries actives explose en produit cartésien :

Nombre de séries = valeurs_label₁ × valeurs_label₂ × … × valeurs_labelₙ

Avec 5 méthodes HTTP × 10 status codes × 20 services × 100 000 user_id, vous obtenez 100 millions de séries. C’est ingérable.

LabelPourquoi c’est dangereuxAlternative
user_idValeurs non bornées (croissance continue)Logger dans les traces, pas dans les métriques
request_idUnique par requête → autant de séries que de requêtesJamais dans un label de métrique
url_pathLes chemins dynamiques (/users/12345) créent autant de séries que d’utilisateursNormaliser : /users/:id
pod_nameChange à chaque redéploiementUtiliser deployment, namespace
timestampCrée une série par instantNe jamais utiliser comme label

Expliquer la cardinalité ne suffit pas — il faut un mécanisme contractuel pour la contrôler dans la durée. Le principe : chaque équipe ou service reçoit un budget de séries actives, avec des seuils d’alerte.

ParamètreSeuil recommandéAction si dépassé
Budget par service2 000 - 10 000 séries activesL’équipe doit justifier les labels ou en supprimer
Budget par métrique< 1 000 séries par nom de métriqueInvestigation : label non borné probable
Seuil d’alerte global80 % de la capacité PrometheusAlerte vers l’équipe plateforme
ArbitrageL’équipe plateforme/SRE arbitre la suppression d’un label si le budget est dépassé

Pour surveiller ces budgets, utilisez ces requêtes Prometheus :

# Nombre total de séries actives
count({__name__=~".+"})
# Top 10 des métriques par nombre de séries
topk(10, count by (__name__)({__name__=~".+"}))
# Séries par service (si le label existe)
count by (service)({__name__=~".+"})
  1. Mesurez avant d’agir

    Les requêtes ci-dessus vous donnent l’état actuel. Les métriques avec plus de 10 000 séries méritent une investigation.

  2. Appliquez le relabeling

    Le metric_relabel_configs de Prometheus permet de supprimer ou réécrire des labels avant l’ingestion. Exemple — supprimer les labels dangereux sur une métrique tierce :

    # prometheus.yml — scrape_configs
    scrape_configs:
    - job_name: "mon-service"
    metric_relabel_configs:
    # Supprimer le label user_id (cardinalité non bornée)
    - source_labels: [user_id]
    regex: ".+"
    action: labeldrop
    # Supprimer le label request_id
    - source_labels: [request_id]
    regex: ".+"
    action: labeldrop
    # Normaliser les chemins dynamiques
    - source_labels: [path]
    regex: "/users/[^/]+"
    target_label: path
    replacement: "/users/:id"
  3. Normalisez les chemins dynamiques

    Remplacez /users/12345/orders/67890 par /users/:id/orders/:id dans le label path — au niveau du SDK ou de l’instrumentation, pas dans Prometheus. Le relabeling ci-dessus est un filet de sécurité, pas la solution principale.

  4. Revoyez les labels à chaque ajout de métrique

    Avant d’ajouter un label, posez-vous la question : “combien de valeurs distinctes ce label peut-il avoir ?” Si la réponse est “non borné” ou “plus de 1 000”, il ne devrait probablement pas être un label de métrique.

Les données de télémétrie traversent des pipelines, sont stockées dans des bases partagées et affichées sur des dashboards accessibles à plusieurs équipes. Elles contiennent parfois — involontairement — des informations sensibles.

Type de donnéeExemplesRisqueObligation
PII (données personnelles)E-mail, nom, adresse IP, numéro de téléphoneNon-conformité RGPD, amendesMasquer ou pseudonymiser avant ingestion
SecretsTokens API, mots de passe, clés privéesCompromission du systèmeNe jamais logger — filtrer dans le collecteur
Headers d’authentificationAuthorization, CookieUsurpation de sessionExclure du champ http.request.header
Données financièresNuméro de carte, IBANViolation PCI-DSSMasquer (****1234) ou exclure
Données médicalesDiagnostics, prescriptionsViolation réglementaireExclure complètement

Le masquage doit intervenir le plus tôt possible dans le pipeline — avant le stockage, jamais après :

NiveauCommentAvantage
Au codeNe pas logger la donnée en premier lieuSolution la plus sûre
Dans le SDKProcessors OTel (redaction, transform)Masquage avant export
Dans le CollectorProcessor transform ou filterPoint central, indépendant du code
Dans l’ingestionPipeline Logstash, Loki pipeline stagesDernier filet de sécurité

Exemple : masquage dans le Collector OpenTelemetry

Section intitulée « Exemple : masquage dans le Collector OpenTelemetry »

Le processor transform du Collector permet de supprimer ou masquer des attributs sensibles avant l’export vers le backend :

otel-collector-config.yaml
processors:
transform:
trace_statements:
- context: span
statements:
# Supprimer le header Authorization des attributs
- delete_key(attributes, "http.request.header.authorization")
# Masquer l'email utilisateur (garder le domaine)
- replace_pattern(attributes["enduser.email"],
"^[^@]+", "****")
log_statements:
- context: log
statements:
# Supprimer les tokens qui auraient été loggés
- replace_pattern(body,
"Bearer [A-Za-z0-9\\-._~+/]+=*", "Bearer [REDACTED]")
# Masquer les adresses email dans le corps
- replace_pattern(body,
"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}",
"****@****.***")
service:
pipelines:
traces:
processors: [transform, batch]
logs:
processors: [transform, batch]
  • Audit régulier : recherchez les patterns sensibles dans vos logs et spans (regex sur e-mails, tokens, numéros de carte)
  • Tests de pipeline : envoyez des données de test contenant des PII et vérifiez qu’elles sont masquées en sortie
  • Séparation des environnements : les données de production ne doivent pas être accessibles depuis les environnements de développement
  • Rétention limitée : plus une donnée contenant des PII est conservée longtemps, plus le risque d’exposition augmente

Dans une organisation avec plusieurs équipes, chaque équipe ne devrait voir que les données qui la concernent. C’est le principe du multi-tenant : une seule infrastructure d’observabilité, mais des frontières de visibilité entre les équipes.

Grafana implémente un modèle de contrôle d’accès à trois niveaux, disponible dans toutes les éditions (OSS, Cloud, Enterprise) :

NiveauMécanismeCe qu’il contrôle
OrganisationsIsolation forte (instances séparées de datasources, dashboards, alertes)Séparation entre clients / business units
Teams + FoldersPermissions par dossier de dashboardsSéparation entre équipes dans une même organisation
Rôles (Viewer, Editor, Admin)Actions autorisées par utilisateur ou teamCréer, modifier, voir

En pratique :

  • Viewer : consulte les dashboards et explore les données — ne peut rien modifier
  • Editor : crée et modifie les dashboards, les alertes, les annotations
  • Admin : gère les datasources, les utilisateurs, les permissions

Le contrôle d’accès dans Grafana ne suffit pas si les backends eux-mêmes ne sont pas multi-tenant. Voici l’état de l’art :

BackendMulti-tenant natifMécanisme
Mimir (métriques)OuiHeader X-Scope-OrgID — isolation par tenant au stockage
Loki (logs)OuiHeader X-Scope-OrgID — même principe
Tempo (traces)OuiHeader X-Scope-OrgID
Prometheus (standalone)NonUn Prometheus par tenant, ou Mimir en frontal
ElasticsearchVia indices + sécuritéIndex par tenant + rôles Elasticsearch

Sans conventions partagées, chaque équipe invente son propre schéma de nommage, ses propres labels, ses propres niveaux de log. Le résultat : des dashboards incompatibles, des requêtes qui ne fonctionnent que pour un service, et une corrélation inter-services impossible.

Adoptez les conventions Prometheus/OpenMetrics :

RègleExemple correctExemple incorrect
snake_casehttp_request_duration_secondshttpRequestDuration
Unité dans le nom_seconds, _bytes, _total_ms, _kb, sans unité
Suffixe _total pour les countershttp_requests_totalhttp_requests
Suffixe _info pour les métadonnéesbuild_infobuild_metadata
Pas de type dans le nomhttp_request_duration_secondshttp_request_duration_seconds_histogram

Définissez un socle de labels que tous les services doivent exposer :

Label PrometheusAttribut OTel (Semantic Conventions)UsageExemple
serviceservice.nameIdentifie le composant émetteurpayment-api
environmentdeployment.environment.nameDistingue prod/staging/devproduction
versionservice.versionIdentifie la version déployée2.3.1
namespacek8s.namespace.nameScope Kubernetes / organisationnelcheckout

Si vous utilisez OpenTelemetry, mappez ces attributs vers les labels Prometheus dans le Collector via le processor resource ou directement dans l’exporteur Prometheus.

Imposez une grille unique à tous les services :

NiveauSignificationAlerte ?
DEBUGDétails de développement, désactivé en productionNon
INFOÉvénement normal attenduNon
WARNSituation anormale mais non bloquanteMonitoring
ERRORÉchec d’une opération, intervention nécessaireOui
FATALProcessus irrécupérable, va s’arrêterOui (immédiat)

Règle clé : un ERROR doit toujours être actionnable — si personne ne doit agir, c’est un WARN. Si trop d’ERROR arrivent sans action, le niveau est mal calibré et crée du bruit qui masque les vrais problèmes.

Les conventions ne servent que si elles sont écrites, versionnées et accessibles :

  1. Créez un document de référence

    Un fichier OBSERVABILITY-CONVENTIONS.md dans votre repo principal, décrivant les labels obligatoires, les conventions de nommage, les niveaux de log, et les règles de rétention.

  2. Automatisez la validation

    Utilisez des linters ou des règles de relabeling dans le Collector pour rejeter les métriques qui ne respectent pas les conventions (label manquant, format incorrect).

  3. Revoyez lors des design reviews

    Chaque nouveau service devrait passer par une checklist d’observabilité avant le déploiement : métriques exposées, labels conformes, niveaux de log calibrés.

  4. Mesurez la conformité

    Créez un dashboard “health de l’observabilité” qui montre le pourcentage de services conformes, le nombre de séries non étiquetées, le volume de logs par niveau.

La gouvernance, c’est aussi qui décide quoi. Sans clarification des responsabilités, les conventions restent des vœux pieux.

ActivitéPlateforme / SREÉquipes devSécurité / Compliance
Politiques de rétentionR (définit et applique)C (consulté sur besoins)A (valide conformité RGPD)
Quotas / budgets cardinalitéR (définit les seuils)I (informé)
Pipeline CollectorR (déploie et maintient)C (remonte les besoins)A (valide masquage PII)
Instrumentation (métriques, logs)C (revue de conformité)R (implémente)
Labels et conventions de nommageR (définit les standards)R (les applique dans le code)
RBAC / accès GrafanaR (gère les rôles)I (reçoit les accès)A (audit)
Masquage PII dans le pipelineR (implémente les processors)C (signale les champs sensibles)A (valide, audite)
Alerting (création de règles)C (revue impact perf)R (crée les alertes métier)
Audit et conformitéI (fournit les données)I (répond aux questions)R (exécute les audits)

Légende : R = Responsable (fait), A = Accountable (valide/approuve), C = Consulté, I = Informé.

PiègeConséquenceSolution
Pas de politique de rétentionCroissance linéaire des coûts sans valeur ajoutéeDéfinir des durées par signal et par niveau de sévérité
Labels non bornés dans les métriquesExplosion de cardinalité → OOM PrometheusPas de user_id, request_id, url_path dynamique dans les labels
Données personnelles dans les logs/tracesNon-conformité RGPD, risque juridiqueMasquer au plus tôt (code > SDK > Collector)
Tout le monde Admin dans GrafanaModifications accidentelles, pas de traçabilitéViewer par défaut, Editor par équipe, Admin limité
Conventions non documentéesChaque équipe invente son schéma, corrélation impossibleFichier de conventions versionné + linter automatisé
Rétention identique pour tous les signauxGaspillage (traces gardées 90 jours) ou frustration (métriques supprimées à 7 jours)Adapter la rétention au cycle de vie de chaque signal
Pas de budget cardinalitéDécouverte de l’explosion au moment de l’OOMSeuils par service, alertes à 80 %, revue lors des design reviews
Pipeline de masquage non testéFausse confiance, PII stockées quand mêmeTests avec données fictives contenant des patterns sensibles
Même gouvernance pour tous les environnementsTrop restrictif en dev (freine le debug), trop permissif en prod (risque PII)Politiques différenciées dev/staging/prod
  1. Le coût de l’observabilité suit la formule Volume × Rétention × Requêtage — agir sur chaque facteur a un impact direct

  2. La rétention doit être adaptée au signal : 15 jours de résolution fine pour les métriques, 7-30 jours pour les logs, 7-15 jours pour les traces — avec du downsampling ou du tiering pour le long terme

  3. Les politiques varient par environnement : DEBUG et 100 % de traces en dev, rétention calibrée et masquage PII strict en production

  4. La cardinalité est le piège n°1 des métriques : un seul label à valeurs non bornées peut provoquer un OOM — budgétisez les séries par service

  5. Les données sensibles (PII, secrets, tokens) doivent être masquées le plus tôt possible dans le pipeline — le Collector OTel est le point central pour ça

  6. Le RBAC et le multi-tenant garantissent que chaque équipe voit uniquement ses données — le header X-Scope-OrgID est le standard dans l’écosystème Grafana, injecté par la gateway, jamais par le client

  7. Les conventions d’équipe (nommage, labels, niveaux de log) sont le socle invisible qui rend tout le reste possible — documentez-les, automatisez leur validation

  8. La gouvernance a besoin d’un RACI clair : l’équipe plateforme définit les politiques, les devs instrumentent, la sécurité audite

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.