perf sentineldocs
ENGitHub
Documentation / Métriques

Référence des metrics exposées

Ce document liste toutes les metrics exposées par le daemon perf-sentinel sur /metrics (format Prometheus text). L'endpoint sert à la fois text/plain; version=0.0.4 (Prometheus historique) et application/openmetrics-text; version=1.0.0 (OpenMetrics) via content negotiation, et émet des exemplars quand des trace_id sont disponibles côté findings.

Introduction à Prometheus et OpenMetrics

Si vous n'avez jamais utilisé Prometheus, cette introduction courte est un préalable pour la suite du document. Elle suppose que vous savez ce qu'est HTTP et ce qu'est une métrique. Elle ne suppose pas de familiarité avec le langage de requête Prometheus ou l'opérateur Kubernetes. Les autres docs perf-sentinel renvoient ici pour les concepts Prometheus, voir Déploiement Helm et API de query.

Qu'est-ce que Prometheus. Prometheus est un projet de la Cloud Native Computing Foundation (CNCF), le système de métriques open source le plus largement déployé dans l'écosystème cloud-native. Il fonctionne par scraping : toutes les 15 à 60 secondes, le serveur Prometheus fait une requête HTTP GET sur l'endpoint /metrics de chaque cible, parse la réponse, et stocke les valeurs sous forme de séries temporelles. perf-sentinel expose un tel endpoint /metrics quand il tourne en mode daemon. Les opérateurs qui font déjà tourner Prometheus ajoutent perf-sentinel à leurs scrape_configs, et les métriques du daemon apparaissent à côté du reste de leur infrastructure.

Deux formats texte servis par perf-sentinel. La content negotiation choisit lequel le scraper reçoit.

  • text/plain; version=0.0.4 est le format d'exposition Prometheus original. Stable depuis 2014.
  • application/openmetrics-text; version=1.0.0 est OpenMetrics, l'évolution standardisée du format Prometheus publiée par la CNCF en 2020. C'est principalement un sur-ensemble, avec deux ajouts pratiques utilisés par perf-sentinel : les en-têtes # UNIT par métrique, et les exemplars (références de trace par point qui permettent à un panel Grafana de sauter d'un pic de métrique vers la trace exacte qui l'a produit).

Types de métriques. Chaque métrique ci-dessous porte un des trois types.

  • Counter, une valeur qui ne fait que monter (par exemple le nombre de spans OTLP ingérés). Remise à zéro uniquement au redémarrage. À lire en rate(metric[5m]) pour avoir un taux par seconde, jamais la valeur brute.
  • Gauge, une valeur qui monte et descend (par exemple le nombre de findings en vol, ou la mémoire résidente). À lire telle quelle.
  • Histogram, une distribution d'observations bucketisée par valeur (par exemple la latence de détection). Exposé comme plusieurs séries temporelles : _bucket{le=...} par bucket, plus _sum et _count. À lire avec histogram_quantile(0.99, ...) pour obtenir des percentiles de latence.

Pour aller plus loin. prometheus.io, spec OpenMetrics, exemplars dans OpenMetrics.

Metrics process (depuis 0.5.19, Linux uniquement)

Metrics standard du process_collector de la crate prometheus. Enregistrées uniquement sur Linux (les reads procfs sous-jacents échouent sur macOS/Windows). Les opérateurs sur des hôtes non-Linux ne voient que les metrics perf_sentinel_*.

MetricTypeDescription
process_resident_memory_bytesgaugeRSS du processus daemon.
process_virtual_memory_bytesgaugeMémoire virtuelle.
process_open_fdsgaugeFile descriptors ouverts.
process_max_fdsgaugeFile descriptors max autorisés.
process_start_time_secondsgaugeTimestamp Unix du démarrage du processus.
process_cpu_seconds_totalcounterTemps CPU cumulatif.

