perf sentinelperf sentineldocs
FRENGitHub
Documentation / Inspect (TUI)

TUI interactif

perf-sentinel embarque un TUI interactif pour explorer les findings, les arbres de spans et les corrélations cross-trace. Il expose trois vues en un seul drill-down : Analyze (le tableau de bord de synthèse), Inspect (le navigateur multi-panneaux) et Explain (l'arbre de spans plein écran d'une trace). Quel que soit le point d'entrée, on circule entre les trois vues sans quitter le TUI. Une quatrième vue, Disclose, reste à part : elle prévisualise un rapport de divulgation publique au lieu d'explorer des findings, elle n'a donc pas de drill-down vers les trois autres (voir Divulgation).

Points d'entrée :

  • perf-sentinel analyze --tui [--input <events.json>] : ouvre sur la vue Analyze.
  • perf-sentinel demo --tui : même vue sur le jeu de démonstration embarqué, sans fichier d'entrée.
  • perf-sentinel inspect --input <events.json> : ouvre sur la vue Inspect, lit un fichier d'événements brut ou un JSON Report pré-calculé.
  • perf-sentinel explain --tui --trace-id <id> --input <events.json> : ouvre sur la vue Explain, centrée sur cette trace.
  • perf-sentinel query --daemon <URL> inspect [--sort <KEY>] : mode live, ouvre sur Inspect, lit les findings et les traces depuis un daemon en cours d'exécution via HTTP. --sort prend les mêmes clés que analyze --sort.
  • perf-sentinel disclose --tui --input <archive>... --org-config <PATH> : ouvre l'aperçu Disclose.

En mode live (0.5.24+), le TUI permet aussi à l'opérateur d'acquitter et de révoquer des findings interactivement depuis le terminal.

Ce TUI est le navigateur de traces et de findings du développeur. Pour le monitoring d'exploitation, il existe un TUI opérateur live séparé, perf-sentinel query monitor (depuis 0.8.8). Il a six onglets, parcourus avec Tab : Advisor (les indications du conseiller de réglages du daemon), Energy (le mix énergie/carbone effectif par service et par région), Trends (courbes braille live de l'énergie/carbone par fenêtre et des jauges runtime en part de leur plafond configuré), Scrapers (santé live des backends énergie via /api/energy), Config (les paramètres du daemon en lecture seule, avec leur défaut et une explication d'une ligne pour chacun) et Incidents (les redémarrages et événements mémoire postés par l'alerting, chacun avec les findings figés de sa fenêtre, depuis 0.20.0). Les onglets se rafraîchissent depuis le daemon toutes les --refresh secondes (défaut 5). Quand le daemon devient injoignable, le dernier instantané valide reste affiché avec un indicateur d'obsolescence. Lecture seule : pas d'acquittement. Aucune clé d'API n'est requise sauf pour l'onglet Incidents, ou pour chaque onglet sur un daemon avec [daemon] require_read_key = true. Passez --api-key-file (ou PERF_SENTINEL_DAEMON_API_KEY), la clé en lecture seule [daemon] read_api_key suffit, et le moniteur l'envoie à chaque interrogation.

Vues et drill-down

Les trois vues forment un seul drill-down. Enter descend, Esc remonte :

Analyze  --Enter-->  Inspect  --Enter-->  Explain
         <---Esc---           <---Esc---
  • Analyze : la synthèse à défilement (gaspillage GreenOps, principaux postes, quality gate), le même contenu que la sortie stdout d'analyze. Enter descend vers Inspect.
  • Inspect : le navigateur multi-panneaux décrit ci-dessous. Enter parcourt les panneaux puis, depuis Detail, ouvre Explain. Esc remonte vers Analyze.
  • Explain : l'arbre de spans annoté de la trace sélectionnée, plein écran, avec défilement. Esc revient au panneau Detail d'Inspect.

Une barre d'onglets en haut met en évidence la vue active. Les arbres de spans se dessinent depuis des spans bruts (inspect --input <events>.json ou query inspect) ou depuis les arbres masqués qu'un Report porte (un instantané daemon, ou tempo/jaeger-query --format json). Une trace dont l'entrée ne contient pas les spans affiche une indication à la place.

Disposition

L'écran se découpe en une disposition sur 2 lignes :

┌─ Traces ──┬─ Findings ────────────────┬─ Correlations ────┐
│ trace-1   │ [1] N+1 SQL CRITICAL      │ svc-a -> svc-b    │
│ trace-2   │ [2] Redundant SQL WARNING │ ...               │
│ ...       │ [3] Slow HTTP INFO        │                   │
├───────────┴───────────────────────────┴───────────────────┤
│ Detail (full-width, span tree + finding metadata)         │
└───────────────────────────────────────────────────────────┘

La bordure du panneau actif est cyan, celles des autres restent grises.

Raccourcis clavier

La navigation fonctionne aux flèches partout. Dans la vue Inspect, les touches vim h / j / k / l s'appliquent aussi, et j / k font défiler les vues Analyze et Explain.

ToucheAction
qQuitter
↑ / kMonte la sélection, ou fait défiler (Analyze, Explain)
↓ / jDescend la sélection, ou fait défiler (Analyze, Explain)
→ / Tab / lPasse au panneau suivant (Inspect)
← / BackTab / hPasse au panneau précédent (Inspect)
EnterDescend d'un cran dans le drill-down (voir ci-dessous)
EscRemonte d'un cran
mBascule le mode souris pour glisser les bordures
rRéinitialise les tailles des panneaux (Inspect)
sPasse au tri suivant : impact, sévérité, id (Inspect)
fPasse au filtre de sévérité suivant (Inspect)
aAcquitter le finding sélectionné (mode live)
uRévoquer l'ack existant (mode live)

s ordonne les deux listes à la fois, les traces et les findings de la trace sélectionnée, sur les mêmes clés et les mêmes directions que analyze --sort et le dashboard. --sort sur analyze --tui et sur query inspect ouvre directement dans cet ordre.

f fait passer le panneau Findings par toutes les sévérités, puis critical, warning et info isolément. Le titre du panneau et la barre d'onglets nomment tous deux le filtre actif, et une trace dont tous les findings sont filtrés garde sa ligne avec un panneau vide : la liste des traces répond à ce qui a tourné, pas à ce qui correspond.

m bascule la capture souris (optionnelle, la sélection et le copier-coller natifs du terminal restent donc disponibles quand elle est coupée). Une fois activée, glisser la bordure entre deux panneaux redistribue leur espace. Survoler une bordure la met en évidence avec une poignée, car une application terminal ne peut pas changer le curseur souris de l'OS. r réinitialise la disposition par défaut. Les tailles sont propres à la session et non persistées.

Enter descend : d'Analyze vers Inspect, puis à travers les panneaux d'Inspect (Traces, Findings, Detail), puis de Detail vers Explain. Depuis le panneau Correlations, il saute vers le Detail de la trace d'exemple de la corrélation. Esc inverse chaque étape, remontant des panneaux de tête d'Inspect jusqu'à Analyze.

a et u sont sans effet en mode batch (inspect --input) puisque l'acquittement a besoin d'un daemon qui tourne pour persister.

Workflow d'acquittement (mode live)

Quand le TUI est lancé via query inspect, il récupère les findings avec ?include_acked=true pour que les findings déjà acquittés apparaissent dans la liste avec un indicateur italique gris [acked by <user>] en fin de ligne.

a : créer un ack

Presser a sur un finding sélectionné ouvre une modale centrée sur l'écran avec trois champs de saisie :

