Aller au contenu
Outils medium

Grafana Tempo : stocker et requêter des traces distribuées

12 min de lecture

Grafana Tempo est un backend open source qui stocke les traces distribuées de vos applications et les rend consultables depuis Grafana. Là où Jaeger ou Elasticsearch indexent chaque trace, Tempo n'indexe que le trace ID : le reste part directement dans un stockage objet (S3, GCS, MinIO). Résultat, un coût de stockage très bas, même à fort volume.

Ce guide s'adresse aux débutants et intermédiaires qui exploitent déjà Grafana et veulent y suivre une requête de service en service. Vous allez démarrer Tempo en local, lui envoyer des traces OTLP, les requêter en TraceQL et voir comment passer en production sur stockage objet.

  • Comprendre ce que Tempo résout et sa différence avec Jaeger ou Zipkin.
  • Démarrer Tempo en local avec Docker, puis sur Kubernetes avec Helm.
  • Envoyer des traces au format OTLP et vérifier l'ingestion.
  • Requêter vos traces avec le langage TraceQL.
  • Configurer un stockage objet S3 pour la production.

Une trace distribuée reconstitue le trajet complet d'une requête à travers vos microservices : le frontend appelle une API, qui interroge une base, qui contacte un service de paiement. Sans traçage, une requête lente reste un mystère. Avec Tempo, vous voyez quel service a consommé le temps et l'erreur est apparue.

Le pari de Tempo est radical : ne pas indexer le contenu des traces. Les moteurs classiques maintiennent des index coûteux en CPU et en disque ; Tempo s'en passe et écrit les blocs bruts dans un stockage objet bon marché. Ce choix explique son positionnement et ses quelques limites.

Problème courantRéponse de Tempo
Coût de stockage élevé de Jaeger ou ElasticsearchPas d'index, donc stockage objet peu cher
Intégration Grafana à câblerNatif Grafana, même éditeur
Formats de traces hétérogènesAccepte OTLP, Jaeger, Zipkin, OpenCensus
Corréler traces, logs et métriquesTraceQL plus liens vers Loki et Prometheus

Tempo se déploie de deux façons : en mode monolithique, un seul binaire pour le développement et les petits volumes, ou en mode microservices (chart tempo-distributed), où chaque rôle scale indépendamment en production. Comprendre les composants aide à lire les logs et à dimensionner le cluster.

ComposantRôle
DistributorReçoit les traces, les valide et les répartit vers les ingesters
IngesterBufferise puis écrit les traces dans le stockage objet
CompactorFusionne les blocs pour réduire leur nombre et le coût de lecture
QuerierExécute les requêtes TraceQL sur les blocs
Query FrontendMet en cache et parallélise les requêtes lourdes

En mode monolithique, ces cinq rôles tournent dans un même processus : c'est ce que vous lancez pour tester ci-dessous.

Le plus rapide pour découvrir Tempo est un conteneur unique avec un stockage sur disque local. On écrit d'abord une configuration minimale qui ouvre un récepteur OTLP (gRPC sur 4317, HTTP sur 4318) et range les blocs dans /tmp/tempo.

Fenêtre de terminal
cat > tempo.yaml << 'EOF'
stream_over_http_enabled: true
server:
http_listen_port: 3200
grpc_listen_port: 9095
distributor:
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
storage:
trace:
backend: local
local:
path: /tmp/tempo/blocks
wal:
path: /tmp/tempo/wal
EOF

On lance ensuite Tempo en épinglant la version, pour un résultat reproductible :

Fenêtre de terminal
docker run -d --name tempo \
-p 3200:3200 -p 4317:4317 -p 4318:4318 \
-v "$(pwd)/tempo.yaml:/etc/tempo.yaml" \
grafana/tempo:3.0.2 \
-config.file=/etc/tempo.yaml

Vérification : curl http://localhost:3200/ready doit répondre ready. Si la commande renvoie connection refused, le conteneur n'est pas encore démarré, consultez docker logs tempo.

Sur un cluster, Grafana fournit deux charts. Le chart tempo installe le mode monolithique, suffisant pour un environnement de test ou de faible volume. Le chart tempo-distributed déploie chaque composant séparément et vise la production.

Fenêtre de terminal
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
# Mode monolithique (test / faible volume)
helm install tempo grafana/tempo \
--namespace monitoring --create-namespace

Pour la production, on part sur tempo-distributed avec un backend S3, seul choix qui tient la montée en charge :

Fenêtre de terminal
helm install tempo grafana/tempo-distributed \
--namespace monitoring --create-namespace \
--set storage.trace.backend=s3 \
--set storage.trace.s3.bucket=mon-bucket-tempo \
--set storage.trace.s3.endpoint=s3.eu-west-3.amazonaws.com

Tempo est agnostique du format : il accepte les principaux protocoles de traces sur des ports distincts. C'est utile pour migrer progressivement depuis Jaeger ou Zipkin sans réinstrumenter toutes les applications d'un coup.

ProtocolePort gRPCPort HTTPUsage
OTLP43174318Recommandé, standard OpenTelemetry
Jaeger1425014268Migration depuis Jaeger
Zipkin-9411Migration depuis Zipkin
OpenCensus55678-Historique

Le standard à privilégier reste OTLP (OpenTelemetry) : il unifie traces, métriques et logs sous un même protocole. Pour accepter plusieurs formats en parallèle, on ajoute les récepteurs correspondants sous distributor.receivers.

distributor:
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
jaeger:
protocols:
grpc:
endpoint: 0.0.0.0:14250
thrift_http:
endpoint: 0.0.0.0:14268
zipkin:
endpoint: 0.0.0.0:9411