Coût par scrape. Le collector lit /proc/self/{stat,status,limits} et parcourt /proc/self/fd/ à chaque scrape. Sur un daemon avec des milliers de connexions OTLP longue durée plus des scrapers sortants, le parcours FD peut dominer entre 1 et 5 ms par scrape. Le lock Registry::gather() Prometheus est tenu pendant ce temps, donc un collector lent bloque les scrapes concurrents quand plusieurs scrapers (Prometheus + vmagent + sidecar) ciblent le même endpoint. Acceptable à l'intervalle typique de 15 à 60 secondes, à noter pour des intervalles plus serrés.

Périmètre d'exposition. Quand l'opérateur bind l'endpoint metrics sur 0.0.0.0 (défaut des Pods Kubernetes pour le scraping intra-cluster), les metrics process exposent des signaux opérationnellement sensibles : uptime via process_start_time_seconds (inférence de patch / restart), pression sur les file descriptors via process_open_fds et process_max_fds (oracle de saturation), empreinte mémoire via process_resident_memory_bytes. Le --listen-address par défaut est 127.0.0.1, ce qui restreint le scraping à l'hôte ou au Pod lui-même. Pour les topologies de scraping cluster-wide, mettre /metrics derrière une NetworkPolicy Kubernetes et préférer du mTLS côté Prometheus pour qu'un Pod voisin ne puisse pas lire l'état process du daemon librement.

Metrics d'ingestion OTLP

MetricTypeLabelsDescription
perf_sentinel_otlp_rejected_totalcounterreasonTotal des requêtes OTLP rejetées par le daemon depuis le démarrage, par raison (depuis 0.5.19).
perf_sentinel_otlp_spans_received_totalcounter(aucun)Total des spans OTLP reçus toutes requêtes confondues, avant le filtrage I/O (depuis 0.8.7).
perf_sentinel_otlp_spans_filtered_totalcounterreasonSpans OTLP écartés par la conversion parce qu'ils ne sont pas des opérations I/O analysables (depuis 0.8.7).

Valeurs du label reason :

  • unsupported_media_type (HTTP uniquement) : Content-Type n'est pas application/x-protobuf. perf-sentinel n'implémente pas la variante OTLP encodée en JSON.
  • parse_error (HTTP uniquement) : décodage protobuf raté.
  • channel_full (HTTP et gRPC) : le canal d'événements est saturé ou fermé et le daemon n'a pas pu enqueuer le batch. L'enqueue attend jusqu'à 2 secondes avant de rejeter, les rafales courtes sont donc absorbées sans rejet tandis qu'une saturation soutenue ressort vite. La voie HTTP renvoie 503, la voie gRPC renvoie UNAVAILABLE en saturation (les deux sont retryables selon la spec OTLP) et INTERNAL seulement quand le canal est fermé pendant l'arrêt.

Les 3 reasons sont pré-warmées à 0 au démarrage pour que les dashboards puissent plotter la ligne zéro avant le premier rejet.

payload_too_large n'est pas comptabilisé par cette metric. Tower-http (RequestBodyLimitLayer) côté HTTP et tonic (max_decoding_message_size) côté gRPC appliquent la limite en amont et renvoient 413 / RESOURCE_EXHAUSTED avant que le handler applicatif ne tourne. Les opérateurs préoccupés par la taille de payload doivent monitorer les logs du proxy ou de la gateway upstream, ou câbler un counter de rejet tower-http dans leur stack.

Les deux counters au niveau span exposent le taux de rétention du filtre I/O délibéré (seuls les spans SQL et HTTP sortants sont analysables, voir Limites). Une flotte dont l'instrumentation supprime db.statement ou http.url convertit chaque requête en zéro événement alors que les requêtes continuent de répondre en succès, et seule cette paire de counters rend cela visible : perf_sentinel_otlp_spans_received_total qui monte pendant que perf_sentinel_events_processed_total reste plat signifie que les spans arrivent mais qu'aucun ne porte d'attribut analysable. Valeurs du label reason de perf_sentinel_otlp_spans_filtered_total, pré-warmées à 0 :

  • not_io : le span ne porte ni statement db.* ni url ou méthode HTTP (span interne, hit de cache, middleware...). Dominant attendu sur les flottes bien instrumentées.
  • missing_db_statement : le span a db.system mais ni db.statement ni db.query.text. Typique des drivers configurés pour omettre le texte des requêtes.
  • missing_http_url : le span a une méthode HTTP mais ni http.url ni url.full.

