1. Des traces utiles #
Qualité de l'instrumentation.
Conventions #
- Utilisez les conventions sémantiques OpenTelemetry (
http.request.method,db.system,service.name...). - Nommez les spans par opération stable (
GET /orders/{id}), jamais avec des identifiants variables. - Ajoutez des attributs métier à faible risque (
order.type) ; aucune donnée personnelle. - Propagez le contexte partout (HTTP, messagerie) et alignez
OTEL_PROPAGATORS.
export OTEL_SERVICE_NAME=checkout
export OTEL_RESOURCE_ATTRIBUTES="service.namespace=shop,service.version=1.4.2,deployment.environment=prod"
# Masquer les données sensibles dans le Collector / Alloy
otelcol.processor.attributes "redact" { action { key = "user.email" action = "hash" } output { traces = [otelcol.processor.batch.default.input] } }2. Maîtriser le volume #
Échantillonner sans perdre l'essentiel.
Stratégie #
// Garder 100 % des erreurs et des traces lentes, 5 % du reste
otelcol.processor.tail_sampling "smart" {
decision_wait = "10s"
policy { name = "erreurs" type = "status_code" status_code { status_codes = ["ERROR"] } }
policy { name = "lentes" type = "latency" latency { threshold_ms = 1000 } }
policy { name = "reste" type = "probabilistic" probabilistic { sampling_percentage = 5 } }
output { traces = [otelcol.exporter.otlp.tempo.input] }
}# Mesurer l'effet : spans reçus vs rejetés
sum(rate(tempo_distributor_spans_received_total[5m]))
sum by (reason) (rate(tempo_discarded_spans_total[5m]))
# Taille moyenne d'une trace
sum(rate(tempo_distributor_bytes_received_total[5m])) / sum(rate(tempo_distributor_traces_per_batch_count[5m]))Erreur Courante : Le tail sampling exige que tous les spans d'une trace arrivent au même collecteur : utilisez un exporterloadbalancing(routing_key = traceID) devant la couche d'échantillonnage.
3. Requêter efficacement #
TraceQL et corrélation.
Bonnes habitudes #
{ resource.service.name = "checkout" && status = error && duration > 500ms } # attributs qualifiés, filtres précis
{ resource.service.name = "checkout" } >> { span.db.system = "postgresql" } | count() > 10 # N+1
{ status = error } | rate() by (resource.service.name) # TraceQL metrics- Limitez la plage de temps et le nombre de résultats : une recherche TraceQL lit des blocs entiers.
- Démarrez toujours par les exemplars ou les logs pour obtenir un TraceID, puis ouvrez la trace.
- Dérivez des métriques RED avec le metrics-generator plutôt que de rechercher en masse.
4. Exploitation et revue #
Checklist avant la production.
Dimensionnement et alertes #
# Alertes de base
sum(rate(tempo_discarded_spans_total[5m])) > 0
tempodb_compaction_outstanding_blocks > 100
histogram_quantile(0.99, sum by (le) (rate(tempo_request_duration_seconds_bucket{route="api_traces_traceid"}[5m]))) > 3
tempo_ingester_live_traces / on() group_left() tempo_limits_defaults{limit_name="max_traces_per_user"} > 0.8| Question de revue | Réponse attendue |
|---|---|
| Le TraceID est-il dans tous les logs ? | Oui, format hexadécimal sur 32 caractères |
| Y a-t-il des données personnelles dans les attributs ? | Non, redaction dans le collecteur |
| Quelle est la rétention ? | Définie par besoin (7 – 30 jours typiquement) |
| Que se passe-t-il si Tempo est indisponible ? | File d'attente et retry côté collecteur, pas d'impact applicatif |
| Les limites protègent-elles le cluster ? | overrides par tenant, alertes sur rejets |
Schéma de référence et vérification rapide #
Visualiser le principe et le contrôler en ligne de commande.
Schéma de référence #
curl -s localhost:12345/metrics | grep -E 'otelcol_processor_tail_sampling'