perf sentinelperf sentineldocs
FRENGitHub
Documentation / Schéma

Référence schéma : perf-sentinel-report v1.8

Ce document décrit la forme JSON d'un rapport de transparence périodique en prose. Le JSON Schema lisible par machine se trouve dans docs/schemas/perf-sentinel-report-v1.json (draft 2020-12). Deux exemples remplis sont sous docs/schemas/examples/.

La v1.1 ajoute les niveaux canonical_waste et operational_waste à aggregate. La v1.2 ajoute aggregate.temporal_coverage (un signal de continuité de mesure), scope_manifest.coverage_basis (un marqueur de provenance) et le point d'extension réservé integrity.cross_period_log. La v1.3 ajoute methodology.standard_crosswalk (une correspondance interprétative vers les datapoints ESRS E1) et applications[].anti_patterns[].rgesn_criteria par pattern (critères RGESN 2024). La v1.4 ajoute aggregate.database_waste (l'énergie et le carbone évitables du travail SQL aux deux seuils, avec ses modèles de provenance, une décomposition informative jamais ajoutée par-dessus un total). La v1.5 ajoute la prise en charge du messaging : deux valeurs à PatternName (n_plus_one_messaging, slow_messaging) et aggregate.messaging_waste, émis dès lors que des spans de publication vers un broker sont ingérés. messaging_waste est le jumeau de database_waste pour le travail de publication, tout aussi informatif et tout aussi jamais ajouté par-dessus un total, même si le sens de son erreur dépend de son étiquette model (voir Limites). Les deux blocs de gaspillage gagnent aussi declared_windows et declared_energy_kwh, qui portent la part du chiffre qu'un opérateur a déclarée plutôt que mesurée, pour qu'une déclaration de cluster provisionné ne soit jamais publiée dans measured_energy_kwh. Ils sont omis quand ils valent zéro. La v1.6 rend visibles les paramètres carbone, via quatre champs de methodology.calibration_inputs. carbon_methodologies porte les tags SCI observés sur les fenêtres de la période, qui disent si le transport réseau est entré dans le numérateur. embodied_gco2_total est le terme M de SCI sommé sur la période. embodied_gco2_per_request est ce total divisé par total_requests, donc comparable d'un rapport à l'autre et indépendant du volume de trafic. scoring_coefficients porte les coefficients avec lesquels les fenêtres ont été scorées, sous forme de chaînes key=value, deux entrées pour une même clé signalant un changement en cours de période. Les réglages derrière ces champs, à commencer par [green] embodied_carbon_per_request_gco2 et [green] network_energy_per_byte_kwh, mettent à l'échelle les chiffres publiés et n'apparaissaient nulle part dans le rapport : diviser un coefficient par deux ne laissait aucune trace. carbon_methodologies, embodied_gco2_total et scoring_coefficients sont lus sur les fenêtres archivées plutôt que sur la configuration de la machine qui lance disclose, seule source correcte quand la période a été produite ailleurs. Plusieurs entrées dans carbon_methodologies signalent que la période couvre des méthodologies de numérateur historiques et actuelles, ou, avec sci_v1_numerator+transport+hosts à côté de sci_v1_numerator+transport, que certaines fenêtres ont été scorées avec une source d'hôte de base de données ou de broker configurée. La v1.6 décompose aussi le total publié : aggregate.carbon_breakdown donne les termes opérationnel, embarqué et transport, dont la somme fait total_carbon_kgco2eq. Seul le terme opérationnel porte une part évitable, celle que quantifient les niveaux de gaspillage. Le matériel amorti et le transport réseau ne se réduisent pas en corrigeant un anti-pattern : lire le total seul mélange donc ce sur quoi un opérateur peut agir et ce sur quoi il ne peut pas. Le bloc porte aussi database_kgco2eq_out_of_total et messaging_kgco2eq_out_of_total pour les chiffres mesurés, modélisés ou déclarés de base de données et de broker qu'une fenêtre a gardés à côté de ses totaux : fenêtres archivées avant que l'énergie des hôtes entre dans les totaux, ou dont le chiffre ne portait pas de carbone. Le carbone estimé de repli est déjà inclus dans le total des services et reste exclu ici. Les deux sont hors de la somme et hors de total_carbon_kgco2eq. Ils sont publiés ici pour que tout chiffre carbone produit par une exécution se lise au même endroit. Chaque terme de la décomposition est omis quand sa valeur est nulle, pour qu'un terme non mesuré ne se lise jamais comme mesuré à zéro, et la méthodologie indique toujours que le transport fait partie du numérateur actuel. Le transport reste le moins certain des trois quand il est présent : les valeurs publiées s'étalent sur deux ordres de grandeur, son coefficient est donc fixe depuis la 0.9.25 (0.04 kWh/Go, plus configurable, chaque divulgation met le même trafic à la même échelle). Le terme est aussi publié sous la fourchette de coefficients sourcée, transport_kgco2eq_low (0.001 kWh/Go, Cloud Carbon Footprint) et transport_kgco2eq_high (0.059 kWh/Go, segment réseau du Sustainable Web Design Model v4, un plafond). La v1.6 remplit aussi integrity.trace_integrity_chain, réservé et toujours nul jusqu'ici. Le daemon chaîne par hachage chaque fenêtre archivée au moment où il l'écrit, et disclose parcourt cette chaîne pendant l'agrégation, en publiant combien de fenêtres se vérifient, combien ne portent aucune chaîne (écrites avant que cela existe) et combien de ruptures ont été trouvées. Une rupture signale une fenêtre éditée, supprimée ou réordonnée après son écriture. Les ruptures trouvées dans les mêmes fichiers mais hors de la période sont comptées à part, sous breaks_outside_period, puisqu'une archive glissante peut couvrir des années et que ce rapport ne répond que de sa propre période. Le rapport est produit quand même et le dit au lieu d'échouer, si bien qu'une archive tronquée ou une rotation donne encore un rapport partiel qui ne cache pas ses lacunes. La chaîne a deux limites. Elle ne voit pas une troncature nette de la fin d'une archive, qui laisse une chaîne plus courte mais cohérente qu'aucun champ interne au fichier ne peut contredire. Et elle n'atteste pas la source : qui contrôle le daemon et ses fichiers peut régénérer une chaîne cohérente, et le champ tombe sous le content_hash pour qu'un compteur de ruptures ne puisse pas être remis à zéro sous une signature valide. Fermer ce dernier écart demande un ancrage externe de la tête de chaîne, ce à quoi integrity.cross_period_log reste réservé. La v1.7 complète le verdict de chaîne avec deux champs de trace_integrity_chain dérivés du compteur cumulatif drops que chaque ligne d'archive porte depuis la v1.7. windows_dropped compte les fenêtres que le daemon a produites mais n'a pas pu archiver sur la période (canal plein, writer arrêté, échec de sérialisation ou d'écriture). drop_counter_resets compte le nombre de fois où le compteur a reculé dans la période, une par redémarrage du daemon, chacune faisant de windows_dropped une borne basse sur l'intervalle qu'elle couvre. Le chiffre ne dit rien des fenêtres jamais produites (daemon à l'arrêt) : aggregate.temporal_coverage borne celles-là. Les deux champs sont omis quand aucune ligne archivée ne portait le compteur, pour qu'une archive écrite avant la v1.7 ne se lise jamais comme zéro perte. La v1.8 ajoute les flux des gestionnaires de réseau à methodology.calibration_inputs.carbon_intensity_source : rte_eco2mix, neso, fingrid, energinet, ree_esios, open_electricity, mavir et em6. La v1.8 ajoute aussi aggregate.carbon_breakdown.database_kgco2eq et messaging_kgco2eq, le carbone mesuré, modélisé ou déclaré des hôtes de base de données et de broker que les fenêtres ont compté dans leurs totaux. La décomposition a alors cinq termes inclus dans le total, dont la somme fait total_carbon_kgco2eq sur les fenêtres marquées +transport, et un chiffre d'hôte inclus dans les totaux n'atteint jamais les champs *_out_of_total. Les deux blocs de gaspillage gagnent cinq champs, chacun omis quand il est nul ou vide : in_totals_energy_kwh et in_totals_windows (la part d'hôte que les fenêtres ont comptée dans leurs totaux), placements (les placements d'hôte déclarés), et modeled_energy_kwh et modeled_windows (un quatrième compartiment de provenance, pour l'énergie d'hôte interpolée à partir d'une lecture CPU). La divulgation demeure une estimation directionnelle, pas de qualité réglementaire. Le schéma accepte perf-sentinel-report/v1.0 jusqu'à v1.8. Chaque champ ajouté prend une valeur par défaut quand il est absent, donc les lecteurs et rapports plus anciens restent valides et le content_hash d'un rapport plus ancien reste identique quand il est rehashé sur un binaire plus récent.

Clés racine

clétyperequisenotes
schema_versionstring (enum)oui"perf-sentinel-report/v1.8" (accepte aussi "…/v1.7", "…/v1.6", "…/v1.5", "…/v1.4", "…/v1.3", "…/v1.2", "…/v1.1", "…/v1.0")
report_metadataobjectouivoir Métadonnées de rapport
organisationobjectouivoir Organisation
periodobjectouivoir Période
scope_manifestobjectouivoir Manifeste de scope
methodologyobjectouivoir Méthodologie
aggregateobjectouivoir Agrégat
applicationsarrayouihomogène : toutes les entrées G1 ou toutes G2, voir Applications
integrityobjectouivoir Intégrité
notesobjectouivoir Notes

Le schéma ne fixe pas additionalProperties: false. De nouveaux champs peuvent être ajoutés dans une montée de version mineure SemVer sans casser les consommateurs qui ne lisent que l'ensemble documenté.

Métadonnées de rapport

Un rapport de divulgation porte trois axes orthogonaux à lire avant tout parsing des données. intent indique à qui le rapport est destiné (brouillon privé, publication externe, ou publication auditée par un tiers). confidentiality_level indique le niveau de détail par service exposé (détail complet des anti-patterns G1 vs comptages G2 agrégés). integrity_level indique quelles primitives cryptographiques garantissent le document (rien, hash de contenu seul, signé Sigstore, signé avec attestation de build SLSA). Ensemble, ils permettent à un auditeur ou un journaliste de filtrer le corpus avant de faire confiance à un chiffre à l'intérieur.

intent vaut internal | official | audited. audited est réservé pour une release future : le schéma JSON accepte la valeur pour la compatibilité ascendante, mais la CLI le refuse aujourd'hui avec le code de sortie 2. confidentiality_level vaut internal | public. integrity_level vaut none | hash-only | signed | signed-with-attestation | audited. Par défaut, la CLI produit hash-only. generated_at est un horodatage UTC RFC 3339. generated_by vaut daemon | cli-batch | ci. perf_sentinel_version est la chaîne SemVer du binaire qui a écrit le fichier. report_uuid est un UUID v4 estampillé par exécution.

Organisation

name est requis et non vide. country est en ISO 3166-1 alpha-2, majuscules. identifiers est un objet ouvert avec siren, vat, lei, opencorporates_url, domain optionnels. sector est un code NACE rev2 optionnel.

Le domaine de publication (par exemple transparency.example.fr) est traité comme un identifiant implicite quand notes.reference_urls.project est publié depuis cet hôte. Le schéma ne l'impose pas.

Période

from_date et to_date sont des dates calendaires ISO 8601 (YYYY-MM-DD). period_type vaut calendar-quarter | calendar-month | calendar-year | custom. days_covered vaut to_date - from_date + 1. Le validateur de l'intent officiel impose days_covered >= 30.

Manifeste de scope

total_applications_declared est la taille du portefeuille applicatif de l'organisation. applications_measured est le nombre de services pour lesquels le rapport porte des données. Chaque entrée de applications_excluded porte service_name et un reason non vide. environments_measured liste les environnements définis par l'opérateur et observés (par exemple ["prod"]). total_requests_in_period est une estimation opérateur optionnelle, requests_measured est ce que Perf Sentinel a observé. coverage_percentage vaut requests_measured / total_requests_in_period * 100 quand le premier est renseigné.

coverage_basis (v1.2) rend la frontière de confiance explicite, en bande. Il liste quels champs de scope sont operator_declared (assertions non auditées que le binaire ne peut pas vérifier : les dénominateurs total_applications_declared et total_requests_in_period, plus les listes d'exclusion) versus machine_derived (calculés par l'agrégateur depuis les archives : applications_measured, requests_measured, coverage_percentage). Un lecteur de coverage_percentage doit traiter son dénominateur comme une assertion opérateur : un opérateur qui fixe total_requests_in_period bas peut présenter une couverture proche de 100 % d'un univers qu'il a lui-même défini. C'est inhérent à un modèle d'auto-déclaration. Les garanties d'intégrité cryptographique lient le rapport publié, pas l'honnêteté de la taille de portefeuille déclarée. Voir 08 · Divulgation périodique.

Méthodologie

sci_specification référence la révision SCI (par exemple "ISO/IEC 21031:2024"). perf_sentinel_version reprend le champ des métadonnées pour les consommateurs qui n'indexent que le bloc méthodologie. enabled_patterns et disabled_patterns portent chacun des noms de patterns issus de l'ensemble fermé défini par FindingType::as_str() (12 valeurs). core_patterns_required est la liste fermée des patterns dont la remédiation coupe directement de l'I/O et du carbone : n_plus_one_sql, n_plus_one_http, redundant_sql, redundant_http. conformance vaut core-required | extended | partial, core-required étant le seuil minimum pour un rapport intent = "official". calibration_inputs.carbon_intensity_source vaut electricity_maps | rte_eco2mix | neso | fingrid | energinet | ree_esios | open_electricity | mavir | em6 | static_tables | mixed. rte_eco2mix, neso, fingrid, energinet, ree_esios, open_electricity, mavir et em6 désignent les flux gratuits des gestionnaires de réseau français, britannique, finlandais, danois, espagnol, australien, hongrois et néo-zélandais, des chiffres d'émissions directes qui ne se comparent pas à une intensité Electricity Maps en cycle de vie. specpower_table_version est la version de la table SPECpower / coefficients CCF embarquée, déclarée dans le TOML de config org ou, quand celui-ci l'omet, remplie par disclose avec la date de la table du binaire. binary_specpower_vintage (0.7.3+) est la chaîne de millésime que le binaire embarque au build, renseignée automatiquement par perf-sentinel disclose. Les consommateurs peuvent comparer les deux chaînes pour détecter une dérive entre la déclaration opérateur et les données embarquées. scaphandre_used indique si le proxy énergie temps réel vient de Scaphandre RAPL. C'est un champ historique spécifique à Scaphandre : il précède les autres backends d'énergie mesurée et n'a jamais été généralisé, il reste donc à false pour une période mesurée avec Alumet, Kepler ou Redfish. energy_source_models est la source de vérité générale pour savoir quelles sources d'énergie ont produit les chiffres d'une période. Il est dérivé automatiquement des fenêtres archivées et porte l'étiquette de chaque backend (alumet_rapl, scaphandre_rapl, kepler_ebpf, redfish_bmc, cloud_specpower, io_proxy_v*). kepler_ebpf est un nom historique : depuis Kepler 0.10, seule version que lit Perf Sentinel, la source est RAPL (sysfs/powercap, hwmon expérimental), pas eBPF. Les consommateurs doivent lire energy_source_models et traiter scaphandre_used comme un indice hérité. Généraliser le champ casserait un schéma publié, haché et attesté, c'est donc reporté à une révision ultérieure du schéma. standard_crosswalk (v1.3) est une correspondance interprétative des chiffres du rapport vers les datapoints ESRS E1 (total_energy_kwh vers E1-5, le terme carbone opérationnel vers E1-6 Scope 2 location-based, le carbone embarqué vers E1-6 Scope 3). Il porte son propre tableau caveats. C'est une aide à la correspondance, pas une certification : le chiffre location-based n'est pas la valeur Scope 2 market-based qu'ESRS exige aussi, et l'intervalle d'incertitude 2x s'applique toujours. Absent sur les rapports pré-v1.3.

calibration_applied (0.7.0+) vaut true si au moins une fenêtre de scoring de la période a appliqué des coefficients de calibration opérateur par service à l'énergie proxy. Le flag est méthodologiquement distinct de scaphandre_used et energy_source_models : ceux-ci décrivent quelle source d'énergie a produit les chiffres, ce flag décrit si ces chiffres ont été ensuite ajustés par des coefficients opérateur.

Agrégat

Voir aussi. L'introduction énergie et SCI dans la doc méthodologie définit les termes SCI v1.0 (E, I, M), efficiency_score, io_waste_ratio, Scaphandre, SPECpower et le vocabulaire associé utilisé par tous les champs ci-dessous.

Sommes sur toute la période et tout le tableau applications. total_requests, total_energy_kwh, total_carbon_kgco2eq et estimated_optimization_potential_kgco2eq sont des nombres finis non négatifs. aggregate_waste_ratio est dans [0, 1]. aggregate_efficiency_score est dans [0, 100] et vaut clamp(100 - 100 * io_waste_ratio, 0, 100). anti_patterns_detected_count est la somme de toutes les occurrences par service, y compris les patterns non évitables.

Niveaux de gaspillage (1.1+)

Le rapport porte le gaspillage évitable, énergie et carbone, à deux seuils de détection N+1, côte à côte, pour rendre l'écart auditable :

  • canonical_waste est calculé à un seuil N+1 fixe épinglé dans le binaire (2), pas la config de l'opérateur. C'est le chiffre non manipulable : un opérateur ne peut pas le réduire en relâchant son propre seuil. C'est le chiffre évitable de référence, et depuis la v1.1 les champs plats estimated_optimization_potential_kgco2eq, aggregate_waste_ratio et aggregate_efficiency_score sont des alias de ce niveau (ils portaient la valeur opérationnelle en v1.0).
  • operational_waste est calculé au seuil N+1 configuré par l'opérateur et enregistre ce seuil dans n_plus_one_threshold. Le comparer à canonical_waste montre combien de gaspillage évitable le seuil de l'opérateur masque.

Chaque niveau porte n_plus_one_threshold (entier), energy_kwh et carbon_kgco2eq (non négatifs), waste_ratio ([0, 1]) et efficiency_score ([0, 100]). Pour intent = "official", le validateur exige que canonical_waste.n_plus_one_threshold égale le seuil canonique du binaire. Le seuil opérationnel est le choix enregistré de l'opérateur et n'est pas borné, puisqu'un seuil relâché est ce que ce niveau sert à exposer. L'énergie et le carbone totaux (total_energy_kwh, total_carbon_kgco2eq) sont dérivés des spans et indépendants des deux seuils.

Gaspillage base de données (v1.4)

database_waste est un objet optionnel portant l'énergie et le carbone évitables du travail SQL sur la période. C'est une décomposition informative des totaux et des niveaux de gaspillage, jamais ajoutée par-dessus total_energy_kwh, total_carbon_kgco2eq, canonical_waste ni operational_waste, absente des rapports pré-v1.4 et quand aucune fenêtre n'a porté le chiffre. Le chiffre par fenêtre est une énergie multipliée par le ratio de gaspillage SQL seul, et cette énergie est soit une énergie d'hôte de base de données, soit le repli estimé. L'énergie d'hôte vient de l'une de trois sources. Mesurée (alumet_rapl), quand [green.alumet.database] est configuré et qu'une lecture est arrivée : l'énergie du cgroup Alumet de la base de données déclaré, borne basse de cet hôte limitée au CPU. Modélisée (cloud_specpower), quand [green.database_static] déclare une cpu_query : l'enveloppe SPECpower de son instance_type interpolée à cette lecture CPU, ni une lecture de la puissance de l'hôte ni un plafond. Déclarée (database_specpower), quand [green.database_static] déclare nodes et instance_type sans cpu_query : le plafond SPECpower de la grappe, une déclaration de l'opérateur sur des hôtes provisionnés. La même étiquette couvre les intervalles où une déclaration dédiée avec cpu_query n'a reçu aucune lecture fraîche pendant trois intervalles de scrape, démarrage du daemon avant sa première lecture compris, et où son plafond a facturé. Une fenêtre compte son chiffre d'hôte dans ses totaux et ses deux niveaux de gaspillage dès que son carbone est converti, et son chiffre archivé porte alors in_totals: true, avec le placement de [green.database_static] quand il est déclaré. Ces totaux le contiennent déjà, son carbone publié en carbon_breakdown.database_kgco2eq. Un chiffre d'hôte qu'une fenêtre a gardé à côté de ses totaux, archivé avant que l'énergie d'hôte y entre ou sans carbone, alimente plutôt database_kgco2eq_out_of_total. Estimée, sinon : la part côté application des spans SQL de la fenêtre, l'énergie que le scoring des spans a donnée aux services qui les ont émis, déjà comprise dans les totaux, et sa part de gaspillage déjà comprise dans les niveaux de gaspillage. Le chiffre estimé ne contient aucune énergie d'hôte de base de données, et l'ajouter à canonical_waste compterait deux fois les mêmes opérations SQL, valorisées de deux façons. models porte les étiquettes de provenance distinctes observées sur la période, un auditeur distingue donc mesure et modèle sans quitter le rapport. Quatre compartiments répartissent les fenêtres et l'énergie par provenance : measured_*, modeled_*, declared_* et estimated_windows, et dès que l'un d'eux est non nul measured_windows + modeled_windows + declared_windows + estimated_windows vaut windows_with_figure. in_totals_energy_kwh et in_totals_windows donnent la part d'hôte que les fenêtres ont comptée dans leurs totaux : une partie de energy_kwh déjà comprise dans total_energy_kwh, jamais un terme à ajouter, au plus energy_kwh, et sur au plus les fenêtres mesurées, modélisées et déclarées. placements liste les placements déclarés sur la période (dedicated, shared), une déclaration de l'opérateur sur l'endroit où tournent les hôtes, pas une mesure. messaging_waste se lit de la même façon : alumet_rapl, cloud_specpower et broker_specpower sont une énergie d'hôte de broker issue de [green.alumet.broker] ou de [green.broker_static], comptée dans les totaux selon la même règle (carbon_breakdown.messaging_kgco2eq), estimated est la part côté application des spans de publication. windows_with_figure compte les fenêtres qui portaient le bloc. Les chiffres operational_* utilisent le seuil N+1 de l'opérateur. Les chiffres canonical_* recalculent le ratio SQL au seuil canonique épinglé dans le binaire contre la même énergie, la même construction anti-manipulation que les niveaux de gaspillage ci-dessus.

Signaux de qualité (0.7.0+)

L'agrégat porte quatre champs optionnels qui décrivent la qualité des archives sources, pas la charge applicative elle-même. Ils permettent à un auditeur d'évaluer quelle proportion de la période a été mesurée directement plutôt qu'inférée d'un proxy.

  • period_coverage est dans [0, 1] et vaut runtime_windows / (runtime_windows + fallback_windows). Une valeur de 1.0 signifie que toutes les fenêtres de scoring de la période portaient une énergie calibrée au runtime (Scaphandre ou cloud SPECpower). Une valeur de 0.0 signifie que toutes les fenêtres se sont rabattues sur le proxy I/O. Le validateur refuse un rapport intent = "official" avec period_coverage < 0.75, voir 08 · Divulgation périodique pour la justification du seuil.
  • runtime_windows_count et fallback_windows_count portent les compteurs absolus derrière ce ratio, pour qu'un lecteur puisse distinguer "9 fenêtres sur 10 calibrées au runtime" de "900 sur 1000".
  • binary_versions est l'ensemble des versions distinctes du binaire Perf Sentinel qui ont produit les archives repliées dans cette période. Une période qui couvre plusieurs versions (mise à jour du daemon en milieu de trimestre, releases asynchrones entre équipes) porte plus d'une entrée dans cet ensemble, ce que signale le disclaimer du rapport.

Champs de qualité par service (0.7.0+)

  • per_service_energy_models associe chaque service à l'ensemble des tags de modèle énergétique observés sur la période (scaphandre_rapl, cloud_specpower, io_proxy_v3, etc.). Le suffixe +cal est retiré avant insertion. Le flag calibration_applied de methodology.calibration_inputs, qui vaut pour toute la période, porte cette information à la place.
  • per_service_measured_ratio est la moyenne par service de la fraction par fenêtre des spans dont l'énergie a été résolue par Scaphandre ou cloud SPECpower. Une valeur proche de 1.0 signifie que le service est entièrement mesuré sur la période, 0.0 qu'il s'appuie sur le repli proxy. C'est une 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 à la moyenne.

Couverture temporelle (v1.2)

temporal_coverage est un signal de continuité : quelle part de la période déclarée a porté des mesures. C'est un objet avec temporal_coverage (dans [0, 1], égal à observed_days / days_in_period), observed_days (jours calendaires UTC distincts portant au moins une fenêtre archivée), days_in_period (reflète period.days_covered) et largest_gap_days (la plus longue suite de jours consécutifs de la période sans fenêtre).

À lire comme une borne basse de l'activité, pas comme l'uptime du daemon. L'archivage du daemon est déclenché par le trafic : une fenêtre sans trafic n'écrit rien, donc les jours légitimement calmes (nuits, week-ends, services peu sollicités) abaissent le chiffre. Pour cette raison ce n'est jamais une barrière dure official. La CLI disclose publie la valeur, émet un avertissement sur stderr sous un seuil informatif, et ajoute un disclaimer en bande portant la même mise en garde. Il existe pour qu'un lecteur distingue une période mesurée en continu d'une période où le daemon n'a tourné que quelques jours, ce que le days_covered calendaire seul ne peut pas révéler.

Applications

Deux granularités, homogènes par rapport. Le validateur refuse un rapport qui mélangerait les deux. Dans les deux, endpoints_observed compte les endpoints distincts qu'un service a servis sur la période, suivis jusqu'à 1024 par service. Un service qui atteint ce plafond affiche 1024, une borne basse de son nombre réel.

G1 (intent internal)

Chaque entrée porte les totaux au niveau service plus un tableau anti_patterns: [...]. Chaque détail anti-pattern a type (un des 12 patterns connus), occurrences, estimated_waste_kwh, estimated_waste_kgco2eq, first_seen, last_seen. occurrences compte les findings qu'un service détient, tandis que estimated_waste_* porte aussi sa part des findings dont il a émis les spans sous le finding d'un autre service (depuis 0.18.0, sur les fenêtres archivées par 0.18.0 ou plus récent), une ligne peut donc afficher du gaspillage avec zéro occurrence. estimated_waste_kwh vaut les opérations I/O évitables du pattern multipliées par l'énergie propre du service par opération sur la période, son energy_kwh divisé par ses opérations I/O (zéro quand il n'en a enregistré aucune). Une ligne peut dépasser le energy_kwh du service quand ses opérations évitables ont été comptées dans des fenêtres sans I/O pour ce service. Il partage le périmètre du energy_kwh de l'application : l'hôte du service émetteur, sans hôte de base de données ni de broker. estimated_waste_kgco2eq multiplie cette énergie par le carbon_kgco2eq / energy_kwh du service. Valorisées à une moyenne de période, ces lignes ne se somment pas en canonical_waste ni en operational_waste, qui valorisent chaque fenêtre à son propre carbone opérationnel. Les horodatages sont en UTC RFC 3339. rgesn_criteria (v1.3) est la liste interprétative des critères RGESN 2024 auxquels le pattern se rapporte (voir Méthodologie), vide pour slow_* et absente sur les rapports pré-v1.3. display_name et service_version sont des indications optionnelles.

G2 (intent official avec confidentiality public)

Chaque entrée porte les mêmes totaux au niveau service mais remplace le tableau par un seul entier anti_patterns_detected_count. Le schéma impose que les entrées G2 ne portent pas de champ anti_patterns, et inversement.

Les deux granularités sont encodées dans le JSON Schema avec des clauses not: { required: [...] } mutuellement exclusives pour rendre la discrimination explicite aux validateurs de schéma.

Intégrité

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.

content_hash est "sha256:<64-hex>" sur la forme JSON canonique du document avec le champ content_hash mis à chaîne vide. Le schéma accepte aussi une chaîne vide pour ce champ afin que les exemples puissent être livrés sans hash intégré. binary_hash est "sha256:<64-hex>" du binaire Perf Sentinel qui a produit le fichier. binary_verification_url pointe vers l'artefact de release où les consommateurs récupèrent le même binaire. trace_integrity_chain porte le verdict de la chaîne source depuis la v1.6 et vaut null sur les rapports antérieurs, jamais omis, puisque retirer la clé changerait les octets canoniques de tout rapport déjà publié.

signature (0.7.0+) vaut soit null (rapport hash-only) soit un objet typé avec format ("sigstore-cosign-intoto-v1"), bundle_url, signer_identity, signer_issuer, rekor_url, rekor_log_index, et signed_at. Les champs permettent collectivement à un vérifieur de localiser le bundle cosign et la preuve d'inclusion Rekor.

binary_attestation (0.7.0+) est optionnel et, quand présent, porte un format ("slsa-provenance-v1"), attestation_url, builder_id, git_tag, git_commit, et slsa_level ("L2" pour les releases officielles, le niveau que GitHub documente pour ses attestations d'artefacts seules. Le schéma accepte aussi "L3", pour un build isolé dans un workflow réutilisable). Les consommateurs vérifient le binaire téléchargé depuis binary_verification_url avec gh attestation verify <binary> --owner robintra --signer-repo robintra/perf-sentinel pour les releases 0.7.1 à 0.26.2, gh attestation verify <binary> --repo Institut-du-Numerique-Responsable/perf-sentinel pour les suivantes, ou avec slsa-verifier verify-artifact --provenance-path multiple.intoto.jsonl ... pour l'ancienne 0.7.0.

cross_period_log (v1.2) est réservé et absent aujourd'hui. C'est le point d'extension du schéma pour un journal externe en ajout seul ou de type Rekor qui chaîne les rapports périodiques successifs, afin qu'un tiers puisse détecter un opérateur qui aurait silencieusement arrêté de publier sur plusieurs périodes, le seul trou que les garanties d'intégrité par rapport ne peuvent pas combler. Il ne sera renseigné que sous un futur intent = "audited", aux côtés de l'attestation d'audit externe.

integrity_level dans report_metadata vaut none, hash-only, signed, signed-with-attestation (0.7.0+), audited. Le lecteur peut l'utiliser comme filtre rapide avant de parser le bloc d'intégrité.

Notes

disclaimers porte huit déclarations par défaut : les deux avertissements standard d'incertitude (estimation directionnelle, fourchette multiplicative ~2x ; la spécification SCI elle-même ne définit aucune disposition d'incertitude), la précision sur le scope embarqué (exclu du potentiel d'optimisation), la note sur le carbone embarqué par service (opérationnel uniquement au niveau service, total au niveau agrégat), la mise en garde sur l'attribution runtime (les archives calibrées au runtime portent des données par service, les plus anciennes se rabattent sur la part d'I/O), deux lignes d'adéquation réglementaire (inadapté à CSRD / GHG Scope 3, référence méthodologique), et la note de correspondance ESRS E1 (la correspondance standard_crosswalk est une aide, pas un substitut à un inventaire CSRD audité). Les opérateurs peuvent surcharger la liste dans leur TOML org-config. reference_urls est un objet ouvert qui associe des clés courtes (methodology, schema, project) à des URLs. Les opérateurs peuvent ajouter des clés personnalisées.

Boavizta et autres champs omis

boavizta_version a été envisagé pour calibration_inputs mais ne fait pas partie du schéma actuel parce que Perf Sentinel ne consomme pas de données Boavizta aujourd'hui. Le champ reviendra quand l'intégration sera livrée. Les consommateurs de schéma DOIVENT tolérer des champs inconnus sans erreur parce que Perf Sentinel en ajoutera dans des révisions mineures.

Versionnement

Un changement du schéma incompatible avec les versions antérieures incrémente la version majeure dans schema_version (v2.0, v3.0). Les changements additifs (nouveaux champs optionnels, nouvelles valeurs d'énumération que les consommateurs peuvent traiter comme inconnues) incrémentent la partie mineure (v1.1, v1.2). L'URL $id du JSON Schema ne contient que la version majeure.

Renvois

  • Divulgation est le guide d'utilisation côté opérateur.
  • Méthodologie couvre la chaîne de calcul qui remplit aggregate et les champs énergie/carbone par application.
  • docs/schemas/perf-sentinel-report-v1.json est le JSON Schema de référence.
  • docs/schemas/examples/example-internal-G1.json et example-official-public-G2.json sont des exemples remplis.