1. Les sélecteurs de spans #
Les accolades vides sont valides, mais coûteuses.
Attributs et portées #
{ resource.service.name = "checkout" } # attribut de ressource
{ span.http.status_code = 500 } # attribut de span
{ .http.status_code = 500 } # portée implicite (span puis ressource)
{ name = "POST /payer" } # nom du span
{ status = error } # statut : error | ok | unset
{ kind = server } # kind : server, client, producer...
{ duration > 2s } # durée du span
{ traceDuration > 5s } # durée de la trace complète
{ resource.service.name =~ "api-.*" && span.http.method != "GET" } # regex, &&, ||Bonne Pratique : Utilisez les noms d'attributs qualifiés (span./resource.) : la recherche est plus rapide et sans ambiguïté.
2. Opérateurs structurels #
Relier des spans entre eux.
Parent, enfant et descendant #
# Appels de paiement en erreur sous le service checkout (descendant)
{ resource.service.name = "checkout" } >> { resource.service.name = "payment" && status = error }
# Enfant direct
{ resource.service.name = "frontend" } > { resource.service.name = "checkout" }
# Spans frères (sibling)
{ span.db.system = "postgresql" } ~ { span.db.system = "redis" }
# Remontée : trouver l'ancêtre d'un span lent
{ duration > 1s } << { resource.service.name = "gateway" }| Opérateur | Signification |
|---|---|
>> | A est un ancêtre de B |
> | A est le parent direct de B |
~ | A et B sont frères |
<< / < | Versions inversées |
3. Agrégations et sélection #
Analyser le résultat.
Pipeline TraceQL #
# Traces avec plus de 10 requêtes SQL (problème N+1 probable)
{ span.db.system = "postgresql" } | count() > 10
# Traces dont la durée moyenne des spans HTTP dépasse 500 ms
{ span.http.method != "" } | avg(duration) > 500ms
# Afficher uniquement certains attributs dans les résultats
{ status = error } | select(span.http.url, resource.service.name, span.exception.message)
# Regrouper
{ resource.service.name = "api" } | by(span.http.route) | count() > 5Via l'API et Tempo CLI #
curl -G -s http://localhost:3200/api/search \
--data-urlencode 'q={ resource.service.name = "checkout" && status = error }' \
--data-urlencode 'limit=20' --data-urlencode 'start='$(date -d '1 hour ago' +%s) --data-urlencode 'end='$(date +%s) | jq '.traces[].traceID'
curl -s http://localhost:3200/api/search/tags | jq # attributs disponibles
curl -s http://localhost:3200/api/search/tag/service.name/values | jq4. Requêtes de diagnostic prêtes à l'emploi #
Un petit catalogue.
Catalogue #
| Objectif | Requête TraceQL |
|---|---|
| Erreurs récentes d'un service | { resource.service.name = "checkout" && status = error } |
| Requêtes lentes (> 2 s) | { kind = server && duration > 2s } |
| Appels HTTP 5xx sortants | { kind = client && span.http.status_code >= 500 } |
| Retries excessifs | { name = "http.retry" } | count() > 3 |
| Une trace par utilisateur | { span.user.id = "42" } |