Metrics d'analyse et de findings

MetricTypeLabelsDescription
perf_sentinel_findings_totalcountertype, severityFindings détectés depuis le démarrage. type reflète l'enum Finding.finding_type, severity vaut critical / warning / info. Porte des exemplars OpenMetrics quand un trace_id est disponible.
perf_sentinel_traces_analyzed_totalcounter(aucun)Compte cumulatif de traces traitées par l'event loop.
perf_sentinel_events_processed_totalcounter(aucun)Compte cumulatif d'events traités par l'event loop.
perf_sentinel_active_tracesgauge(aucun)Traces actuellement actives dans la fenêtre glissante.
perf_sentinel_analysis_queue_depthgauge(aucun)Lots en attente dans la file du worker d'analyse (incrémenté à l'enfilement, décrémenté quand le worker prend un lot). Une valeur non nulle durable signifie que detect+score prend du retard sur l'ingestion.
perf_sentinel_stored_findingsgauge(aucun)Findings actuellement retenus dans le ring buffer de la query API (depuis 0.8.8). À apparier avec perf_sentinel_max_retained_findings pour un ratio de headroom.
perf_sentinel_max_active_tracesgauge(aucun)Plafond configuré de la fenêtre glissante ([daemon] max_active_traces), positionné une fois au démarrage (depuis 0.8.8). À apparier avec perf_sentinel_active_traces. Le conseiller de réglages alerte à 90 %.
perf_sentinel_analysis_queue_capacitygauge(aucun)Plafond configuré de la file du worker d'analyse ([daemon] analysis_queue_capacity), positionné une fois au démarrage (depuis 0.8.8). À apparier avec perf_sentinel_analysis_queue_depth.
perf_sentinel_max_retained_findingsgauge(aucun)Plafond configuré du ring buffer de findings ([daemon] max_retained_findings), positionné une fois au démarrage (depuis 0.8.8). À apparier avec perf_sentinel_stored_findings.
perf_sentinel_analysis_shed_batches_totalcounter(aucun)Lots d'analyse délestés parce que la file du worker était pleine ou que le worker s'est arrêté. Remplace le drop implicite précédent : chaque délestage est compté ici. Alerte sur rate(...) > 0.
perf_sentinel_analysis_shed_traces_totalcounter(aucun)Traces abandonnées par les lots délestés comptés dans perf_sentinel_analysis_shed_batches_total.
perf_sentinel_correlator_pairs_evicted_totalcounter(aucun)Paires du corrélateur inter-traces évincées par le plafond max_tracked_pairs (depuis 0.8.7). Un taux soutenu signifie que la topologie de corrélation dépasse le plafond et que les paires les moins comptées sont recyclées, /api/correlations peut donc perdre des entrées entre deux lectures.
perf_sentinel_slow_duration_secondshistogramtypeHistogramme de durée pour les spans dépassant le seuil slow, par type (sql ou http_out). Buckets : 0.1, 0.25, 0.5, 0.75, 1, 1.5, 2, 3, 5, 10, 30 secondes. Utilisé par histogram_quantile() Grafana pour des percentiles précis sur des déploiements daemon shardés.
perf_sentinel_export_report_requests_totalcounter(aucun)Total des requêtes GET /api/export/report. Inclut les réponses cold-start (200 avec enveloppe vide).

Metrics d'ack (depuis 0.5.21)

Activité des opérateurs sur l'API ack du daemon (POST / DELETE /api/findings/{signature}/ack). Les acks TOML chargés depuis .perf-sentinel-acknowledgments.toml au démarrage sont en lecture seule et ne sont pas comptés ici, aucune opération n'a lieu après le chargement initial.

MetricTypeLabelsDescription
perf_sentinel_ack_operations_totalcounteractionOpérations ack et unack réussies.
perf_sentinel_ack_operations_failed_totalcounteraction, reasonOpérations ack et unack en échec, ventilées par raison.

Valeurs du label action : ack, unack.

Valeurs du label reason :

  • already_acked (HTTP 409, action=ack uniquement) : signature déjà présente dans le JSONL daemon, ou couverte par une baseline TOML CI encore active. Les deux cas sont comptés sur la même série.
  • not_acked (HTTP 404, action=unack uniquement) : la signature n'a pas d'ack daemon actif.
  • unauthorized (HTTP 401) : [daemon.ack] api_key est défini et la requête est sans header X-API-Key ou avec un header invalide. La série est pré-chauffée à zéro, donc une valeur non nulle confirme que api_key est configurée (le counter n'incrémente que quand l'auth est appliquée).
  • no_store (HTTP 503) : store ack daemon désactivé ([daemon.ack] enabled = false, ou chemin par défaut non résolvable au démarrage).
  • invalid_signature (HTTP 400) : le segment {signature} ne passe pas la validation de format canonique.
  • limit_reached (HTTP 507, action=ack uniquement) : MAX_ACTIVE_ACKS (10 000) atteint, refus du nouvel ack.
  • file_too_large (HTTP 507, action=ack uniquement) : l'append ferait dépasser le JSONL au-dessus de 64 Mio. Saturation par daemon, indique qu'une compaction est nécessaire au prochain redémarrage ou que la limite doit être relevée. Côté unack ce cas remonte sous internal_error (HTTP 500), les endpoints ack ne différencient pas la limite sur l'écriture unack aujourd'hui.
  • entry_too_large (HTTP 507, action=ack uniquement) : un seul record dépasse 4 Kio après sérialisation, typiquement parce que le champ by ou reason fourni par le caller est trop gros. Mauvais usage par requête, indique que la validation côté client doit être resserrée. Même réserve unack que pour file_too_large.
  • internal_error (HTTP 500) : erreur d'IO, de sérialisation, symlink refusé, permissions trop ouvertes, ou pas de chemin de stockage par défaut au moment de l'écriture.

Pré-chauffe. Les deux counters émettent zéro pour les combinaisons documentées atteignables avant la première requête, de sorte que les dashboards peuvent utiliser rate() sans clause absent(). Le set pré-chauffé compte 2 séries succès (action=ack et action=unack) plus 13 séries d'échec (8 raisons sur action=ack, 5 sur action=unack). Les combinaisons impossibles (par exemple action=ack,reason=not_acked ou action=unack,reason=already_acked) ne sont volontairement pas pré-chauffées pour éviter de fausses séries.

Exemples de requêtes.

  • rate(perf_sentinel_ack_operations_total[5m]) : opérations ack et unack par seconde, utile pour les courbes de tendance.
  • sum by (reason) (rate(perf_sentinel_ack_operations_failed_total{action="ack"}[5m])) : échecs ack par raison. Pic sur unauthorized qui indique une mauvaise configuration auth, pic sur entry_too_large qui pointe un client mal calibré (charges by / reason trop volumineuses), pic sur limit_reached ou file_too_large qui signale une saturation du store.

Compteurs de scrape Scaphandre (depuis 0.5.25)

