Session 9 — APM : Tempo + Pyroscope + Dashboards + Debug NAS¶
Durée : ~6 heures Conversations : 3 Objectif initial : Mettre en place la stack APM complète (traces distribuées + profiling continu) Objectif final : Tempo + Pyroscope opérationnels sur NAS Synology, dashboards Grafana APM, agents JVM injectés
✅ Ce qui a été livré¶
Infrastructure APM :
- tempo/tempo-config.yml — Tempo 2.4.2 single-binary, OTLP gRPC/HTTP, metrics_generator → Prometheus remote_write
- pyroscope/pyroscope-config.yml — Pyroscope 1.18.1, profiling JVM continu
- grafana/provisioning/datasources/tempo.yml + pyroscope.yml — datasources avec UIDs fixes (tempo, pyroscope)
- docker-compose.yml + docker-compose.build.yml — ajout services perfshop-tempo et perfshop-pyroscope
Agents JVM (Dockerfile.synology v30) :
- opentelemetry-javaagent.jar 1.33.6 — traces OTLP vers Tempo
- pyroscope.jar 0.14.0 — profiling CPU/heap vers Pyroscope
- Injection via JAVA_OPTS dans docker-compose (aucune dépendance Maven)
Dashboards Grafana :
- grafana/dashboards/dashboard-apm-formateur.json — traces, flamegraphs CPU/heap, JVM détail, chaos fonctionnel
- grafana/dashboards/dashboard-apm-eleve.json — version simplifiée sans flamegraphs avancés, avec guide markdown
Documentation :
- mkdocs/docs/monitoring/apm.md — architecture, config Tempo, Pyroscope, vérifications, notes de version
🐛 Debug NAS — Problèmes rencontrés et résolus¶
WAL Tempo corrompu : Volume tempo-data issu d'une version latest incompatible. Résolu par suppression du volume et redémarrage.
UIDs datasources Grafana : Les datasources tempo et pyroscope n'étaient pas reconnues par les dashboards. Résolu en fixant les UIDs dans les fichiers de provisioning.
Migration grafana/tempo:latest → 2.4.2 : latest pointait vers Tempo 2.6+ qui introduit une architecture distribuée incompatible avec le mode single-binary sans Kafka. Symptôme : erreur empty ring au démarrage.
Panel Traces "No data" : Grafana 12 utilise queryType: "traceqlSearch" qui appelle /api/v2/search — endpoint inexistant sur Tempo 2.4.2 (404). Résolu : queryType: "traceql" + type: "table".
🤖 Erreurs imputables à Claude AI — Session 9¶
❌ Erreur S9-1 — Config YAML Tempo invalide (indentation)¶
Ce que j'ai proposé : Un tempo-config.yml avec une indentation incorrecte dans le bloc metrics_generator.storage.
Ce qui s'est passé : Tempo refusait de démarrer avec une erreur de parsing YAML. Détecté sur le NAS aux logs du container.
Pourquoi c'était une erreur : YAML est sensible à l'indentation. Le fichier n'a pas été validé avant livraison.
Temps perdu : ~20 min | Sévérité : ⭐⭐
❌ Erreur S9-2 — grafana/tempo:latest au lieu de version fixée¶
Ce que j'ai proposé : image: grafana/tempo:latest dans les docker-compose.
Ce qui s'est passé : latest a résolu vers Tempo 2.6+ dont l'architecture single-binary est incompatible. Erreur empty ring au démarrage, panel Traces en erreur 500.
Pourquoi c'était une erreur : Pour une stack pédagogique stable, les images "infrastructure" doivent être fixées à une version testée. latest est acceptable pour les images applicatives buildées en CI, pas pour les composants de la stack de monitoring.
Temps perdu : ~45 min (diagnostic + migration) | Sévérité : ⭐⭐⭐⭐
❌ Erreur S9-3 — queryType: "traceqlSearch" incompatible Tempo 2.4.2¶
Ce que j'ai proposé : Panel Traces avec queryType: "traceqlSearch" — valeur par défaut suggérée par la documentation Grafana.
Ce qui s'est passé : Grafana 12 appelle /api/v2/search pour traceqlSearch, endpoint inexistant sur Tempo 2.4.2 (404). Panel "No data" malgré 40 traces confirmées dans le Query Inspector.
Pourquoi c'était une erreur : La documentation Grafana décrit le comportement pour Tempo 2.5+. La matrice de compatibilité Grafana/Tempo n'a pas été consultée.
Temps perdu : ~40 min | Sévérité : ⭐⭐⭐
❌ Erreur S9-4 — type: "traces" affiche "No data" (traceDuration null)¶
Ce que j'ai proposé : Après correction de queryType, panel type: "traces" pour afficher les traces récentes.
Ce qui s'est passé : "No data" persistait. Query Inspector confirmait 40 traces et status 200. Cause : le type traces de Grafana 12 requiert un champ traceDuration non null — Tempo 2.4.2 ne remplit pas durationNanos dans /api/search.
Pourquoi c'était une erreur : Deux bugs distincts masqués l'un derrière l'autre. Le type table était la bonne alternative.
Temps perdu : ~25 min | Sévérité : ⭐⭐
📊 Récapitulatif Session 9¶
| # | Erreur | Temps perdu | Sévérité |
|---|---|---|---|
| S9-1 | Config YAML Tempo — indentation invalide | ~20 min | ⭐⭐ |
| S9-2 | tempo:latest → Tempo 2.6+ incompatible |
~45 min | ⭐⭐⭐⭐ |
| S9-3 | traceqlSearch → /api/v2/search 404 sur Tempo 2.4.2 |
~40 min | ⭐⭐⭐ |
| S9-4 | type: traces → "No data" (traceDuration null) |
~25 min | ⭐⭐ |
| TOTAL | ~130 min |
Pattern : Trois erreurs sur quatre liées à des incompatibilités de version non anticipées. Le tag latest en infrastructure est le plus coûteux — 45 min pour un tag qui aurait dû être fixé dès le début. La matrice de compatibilité Grafana/Tempo est critique : Grafana 12 + Tempo 2.4.2 nécessite queryType: traceql + type: table.