perf sentinelperf sentineldocs
FRENGitHub
Documentation / Méthodologie

Méthodologie

Ce sujet existe en version animée : voir l’étage Énergie dans le synoptique →

Ce document explique comment Perf Sentinel transforme des traces OpenTelemetry en champs efficiency_score, energy_kwh et carbon_kgco2eq exposés dans un rapport de transparence périodique. Il condense les notes de design par étage que l'on trouve dans docs/FR/design/ et Architecture. La cible est un auditeur ou un data scientist qui veut vérifier la chaîne de calcul de bout en bout sans lire tout l'arbre source.

Pipeline en un coup d'œil

events -> normalize -> correlate -> detect -> score -> report

Chaque étage est une fonction pure sur les données, avec des traits uniquement aux frontières d'I/O (IngestSource, ReportSink). Un finding produit par detect est apparié avec une estimation d'impact environnemental issue de score, puis agrégé par l'agrégateur de transparence périodique sur une période calendaire.

Introduction : énergie et SCI v1.0

Si vous n'avez jamais implémenté un scoring carbone pour des workloads logiciels, cette introduction courte est un préalable pour les formules de la suite du document. Elle ne suppose pas de familiarité préalable avec les cadres réglementaires (CSRD, GHG Protocol, RGESN) ni avec l'outillage énergétique (SCI v1.0, RAPL, Scaphandre, SPECpower, Boavizta, API Electricity Maps). Chaque terme est défini en une ligne à sa première apparition. Les autres docs Perf Sentinel renvoient ici pour les concepts de scoring vert, voir Configuration et Schéma.