Émis par tick du scraper Scaphandre côté daemon (la tâche qui récupère scaph_process_power_consumption_microwatts depuis l'endpoint [green.scaphandre] configuré, toutes les scrape_interval_secs). Enregistrés uniquement quand le daemon est compilé avec la feature daemon.

MetricTypeLabelsDescription
perf_sentinel_scaphandre_scrape_totalcounterstatusTotal des tentatives de scrape Scaphandre depuis le démarrage, partitionné par issue.
perf_sentinel_scaphandre_scrape_failed_totalcounterreasonTotal des scrapes Scaphandre en échec depuis le démarrage, partitionné par cause.
perf_sentinel_scaphandre_last_scrape_age_secondsgauge(aucun)Secondes depuis le dernier scrape réussi (remis à 0 sur succès). Canari pour scraper bloqué.

Valeurs du label status : success, failed. Pré-chauffés à zéro pour que les dashboards tracent un taux nul avant le premier scrape.

Valeurs du label reason :

  • unreachable : échec transport bas niveau (connexion refusée, échec DNS, erreur TLS handshake, host down). L'endpoint n'est pas joignable depuis le pod du daemon.
  • timeout : la deadline de 3 secondes sur l'appel HTTP par scrape a expiré avant la réponse.
  • http_error : l'endpoint a répondu avec un statut non-2xx.
  • body_read_error : erreur transport pendant le streaming du corps de réponse, après une lecture de statut réussie.
  • request_error : hyper n'a pas réussi à construire la requête HTTP depuis l'URI (post-validation). Rare, indique un cas-limite de configuration que le parser d'URI a manqué.
  • invalid_utf8 : le corps de réponse n'est pas de l'UTF-8 valide. Scaphandre émet toujours du texte Prometheus ASCII-safe, donc presque toujours signe que l'endpoint n'est pas Scaphandre.

Pré-chauffage. Les deux compteurs émettent zéro pour chaque valeur de label documentée avant le premier scrape, donc les requêtes rate() n'ont pas besoin de garde absent(). L'ensemble pré-chauffé est de 2 séries status plus 6 séries reason. Les échecs de parsing de configuration (URI d'endpoint invalide) abortent la tâche scraper au démarrage avant que le compteur soit touché, ils ne sont visibles que dans les logs daemon au niveau error.

Exemples de requêtes.

  • rate(perf_sentinel_scaphandre_scrape_total{status="success"}[5m]) divisé par rate(perf_sentinel_scaphandre_scrape_total[5m]) : ratio de succès des scrapes sur 5 minutes. Utile pour un panel SLO ou une alerte (< 0.95 sur 15 minutes signale un scraper dégradé).
  • topk(1, increase(perf_sentinel_scaphandre_scrape_failed_total[1h])) : raison d'échec dominante sur l'heure écoulée. Un unreachable persistant pointe typiquement vers un exporteur Scaphandre absent du host, un http_error persistant vers un exporteur derrière un reverse proxy qui renvoie le mauvais statut, un invalid_utf8 persistant vers un endpoint qui n'est pas Scaphandre du tout.

Metrics GreenOps

MetricTypeLabelsDescription
perf_sentinel_io_waste_ratiogauge(aucun)Ratio I/O waste cumulatif (avoidable / total) depuis le démarrage. Utiliser rate() sur les counters sous-jacents pour des valeurs sur fenêtre.
perf_sentinel_energy_kwhgauge(aucun)Énergie du workload sur la dernière fenêtre de scoring, kWh (depuis 0.8.8). Total scalaire seulement : le détail par service et par région reste hors /metrics (cardinalité) et vit sur les onglets Energy/Trends de query monitor.
perf_sentinel_carbon_gco2gauge(aucun)Carbone opérationnel de la dernière fenêtre de scoring, grammes CO2e, sommé sur les régions (depuis 0.8.8). Même logique scalaire que perf_sentinel_energy_kwh.
perf_sentinel_total_io_opscounter(aucun)Total cumulatif d'ops I/O traitées.
perf_sentinel_avoidable_io_opscounter(aucun)Total cumulatif d'ops I/O évitables détectées.
perf_sentinel_service_io_ops_totalcounterserviceOps I/O cumulatives par service (lu par chaque scraper d'énergie mesurée pour l'attribution énergie par service). La cardinalité du label est plafonnée à 1024 services distincts par exécution du daemon, les nouveaux services au-delà du plafond ne sont pas attribués.
perf_sentinel_service_io_ops_overflow_totalcounter(aucun)Ops I/O non attribuées à un counter par service parce que le plafond de cardinalité de 1024 services était atteint (depuis 0.8.7). Une hausse continue signifie que le débit par service et l'attribution d'énergie mesurée sous-comptent les services nouvellement vus.
perf_sentinel_scaphandre_last_scrape_age_secondsgauge(aucun)Secondes depuis le dernier scrape Scaphandre réussi. Reste à 0 quand Scaphandre n'est pas configuré. Utile pour des alertes scraper bloqué.
perf_sentinel_cloud_energy_last_scrape_age_secondsgauge(aucun)Même pattern pour le scraper cloud SPECpower.
perf_sentinel_kepler_last_scrape_age_secondsgauge(aucun)Même pattern pour le scraper Kepler. Voir le piège de staleness zéro-échantillon plus haut.
perf_sentinel_redfish_last_scrape_age_secondsgauge(aucun)Même pattern pour le scraper BMC Redfish.

Kinds de warning : transitoire vs collant

Report.warning_details (depuis 0.5.19) compte trois kinds stables, chacun avec un cycle de vie différent. La distinction compte pour la stratégie de monitoring : un warning transitoire se résout seul, un collant persiste jusqu'au redémarrage du daemon.

KindCycle de vieÉmis quandEffacé par
cold_startTransitoireevents_processed_total == 0 ou traces_analyzed_total == 0 sur le daemonPremier batch réussi (les deux compteurs strictement positifs)
ingestion_dropsCollantperf_sentinel_otlp_rejected_total{reason="channel_full"} > 0 depuis le démarrageRedémarrage du daemon (reset du compteur)
tuningMixteUn compteur lifetime montre un réglage sous-dimensionné pour la charge (voir dessous)Redémarrage pour les règles à compteurs, baisse de charge pour la règle de fenêtre

cold_start est un warning d'état : "le snapshot n'est pas significatif maintenant". ingestion_drops est un warning d'audit : "à un moment depuis le démarrage le canal a saturé, voici le count pour le post-mortem". Acquitter des findings via l'API ack du daemon n'efface aucun kind, ils reflètent l'état du daemon, pas la sortie de détection.

Le conseiller tuning (depuis 0.8.7)

Les entrées tuning sont des conseils de configuration : chaque message nomme le réglage, sa valeur actuelle et l'ajustement suggéré. Six règles tournent à chaque appel /api/export/report :

DéclencheurRéglage suggéré
perf_sentinel_otlp_rejected_total{reason="channel_full"} > 0[daemon] ingest_queue_capacity
perf_sentinel_analysis_shed_batches_total > 0[daemon] analysis_queue_capacity ou plus de CPU
perf_sentinel_active_traces à 90 % ou plus de max_active_traces[daemon] max_active_traces ou un trace_ttl_ms plus bas
perf_sentinel_service_io_ops_overflow_total > 0Agréger ou réduire les noms de services (le plafond de 1024 séries est fixe)
perf_sentinel_correlator_pairs_evicted_total > 0 avec corrélation activée[daemon.correlation] max_tracked_pairs
Tous les spans OTLP reçus filtrés comme non analysables (après 1000 spans)Corriger les attributs de spans ou pointer les services instrumentés vers cet endpoint

Les règles à compteurs sont collantes (les compteurs lifetime ne se réinitialisent qu'au redémarrage). La règle de fenêtre de traces lit une gauge, elle apparaît et disparaît donc avec la charge. Le conseiller lit le snapshot de config pris au démarrage du daemon, un hint reflète donc toujours les valeurs réellement utilisées par le process en cours.

Références croisées

  • Champ Report.warning_details (warnings de snapshot côté opérateur) : voir Runbook section "Lire les warnings du Report".
  • Workflow d'acquittements (suppression de findings cross-format) : voir Acquittements.
  • Emitter SARIF pour intégration CI : voir SARIF.