RousselTMLEARNING

Observabilité

Corréler traces, logs, métriques et profils dans Grafana

Relier Tempo aux logs (Loki), aux métriques (Prometheus) et aux profils (Pyroscope) : tracesToLogs, tracesToMetrics, exemplars, derived fields et provisioning.

1. Pourquoi corréler ? #

Réduire le temps de diagnostic.

Le parcours type #

Une alerte signale un taux d'erreurs élevé. Vous ouvrez le graphe de métriques, cliquez sur un exemplar pour voir une trace lente, puis sur le span fautif pour afficher les logs du même pod au même instant, enfin le profil CPU qui explique le goulot. Tout cela suppose des liens configurés et des labels cohérents.

Corrélation des signaux autour du TraceID
Le TraceID est présent dans les logs ; les labels (service, namespace) alignent logs et métriques.

2. Provisionner la source Tempo #

Les liens vers les autres signaux.

datasource.yml #

apiVersion: 1
datasources:
  - name: Tempo
    type: tempo
    uid: tempo
    url: http://tempo:3200
    jsonData:
      tracesToLogsV2:
        datasourceUid: loki
        spanStartTimeShift: "-5m"
        spanEndTimeShift: "5m"
        filterByTraceID: true
        filterBySpanID: false
        tags:
          - { key: service.name, value: app }
          - { key: k8s.namespace.name, value: namespace }
      tracesToMetrics:
        datasourceUid: prometheus
        tags: [{ key: service.name, value: service }]
        queries:
          - name: Taux de requêtes
            query: sum(rate(traces_spanmetrics_calls_total{$$__tags}[5m]))
      tracesToProfiles:
        datasourceUid: pyroscope
        tags: [{ key: service.name, value: service_name }]
        profileTypeId: "process_cpu:cpu:nanoseconds:cpu:nanoseconds"
      serviceMap: { datasourceUid: prometheus }
      nodeGraph: { enabled: true }
À savoir : La clé de gauche (service.name) est l'attribut de span ; la valeur (app) est le label Loki utilisé pour filtrer les logs : adaptez-la à vos labels.

3. Du log à la trace : derived fields #

Cliquer sur un TraceID dans un log.

Source Loki #

- name: Loki
  type: loki
  uid: loki
  url: http://loki:3100
  jsonData:
    derivedFields:
      - name: TraceID
        matcherRegex: '"trace_id":"(\\w+)"'
        url: '$${__value.raw}'
        datasourceUid: tempo
        urlDisplayLabel: Voir la trace
# Les logs doivent contenir le TraceID : exemple avec un logger Python
import logging
from opentelemetry import trace
ctx = trace.get_current_span().get_span_context()
logging.info("paiement refusé", extra={"trace_id": format(ctx.trace_id, "032x")})
Bonne Pratique : Avec l'auto-instrumentation OpenTelemetry (OTEL_PYTHON_LOG_CORRELATION=true), le TraceID et le SpanID sont ajoutés automatiquement aux logs.

4. Vérifier la cohérence #

Les labels doivent s'aligner.

Checklist #

  • Le même service.name (traces) ↔ app/service (logs, métriques).
  • Les exemplars activés côté Prometheus (--enable-feature=exemplar-storage) et côté application.
  • Les horloges synchronisées (NTP) : un décalage fausse la fenêtre de temps des liens.
  • Le TraceID écrit dans les logs au format hexadécimal sur 32 caractères.
# Vérifier la présence du TraceID dans les logs
logcli query '{app="checkout"} |= "trace_id"' --since=10m --limit=3
# Vérifier les exemplars exposés par l'application
curl -s -H 'Accept: application/openmetrics-text' http://app:8080/metrics | grep -m3 'trace_id'

Articles liés

Grafana Tempo : le backend de traces distribuées à grande échelle

Comprendre le tracing distribué et Grafana Tempo : traces, spans, TraceID, architecture (distributor, ingeste…

Installer Grafana Tempo (Docker Compose, binaire et Helm)

Installer Grafana Tempo : configuration tempo.yaml, Docker Compose avec Grafana et Prometheus, ports OTLP, vé…

Envoyer des traces vers Tempo : instrumentation OpenTelemetry et Alloy

Produire et acheminer des traces vers Tempo : auto-instrumentation Python/Java/Node, SDK manuel, variables d'…

Pour aller plus loin