Tempo n'a pas d'interface propre : il se consulte depuis Grafana, où il devient une source de données. La configuration prend moins d'une minute et débloque la navigation croisée entre traces, logs et métriques.

  1. Ouvrir Grafana sur http://localhost:3000 (identifiants par défaut admin / admin).

  2. Ajouter la source : menu Connexions, Data sources, Add data source, choisir Tempo.

  3. Renseigner l'URL : http://tempo:3200 sur Kubernetes, ou l'adresse de votre conteneur.

  4. Activer la corrélation (recommandé) : associez une source Loki (trace vers logs) et Prometheus (trace vers métriques).

  5. Valider avec « Save & test » : Grafana confirme la connexion.

TraceQL est le langage de requête de Tempo, dans l'esprit de PromQL ou LogQL. Il sélectionne des spans selon leurs attributs : nom de service, code HTTP, durée. C'est lui qui transforme un stockage brut en outil d'investigation.

# Toutes les traces (exploration)
{ }
# Requêtes lentes du service checkout
{ resource.service.name = "checkout" && duration > 2s }
# Erreurs HTTP dans le frontend
{ resource.service.name = "frontend" && span.http.status_code >= 500 }
# Spans portant un attribut métier précis
{ span.user.id = "12345" }

Deux préfixes structurent les filtres : resource. cible les attributs de la ressource (le service, l'hôte), span. cible ceux du span (méthode HTTP, code retour). On les combine avec && et || pour cerner exactement le problème.

Parcourir les traces une par une ne dit pas si un service se dégrade globalement. Le metrics generator de Tempo calcule des span metrics, des métriques Prometheus dérivées des traces : taux d'appels, latence, taux d'erreur. Ce sont les indicateurs RED (Rate, Errors, Duration), directement exploitables en dashboard.

metrics_generator:
registry:
external_labels:
source: tempo
storage:
path: /var/tempo/wal
remote_write:
- url: http://prometheus:9090/api/v1/write
traces_storage:
path: /var/tempo/generator
processor:
span_metrics:
dimensions:
- service.name
- http.method
- http.status_code

Tempo pousse alors dans Prometheus des séries comme traces_spanmetrics_latency_bucket (histogramme de latence) et traces_spanmetrics_calls_total (nombre d'appels). Vous surveillez la santé d'un service sans lire une seule trace, puis vous plongez dans les traces uniquement quand une métrique dérape.

En production, la configuration bascule sur un backend objet et fixe une rétention raisonnable. Les traces ont une valeur surtout récente : garder plus de quelques jours coûte cher pour peu d'usage.

storage:
trace:
backend: s3
s3:
bucket: mon-bucket-tempo
endpoint: s3.eu-west-3.amazonaws.com
region: eu-west-3
access_key: ${AWS_ACCESS_KEY_ID}
secret_key: ${AWS_SECRET_ACCESS_KEY}
wal:
path: /var/tempo/wal
compactor:
compaction:
block_retention: 168h # 7 jours
overrides:
defaults:
ingestion:
rate_limit_bytes: 15000000 # 15 Mo/s par tenant
burst_size_bytes: 20000000

Trois réglages comptent : le backend S3 pour le volume, le block_retention du compactor pour maîtriser le coût, et les limites d'ingestion (rate_limit_bytes) pour qu'un service bavard ne sature pas la plateforme. En production, pensez aussi à échantillonner (1 à 10 % des traces) côté instrumentation pour réduire le débit à la source.

La plupart des incidents Tempo se règlent en quelques vérifications. Voici les symptômes les plus fréquents et leur cause probable.

SymptômeCause probableSolution
connection refused sur :4317Tempo non démarré ou port non exposéVérifier docker logs tempo et les -p
« Trace not found » dans GrafanaTrace ID erroné ou trace expiréeContrôler le block_retention
ingestion rate limitedTrop de spans par secondeAugmenter rate_limit_bytes
Échec de compactionStockage plein ou droits S3Vérifier le bucket et ses permissions

Pour valider une chaîne d'ingestion sans instrumenter d'application, envoyez une trace de test en OTLP HTTP :

Fenêtre de terminal
curl -X POST http://localhost:4318/v1/traces \
-H "Content-Type: application/json" \
-d '{
"resourceSpans": [{
"resource": {"attributes": [{"key": "service.name", "value": {"stringValue": "test"}}]},
"scopeSpans": [{
"spans": [{
"traceId": "5B8EFFF798038103D269B633813FC60C",
"spanId": "EEE19B7EC3C1B174",
"name": "test-span",
"kind": 1,
"startTimeUnixNano": "1544712660000000000",
"endTimeUnixNano": "1544712661000000000"
}]
}]
}]
}'

La trace apparaît ensuite dans Grafana en cherchant le trace ID 5b8efff798038103d269b633813fc60c.

  1. Tempo stocke les traces sans les indexer : seul le trace ID est indexé, le reste part en stockage objet peu cher.
  2. OTLP est le format recommandé, mais Tempo accepte aussi Jaeger, Zipkin et OpenCensus pour migrer en douceur.
  3. Tempo se consulte depuis Grafana : pas d'interface autonome, mais une navigation croisée traces, logs, métriques.
  4. TraceQL filtre les spans par attribut (resource. et span.) pour cibler un problème.
  5. En production, stockage S3, rétention courte et limites d'ingestion : les trois réglages qui tiennent le coût et la stabilité.

Ce site vous est utile ?

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

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn