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.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- 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.
Pourquoi choisir Tempo comme backend de traces
Section intitulée « Pourquoi choisir Tempo comme backend de traces »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 où 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 courant | Réponse de Tempo |
|---|---|
| Coût de stockage élevé de Jaeger ou Elasticsearch | Pas d'index, donc stockage objet peu cher |
| Intégration Grafana à câbler | Natif Grafana, même éditeur |
| Formats de traces hétérogènes | Accepte OTLP, Jaeger, Zipkin, OpenCensus |
| Corréler traces, logs et métriques | TraceQL plus liens vers Loki et Prometheus |
L'architecture de Tempo
Section intitulée « L'architecture de Tempo »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.
| Composant | Rôle |
|---|---|
| Distributor | Reçoit les traces, les valide et les répartit vers les ingesters |
| Ingester | Bufferise puis écrit les traces dans le stockage objet |
| Compactor | Fusionne les blocs pour réduire leur nombre et le coût de lecture |
| Querier | Exécute les requêtes TraceQL sur les blocs |
| Query Frontend | Met 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.
Démarrer Tempo en local avec Docker
Section intitulée « Démarrer Tempo en local avec Docker »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.
cat > tempo.yaml << 'EOF'stream_over_http_enabled: trueserver: 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/walEOFOn lance ensuite Tempo en épinglant la version, pour un résultat reproductible :
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.yamlVé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.
Déployer Tempo sur Kubernetes avec Helm
Section intitulée « Déployer Tempo sur Kubernetes avec Helm »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.
helm repo add grafana https://grafana.github.io/helm-chartshelm repo update
# Mode monolithique (test / faible volume)helm install tempo grafana/tempo \ --namespace monitoring --create-namespacePour la production, on part sur tempo-distributed avec un backend S3, seul choix qui tient la montée en charge :
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.comLes protocoles de traces supportés
Section intitulée « Les protocoles de traces supportés »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.
| Protocole | Port gRPC | Port HTTP | Usage |
|---|---|---|---|
| OTLP | 4317 | 4318 | Recommandé, standard OpenTelemetry |
| Jaeger | 14250 | 14268 | Migration depuis Jaeger |
| Zipkin | - | 9411 | Migration depuis Zipkin |
| OpenCensus | 55678 | - | 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:9411Connecter Tempo à Grafana
Section intitulée « Connecter Tempo à Grafana »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.
-
Ouvrir Grafana sur
http://localhost:3000(identifiants par défautadmin/admin). -
Ajouter la source : menu Connexions, Data sources, Add data source, choisir Tempo.
-
Renseigner l'URL :
http://tempo:3200sur Kubernetes, ou l'adresse de votre conteneur. -
Activer la corrélation (recommandé) : associez une source Loki (trace vers logs) et Prometheus (trace vers métriques).
-
Valider avec « Save & test » : Grafana confirme la connexion.
Interroger les traces avec TraceQL
Section intitulée « Interroger les traces avec TraceQL »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.
Générer des métriques depuis les traces
Section intitulée « Générer des métriques depuis les traces »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_codeTempo 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.
Passer en production avec un stockage S3
Section intitulée « Passer en production avec un stockage S3 »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: 20000000Trois 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.
Dépannage
Section intitulée « Dépannage »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ôme | Cause probable | Solution |
|---|---|---|
connection refused sur :4317 | Tempo non démarré ou port non exposé | Vérifier docker logs tempo et les -p |
| « Trace not found » dans Grafana | Trace ID erroné ou trace expirée | Contrôler le block_retention |
ingestion rate limited | Trop de spans par seconde | Augmenter rate_limit_bytes |
| Échec de compaction | Stockage plein ou droits S3 | Vé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 :
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.
FAQ : questions fréquentes
Section intitulée « FAQ : questions fréquentes »À retenir
Section intitulée « À retenir »- Tempo stocke les traces sans les indexer : seul le trace ID est indexé, le reste part en stockage objet peu cher.
- OTLP est le format recommandé, mais Tempo accepte aussi Jaeger, Zipkin et OpenCensus pour migrer en douceur.
- Tempo se consulte depuis Grafana : pas d'interface autonome, mais une navigation croisée traces, logs, métriques.
- TraceQL filtre les spans par attribut (
resource.etspan.) pour cibler un problème. - En production, stockage S3, rétention courte et limites d'ingestion : les trois réglages qui tiennent le coût et la stabilité.