Les cadres réglementaires en jeu. Perf Sentinel aligne son modèle carbone sur trois cadres dont les lecteurs ont pu entendre parler. Aucun n'est requis pour suivre la suite du document.

  • CSRD (Corporate Sustainability Reporting Directive) est le régime obligatoire UE 2024 de reporting de durabilité. Les grandes entreprises européennes doivent publier des inventaires d'émissions audités selon trois scopes (directes, électricité achetée, chaîne de valeur). Perf Sentinel peut alimenter une pipeline CSRD en données d'activité, mais n'est pas en soi un outil de reporting CSRD.
  • GHG Protocol (Greenhouse Gas Protocol) est le standard international de comptabilité des émissions des entreprises publié par le WRI/WBCSD, la référence de facto derrière la CSRD et la plupart des régulations nationales. Le Scope 2 couvre l'électricité achetée, le Scope 3 couvre tout le reste en amont et aval, y compris le calcul logiciel acheté en cloud.
  • RGESN (Référentiel Général d'Écoconception de Services Numériques) est le cadre français d'écoconception des services numériques publié par ARCEP, Arcom et ADEME en 2024. Il vérifie 78 critères couvrant architecture, contenu, hébergement et cycle de vie. Perf Sentinel associe chaque détecteur aux critères qu'il sert, voir la correspondance RGESN 2024 ci-dessous.

Pourquoi SCI v1.0. Software Carbon Intensity est le standard développé par la Green Software Foundation et publié comme ISO/IEC 21031:2024 (ISO/IEC JTC 1, mars 2024). L'artefact publié par la GSF est la SCI Specification, révision courante v1.1. Il définit un score carbone par unité fonctionnelle pour le logiciel, SCI = (E * I) + M, exprimé en gCO2eq par requête (ou par toute unité fonctionnelle choisie). Les trois termes correspondent à trois phénomènes physiques distincts mesurés chacun par un outillage différent. Perf Sentinel utilise SCI v1.0 parce que (a) c'est la méthodologie la plus largement adoptée pour comparer les émissions logicielles entre organisations, (b) elle sépare proprement l'optimisation marginale/évitable de la comptabilité d'inventaire totale, (c) elle est référencée par RGESN et alignée sur les frontières GHG Protocol Scope 2/3.

Les trois termes SCI.

  • E (Énergie) est l'électricité consommée par opération, en kWh. Perf Sentinel résout ce terme depuis la source configurée au runtime : un proxy I/O ou un des cinq backends mesurés. Le proxy est io_proxy_v3, environ 1e-7 kWh par opération d'I/O, directionnel uniquement, optionnellement recalibré par des coefficients fournis par l'opérateur via [green] calibration_file. Les backends mesurés sont Alumet RAPL, Scaphandre RAPL, Kepler RAPL réparti au temps CPU, Redfish BMC (puissance du châssis), et le pourcentage CPU fourni par le cloud projeté sur des tables SPECpower. Quand plusieurs couvrent le même service, le daemon garde la lecture de plus haute fidélité, dans cet ordre, voir l'échelle de fidélité dans Énergie & carbone. La source retenue est exposée dans methodology.calibration.energy_source_models pour qu'un auditeur vérifie quel chemin a produit E. Chaque barreau de l'échelle, le proxy I/O compris, chiffre l'hôte propre du service émetteur pour chaque opération qu'il émet : CPU, mémoire et pile réseau de cet hôte. L'appelé (serveur de base de données, broker, service en aval) n'y figure jamais. L'énergie des hôtes de base de données et de broker n'entre dans un rapport que par une source déclarée ou mesurée : [green.alumet.database], [green.database_static], [green.alumet.broker] ou [green.broker_static]. Le daemon la compte alors dans les totaux de la fenêtre comme un terme d'hôte, jamais dans les chiffres d'un service, voir Termes d'hôte de base de données et de broker. Les poids par verbe SQL et les paliers HTTP sont des poids relatifs qui classent les familles d'opérations. Leurs ratios viennent de benchmarks de serveurs de base de données, mais ils ne facturent aucun hôte de base de données.
  • I (Intensité du réseau) est le carbone émis par kWh par le réseau électrique local, en gCO2eq/kWh. Perf Sentinel embarque une table statique (couvrant toutes les régions cloud majeures et les principaux réseaux nationaux) et accepte une surcharge en direct via l'API Electricity Maps quand [green.electricity_maps] est configuré. Les lignes sur réseau national sont régénérées deux fois par an depuis les données annuelles Ember (base génération), via une PR de revue ouverte par le workflow refresh-datasets. Les lignes subnationales (Amérique du Nord, Brésil BR-CS) restent maintenues à la main depuis des sources zonales en base consommation. La source est exposée dans methodology.calibration.carbon_intensity_source comme une des valeurs static_tables, electricity_maps, rte_eco2mix, neso, fingrid, energinet, ree_esios, open_electricity, mavir, em6, ou mixed.
  • M (Carbone embarqué) couvre les émissions de fabrication du silicium sous-jacent (CPU, RAM, réseau, construction datacentre), amorties par requête. Perf Sentinel utilise un coefficient par défaut dérivé de Boavizta plus l'article HotCarbon 2024, surchargeable via [green] embodied_carbon_per_request_gco2. M est indépendant de la région et s'ajoute après E * I.

Qui lit quelle valeur. Un auditeur durabilité qui prépare une soumission CSRD scope 2 se soucie de total_carbon_kgco2eq et du bloc methodology.* qui prouve la source de chaque terme. Un SRE qui optimise le système se soucie de estimated_optimization_potential_kgco2eq, qui vaut canonical_waste.carbon_kgco2eq : la somme sur les fenêtres de (operational_gco2 * min(1, canonical_avoidable_io / accounted_io) + G_db * r_c_sql + G_msg * r_c_msg) / 1000, avec l'énergie du backend qui a scoré chaque fenêtre. G_db et G_msg sont le carbone des hôtes de base de données et de broker qu'une fenêtre a compté dans ses totaux (zéro sinon), r_c_sql et r_c_msg leurs ratios SQL et messaging au seuil canonique : chaque terme d'hôte compte une fois, au ratio des opérations qu'il sert. Il exclut M parce qu'on ne dé-fabrique pas du silicium en corrigeant un N+1. L'efficiency_score (0-100) est le résumé opérateur dérivé uniquement de io_waste_ratio, pas des émissions absolues.

Limite connue : intervalle d'incertitude 2x. L'estimation carbone est livrée avec une fourchette multiplicative 2x explicite. Cette fourchette signale que le modèle directionnel (en particulier le proxy I/O et les tables statiques d'intensité réseau) ne convient pas au reporting d'émissions à valeur réglementaire. Resserrer la fourchette demande un terme E mesuré (n'importe quel backend de l'Énergie & carbone : Alumet ou Scaphandre RAPL, Kepler, Redfish BMC, SPECpower cloud) et Electricity Maps en direct pour le terme I. La discussion complète sur l'incertitude vit dans Limites.

Termes connexes que vous rencontrerez dans les sections ci-dessous. Une ligne par terme seulement, les définitions complètes sont dans les références liées.

  • RAPL (Running Average Power Limit) est une fonctionnalité CPU Intel qui expose un compteur d'énergie matériel lisible via /sys/class/powercap/intel-rapl/. Il donne la consommation électrique par package à granularité milliseconde, sans instrumentation côté application. Les CPU AMD exposent une interface similaire sous un MSR différent. RAPL est ce que Scaphandre lit.
  • Scaphandre est un profileur d'énergie open source qui interroge les compteurs RAPL et expose les lectures de puissance par processus comme un endpoint Prometheus. Perf Sentinel scrape Scaphandre et attribue les lectures aux services instrumentés OTel via correspondance PID. Projet.
  • SPECpower (SPECpower_ssj2008) est une suite de benchmarks qui projette le pourcentage d'utilisation CPU sur la consommation électrique pour un SKU serveur publié. La méthodologie Cloud Carbon Footprint utilise les courbes SPECpower comme proxy quand la mesure directe n'est pas disponible. Perf Sentinel embarque une table SPECpower pour les principaux SKU cloud. Benchmark.
  • CCF (Cloud Carbon Footprint) est la méthodologie open source qu'Etsy a publiée en 2020, qui combine tables SPECpower, intensités de réseau par région cloud, et amortissement embarqué. Le chemin cloud-energy de Perf Sentinel est compatible CCF, mêmes entrées, mêmes coefficients. Projet.
  • Ember est le think tank énergie qui publie des données électriques annuelles ouvertes (CC-BY-4.0), dont l'intensité CO2 de la production par pays. Les lignes sur réseau national de la table statique embarquée en sont régénérées. Données.
  • Boavizta est l'association française qui publie des méthodologies ouvertes et des données de référence pour l'analyse de cycle de vie des équipements numériques, en particulier les coefficients de carbone embarqué pour CPU et serveurs. Le terme M par défaut dans Perf Sentinel dérive de Boavizta plus l'article HotCarbon 2024. Projet.
  • API Electricity Maps est le service commercial (son offre API gratuite est réservée aux usages non commerciaux) qui publie l'intensité carbone horaire par zone (gCO2eq/kWh) pour plus de 250 zones dans le monde. Perf Sentinel l'appelle à la demande quand [green.electricity_maps] est configuré. Chaque requête retourne soit un facteur direct (génération opérationnelle uniquement) soit un facteur lifecycle (opérationnel plus fabrication des actifs de production). Perf Sentinel enregistre celui qui a été utilisé. Doc API.
  • gCO2eq / kgCO2eq signifie "grammes (ou kilogrammes) de CO2 équivalent". Équivalent parce que les gaz à effet de serre autres que le CO2 (méthane, protoxyde d'azote, ...) sont pondérés par leur pouvoir de réchauffement global ramené à une base CO2. Unité standard utilisée dans CSRD, GHG Protocol, SCI.
  • Émissions marginales vs moyennes. L'émission moyenne est l'intensité moyenne du réseau sur une fenêtre (ce que donnent les tables statiques et la plupart des réponses Electricity Maps). L'émission marginale est l'intensité du prochain kWh consommé (souvent une centrale fossile de pointe), pertinente pour des décisions de décalage de charge mais pas pour le reporting d'inventaire. Perf Sentinel rapporte la moyenne : SCI v1.1 (2024) autorise l'intensité marginale court terme, marginale long terme ou moyenne (le texte SCI v1.0 / ISO exigeait les taux marginaux). Le scoring marginal est une amélioration future.

Ancrage dans la littérature

Le choix méthodologique d'exposer un score directionnel (efficiency_score calculé sur io_waste_ratio) et de classer les endpoints par impact relatif, plutôt que de rapporter une valeur absolue en watts, s'appuie sur une littérature indépendante autour de la mesure énergétique logicielle.

  • Les compteurs énergétiques matériels sont précis pour leur périmètre. Khan, Hirki, Niemi, Nurminen et Ou (RAPL in Action: Experiences in Using RAPL for Power Measurements, ACM TOMPECS 3(2):1-26, 2018) caractérisent RAPL comme une source d'énergie fiable pour les packages CPU et DRAM qu'il couvre, avec la réserve connue qu'il n'inclut pas la périphérie, le stockage ni les pertes d'alimentation.
  • Les compteurs logiciels suivent le signal matériel. Jay, Ostapenco, Lefèvre, Trystram, Orgerie et Fichel (An experimental comparison of software-based power meters: focus on CPU and GPU, IEEE/ACM CCGrid 2023) rapportent une forte corrélation entre les compteurs logiciels (dont Scaphandre) et un wattmètre externe, tout en montrant que l'écart résiduel entre matériel et logiciel est significatif et non constant selon les workloads. Les compteurs logiciels sont de bons porteurs de signal, pas des substituts à la mesure absolue.
  • Le relatif l'emporte sur l'absolu, et les déterminants principaux sont les patterns de requêtes. Ruch (Towards Greener Software: Measuring Performance and Energy Efficiency of Enterprise Applications, MSE Project Thesis, OST Eastern Switzerland University of Applied Sciences, superviseur Prof. Dr. Olaf Zimmermann, 2025) établit que les valeurs absolues d'énergie ne sont pas comparables entre systèmes d'exploitation, applications et jeux d'instructions, alors que la distribution relative de la consommation l'est, à travers OS, applications et ensembles d'opérations. Ce même travail identifie les patterns d'accès base de données (nombre de requêtes, volume d'enregistrements lus, technologie d'accès) comme les déterminants énergétiques majeurs des applications d'entreprise.

Perf Sentinel se situe dans cette tradition. Le pipeline classe les endpoints par IIS relatif, compare les runs par deltas d'io_waste_ratio, et détecte les patterns d'accès base de données et inter-services que la littérature identifie comme déterminants énergétiques majeurs (N+1 SQL, N+1 HTTP, redundant SQL, redundant HTTP, fetch-all, fanout, chatty services, appels sérialisés). Il ne revendique pas une précision absolue de niveau wattmètre. La fourchette multiplicative 2x sur l'estimation carbone, le positionnement explicite comme compteur de gaspillage directionnel, et la discussion complète du périmètre et de la précision vivent dans Limites.

I/O Intensity Score (IIS)

Le proxy de base pour l'énergie est le nombre d'opérations d'I/O par couple (service, endpoint). Perf Sentinel compte les spans SQL, HTTP sortants et de publication de messages comme des opérations d'I/O.

  • total_io_ops : nombre de spans d'I/O sur l'ensemble des traces de la fenêtre analysée.
  • avoidable_io_ops : nombre de spans d'I/O attribués à des anti-patterns évitables. Les patterns évitables sont N+1 SQL, N+1 HTTP, N+1 messaging, redundant SQL et redundant HTTP, tous énumérés par FindingType::is_avoidable_io(). Les deux premiers et les deux derniers sont aussi listés dans core_patterns_required de toute divulgation officielle, le N+1 messaging non, car un bus de messages n'est pas assez universel pour être exigé de toute organisation qui publie.
  • Les commandes de gestion de connexion et de session (COMMIT, SET, SELECT set_config(...), pings de pool) n'atteignent jamais ce compteur : les détecteurs de répétition les ignorent, aucun finding ne les attribue donc. Elles restent dans total_io_ops, puisqu'un driver poolé en exécute une par acquisition de connexion, mais elles ne sont pas évitables et aucune remédiation par batch ne s'y applique. Voir la section "Commandes de session et ratio de gaspillage" de Limites pour la frontière de l'exclusion.
  • io_waste_ratio = avoidable_io_ops / total_io_ops, dans [0, 1].
  • total_sql_io_ops et avoidable_sql_io_ops : la part SQL des deux compteurs ci-dessus, avec la même sémantique de déduplication restreinte aux types de findings SQL. Ils permettent d'appliquer le ratio de gaspillage SQL à une énergie de base de données mesurée en dehors de Perf Sentinel (par exemple Alumet sur le cgroup de la base) : db_waste = measured_db_energy * avoidable_sql_io_ops / total_sql_io_ops. Les deux valent 0 dans les rapports produits par des versions antérieures à ces champs.
  • total_messaging_io_ops et avoidable_messaging_io_ops : la même paire pour les publications de messages, appliquée à une lecture d'énergie de broker plutôt que de base de données : broker_waste = broker_energy * avoidable_messaging_io_ops / total_messaging_io_ops. L'énergie du broker est mesurée (Alumet sur son cgroup), modélisée (une cpu_query sur [green.broker_static], son enveloppe SPECpower interpolée à ce CPU, cloud_specpower), déclarée (un cluster provisionné lu dans la table SPECpower embarquée) ou estimée comme la part côté application des spans de publication, l'énergie que le scoring des spans a donnée aux services qui publient, et l'étiquette model du chiffre indique laquelle. Un chiffre mesuré, modélisé ou déclaré est une énergie d'hôte de broker, que le daemon compte dans les totaux comme un terme d'hôte dès que son carbone est converti. L'estimation y est déjà comprise et n'y est jamais ajoutée une seconde fois. Contrairement au chiffre de la base de données, le sens de l'erreur dépend de la source : une mesure sous-compte (l'attribution par défaut d'Alumet ne couvre que le CPU), un modèle suit la charge sur une enveloppe qui laisse de côté le stockage et le réseau, une déclaration borne le calcul à pleine charge sans le stockage ni le réseau, l'estimation ne contient aucune énergie d'hôte de broker. Voir Limites.
  • database_waste : cette même formule calculée à chaque exécution, étiquetée par model. Quand [green.alumet.database] est déclaré et que le daemon a reçu une lecture, l'énergie est l'énergie de fenêtre mesurée du cgroup de la base (model = "alumet_rapl"). Dans ce cas, la région de l'hôte de la base (sa propre region, celle de [green.database_static] ou [green] default_region, l'une d'elles est requise) convertit l'énergie et le gaspillage en gCO2 avec l'intensité réseau de la région (temps réel Electricity Maps si disponible, annuelle embarquée sinon) et le PUE du fournisseur, profils horaires non appliqués. Quand [green.database_static] déclare les hôtes à la place, l'énergie est leur plafond SPECpower (model = "database_specpower") ou, avec une cpu_query, leur enveloppe SPECpower interpolée au CPU des hôtes (model = "cloud_specpower"), convertie à la même région. Quand aucune source de base n'existe (exécutions batch, ou ni [green.alumet.database] ni [green.database_static]), le chiffre se rabat sur une estimation : la part côté application des spans SQL de la fenêtre, l'énergie que le scoring des spans a résolue pour eux, multipliée par le ratio de gaspillage SQL, étiquetée model = "estimated". Les poids par verbe et la calibration ne s'appliquent qu'aux spans du proxy, un coefficient par op mesuré ou cloud les remplace, et le carbone utilise la région du service émetteur. Une base déclarée sans lecture reçue n'émet rien. Son énergie se reporte sur la prochaine fenêtre livrée, si bien que le total de période ne compte jamais deux fois. Le mesuré est une énergie d'hôte de base de données, une borne basse CPU seulement, et les chiffres modélisés et déclarés sont eux aussi une énergie d'hôte. Les trois comptent dans les totaux comme un terme d'hôte dès que leur carbone est converti (voir Termes d'hôte de base de données et de broker). L'estimé réutilise l'énergie par span exactement telle que le scoring l'a résolue (sources mesurées par service quand elles existent, proxy I/O avec son encadrement 2x sinon) : c'est donc la part côté application de energy_kwh/co2, sans aucune énergie d'hôte de base de données, et elle n'y est jamais ajoutée. La divulgation le porte comme bloc séparé aggregate.database_waste (v1.4) avec les deux seuils et les modèles de provenance, une ventilation jamais ajoutée par-dessus les totaux. Voir la section "Limites de précision Alumet" de Limites.

Énergie par opération

L'énergie opérationnelle est approximée par un proxy à coefficient unique :

energy_kwh = total_io_ops * ENERGY_PER_IO_OP_KWH

ENERGY_PER_IO_OP_KWH = 1e-7 kWh est documenté dans score/carbon.rs et étiqueté comme modèle io_proxy_v3. Le coefficient est une estimation directionnelle, pas une mesure. Il chiffre l'hôte propre du service émetteur pour chaque opération qu'il émet, jamais l'appelé.

Lorsque l'opérateur branche un des backends mesurés (Alumet, Scaphandre, Kepler, Redfish, ou le scraper cloud SPECpower), Perf Sentinel substitue une énergie mesurée par service sur le même périmètre, l'hôte du service émetteur, et bascule le tag de modèle en conséquence (alumet_rapl, scaphandre_rapl, kepler_ebpf, redfish_bmc, cloud_specpower). La section méthodologie d'un rapport expose scaphandre_used et specpower_table_version pour que les consommateurs sachent quel chemin a produit les chiffres.

CO2 opérationnel

Le terme opérationnel SCI (Software Carbon Intensity) est O = E * I, où E est l'énergie par fenêtre en kWh et I est l'intensité carbone du réseau en gCO2eq/kWh pour la région de la charge.

Perf Sentinel embarque une table d'intensité réseau statique et accepte une surcharge temps réel via l'API Electricity Maps quand [green.electricity_maps] est configurée, ou via les flux gratuits des gestionnaires de réseau pour la France, la Grande-Bretagne, la Finlande, le Danemark, l'Espagne, l'Australie, la Hongrie et la Nouvelle-Zélande ([green.rte_eco2mix], [green.neso], [green.fingrid], [green.energinet], [green.ree_esios], [green.open_electricity], [green.mavir], [green.em6], émissions directes, Electricity Maps l'emportant là où les deux s'appliquent). Les lignes sur réseau national sont rafraîchies deux fois par an depuis les données annuelles Ember (base génération, granularité nationale, dernière année disponible par pays), via une PR de revue. Les lignes subnationales (Amérique du Nord, Brésil BR-CS) restent maintenues à la main depuis des sources zonales en base consommation, et les profils horaires sont renormalisés dès qu'une valeur annuelle bouge de plus de 5 pour cent. Les comptabilités génération et consommation divergent surtout sur les réseaux bas carbone reliés aux importations (les lignes nordiques ont été multipliées par plusieurs au changement de source). Les deux restent bien à l'intérieur de la fourchette d'incertitude 2x documentée pour les réseaux fortement carbonés, et cette fourchette reste la réserve qui prime dans tous les cas. Le champ methodology.calibration.carbon_intensity_source d'un rapport vaut electricity_maps, rte_eco2mix, neso, fingrid, energinet, ree_esios, open_electricity, mavir, em6, static_tables ou mixed pour qu'un auditeur puisse vérifier quel chemin a produit le CO2 opérationnel.

CO2 embarqué

Le terme SCI M couvre les émissions du silicium fabriqué, amorties par requête. Perf Sentinel utilise un coefficient par défaut fixe documenté dans config.rs::DEFAULT_EMBODIED_CARBON_PER_REQUEST_GCO2, surchargeable via [green] embodied_carbon_per_request_gco2. Le CO2 embarqué est indépendant de la région, ajouté au CO2 opérationnel avant que le total par fenêtre ne soit sommé sur la période du rapport.

Termes d'hôte de base de données et de broker

Un chiffre d'hôte de base de données ou de broker mesuré ([green.alumet.database], [green.alumet.broker]), modélisé (une cpu_query sur [green.database_static] ou [green.broker_static], cloud_specpower) ou déclaré (le plafond de [green.database_static] ou de [green.broker_static]) entre dans les totaux de la fenêtre comme terme d'hôte, à côté du transport réseau. Seul le daemon watch en produit, car facturer un hôte demande une durée de fenêtre. Un chiffre entre quand il n'est pas la part estimée, que son carbone a été converti à la région de l'hôte et que la fenêtre a un rapport carbone : son énergie et son carbone entrent donc toujours ensemble, et le chiffre porte alors in_totals = true. Un chiffre sans conversion carbone reste hors des totaux, avec in_totals à faux.

Avec A l'énergie des services, O le carbone opérationnel sommé sur les régions, M l'embarqué, T le transport, D et G_db les kWh et gCO2 de l'hôte de base de données, B et G_msg ceux du broker, et r_sql, r_msg les ratios de gaspillage SQL et messaging au seuil de l'opérateur, un terme d'hôte hors des totaux comptant zéro :

energy_kwh         = A + D + B
co2.database_gco2  = G_db
co2.messaging_gco2 = G_msg
co2.total.mid      = O + M + T + G_db + G_msg
co2.avoidable.mid  = O * min(1, avoidable_io / accounted_io) + G_db * r_sql + G_msg * r_msg
co2.sci_per_trace  = co2.total.mid / traces

operational_gco2, regions[] et les maps per_service_* ne portent que l'application : un hôte n'est jamais un service. Les niveaux de gaspillage de la divulgation chiffrent séparément le réservoir applicatif et chaque réservoir d'hôte, chaque hôte au ratio de son propre sous-système, si bien qu'une base n'est jamais chiffrée au ratio d'appels qu'elle ne sert pas :

canonical.energy_kwh   = A * min(1, canonical_io / accounted_io) + D * r_c_sql + B * r_c_msg
canonical.gco2         = O * min(1, canonical_io / accounted_io) + G_db * r_c_sql + G_msg * r_c_msg
operational.energy_kwh = A * min(1, avoidable_io / accounted_io) + D * r_sql + B * r_msg
operational.gco2       = co2.avoidable.mid

r_c_sql et r_c_msg recalculent les ratios SQL et messaging au seuil canonique figé dans le binaire. Le ratio du broker compte un span de publication comme un aller-retour, une borne haute sur Kafka, dont le producteur regroupe les écritures sur le réseau (voir Limites).

Chaque fenêtre scorée avec une source d'hôte configurée étiquette co2.total avec sci_v1_numerator+transport+hosts et co2.avoidable avec sci_v1_operational_ratio+hosts, énergie d'hôte nulle comprise, comme le fait l'étiquette du transport. co2.sci_per_trace garde sci_v1_intensity. Les chiffres estimés (model = "estimated") restent des parts de A et n'entrent jamais une seconde fois dans les totaux.

Agrégation sur une période

perf-sentinel disclose lit les enveloppes Report archivées par fenêtre ({ts, report}) et les replie en trois étapes.

  1. Les enveloppes sont filtrées pour ne garder que celles qui tombent dans la période calendaire demandée.
  2. Les compteurs globaux additionnent total_io_ops, avoidable_io_ops, total.mid (gCO2), avoidable.mid (gCO2). gCO2 est divisé par 1000 pour obtenir kgCO2eq.
  3. L'attribution par service utilise les maps per_service_* calibrées au runtime quand la fenêtre source les porte. Sinon les totaux globaux sont distribués proportionnellement à la part d'I/O par service lue depuis Report.per_endpoint_io_ops. Une fenêtre sans offenders par service est rangée sous _unattributed sauf si --strict-attribution a été passé. L'énergie et le carbone d'hôte comptés dans les totaux n'atteignent jamais un service, quel que soit le chemin : les chemins proportionnel et _unattributed répartissent le total de la fenêtre moins les termes d'hôte, que publient à la place aggregate.carbon_breakdown.database_kgco2eq et messaging_kgco2eq.

efficiency_score = clamp(100 - 100 * io_waste_ratio, 0, 100). L'efficacité par service utilise la même formule sur le ratio évitable / total propre au service.

Les signaux de qualité (0.7.0+) résument quelle part de la période a été mesurée directement plutôt qu'inférée du proxy.

  • period_coverage = runtime_windows / total_windows, dans [0, 1], avec runtime_windows_count et fallback_windows_count qui portent les compteurs absolus derrière le ratio.
  • binary_versions est l'ensemble des versions du binaire Perf Sentinel observées sur la période, une mise à jour de daemon en milieu de période faisant porter plus d'une entrée à cet ensemble.
  • calibration_applied sur methodology.calibration_inputs bascule à true quand au moins une fenêtre a appliqué les coefficients de calibration opérateur à l'énergie proxy.
  • per_service_energy_models et per_service_measured_ratio (à la fois dans GreenSummary par fenêtre et dans Aggregate sur la période) exposent la vue de fidélité par service : quel modèle énergétique a alimenté chaque service et quelle fraction de ses spans a été mesurée.

Les définitions de ces champs au format sérialisé vivent dans les sections "Agrégat" et "Méthodologie" de Schéma.

Correspondance RGESN 2024

Le RGESN 2024 (ARCEP, Arcom, ADEME) définit 78 critères d'écoconception répartis en neuf familles, numérotés family.criterion. La table ci-dessous associe chaque détecteur de Perf Sentinel aux critères dont il sert l'intention.

C'est une correspondance interprétative, pas une certification de conformité. Les titres des critères RGESN ne nomment pas "requête N+1" ni "requête lente". Ce sont les critères qu'une détection aide à satisfaire, exposés pour qu'un auditeur puisse relier un finding au référentiel. La forme exploitable par machine est FindingType::rgesn_criteria() dans le code et le champ rgesn_criteria par pattern dans les détails d'anti-pattern du rapport de transparence.

DétecteurCritères RGESNIntention du critère
n_plus_one_sql, n_plus_one_http, n_plus_one_messaging7.1, 6.1Cache serveur pour les données les plus utilisées, budget de requêtes par écran
redundant_sql, redundant_http7.1, 6.5Cache serveur, éviter le chargement de ressources inutiles
chatty_service4.9, 4.10, 6.1Limiter et éviter les requêtes serveur inutiles, budget de requêtes par écran
excessive_fanout, pool_saturation3.2Architecture qui adapte les ressources à la demande réelle
serialized_calls8.10Minimiser l'impact des calculs et transferts de données asynchrones
slow_sql, slow_http, slow_messaging(aucun)Le RGESN n'a pas de critère sur la latence d'une opération unique. La famille 9 "Algorithmie" cible les charges de machine learning, pas la latence des requêtes.

Limitations connues du schéma v1.0

  • L'énergie et le carbone par service sont calibrés au runtime quand l'archive source les porte. Le GreenSummary de chaque fenêtre expose energy_kwh, energy_model, per_service_energy_kwh, per_service_carbon_kgco2eq et per_service_region. L'agrégateur somme directement ces valeurs. Les archives écrites avant la livraison de cette fonctionnalité ne portent pas les champs : l'agrégateur se rabat alors sur une énergie proxy (total_io_ops × ENERGY_PER_IO_OP_KWH) et une part d'I/O proportionnelle pour le carbone, en émettant un unique tracing::warn! par fichier d'archive concerné. L'ensemble des tags energy_model observés est exposé sous methodology.calibration_inputs.energy_source_models.
  • Le potentiel d'optimisation exclut le carbone embarqué. estimated_optimization_potential_kgco2eq couvre la part opérationnelle évitable plus le carbone des hôtes de base de données et de broker inclus dans les totaux, à leurs ratios SQL et messaging canoniques (on ne peut pas dé-fabriquer du silicium en corrigeant des N+1). L'agrégat total_carbon_kgco2eq se compose des termes opérationnel, embarqué, transport, base de données et broker. Le disclaimer dans notes.disclaimers le précise explicitement.
  • Le carbone par service exclut l'embarqué. Le terme embarqué (M au sens SCI) ne vit qu'au niveau agrégat. sum(per_service_carbon_kgco2eq) × 1000 approxime co2.operational_gco2, pas co2.total.mid.
  • Bucket _unattributed. Les fenêtres dont Report.per_endpoint_io_ops est vide (et qui n'ont pas non plus de maps par service calibrées au runtime) tombent dans le service _unattributed. disclose --strict-attribution refuse ces fenêtres. Les findings de ces fenêtres sont aussi rangés sous _unattributed pour qu'un service ne soit jamais publié avec efficiency_score = 100 et des anti-patterns non nuls.
  • Couverture de la période et seuil de 75% (0.7.0+). Chaque rapport porte aggregate.period_coverage, la fraction des fenêtres de scoring qui ont utilisé l'énergie calibrée au runtime plutôt que le repli sur le proxy. Un rapport intent = "official" avec une couverture sous 0.75 est rejeté par le validateur. Un rapport intent = "internal" sous ce seuil porte un disclaimer explicite dans notes.disclaimers. La justification empirique de 0.75 vit dans 08 · Divulgation périodique.
  • Le ratio mesuré par service est uniforme sur les spans et moyenné par fenêtre (0.7.0+). per_service_measured_ratio dans GreenSummary est la fraction des spans d'un service dont l'énergie a été résolue par l'un des backends mesurés dans cette fenêtre. La valeur au niveau de la période dans Aggregate.per_service_measured_ratio est la moyenne arithmétique simple des ratios par fenêtre, pas pondérée par le nombre de spans : une fenêtre de 10 spans et une fenêtre de 10000 spans contribuent à part égale. Un service dont per_service_energy_model indique scaphandre_rapl avec per_service_measured_ratio de 0.05 a eu une seule observation Scaphandre contre 95% de repli sur le proxy dans la fenêtre : le tag indique la meilleure source observée, le ratio décrit la fidélité.
  • Flag de calibration binaire, à l'échelle de la période (0.7.0+). methodology.calibration_inputs.calibration_applied vaut true dès qu'au moins une fenêtre de la période a eu une calibration opérateur active, même si 89 fenêtres sur 90 ne l'avaient pas. Le texte du disclaimer dans notes.disclaimers reprend cette formulation exacte pour qu'un lecteur ne puisse pas confondre le flag avec "toutes les fenêtres étaient calibrées".
  • Versions du binaire sur la période (0.7.0+). aggregate.binary_versions liste les versions du binaire Perf Sentinel qui ont produit les archives sources. Une période qui couvre plusieurs versions porte un disclaimer qui invite le consommateur à vérifier la compatibilité de version avant de comparer ce rapport à des baselines historiques. L'ensemble est plafonné à 256 entrées. Dans le cas improbable où un trimestre en couvrirait davantage, les entrées en surplus sont silencieusement abandonnées.

Intervalle d'incertitude

Chaque rapport est livré avec un intervalle multiplicatif 2x sur l'estimation carbone. Cet intervalle signale que la sortie est directionnelle et inadaptée à un reporting d'émissions réglementaire (CSRD, GHG Protocol Scope 3). Le bloc notes.disclaimers du rapport le rappelle en anglais lisible par l'opérateur, y compris les limitations spécifiques à la v1.0 ci-dessus.

Vérifier un rapport

Un rapport porte :

  • integrity.content_hash : SHA-256 sur la forme JSON canonique (clés d'objets triées, sérialisation compacte, UTF-8) avec content_hash mis à chaîne vide. Un consommateur recalcule en posant content_hash à "" sur sa propre copie puis en calculant le hash.
  • integrity.binary_hash : SHA-256 du binaire Perf Sentinel qui a produit le fichier, lu via std::env::current_exe(). À coupler avec binary_verification_url pour vérifier que le binaire correspond à une release publiée.

integrity.trace_integrity_chain porte le verdict de la chaîne de hachage de l'archive depuis le schéma v1.6 : combien de fenêtres sont vérifiées, combien ne portent pas de chaîne, et combien de ruptures ont été trouvées. Le champ vaut null sur les rapports écrits avant v1.6. Voir Schéma.

Intégrité cryptographique (0.7.0+)

Voir aussi. L'introduction à Sigstore dans la doc supply-chain définit Cosign, Fulcio, Rekor, in-toto, OIDC et SLSA utilisés dans cette section.

Deux primitives optionnelles s'ajoutent au content hash pour ancrer un rapport publié dans une infrastructure publique.

  • Signature Sigstore (integrity.signature). Quand l'opérateur signe l'attestation in-toto v1 du rapport via cosign sign-blob, le rapport porte des métadonnées (bundle_url, signer_identity, signer_issuer, rekor_url, rekor_log_index, signed_at) qui permettent à un consommateur de récupérer le bundle et de le vérifier via Rekor public. verify-hash refuse les bundles sans preuve d'inclusion Rekor, donc la transparence est une propriété du format, pas une option.
  • Provenance SLSA du binaire (integrity.binary_attestation). Les binaires de release perf-sentinel officiels portent une attestation de provenance SLSA (Build niveau 2) produite par le workflow de release GitHub Actions (actions/attest-build-provenance à partir de v0.7.1, slsa-framework/slsa-github-generator SLSA L2 sur la release v0.7.0). Le rapport enregistre les métadonnées de localisation pour qu'un consommateur vérifie l'attestation contre le binaire référencé par integrity.binary_verification_url, via gh attestation verify <binary> --owner robintra --signer-repo robintra/perf-sentinel pour 0.7.1 à 0.26.2, gh attestation verify <binary> --repo Institut-du-Numerique-Responsable/perf-sentinel pour les suivantes, ou slsa-verifier verify-artifact contre l'ancien asset de release multiple.intoto.jsonl pour la 0.7.0.

Combinées, les deux primitives forment la chaîne source -> SLSA -> binary -> report -> Sigstore signature. verify-hash chaîne le recalcul du content hash, le contrôle que l'attestation signée désigne ce content hash, la signature cosign, et l'indication de vérification SLSA en une commande. La méthodologie, les modes d'échec, et les considérations de confidentialité liées à Rekor public vivent dans 10 · Sigstore & SLSA.