RousselTMLEARNING

Observabilité

Étude de cas : le RUM minimal de ce site, sans cookie, exposé à Prometheus

Comment ce site mesure ses Core Web Vitals avec une quarantaine de lignes de JavaScript, une balise anonyme, des histogrammes Redis et un point /metrics pour Prometheus, et quand passer à Faro.

1. Le besoin #

Mesurer, sans traceur ni cookie.

Contraintes #

Ce site voulait connaître ses Core Web Vitals réels sans cookie, sans identifiant et sans service tiers, pour ne pas avoir besoin de consentement pour cette mesure. Le choix : une mesure minimale, agrégée côté serveur, et exposée à Prometheus.

Chaîne RUM du site
Aucune donnée individuelle n'est conservée : seules des agrégations par type de page.

2. Côté navigateur #

PerformanceObserver et sendBeacon.

Le script #

Le script observe les entrées de performance du navigateur, garde la dernière valeur de chaque indicateur, et envoie une seule balise quand la page passe en arrière-plan :

var m = {};
new PerformanceObserver(function (list) {
  list.getEntries().forEach(function (e) { m.lcp = Math.round(e.startTime); });
}).observe({ type: 'largest-contentful-paint', buffered: true });
// ... idem pour paint (FCP), layout-shift (CLS), event (INP), navigation (TTFB)

document.addEventListener('visibilitychange', function () {
  if (document.visibilityState === 'hidden') {
    navigator.sendBeacon('/rum.php', new Blob([JSON.stringify({ p: pageType(), m: m })], { type: 'application/json' }));
  }
});
Bonne Pratique : sendBeacon est fiable même quand l'utilisateur ferme l'onglet, contrairement à un fetch classique. Le type de page (accueil, article, leçon...) remplace l'URL : aucune donnée de navigation individuelle.

3. Côté serveur #

Des histogrammes pour Prometheus.

Agrégation et exposition #

Le point d'entrée valide la balise (types et bornes), puis incrémente des compteurs d'histogramme dans Redis (un compteur par seau de durée, par indicateur et par type de page). /metrics les expose au format Prometheus :

rtm_rum_lcp_bucket{page="article",le="2500"} 1834
rtm_rum_lcp_bucket{page="article",le="4000"} 1977
rtm_rum_lcp_bucket{page="article",le="+Inf"} 2010
rtm_rum_lcp_count{page="article"} 2010
# LCP au 75e percentile par type de page
histogram_quantile(0.75, sum by (le, page) (rate(rtm_rum_lcp_bucket[1h])))
À savoir : Les seaux suivent les seuils des Core Web Vitals (par exemple 2 500 et 4 000 ms pour le LCP). Le CLS, sans unité, est multiplié par 1 000 pour être stocké en entier : un seuil de 0,1 devient 100.

Faro ou RUM minimal ? #

BesoinRUM minimalFaro
Web Vitals agrégésOuiOui
Erreurs JavaScript avec pileNonOui
Sessions, événements métierNonOui
Traces front vers backNonOui
Aucune donnée individuelleOuiConfigurable
Composants à exploiterAucun nouveauAlloy, Loki, Tempo

Pour un site de contenu, le RUM minimal suffit. Pour une application (tunnel d'achat, espace client), Faro apporte le diagnostic des erreurs et la corrélation avec le back-end.

Articles liés

Monitoring de site web : disponibilité, surveillance HTTPS, certificats et performances

Mettre en place le monitoring d'un site web : surveillance de la disponibilité et du HTTPS, expiration des ce…

Real User Monitoring (RUM) et Core Web Vitals : mesurer ce que vivent les utilisateurs

Pourquoi observer le front-end, ce que mesure le RUM, les Core Web Vitals (LCP, INP, CLS) et leurs seuils, et…

Grafana Faro : architecture et installation

Installer Grafana Faro : le SDK web (npm ou CDN), le récepteur faro.receiver d'Alloy, l'envoi vers Loki et Te…

Pour aller plus loin