{"id":47845418,"url":"https://github.com/robintra/perf-sentinel","last_synced_at":"2026-04-27T00:03:36.921Z","repository":{"id":344470162,"uuid":"1181573685","full_name":"robintra/perf-sentinel","owner":"robintra","description":"Lightweight, polyglot performance anti-pattern detection with built-in carbon-aware scoring.","archived":false,"fork":false,"pushed_at":"2026-04-21T22:07:57.000Z","size":18823,"stargazers_count":11,"open_issues_count":0,"forks_count":2,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-22T00:20:52.513Z","etag":null,"topics":["anti-patterns","cli","devops","devtools","green-software","greenops","microservices","n-plus-one","observability","opentelemetry","performance","rust","sql","tracing"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/robintra.png","metadata":{"files":{"readme":"README-FR.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":"audit.toml","citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-14T10:26:54.000Z","updated_at":"2026-04-21T22:08:03.000Z","dependencies_parsed_at":null,"dependency_job_id":"0f435166-d3ce-47d5-ba08-f75adfe7648a","html_url":"https://github.com/robintra/perf-sentinel","commit_stats":null,"previous_names":["robintra/perf-sentinel"],"tags_count":18,"template":false,"template_full_name":null,"purl":"pkg:github/robintra/perf-sentinel","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robintra%2Fperf-sentinel","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robintra%2Fperf-sentinel/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robintra%2Fperf-sentinel/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robintra%2Fperf-sentinel/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/robintra","download_url":"https://codeload.github.com/robintra/perf-sentinel/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robintra%2Fperf-sentinel/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32158346,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-22T17:06:48.269Z","status":"ssl_error","status_checked_at":"2026-04-22T17:06:19.037Z","response_time":58,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["anti-patterns","cli","devops","devtools","green-software","greenops","microservices","n-plus-one","observability","opentelemetry","performance","rust","sql","tracing"],"created_at":"2026-04-03T21:11:49.372Z","updated_at":"2026-04-27T00:03:36.913Z","avatar_url":"https://github.com/robintra.png","language":"Rust","readme":"\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://www.rust-lang.org/\"\u003e\u003cimg src=\"https://img.shields.io/badge/dynamic/toml?url=https%3A%2F%2Fraw.githubusercontent.com%2Frobintra%2Fperf-sentinel%2Fmain%2FCargo.toml\u0026query=%24.workspace.package.rust-version\u0026suffix=%20stable\u0026label=rust%202024\u0026color=D34516\u0026logo=rust\" alt=\"Rust\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/robintra/perf-sentinel/actions/workflows/ci.yml\"\u003e\u003cimg src=\"https://github.com/robintra/perf-sentinel/actions/workflows/ci.yml/badge.svg\" alt=\"CI\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/robintra/perf-sentinel/actions/workflows/security-audit.yml\"\u003e\u003cimg src=\"https://github.com/robintra/perf-sentinel/actions/workflows/security-audit.yml/badge.svg\" alt=\"Security Audit\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://sonarcloud.io/summary/overall?id=robintrassard_perf-sentinel\"\u003e\u003cimg src=\"https://sonarcloud.io/api/project_badges/measure?project=robintrassard_perf-sentinel\u0026metric=coverage\" alt=\"Coverage\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://sonarcloud.io/summary/overall?id=robintrassard_perf-sentinel\"\u003e\u003cimg src=\"https://sonarcloud.io/api/project_badges/measure?project=robintrassard_perf-sentinel\u0026metric=alert_status\" alt=\"Quality Gate\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/robintra/perf-sentinel/actions/workflows/release.yml\"\u003e\u003cimg src=\"https://github.com/robintra/perf-sentinel/actions/workflows/release.yml/badge.svg\" alt=\"Release\" /\u003e\u003c/a\u003e\n    \u003ca href=\"https://artifacthub.io/packages/helm/perf-sentinel/perf-sentinel\"\u003e\u003cimg src=\"https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/perf-sentinel\" alt=\"Artifact Hub\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cpicture\u003e\n  \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/robintra/perf-sentinel/main/logo/logo-dark-horizontal.svg\"\u003e\n  \u003cimg alt=\"perf-sentinel\" src=\"https://raw.githubusercontent.com/robintra/perf-sentinel/main/logo/logo-horizontal.svg\"\u003e\n\u003c/picture\u003e\n\nAnalyse les traces d'exécution (requêtes SQL, appels HTTP) pour détecter les requêtes N+1, les appels redondants et évalue l'intensité I/O par endpoint (GreenOps).\n\n## Pourquoi perf-sentinel ?\n\nLes anti-patterns de performance comme les requêtes N+1 existent dans toute application qui fait des I/O, monolithes comme microservices. Dans les architectures distribuées, un appel utilisateur cascade sur plusieurs services, chacun avec ses propres I/O et personne n'a de visibilité sur le chemin complet. Les outils existants résolvent chacun une partie du problème : Hypersistence Utils ne couvre que JPA, Datadog et New Relic sont des agents propriétaires lourds qu'on ne veut pas forcément déployer dans tous les pipelines, les détecteurs de Sentry sont solides mais liés à son SDK et à son backend. Aucun ne propose un quality gate CI au niveau protocole qu'on peut auto-héberger.\n\nperf-sentinel adopte une approche différente : **l'analyse au niveau protocole**. Il observe les traces produites par l'application (requêtes SQL, appels HTTP) quel que soit le langage ou l'ORM utilisé. Il n'a pas besoin de comprendre JPA, EF Core ou SeaORM : il voit les requêtes qu'ils génèrent.\n\n## Aperçu rapide\n\nDans le tableau de bord :\n\n```bash\nperf-sentinel report --input traces.json --output report.html\n```\n\n\u003cpicture\u003e\n  \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/report/dashboard_dark.gif\"\u003e\n  \u003cimg alt=\"tour du dashboard\" src=\"https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/report/dashboard_light.gif\"\u003e\n\u003c/picture\u003e\n\n...ou dans le terminal :\n\n```bash\nperf-sentinel analyze --input traces.json\n```\n\n![demo](https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/analyze/demo.gif)\n\n## GreenOps : scoring éco-conception intégré\n\nChaque finding inclut un **I/O Intensity Score (IIS)** : le nombre d'opérations I/O générées par requête utilisateur pour un endpoint donné. Réduire les I/O inutiles (N+1, appels redondants) améliore les temps de réponse *et* réduit la consommation énergétique : ce ne sont pas des objectifs concurrents.\n\n- **I/O Intensity Score** = opérations I/O totales pour un endpoint / nombre d'invocations\n- **I/O Waste Ratio** = opérations I/O évitables (issues des findings) / opérations I/O totales\n\nAligné avec le modèle **Software Carbon Intensity** ([SCI v1.0 / ISO/IEC 21031:2024](https://github.com/Green-Software-Foundation/sci)) de la Green Software Foundation. Le champ `co2.total` contient le **numérateur SCI** `(E × I) + M` sommé sur les traces analysées, pas le score d'intensité par requête. Le scoring multi-région est automatique quand les spans OTel portent l'attribut `cloud.region`. **Plus de 30 régions cloud** disposent de profils d'intensité carbone horaire intégrés, avec une variation saisonnière (mois x heure) pour FR, DE, GB et US-East. En mode daemon, le coefficient énergétique peut être affiné via [Scaphandre](https://github.com/hubblo-org/scaphandre) (RAPL bare-metal) ou l'estimation cloud-native CPU% + SPECpower pour les VMs AWS/GCP/Azure (section `[green.cloud]`) et l'intensité du réseau électrique peut être récupérée en temps réel via l'**API Electricity Maps**, avec repli automatique sur le modèle proxy I/O. Les utilisateurs peuvent fournir leurs propres profils horaires via `[green] hourly_profiles_file` ou ajuster les coefficients du modèle proxy depuis des mesures terrain via `perf-sentinel calibrate`.\n\n\u003e **Note :** les estimations CO₂ sont **directionnelles**, pas auditables. Chaque estimation porte un intervalle d'incertitude multiplicative `~2×` (`low = mid/2`, `high = mid×2`) car le modèle proxy I/O est approximatif. perf-sentinel est un **compteur de gaspillage**, pas un outil de comptabilité carbone. Ne l'utilisez pas pour le reporting CSRD ou GHG Protocol Scope 3. Voir [docs/FR/LIMITATIONS-FR.md](docs/FR/LIMITATIONS-FR.md#précision-des-estimations-carbone) pour la méthodologie complète.\n\n## Positionnement\n\nLa détection d'anti-patterns de performance basée sur les traces existe déjà dans les APM matures et dans plusieurs outils open source. La niche de perf-sentinel est d'être léger, indépendant du runtime, intégré au CI/CD et carbon-aware, pas de remplacer une suite d'observabilité complète.\n\n| Capacité                    | [Hypersistence Optimizer](https://vladmihalcea.com/hypersistence-optimizer/) | [Datadog APM + DBM](https://www.datadoghq.com/product/apm/) | [New Relic APM](https://newrelic.com/platform/application-monitoring) | [Sentry](https://sentry.io/for/performance/) | [Digma](https://digma.ai/)  | **perf-sentinel**                           |\n|-----------------------------|------------------------------------------------------------------------------|-------------------------------------------------------------|-----------------------------------------------------------------------|----------------------------------------------|-----------------------------|---------------------------------------------|\n| Détection N+1 SQL           | JPA uniquement, en test                                                      | Oui, automatique (DBM)                                      | Oui, automatique                                                      | Oui, OOTB                                    | Oui, orienté IDE (JVM/.NET) | Oui, au niveau protocole, tout runtime OTel |\n| Détection N+1 HTTP          | Non                                                                          | Oui, service maps                                           | Oui, corrélation de traces                                            | Oui, détecteur N+1 API Call                  | Partiel                     | Oui                                         |\n| Support polyglotte          | Java uniquement                                                              | Agents par langage                                          | Agents par langage                                                    | SDK par langage, la plupart                  | JVM + .NET (Rider beta)     | Tout runtime instrumenté OTel               |\n| Corrélation cross-service   | Non                                                                          | Oui                                                         | Oui                                                                   | Oui                                          | Limitée (IDE local)         | Via trace ID                                |\n| Scoring GreenOps / SCI v1.0 | Non                                                                          | Non                                                         | Non                                                                   | Non                                          | Non                         | Intégré (directionnel)                      |\n| Empreinte runtime           | Bibliothèque (sans overhead)                                                 | Agent (~100-150 Mo RSS)                                     | Agent (~100-150 Mo RSS)                                               | SDK + backend                                | Backend local (Docker)      | Binaire standalone (\u003c10 Mo RSS)             |\n| Quality gate CI/CD natif    | Assertions de tests manuelles                                                | Alertes, pas de gate de build                               | Alertes, pas de gate de build                                         | Alertes, pas de gate de build                | Non                         | Oui (exit 1 sur dépassement de seuil)       |\n| Licence                     | Commerciale (Optimizer)                                                      | Propriétaire SaaS                                           | Propriétaire SaaS                                                     | FSL (bascule Apache-2 après 2 ans)           | Freemium, propriétaire      | AGPL-3.0                                    |\n\nLes empreintes d'agent pour les APM commerciaux sont des ordres de grandeur issus de retours publics de déploiement ; l'overhead réel dépend du périmètre d'instrumentation.\n\n### Ce que perf-sentinel n'est pas\n\nUne comparaison honnête passe par nommer ce que perf-sentinel ne fait pas :\n\n- **Pas un remplacement d'APM complet.** Pas de dashboards, pas d'UI d'alerting, pas de RUM, pas d'agrégation de logs, pas de profiling distribué. Si vous en avez besoin, Datadog, New Relic et Sentry restent les bons outils.\n- **Pas une solution de monitoring temps réel.** Le mode daemon diffuse des findings en streaming, mais le centre de gravité du projet reste le quality gate CI/CD et l'analyse post-hoc de traces, pas l'observabilité live en production.\n- **Pas un outil de comptabilité carbone réglementaire.** À utiliser pour chasser le gaspillage, pas pour produire un reporting CSRD ou GHG Protocol Scope 3. Voir la note GreenOps plus haut pour les limites méthodologiques.\n- **Pas un remplacement pour l'énergie mesurée.** Le modèle I/O-vers-énergie reste une approximation. Pour de la mesure de puissance par processus précise, utilisez Scaphandre (supporté en entrée) ou les APIs énergie de votre fournisseur cloud.\n- **Pas zero-config.** La détection au niveau protocole requiert que vos applications émettent des traces OTel. Si votre stack n'est pas instrumenté, perf-sentinel n'a rien à analyser.\n- **Pas un plugin IDE.** Pour du feedback in-IDE pendant que vous codez en JVM/.NET, [Digma](https://digma.ai/) propose une expérience JetBrains bien intégrée.\n\nperf-sentinel est un outil complémentaire centré sur un problème précis : détecter les anti-patterns d'I/O dans les traces, scorer leur impact (y compris carbone) et enforcer des seuils en CI. Utilisez-le à côté de votre stack d'observabilité existante, pas à sa place.\n\n## Que remonte-t-il ?\n\nPour chaque anti-pattern détecté, perf-sentinel remonte :\n\n- **Type :** N+1 SQL, N+1 HTTP, requête redondante, SQL lent, HTTP lent, fanout excessif, service bavard (chatty service), saturation du pool de connexions ou appels sérialisés. Les corrélations cross-trace sont aussi remontées en mode daemon\n- **Template normalisé :** la requête ou l'URL avec les paramètres remplacés par des placeholders (`?`, `{id}`)\n- **Occurrences :** combien de fois le pattern s'est déclenché dans la fenêtre de détection\n- **Endpoint source :** quel endpoint applicatif l'a généré (ex : `GET /api/orders`)\n- **Suggestion :** par exemple *\"batch cette requête\"*, *\"utilise un batch endpoint\"*, *\"ajouter un index\"*\n- **Localisation source :** quand les spans OTel portent les attributs `code.function`, `code.filepath`, `code.lineno`, les findings affichent le fichier source et la ligne d'origine. Les rapports SARIF incluent des `physicalLocations` pour les annotations inline GitHub/GitLab\n- **Impact GreenOps :** estimation des I/O évitables, I/O Intensity Score, objet `co2` structuré (`low`/`mid`/`high`, termes opérationnel + embodié SCI v1.0), breakdown par région quand le scoring multi-région est actif\n\nTu peux aussi explorer une trace unique avec le mode `explain` en arbre, qui annote les findings directement à côté des spans concernés :\n\n![vue en arbre explain](https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/explain/demo.gif)\n\nOu navigue dans les traces, les findings et les arbres de spans de manière interactive avec le TUI `inspect` (3 panneaux, navigation au clavier) :\n\n![TUI inspect](https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/inspect/demo.gif)\n\nOu produis un dashboard HTML single-file avec `report` pour l'exploration post-CI en navigateur. Double-clic pour l'ouvrir hors ligne, clic sur un finding pour sauter à son arbre de trace, bascule dark/light, le tout dans un seul fichier autonome sans ressource externe :\n\n```bash\nperf-sentinel report --input traces.json --output report.html\n```\n\nLe tour du dashboard est affiché en haut de cette page sous [Aperçu rapide](#aperçu-rapide). Les captures figées par onglet sont dans la section **Captures** en bas.\n\nOu classe les hotspots SQL depuis un export `pg_stat_statements` PostgreSQL avec `pg-stat`. Quatre classements (par temps total, par nombre d'appels, par latence moyenne, par blocs shared-buffer touchés) aident à repérer les requêtes qui dominent la DB sans apparaître dans tes traces, signe d'un trou d'instrumentation :\n\n![hotspots pg-stat](https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/pg-stat/demo.gif)\n\nEnfin, ajuste les coefficients I/O-vers-énergie à ton infrastructure réelle avec `calibrate`, qui corrèle un fichier de traces avec des mesures d'énergie (Scaphandre, supervision cloud, etc.) et génère un fichier TOML chargeable via `[green] calibration_file` :\n\n![flux calibrate](https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/calibrate/demo.gif)\n\n\u003cdetails\u003e\n\u003csummary\u003eImages fixes\u003c/summary\u003e\n\n**Configuration** (`.perf-sentinel.toml`) :\n\n![config](https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/analyze/config.png)\n\n**Rapport d'analyse** (le premier GIF ci-dessus défile dans le rapport complet, les quatre images fixes ci-dessous le couvrent page par page, avec un léger recouvrement pour que chaque finding apparaisse en entier sur au moins une page) :\n\n![page 1 : N+1 SQL, N+1 HTTP, SQL redondant](https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/analyze/report-1.png)\n\n![page 2 : HTTP redondant, SQL lent, HTTP lent](https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/analyze/report-2.png)\n\n![page 3 : fanout excessif, service bavard, saturation du pool](https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/analyze/report-3.png)\n\n![page 4 : appels sérialisés, résumé GreenOps, quality gate](https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/analyze/report-4.png)\n\n**Mode explain** (vue en arbre d'une trace unique, `perf-sentinel explain --trace-id \u003cid\u003e`). Les findings rattachés à un span (N+1, redondant, lent, fanout) sont affichés inline à côté du span concerné ; les findings de niveau trace (service bavard, saturation du pool, appels sérialisés) sont remontés dans une section dédiée au-dessus de l'arbre :\n\n![vue en arbre explain avec annotation de fanout excessif sur le span parent](https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/explain/tree.png)\n\n![header trace-level explain avec warning de service bavard](https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/explain/trace-level.png)\n\n**Mode inspect** (TUI interactif, `perf-sentinel inspect`). Le header du panneau findings colore chaque finding selon sa sévérité ; les cinq images fixes ci-dessous parcourent la fixture démo à travers les trois niveaux de sévérité plus une vue du panneau détail avec sa fonction de scroll :\n\n![TUI inspect, vue initiale : service bavard warning (jaune)](https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/inspect/main.png)\n\n![TUI inspect, panneau détail actif : haut de l'arbre de spans fanout excessif](https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/inspect/detail.png)\n\n![TUI inspect, panneau détail scrollé : moitié basse de l'arbre fanout](https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/inspect/detail-scrolled.png)\n\n![TUI inspect, N+1 SQL critical (rouge) : 10 occurrences, suggestion de batch](https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/inspect/critical.png)\n\n![TUI inspect, HTTP redondant info (cyan) : 3 validations de token identiques](https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/inspect/info.png)\n\n`inspect --input` accepte aussi un Report JSON pré-calculé (par exemple un snapshot daemon issu de `/api/export/report`). Les panels Findings et Correlations s'allument complètement, le panel Detail affiche un message qui pointe vers les deux chemins qui portent les vrais spans :\n\n![TUI inspect, mode Report : 4 panels avec corrélations cross-trace et message Detail](https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/inspect/report-mode.png)\n\n**Mode pg-stat** (`perf-sentinel pg-stat --input \u003cpg_stat_statements.csv\u003e`) : classe les requêtes SQL de trois manières (par temps d'exécution total, par nombre d'appels, par latence moyenne). Cross-référence avec tes traces via `--traces` pour repérer les requêtes qui dominent la DB sans apparaître dans ton instrumentation :\n\n![pg-stat : top hotspots par temps total, appels et latence moyenne](https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/pg-stat/hotspots.png)\n\n**Mode calibrate** (`perf-sentinel calibrate --traces \u003ctraces.json\u003e --measured-energy \u003cenergy.csv\u003e`) :\n\n![entrée calibrate : CSV avec mesures de puissance par service](https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/calibrate/csv.png)\n\n![exécution calibrate : warnings et facteurs par service affichés](https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/calibrate/run.png)\n\n![sortie calibrate : TOML généré avec les facteurs de calibration](https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/calibrate/output.png)\n\n**Dashboard report** (`perf-sentinel report`) : six captures, une par onglet. Les GIFs plus haut déroulent le tour complet, ces captures figent chaque panneau pour lire les détails au zoom. Chaque `\u003cpicture\u003e` sert la variante sombre quand le navigateur annonce `prefers-color-scheme: dark` :\n\n\u003cpicture\u003e\n  \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/report/findings-dark.png\"\u003e\n  \u003cimg alt=\"dashboard report : Findings avec chips Warning + order-svc actifs\" src=\"https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/report/findings.png\"\u003e\n\u003c/picture\u003e\n\n\u003cpicture\u003e\n  \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/report/explain-dark.png\"\u003e\n  \u003cimg alt=\"dashboard report : arbre de trace Explain avec cinq SELECT N+1 surlignés et une suggestion Java JPA\" src=\"https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/report/explain.png\"\u003e\n\u003c/picture\u003e\n\n\u003cpicture\u003e\n  \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/report/pg-stat-dark.png\"\u003e\n  \u003cimg alt=\"dashboard report : classement pg_stat par Calls, 15 lignes\" src=\"https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/report/pg-stat.png\"\u003e\n\u003c/picture\u003e\n\n\u003cpicture\u003e\n  \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/report/diff-dark.png\"\u003e\n  \u003cimg alt=\"dashboard report : onglet Diff, un finding flaggé en régression\" src=\"https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/report/diff.png\"\u003e\n\u003c/picture\u003e\n\n\u003cpicture\u003e\n  \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/report/correlations-dark.png\"\u003e\n  \u003cimg alt=\"dashboard report : onglet Correlations, trois paires cross-trace avec confiance et lag médian\" src=\"https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/report/correlations.png\"\u003e\n\u003c/picture\u003e\n\n\u003cpicture\u003e\n  \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/report/greenops-dark.png\"\u003e\n  \u003cimg alt=\"dashboard report : onglet GreenOps avec breakdown CO2 multi-région sur eu-west-3, us-east-1 et eu-central-1\" src=\"https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/report/greenops.png\"\u003e\n\u003c/picture\u003e\n\n\u003cpicture\u003e\n  \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/report/cheatsheet-dark.png\"\u003e\n  \u003cimg alt=\"dashboard report : modal cheatsheet listant la table complète des raccourcis clavier\" src=\"https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/img/report/cheatsheet.png\"\u003e\n\u003c/picture\u003e\n\n\u003c/details\u003e\n\nEn mode CI (`perf-sentinel analyze --ci`), la sortie est un rapport JSON structuré :\n\n\u003cdetails\u003e\n\u003csummary\u003eExemple de rapport JSON\u003c/summary\u003e\n\n```json\n{\n  \"analysis\": {\n    \"duration_ms\": 0,\n    \"events_processed\": 10,\n    \"traces_analyzed\": 1\n  },\n  \"findings\": [\n    {\n      \"type\": \"n_plus_one_sql\",\n      \"severity\": \"critical\",\n      \"trace_id\": \"trace-demo-nplus-sql\",\n      \"service\": \"order-svc\",\n      \"source_endpoint\": \"POST /api/orders/42/submit\",\n      \"pattern\": {\n        \"template\": \"SELECT * FROM order_item WHERE order_id = ?\",\n        \"occurrences\": 10,\n        \"window_ms\": 450,\n        \"distinct_params\": 10\n      },\n      \"suggestion\": \"Use WHERE ... IN (?) to batch 10 queries into one\",\n      \"first_timestamp\": \"2025-07-10T14:32:01.000Z\",\n      \"last_timestamp\": \"2025-07-10T14:32:01.450Z\",\n      \"green_impact\": {\n        \"estimated_extra_io_ops\": 9,\n        \"io_intensity_score\": 10.0,\n        \"io_intensity_band\": \"critical\"\n      },\n      \"confidence\": \"ci_batch\"\n    }\n  ],\n  \"green_summary\": {\n    \"total_io_ops\": 10,\n    \"avoidable_io_ops\": 9,\n    \"io_waste_ratio\": 0.9,\n    \"io_waste_ratio_band\": \"critical\",\n    \"top_offenders\": [\n      {\n        \"endpoint\": \"POST /api/orders/42/submit\",\n        \"service\": \"order-svc\",\n        \"io_intensity_score\": 10.0,\n        \"io_intensity_band\": \"critical\"\n      }\n    ],\n    \"co2\": {\n      \"total\":     { \"low\": 0.000512, \"mid\": 0.001024, \"high\": 0.002048, \"model\": \"io_proxy_v3\", \"methodology\": \"sci_v1_numerator\" },\n      \"avoidable\": { \"low\": 0.000011, \"mid\": 0.000021, \"high\": 0.000043, \"model\": \"io_proxy_v3\", \"methodology\": \"sci_v1_operational_ratio\" },\n      \"operational_gco2\": 0.000024,\n      \"embodied_gco2\":    0.001\n    },\n    \"regions\": [\n      {\n        \"status\": \"known\",\n        \"region\": \"eu-west-3\",\n        \"grid_intensity_gco2_kwh\": 42.0,\n        \"pue\": 1.135,\n        \"io_ops\": 10,\n        \"co2_gco2\": 0.000024,\n        \"intensity_source\": \"monthly_hourly\"\n      }\n    ]\n  },\n  \"quality_gate\": {\n    \"passed\": false,\n    \"rules\": [\n      { \"rule\": \"n_plus_one_sql_critical_max\", \"threshold\": 0.0, \"actual\": 1.0, \"passed\": false },\n      { \"rule\": \"n_plus_one_http_warning_max\", \"threshold\": 3.0, \"actual\": 0.0, \"passed\": true },\n      { \"rule\": \"io_waste_ratio_max\", \"threshold\": 0.1, \"actual\": 0.9, \"passed\": false }\n    ]\n  }\n}\n```\n\n\u003c/details\u003e\n\n### Lecture du rapport\n\nLa CLI affiche un qualificatif `(healthy / moderate / high / critical)` à côté du I/O Intensity Score et du I/O waste ratio. La même classification est émise comme champs siblings dans le rapport JSON (`io_intensity_band`, `io_waste_ratio_band`), pour que les outils downstream (convertisseurs SARIF, dashboards Grafana, extensions IDE) puissent consommer nos heuristiques ou appliquer leurs propres sur les nombres bruts.\n\n| IIS       | Band       | Ancrage                                              |\n|-----------|------------|------------------------------------------------------|\n| \u003c 2.0     | `healthy`  | baseline CRUD simple (≤ 2 I/O par requête)           |\n| 2.0 - 4.9 | `moderate` | au-dessus de la baseline, à surveiller (heuristique) |\n| 5.0 - 9.9 | `high`     | seuil de détection du N+1 (5 occurrences)            |\n| ≥ 10.0    | `critical` | escalade CRITICAL du détecteur N+1                   |\n\n| I/O waste ratio | Band       | Ancrage                                       |\n|-----------------|------------|-----------------------------------------------|\n| \u003c 10%           | `healthy`  |                                               |\n| 10 - 29%        | `moderate` |                                               |\n| 30 - 49%        | `high`     | `[thresholds] io_waste_ratio_max` par défaut  |\n| ≥ 50%           | `critical` | la majorité de l'I/O analysée est du gaspi    |\n\n**Contrat de stabilité JSON :** les valeurs d'enum ci-dessus (`healthy` / `moderate` / `high` / `critical`) sont stables entre versions. Les seuils numériques qui les déclenchent sont versionnés avec le binaire et peuvent évoluer. Les consommateurs qui veulent une classification indépendante de la version doivent lire les champs bruts `io_intensity_score` et `io_waste_ratio` et appliquer leurs propres bandes.\n\nPour la sévérité par finding (`Critical` / `Warning` / `Info` sur chaque type de détecteur), voir [`docs/FR/design/04-DETECTION-FR.md`](docs/FR/design/04-DETECTION-FR.md). Pour le rationale complet des bandes d'interprétation, voir [`docs/FR/LIMITATIONS-FR.md`](docs/FR/LIMITATIONS-FR.md#interprétation-des-scores).\n\n## Démarrage rapide\n\n### Installation depuis crates.io\n\n```bash\ncargo install perf-sentinel\n```\n\n### Télécharger un binaire précompilé\n\nDes binaires pour Linux (amd64, arm64), macOS (arm64) et Windows (amd64) sont disponibles sur la page [GitHub Releases](https://github.com/robintra/perf-sentinel/releases). Les binaires Linux sont compilés contre musl en liaison statique totale : ils tournent sur n'importe quelle distribution (Debian, Ubuntu, Alpine, RHEL, etc.) quelle que soit la version de glibc, et fonctionnent dans une image `FROM scratch`. Les Mac Intel peuvent utiliser le binaire arm64 via Rosetta 2.\n\n```bash\n# Exemple : Linux amd64\ncurl -LO https://github.com/robintra/perf-sentinel/releases/latest/download/perf-sentinel-linux-amd64\nchmod +x perf-sentinel-linux-amd64\nsudo mv perf-sentinel-linux-amd64 /usr/local/bin/perf-sentinel\n```\n\n### Lancer avec Docker\n\n```bash\ndocker run --rm -p 4317:4317 -p 4318:4318 \\\n  ghcr.io/robintra/perf-sentinel:latest watch --listen-address 0.0.0.0\n```\n\nPar défaut, le daemon écoute sur `127.0.0.1` pour des raisons de sécurité. Dans un conteneur cette adresse est injoignable depuis l'hôte, donc le quickstart ci-dessus force le bind avec `--listen-address 0.0.0.0`. Le daemon affiche un avertissement non-loopback au démarrage, c'est attendu. Pour un vrai déploiement, placez un reverse proxy (ou une NetworkPolicy sur Kubernetes) devant, ou montez [`examples/perf-sentinel-docker.toml`](examples/perf-sentinel-docker.toml) pour la topologie compose complète.\n\nPour Kubernetes, un chart Helm est disponible sous [`charts/perf-sentinel/`](charts/perf-sentinel/). Voir [`docs/FR/HELM-DEPLOYMENT-FR.md`](docs/FR/HELM-DEPLOYMENT-FR.md).\n\n### Démo rapide\n\n```bash\nperf-sentinel demo\n```\n\n### Analyse batch (CI)\n\n```bash\nperf-sentinel analyze --input traces.json --ci\n```\n\n### Expliquer une trace\n\n```bash\nperf-sentinel explain --input traces.json --trace-id abc123\n```\n\n### Export SARIF (GitHub/GitLab code scanning)\n\n```bash\nperf-sentinel analyze --input traces.json --format sarif\n```\n\n### Import depuis Jaeger ou Zipkin\n\n```bash\n# Export Jaeger JSON (auto-détecté)\nperf-sentinel analyze --input jaeger-export.json\n\n# Zipkin JSON v2 (auto-détecté)\nperf-sentinel analyze --input zipkin-traces.json\n```\n\n### Analyse pg_stat_statements\n\n```bash\n# Analyser un export pg_stat_statements pour détecter les requêtes coûteuses\nperf-sentinel pg-stat --input pg_stat.csv\n\n# Référence croisée avec les findings de traces\nperf-sentinel pg-stat --input pg_stat.csv --traces traces.json\n\n# Scraper les métriques pg_stat_statements depuis un endpoint Prometheus postgres_exporter\nperf-sentinel pg-stat --prometheus http://prometheus:9090\n```\n\n### Inspection interactive (TUI)\n\n```bash\nperf-sentinel inspect --input traces.json\n```\n\n### Ingestion Tempo\n\n```bash\n# Analyser une trace depuis Grafana Tempo\nperf-sentinel tempo --endpoint http://tempo:3200 --trace-id abc123\n\n# Rechercher et analyser les traces par service\nperf-sentinel tempo --endpoint http://tempo:3200 --service order-svc --lookback 1h\n```\n\n### Calibration des coefficients\n\n```bash\n# Ajuster les coefficients énergie avec des mesures réelles\nperf-sentinel calibrate --traces traces.json --measured-energy rapl.csv --output calibration.toml\n```\n\n### Dashboard HTML\n\n```bash\n# Dashboard HTML single-file pour l'exploration post-mortem dans un navigateur\nperf-sentinel report --input traces.json --output report.html\n\n# Embarquer un onglet de ranking pg_stat_statements\nperf-sentinel report --input traces.json --pg-stat pg_stat.csv --output report.html\n\n# Ou scrape live depuis postgres_exporter Prometheus\nperf-sentinel report --input traces.json --pg-stat-prometheus http://prometheus:9090 --output report.html\n\n# Comparer à une baseline pour review de régression PR\nperf-sentinel report --input after.json --before baseline.json --output report.html\n\n# Piper un snapshot daemon live vers le dashboard\ncurl -s http://daemon:4318/api/export/report | perf-sentinel report --input - --output report.html\n```\n\nLe dashboard fonctionne offline (`file://`), zéro ressource externe, embarque uniquement les traces avec findings pour rester sous ~5 Mo. Clavier : `j`/`k`/`enter`/`esc` sur la liste Findings, `/` pour la recherche par onglet, `?` pour la cheatsheet complète, `g f`/`g e`/`g p`/`g d`/`g c`/`g r` pour switcher d'onglet style vim. Bouton Export CSV sur les onglets Findings, pg_stat, Diff et Correlations. Le fragment d'URL encode l'onglet actif, la recherche et les puces de filtre pour qu'un lien partagé restaure exactement la même vue.\n\n### Diff de régression PR\n\n```bash\n# Comparer deux analyses, fait remonter nouveaux findings, résolutions et changements de sévérité\nperf-sentinel diff --before base.json --after head.json\n\n# Sortie machine pour CI\nperf-sentinel diff --before base.json --after head.json --format json\nperf-sentinel diff --before base.json --after head.json --format sarif\n```\n\nL'identité pour le matching est `(finding_type, service, source_endpoint, pattern.template)`. Buckets de sortie : `new_findings`, `resolved_findings`, `severity_changes`, `endpoint_metric_deltas`. À utiliser dans un job PR pour attraper les régressions avant qu'elles atterrissent sur la branche principale.\n\n### Interroger un daemon en cours d'exécution\n\nToutes les sous-actions affichent une sortie colorée par défaut. Utilisez `--format json` pour le scripting.\n\n```bash\n# Lister les findings récents (sortie colorée par défaut)\nperf-sentinel query findings\nperf-sentinel query findings --service order-svc --severity critical\n\n# Expliquer un arbre de trace avec findings en ligne\nperf-sentinel query explain --trace-id abc123\n\n# TUI interactif avec les données live du daemon\nperf-sentinel query inspect\n\n# Afficher les corrélations cross-trace\nperf-sentinel query correlations\n\n# Vérifier l'état du daemon\nperf-sentinel query status\n\n# Sortie JSON pour le scripting\nperf-sentinel query findings --format json\nperf-sentinel query status --format json\n```\n\n### Mode streaming (daemon)\n\n```bash\nperf-sentinel watch\n```\n\n## Architecture\n\n\u003cpicture\u003e\n  \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/diagrams/svg/pipeline_dark.svg\"\u003e\n  \u003cimg alt=\"Architecture du pipeline\" src=\"https://raw.githubusercontent.com/robintra/perf-sentinel/main/docs/diagrams/svg/pipeline.svg\"\u003e\n\u003c/picture\u003e\n\n## Topologies de déploiement\n\nperf-sentinel supporte trois modèles de déploiement. Choisissez celui qui correspond à votre environnement.\n\n### 1. Analyse batch CI (point de départ recommandé)\n\nAnalysez des fichiers de traces pré-collectés dans votre pipeline CI/CD. Le processus retourne le code 1 si le quality gate échoue.\n\n```bash\n# Dans votre job CI :\nperf-sentinel analyze --ci --input traces.json --config .perf-sentinel.toml\n```\n\nCréez un `.perf-sentinel.toml` à la racine de votre projet :\n\n```toml\n[thresholds]\nn_plus_one_sql_critical_max = 0    # zéro tolérance pour les N+1 SQL\nio_waste_ratio_max = 0.30          # max 30% d'I/O évitables\n\n[detection]\nn_plus_one_min_occurrences = 5\nslow_query_threshold_ms = 500\n\n[green]\nenabled = true\ndefault_region = \"eu-west-3\"                  # optionnel : active la conversion en gCO2eq\nembodied_carbon_per_request_gco2 = 0.001      # terme M SCI v1.0, défaut 0,001 g/req\n\n# Surcharges optionnelles par service pour les déploiements multi-région\n# (utilisées quand cloud.region OTel est absent des spans) :\n# [green.service_regions]\n# \"order-svc\" = \"us-east-1\"\n# \"chat-svc\"  = \"ap-southeast-1\"\n```\n\nFormats de sortie : `--format text` (coloré, par défaut), `--format json` (structuré), `--format sarif` (GitHub/GitLab code scanning).\n\n### 2. Collector central (recommandé pour la production)\n\nUn [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/) reçoit les traces de tous les services et les transmet à perf-sentinel. Zéro modification de code dans vos services.\n\n```\napp-1 --\\\napp-2 ---+--\u003e OTel Collector --\u003e perf-sentinel (watch)\napp-3 --/\n```\n\nDes fichiers prêts à l'emploi sont fournis dans [`examples/`](examples/) :\n\n```bash\n# Démarrer le collector + perf-sentinel\ndocker compose -f examples/docker-compose-collector.yml up -d\n\n# Pointez vos apps vers le collector :\n#   OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317\n```\n\nperf-sentinel diffuse les findings en NDJSON sur stdout et expose des métriques Prometheus avec [Grafana Exemplars](docs/FR/INTEGRATION-FR.md) sur `/metrics` (port 4318). Un endpoint `GET /health` de liveness est exposé sur le même port pour les sondes Kubernetes ou load-balancer.\n\nVoir [`examples/otel-collector-config.yaml`](examples/otel-collector-config.yaml) pour la config complète du collector avec les options de sampling et filtrage.\n\n### 3. Sidecar (diagnostic par service)\n\nperf-sentinel tourne à côté d'un service unique, partageant son namespace réseau. Utile pour du debug isolé.\n\n```bash\ndocker compose -f examples/docker-compose-sidecar.yml up -d\n```\n\nL'app envoie les traces à `localhost:4317` (pas de saut réseau). Voir [`examples/docker-compose-sidecar.yml`](examples/docker-compose-sidecar.yml).\n\n---\n\nPour une vue d'ensemble de bout en bout et les quatre topologies supportées, voir [docs/FR/INTEGRATION-FR.md](docs/FR/INTEGRATION-FR.md). Pour l'instrumentation OTLP par langage (Java, Quarkus, .NET, Rust), voir [docs/FR/INSTRUMENTATION-FR.md](docs/FR/INSTRUMENTATION-FR.md). Pour les recettes d'intégration CI (GitHub Actions, GitLab CI, Jenkins) et la sous-commande `diff` pour la détection de régressions sur PR, voir [docs/FR/CI-FR.md](docs/FR/CI-FR.md). Pour la référence complète de configuration, voir [docs/FR/CONFIGURATION-FR.md](docs/FR/CONFIGURATION-FR.md). Pour l'API HTTP de requêtage du daemon (findings, explain, corrélations, status), voir [docs/FR/QUERY-API-FR.md](docs/FR/QUERY-API-FR.md). Pour le workflow post-mortem quand une trace est plus ancienne que la fenêtre live du daemon, voir [docs/FR/RUNBOOK-FR.md](docs/FR/RUNBOOK-FR.md). Pour la documentation de conception détaillée, voir [docs/FR/design/](docs/FR/design/00-INDEX-FR.md).\n\n## Normes et sources de données\n\nLes estimations carbone de perf-sentinel reposent sur une chaîne auditable de normes publiques, de jeux de données de référence et de méthodologie revue par les pairs. La liste d'autorité des citations par référence se trouve dans [`crates/sentinel-core/src/score/carbon.rs`](crates/sentinel-core/src/score/carbon.rs) (docstring de module) et dans [`crates/sentinel-core/src/score/carbon_profiles.rs`](crates/sentinel-core/src/score/carbon_profiles.rs) (commentaires de source par région sur chaque entrée de profil). Cette section est son complément narratif.\n\n### Norme / spécification\n\n- [Software Carbon Intensity v1.0 (ISO/IEC 21031:2024)](https://sci-guide.greensoftware.foundation/), Green Software Foundation. `co2.total` est le numérateur SCI v1.0 `(E × I) + M + T`, pas l'intensité par R. Discussion complète dans [docs/FR/design/05-GREENOPS-AND-CARBON-FR.md](docs/FR/design/05-GREENOPS-AND-CARBON-FR.md).\n\n### Jeux de données de référence\n\n- [Cloud Carbon Footprint (CCF)](https://www.cloudcarbonfootprint.org/) : intensité carbone annuelle par région cloud, valeurs PUE par fournisseur (AWS 1,135, GCP 1,10, Azure 1,185, générique 1,2) et les tables de coefficients SPECpower (~180 types d'instances) qui alimentent le backend énergie `cloud_specpower`.\n- [Electricity Maps](https://www.electricitymaps.com/) : intensités annuelles moyennes pour plus de 30 régions (2023-2024) utilisées comme référence `io_proxy_v1`, plus l'API temps réel (backend `electricity_maps_api`, opt-in via `[green.electricity_maps]`).\n- [ENTSO-E Transparency Platform](https://transparency.entsoe.eu/) : données horaires de production et de consommation utilisées pour dériver les profils mois x heure des zones de marché européennes (FR, DE, GB, IE, NL, SE, BE, FI, IT, ES, PL, NO).\n- Gestionnaires de réseau nationaux : [RTE eCO2mix](https://www.rte-france.com/en/eco2mix) (France), [Fraunhofer ISE energy-charts.info](https://www.energy-charts.info/?l=fr\u0026c=DE) (Allemagne), [National Grid ESO Carbon Intensity API](https://carbonintensity.org.uk/) (Royaume-Uni), [EIA Open Data API](https://www.eia.gov/opendata/) pour les balancing authorities américaines (PJM, CAISO, BPA), [rapports annuels Hydro-Québec](https://www.hydroquebec.com/sustainable-development/) (Canada), [AEMO NEM](https://www.aemo.com.au/) / [OpenNEM](https://opennem.org.au/) (Australie).\n- [Scaphandre](https://github.com/hubblo-org/scaphandre) : mesure de puissance par processus via RAPL Intel / AMD, scrapée depuis son endpoint Prometheus quand la section `[green.scaphandre]` est configurée.\n\n### Méthodologie académique\n\n- Xu et al., *Energy-Efficient Query Processing*, VLDB 2010. Benchmark énergétique par opération DBMS fondamental qui motive les multiplicateurs `SELECT 0,5x` / `INSERT 1,5x` / `UPDATE 1,5x` / `DELETE 1,2x` du modèle proxy.\n- Tsirogiannis et al., *Analyzing the Energy Efficiency of a Database Server*, SIGMOD 2010. Benchmark compagnon qui établit les coefficients par verbe.\n- Siddik et al., *DBJoules: Towards Understanding the Energy Consumption of Database Management Systems*, 2023. Confirme une variance inter-opérations de 7 à 38 % entre verbes, cross-validation pour la feature `per_operation_coefficients`.\n- Guo et al., *Energy-efficient Database Systems: A Systematic Survey*, ACM Computing Surveys 2022. Panorama du domaine.\n- IDEAS 2025 : framework d'estimation énergétique temps réel pour les requêtes SQL, référencé comme direction de travail pour les futures évolutions de `calibrate`.\n- Mytton, Lunden \u0026 Malmodin, *Estimating electricity usage of data transmission networks*, Journal of Industrial Ecology 2024. Source du défaut 0,04 kWh/GB sur le terme optionnel `include_network_transport` ; la plage 0,03-0,06 kWh/GB du papier est à l'origine du champ configurable `network_energy_per_byte_kwh`.\n- [API Boavizta](https://www.boavizta.org/en/) / HotCarbon 2024 : modèle bottom-up du cycle de vie carbone embodied d'un serveur, référencé pour le calibrage par défaut de `embodied_per_request_gco2`.\n\n## Licence\n\nCe projet est sous licence [GNU Affero General Public License v3.0](LICENSE).\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobintra%2Fperf-sentinel","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frobintra%2Fperf-sentinel","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobintra%2Fperf-sentinel/lists"}