RousselTMLEARNING

Observabilité

Faro et Alloy : recevoir le RUM front-end avec faro.receiver

Configurer faro.receiver : CORS, clé d'API, limite de débit, source maps, puis envoyer erreurs, Web Vitals et traces du navigateur vers Loki et Tempo. Résultats réels.

1. Le rôle de faro.receiver #

Le pont entre navigateur et backend.

Le principe #

Le SDK Grafana Faro collecte dans le navigateur les erreurs JavaScript, les événements, les Core Web Vitals et les traces des appels réseau. Il les envoie en HTTP à faro.receiver, qui écoute par défaut sur le port 12347 et transforme chaque élément en ligne de log (vers Loki) ou en span (vers Tempo).

Du SDK Faro à Loki et Tempo en passant par faro.receiver

2. Une configuration prête pour la production #

Sécuriser un point d’entrée public.

config.alloy #

faro.receiver "frontend" {
  server {
    listen_address       = "0.0.0.0"
    listen_port          = 12347
    cors_allowed_origins = ["https://shop.example.com"]
    api_key              = sys.env("FARO_API_KEY")

    rate_limiting {
      strategy = "per_app"
      rate     = 50
    }
  }

  sourcemaps {
    download = false
    location {
      path                 = "/srv/sourcemaps/{{ .Release }}"
      minified_path_prefix = "https://shop.example.com/assets/"
    }
  }

  extra_log_labels = {service_name = "shop-frontend"}

  output {
    logs   = [loki.write.default.receiver]
    traces = [otelcol.exporter.otlp.tempo.input]
  }
}

loki.write "default" {
  endpoint {
    url = "http://loki:3100/loki/api/v1/push"
  }
}

otelcol.exporter.otlp "tempo" {
  client {
    endpoint = "tempo:4317"
    tls {
      insecure = true
    }
  }
}

Configuration validée avec alloy validate (Alloy v1.21.3, novembre 2026).

Les réglages qui comptent #

RéglageDéfautPourquoi le changer
listen_address127.0.0.1Le navigateur doit joindre le récepteur : écoutez sur 0.0.0.0 derrière un proxy TLS.
cors_allowed_originsvide (CORS désactivé)Listez vos domaines ; ["*"] accepte n’importe quel site.
api_keyvideExige l’en-tête X-API-Key ; sinon HTTP 401.
rate_limiting50 req/s, rafale 100, globalper_app isole chaque application et environnement ; au-delà, HTTP 429.
sourcemaps.downloadtrueLe récepteur télécharge les source maps depuis l’URL envoyée par le client : désactivez-le pour un trafic non maîtrisé et servez-les depuis le disque.
max_allowed_payload_size5MiBLimite la taille d’une requête.
Origine, clé puis débit : les trois contrôles avant acceptation
Ne laissez pas download = true sur un récepteur public : n'importe quel client pourrait faire télécharger à Alloy l'URL de son choix.

3. Ce que reçoit Alloy : un test réel #

Payload, réponses, lignes produites.

Les réponses HTTP #

Nous avons envoyé un payload Faro (un log, un événement, des Web Vitals, une exception et une trace) à Alloy, avec loki.echo et otelcol.exporter.debug pour afficher le résultat :

curl -X POST http://127.0.0.1:12347/collect -H 'Content-Type: application/json' --data @payload.json
# → 401 (clé absente)
curl -X POST http://127.0.0.1:12347/collect -H 'X-API-Key: secret-demo' -H 'Origin: http://127.0.0.1:8099' --data @payload.json
# → HTTP/1.1 202 Accepted
#   Access-Control-Allow-Origin: http://127.0.0.1:8099

Les lignes envoyées à Loki #

Chaque élément devient une ligne logfmt avec un champ kind et le contexte de l'application, de la session, de la page et du navigateur (extrait) :

labels={service_name="shop-frontend"}
kind=log message="panier validé" level=info app_name=shop-frontend app_version=1.4.2 app_environment=production session_id=s-7f3a page_url=https://shop.example.com/checkout browser_name=Firefox
kind=event event_name=checkout_step event_domain=shop event_data_step=payment …
kind=measurement type=web-vitals cls=0.040000 inp=180.000000 lcp=2310.000000 …
kind=exception type=TypeError value="Cannot read properties of undefined (reading 'price')" stacktrace="TypeError: …\n  at computeTotal (https://shop.example.com/assets/app.min.js:1:4821)" …

La trace arrive dans Tempo comme span OpenTelemetry : HTTP POST /api/orders, service.name=shop-frontend, scope @grafana/faro-web-tracing. Dans Loki, filtrez les erreurs :

{service_name="shop-frontend"} | logfmt | kind="exception"
quantile_over_time(0.75, {service_name="shop-frontend"} | logfmt | kind="measurement" | unwrap lcp [5m])

Sources #

Articles liés

Alloy et l'écosystème Grafana Labs : quel composant pour quel outil ?

La carte des intégrations d'Alloy avec Faro, Beyla, k6, Loki, Mimir, Tempo, Pyroscope, Database Observability…

Beyla et Alloy : métriques RED et traces sans code avec beyla.ebpf

Activer l'instrumentation eBPF de Beyla dans Alloy : découverte des services, métriques RED vers Mimir, trace…

Database Observability : suivre requêtes et plans MySQL et PostgreSQL avec Alloy

Les composants database_observability.mysql et .postgres d'Alloy : collecteurs, plans d'exécution, verrous, e…

Pour aller plus loin

Soutenir

♥ SOUTENIR

Soutenez RousselTM Learning

Les formations, articles, TP et attestations restent gratuits et sans publicité intrusive. Une contribution libre, du montant de votre choix, finance l’hébergement, les environnements de TP et l’écriture de nouveaux contenus.

Contribuer avec PayPal Montant libre · carte bancaire ou compte PayPalEn savoir plus
QR code PayPal
Ou scannez ce QR code avec votre téléphone

Merci, chaque contribution compte !