ChampContrainteDéfaut
Reason1 à 256 caractères, une lignevide (requis)
Expiresvide, 24h, 7d, ISO8601, etcvide (pas d'expiration)
By1 à 128 caractèresvariable d'env $USER

Plus deux boutons (Submit / Cancel).

Navigation modale :

ToucheAction
TabFocus sur le champ ou bouton suivant
BackTabFocus sur le champ ou bouton précédent
Enter (texte)Avance au champ suivant
Enter (Submit)Envoie le formulaire
Enter (Cancel)Ferme la modale sans envoyer
EscAnnule la modale
BackspaceSupprime le dernier caractère du champ actif

À l'envoi, le TUI poste sur /api/findings/<sig>/ack et ferme la modale sur 201. En cas d'erreur (4xx/5xx), la modale reste ouverte avec le message d'erreur en bas (texte rouge).

u : révoquer un ack

Presser u sur un finding acquitté ouvre une modale de confirmation. Submit / Enter envoie un DELETE /api/findings/<sig>/ack. Cancel / Esc ferme sans révoquer.

Format expires

Identique à l'utilitaire ack du CLI (depuis 0.5.22) :

  • Vide : pas d'expiration, l'ack persiste jusqu'à révocation manuelle
  • 24h, 7d, 30m : durée relative analysée par humantime
  • 2026-05-11T00:00:00Z : datetime ISO8601 absolu

Une entrée invalide affiche expires: <error> en bas de la modale sans envoyer la requête.

Authentification

Le TUI reprend la résolution d'authentification de l'utilitaire ack du CLI :

  1. Variable d'env PERF_SENTINEL_DAEMON_API_KEY (priorité 1)
  2. Flag --api-key-file <path> sur query inspect (priorité 2)
bash
# variable d'env
export PERF_SENTINEL_DAEMON_API_KEY=$(cat ~/.config/perf-sentinel/key)
perf-sentinel query --daemon http://localhost:4318 inspect

# fichier
perf-sentinel query --daemon http://localhost:4318 inspect \
  --api-key-file ~/.config/perf-sentinel/key

Les deux sont équivalents. Les sauts de ligne en fin de fichier sont supprimés et, sur Unix, le fichier est ouvert avec O_NOFOLLOW (les liens symboliques sont refusés).

Pas d'invite de mot de passe interactive dans le TUI. Le mode raw et l'écran alternatif sont incompatibles avec la saisie TTY de rpassword. Si le daemon répond 401 sans clé en variable d'environnement ni en fichier, la modale affiche "API key required: set PERF_SENTINEL_DAEMON_API_KEY or pass --api-key-file when launching query inspect." Quitter, définir la clé, relancer.

Quand le daemon n'a pas de [daemon.ack] api_key configuré (défaut pour les déploiements loopback), aucune clé n'est requise et la modale envoie directement.

Limites

Le HTTP synchrone fige l'UI

run_loop est synchrone et l'écriture de l'ack daemon est exécutée via tokio::runtime::Handle::current().block_on(...) depuis l'intérieur de la boucle. L'UI se fige pendant la durée de la requête, typiquement 100-300 ms en localhost, plus longtemps sur le réseau. Acceptable pour une version au périmètre minimal. Une refonte en boucle d'événements async pourra suivre si les retours utilisateurs signalent de la friction.

Instantané de la liste des findings

La liste des findings est récupérée une seule fois au démarrage. a/u rafraîchissent uniquement l'état des acks via un second GET /api/findings?include_acked=true. La liste des findings elle-même ne change pas en cours de session. Pour récupérer des traces nouvellement ingérées, quitter et relancer.

Acks TOML visibles, pas modifiables

Les findings acquittés dans .perf-sentinel-acknowledgments.toml (CI ack) apparaissent avec l'indicateur [acked by <user>] et le champ source positionné à toml. Le TUI ne peut pas promouvoir un ack daemon vers TOML ni éditer le fichier TOML. Pour les acks permanents, éditer le fichier via revue PR comme décrit dans Flux d’acquittement.

Le moniteur opérateur live

perf-sentinel query monitor (depuis 0.8.8) est le pendant côté exploitation du navigateur Inspect du développeur ci-dessus. Il tourne contre un daemon vivant, le sonde à cadence fixe (--refresh secondes, défaut 5) et fonctionne en lecture seule. Tab parcourt les six onglets et BackTab revient en arrière, j/k ou les flèches font défiler, q ou Esc quitte. Sur l'onglet Trends, m bascule le mode souris pour glisser les bordures des graphes et r les réinitialise, comme dans le navigateur Inspect. Les données de chaque onglet (indications de config, provenance des sources, intensités par région) sont catégorielles et à haute cardinalité, donc la règle des labels bornés les garde hors du /metrics Prometheus.

  • Advisor affiche les indications du conseiller de réglages du daemon (warning_details), colorées par type. Un daemon bien dimensionné ne signale aucune indication. La capture ci-dessous montre un daemon sous-dimensionné dont la fenêtre de traces est bloquée près de son plafond. [Onglet Advisor : une indication de réglage, traces actives à 90 % ou plus de max_active_traces]
  • Energy montre le mix énergie/carbone effectif directement depuis le green_summary live : par service (source effective, part mesurée, énergie, région) et par région (intensité de grille, source froide embarquée vs chaude temps réel). La ligne de fenêtre nomme la source d'énergie, par exemple source scaphandre_rapl on 2 of 5 services · rest modeled from I/O counts. Un service dont aucune opération n'a été mesurée affiche I/O counts comme source. [Onglet Energy : mix énergie/carbone par service et par région avec des sources d'intensité froides]
  • Trends trace l'historique de sondage en courbes braille live : l'énergie et le carbone par fenêtre de scoring en haut, et en dessous le graphe Headroom, chaque jauge runtime (active_traces, analysis_queue_depth, stored_findings) en pourcentage de son plafond configuré, avec le seuil de 90 % du conseiller de réglages tracé en référence. Quand l'intensité de grille effective est statique, les deux courbes du haut se suivent. Elles divergent dès que l'intensité bouge, soit par le flux temps réel Electricity Maps, soit par un mix régional qui se déplace (la capture ci-dessous met en scène ce second cas). Un point arrive par tick de rafraîchissement, jusqu'à 240 points (20 minutes au défaut de 5 s), et l'historique vit dans le moniteur seul : le relancer repart d'une fenêtre vierge. Les champs de plafond demandent un daemon 0.8.8. Face à un daemon plus ancien, le panneau Headroom se dégrade en indication. [Onglet Trends : courbes d'énergie et de carbone sur l'historique de sondage, pourcentages de headroom sous le seuil advisor]
  • Scrapers lit /api/energy pour la santé live des backends. Ici cloud_energy est configuré mais son endpoint est injoignable, donc son âge de fraîcheur grimpe tandis que les backends non configurés restent en tiret. [Onglet Scrapers : santé des backends, cloud_energy configuré avec un âge de fraîcheur qui grimpe]
  • Config lit /api/config pour les réglages [daemon] effectifs du daemon, en lecture seule. Chaque paramètre montre sa valeur actuelle, le défaut compilé (calculé localement) et une explication d'une ligne de ce qu'il fait. Les valeurs qui diffèrent du défaut sont marquées modified. Les secrets sont résumés côté serveur (TLS configured/not, clés d'API ack et de lecture set/unset, store d'incidents enabled/disabled) et jamais montrés en clair. Nécessite un daemon 0.8.8+, les plus anciens affichent une indication. [Onglet Config : paramètres du daemon avec valeur actuelle, défaut et description, valeurs modifiées signalées]
  • Incidents lit GET /api/incidents pour les redémarrages et événements mémoire que votre alerting a postés au daemon (depuis 0.20.0), du plus récent au plus ancien, chacun avec les findings figés de la fenêtre qui l'a précédé. Chaque incident s'affiche en une ligne en gras, le détail de l'alerte en dessous, puis une ligne indentée par finding. La ligne en gras porte le début en heure locale, le service en ns/service quand l'alerte portait un namespace, le genre, firing ou ended, le nombre de findings et un marqueur de capture : complete, partial quand le ring avait déjà évincé une partie de la fenêtre et que la liste est donc en deçà de ce qui s'est déclenché, ou empty ring. Une ligne de finding montre son type, sa sévérité, son endpoint, son décompte sur la fenêtre et s'il s'est déclenché before ou after le redémarrage, ce marqueur ouvrant la ligne pour qu'un terminal étroit ne le coupe jamais. C'est le seul onglet qui demande une clé d'API, sauf si le daemon tourne avec [daemon] require_read_key = true, qui la demande sur chaque onglet : passez --api-key-file <PATH> (ou posez PERF_SENTINEL_DAEMON_API_KEY), et la clé en lecture seule [daemon] read_api_key suffit. Sans clé l'onglet nomme le 401 et comment en passer une. Un daemon qui tourne avec [daemon.incidents] enabled = false se lit comme une indication 503, un daemon antérieur à 0.20.0 comme une indication 404. Aucun des trois ne bascule [STALE], qui ne suit que le sondage du rapport, et un échec passager garde la dernière liste à l'écran. Le moniteur sonde les 20 incidents les plus récents. perf-sentinel query incidents --offset pagine au-delà et --namespace restreint la liste à un namespace. [Onglet Incidents : un OOM kill de checkout-svc encore actif, sa fenêtre capturée complète, un finding qui se déclenchait avant le redémarrage]

Quand le daemon devient injoignable, le dernier instantané valide reste affiché avec un indicateur [STALE] au lieu de se vider.

Thème du terminal

Les deux TUI (ce moniteur et le navigateur Inspect) suivent le thème du terminal lui-même : ils utilisent les 16 couleurs ANSI nommées et n'imposent jamais de fond, donc un terminal en thème clair les rend sur fond clair et un terminal sombre sur fond sombre. Le texte secondaire (titres, indications, en-têtes de colonnes) utilise l'attribut d'atténuation du terminal plutôt qu'un gris figé, pour rester lisible sur l'un comme sur l'autre fond. Il n'y a pas de flag --theme : configurez les couleurs dans votre émulateur de terminal.

Voir aussi

  • Flux d’acquittement pour la relation entre les acks TOML CI et les acks JSONL daemon, plus la table de décision complète.
  • Référence CLI pour la référence de la sous-commande perf-sentinel ack (équivalent CLI de a/u).
  • Rapport HTML pour le flux d'ack côté navigateur via --daemon-url.
  • API de query pour l'endpoint /api/energy que lit l'onglet Scrapers, et la surface HTTP en lecture seule du daemon.
  • Configuration pour la référence config [daemon.ack] côté serveur.