Aller au contenu
Vous êtes : le contenu s’adapte, la page reste la même
Lecture :
pour toute la page, ajustable zone par zone
Mono-binaire auto-hébergé · OpenTelemetry · Open source AGPL-3.0

Détectez les I/O gaspillées de vos traces. Chiffrez-⁠les en énergie et carbone.

Perf Sentinel repère les N+1, appels redondants, requêtes lentes et fanout dans vos traces OpenTelemetry, en quality gate CI ou en daemon OTLP, puis convertit chaque I/O évitable en énergie et en CO₂.

Un projet open-source porté par
l’Institut du Numérique Responsable
CRITN+1 HTTPGET /api/cart/enrich12 appels → 1 11 appels évitables, corrigeable à inventory/enrich.py:88. Un finding de la démo ci-dessous, onglet Findings.
12 × GET catalog-svc/api/products/{id} · 110 ms · 1 utile, 11 évitables
Ce qui se passe
Pour un seul panier, le service appelle le catalogue produit par produit.
Ce que ça coûte
11 appels évitables par requête, et l’endpoint passe en bande critique d’intensité I/O.
Où corriger
inventory/enrich.py:88
endpoint batch ?ids=…, 12 appels → 1
Voir la trace complète →
Démo interactive :
Ouvrir dans un ongletOuvrir la démo interactive ↗
Rapport HTML ou TUI, selon vos préférences. Hub optionnel mais recommandé.
Le synoptique montre Perf Sentinel de l'intérieur, de la carte des environnements jusqu'aux règles de détection.
// le problème

Pourquoi Perf Sentinel ?

Les anti-patterns d’I/O touchent toute application, monolithe comme microservices. En distribué, une requête traverse plusieurs services en cascade, et le gaspillage n’apparaît qu’en regardant la trace entière.

Perf Sentinel lit les traces que votre application émet déjà (SQL, HTTP, publications vers un broker), quel que soit le langage ou l’ORM : il voit les requêtes générées, sans avoir besoin de comprendre JPA ou EF Core.

Chaque I/O évitable est aussi chiffré en énergie et en CO₂, par le bas et attribuable au code.

Prérequis : vos services émettent des traces OpenTelemetry de leurs appels base de données, HTTP et messagerie, ou des traces Datadog via un Collector OpenTelemetry.

Vérifiez d’abord votre instrumentation : un appel base de données ou HTTP enregistré sans sa requête ou son URL est écarté. Un rapport maigre peut signaler une application saine ou une instrumentation lacunaire.

Ce que ce n’est pas : un APM complet, un profileur continu, ni (pour le moment) une plateforme autonome de comptabilité carbone réglementaire. Voir le comparatif.

Maturité : bêta, pré-1.0, les commandes et la configuration peuvent donc encore changer. En production dans une équipe depuis juin 2026.

Attributs de span requis et mise en place par langage

// ce qui est détecté

Douze anti-patterns d'I/O, au niveau protocole

Sur les requêtes SQL et HTTP que vos services émettent déjà, quel que soit le langage ou l’ORM.

Huit patterns de répétition et de lenteur, par protocole :

SQL
HTTP
Messaging
N+1
Même template répété au moins 5 fois dans une trace, avec des paramètres différents (même destination pour le messaging).
Même template, paramètres différents, au moins 5 fois par trace.
✓
✓
✓
Redondant
Appel identique, paramètres identiques, même trace.
Même appel, mêmes paramètres, dans la même trace.
✓
✓
—
Lent
Même opération au-delà de 500 ms au moins 3 fois dans une trace.
Même opération au-delà de 500 ms, au moins 3 fois.
✓
✓
✓
Exemple : le N+1 de la démoinventory-svc · GET /api/cart/enrich · 12 appels → 1
utileévitable
AVANT
GET /api/cart/enrich
CartService::enrich
GET …/products/1
GET …/products/2
GET …/products/3
GET …/products/4
GET …/products/5
GET …/products/6
GET …/products/7
GET …/products/8
GET …/products/9
GET …/products/10
GET …/products/11
GET …/products/12
12 appels HTTP · 11 évitables~8 ms chacun, l’un après l’autre, sur 110 ms
APRÈS
GET /api/cart/enrich
CartService::enrich
GET …/products?ids=1,…,12
CRITN+1 HTTPGET /api/cart/enrich
Corrigeable à inventory/enrich.py:88 avec un endpoint batch ?ids=…. Le même finding est dans la démo, onglet Findings.
1 appel HTTP · 12 appels → 1durée après correction non mesurée : elle dépend de l’endpoint batch

Et quatre patterns de structure :

span 22 enfants

Fanout excessif

> 20 enfants
Une même opération (span) déclenche plus de 20 appels enfants (SQL, HTTP…), en parallèle ou non.Une même opération déclenche trop d’appels enfants, en parallèle ou non.
ABC requête 16 HTTP sortantssur toute la trace

Service bavard

> 15 HTTP sortants
Une seule requête utilisateur déclenche plus de 15 appels HTTP sortants au total, même répartis sur plusieurs parents. C’est ce qui le distingue du fanout.Trop d’appels HTTP sortants pour une seule requête, tous parents confondus. C’est ce qui le distingue du fanout.
service A · spans SQL 10 en même temps

Saturation de pool

≥ 10 SQL simultanées
Au moins 10 requêtes SQL d’un même service en cours au même instant dans une trace. Signe probable de contention, déduit du chevauchement des spans, pas des métriques du pool.Trop de SQL simultanées d’un même service, déduit du chevauchement des spans.
aujourd’hui · même parent ABC possible ABC en série

Appels sérialisés

≥ 3 appels frères
Au moins 3 appels I/O frères (même parent), sur des templates différents, lancés l’un après l’autre alors qu’ils pourraient partir en parallèle.Des appels frères lancés l’un après l’autre alors qu’ils pourraient partir en parallèle.

Chaque finding embarque : type, sévérité, template normalisé, occurrences, endpoint source, suggestion, localisation source et impact GreenOps. En mode daemon, s’y ajoute la corrélation cross-trace.

Chaque finding indique sa sévérité, le template en cause, l’endpoint source, une suggestion de correction et son impact GreenOps.

// vos technologies

Compatible avec vos langages, frameworks et ORM

La détection lit le protocole, elle fonctionne donc avec tout environnement d’exécution qui émet des traces OpenTelemetry. Ceux ci-dessous ont en plus un guide de mise en place ou des conseils de correction écrits pour eux.

Langages
Frameworks& ORM
Langages
Frameworks& ORM
Guides de mise en place par langage →
// quatre façons de l'exécuter

1 binaire, 2 modes, 4 façons de le déployer

Vos traces
SDK OpenTelemetry
OTel Collector
Datadog via Collector
mode batch
Traces capturées
Mêmes traces, même verdict.
TUIHTML hors ligneSARIFJSON déterministeexit 1 sur seuil
Exploration
en local, démo intégrée
Batch CI
quality gate dans le pipeline
mode daemon
Flux OTLP en continu
gRPC :4317 · HTTP :4318
/metrics Prometheustableau de bord liveAPI de requêtecorrélation cross-trace→ Hub (historique)
Sidecar
un daemon par service
Centralisé
un seul daemon, via Collector

Avec un assistant de code IA

Un plugin amène Perf Sentinel dans le changement sur lequel vous travaillez. Il demande avant chaque modification.

Disponible aujourd’hui pour Claude Code.

  1. avant la production/perf-sentinel:perf-tests

    Écrit des tests d’intégration de performance pour votre changement en cours, les lance sous Perf Sentinel et, si vous le voulez, les branche dans votre CI.

  2. en production, avec le Hub/perf-sentinel:prod-findings

    Lit dans le Hub les findings de vos services, les classe par I/O évitable et les corrige par petits lots, chacun prouvé par un test de non‑régression.

# dans Claude Code
> /plugin marketplace add Institut-du-Numerique-Responsable/perf-sentinel-claude
> /plugin install perf-sentinel@perf-sentinel
Le plugin sur GitHub ↗

Publié par le projet Perf Sentinel, indépendant d’Anthropic. Claude Code est un produit d’Anthropic.

// écrit en rust

Un mono-binaire Rust, mesuré

Rust ≥ 1.99.1 (MSRV)

Les chiffres ci-dessous chronomètrent le pipeline d’analyse seul (mono-thread, sur jeux de données synthétiques) : ils isolent le coût du pipeline, pas un débit de bout en bout.

576k–⁠1.2M
évts/s, débit pipeline (GCP c3-standard-8 x86 à M4 Pro)
0.8–⁠1.9 µs
par évènement, p50 à p99
17 → 980 Mo
RSS du daemon : au repos, puis médiane en production à dix fois la rétention par défaut
Rust 2024
avec binaire statique musl et image FROM scratch
Benchmarks détaillés dans la doc →
// un seul pour la flotte

Un Hub C#, pour l’historique des findings

.NETSDK .NET 10.0.403

En mode daemon, Perf Sentinel garde ses findings en mémoire, les plus anciens évincés d’abord, et /api/findings répond au plus 1 000 lignes : l’état courant, pas l’historique. Le Hub, service séparé, collecte chaque daemon et garde ce qu’une éviction ou un redémarrage effacerait, comme la première apparition d’un finding. Il reçoit aussi les rapports périodiques qu’une tâche planifiée publie, les vérifie, rend leur PDF et les partage par un lien qui expire. Son récap classe ce qu’il faut corriger d’abord et ce qui a bougé, en vue technique et en vue pilotage, et une correction confirmée devient une carte signée à partager.

En mode daemon, Perf Sentinel garde un nombre borné de findings en mémoire : l’état courant, pas l’historique. Le Hub, service séparé, collecte chaque daemon et garde ce qu’une éviction ou un redémarrage effacerait. Il vérifie et partage aussi les rapports périodiques, classe ce qu’il faut corriger d’abord dans un récap, technique ou pilotage, et signe des cartes à partager.

perf-sentinel · daemon 1
perf-sentinel · daemon 2
perf-sentinel · daemon 3
mémoire bornée, éviction des plus anciens
push + reprise
pull de secours (le Hub interroge)
Perf Sentinel Hub
Conserve l’historique des findings, dont la date de première apparition, qui survit :
au redémarrageà l’évictionau changement de template
NavigateurLANCEUR
choisit une source et les réglages du run
le Hub lance Perf Sentinel, puis sert le tableau de bord
~130 ms
démarrage à froid jusqu’à la première réponse (médiane, image arm64)
démarrage à froid
~21 Mo
RSS au repos, avant tout import
RSS au repos
38–⁠40 Mo
image compressée (Hub ~11 Mo, Perf Sentinel ~7 Mo, base chiselée ~21 Mo)
image compressée
NativeAOT
un binaire natif unique, sans runtime .NET, image chiselée non root
binaire natif, sans runtime .NET
// la revue d’équipe

Ce qu’il faut corriger d’abord, jusqu’à la ligne de code

Pour la revue d’équipe, le Hub classe les findings par I/O évitables sur la période et donne pour chacun son correctif, sa place dans le code et sa signature. Les tendances ne comptent que les jours clos. Aucune IA ne le rédige : chaque phrase vient des règles du moteur.

Le récap, vue techniqueMois de juillet 2026 · production
À corriger d’abordclassé par I/O évitables
  1. 1
    N+1 SQLAfficher un paniershopGET /cart/{id}

    Use WHERE ... IN (?) to batch 41 queries into one

    1,9 millionI/O évitablesplus qu’en juin
    Comment corriger
    SELECT * FROM cart_item WHERE cart_id = ?
    Correctif suggéréjava_jpa

    Use JOIN FETCH on the relationship or annotate the repository method with @EntityGraph to load associations in a single query.

    Où dans le code
    CartItemRepository.findByCartId
    shop/src/main/java/acme/cart/CartItemRepository.java:31
    détections
    1 284
    confiance
    daemon_production
    signature
    n_plus_one_sql:shop:GET__cart_{id}:09908701485122dcb9d5d84b7c653b7c
  2. 2
    N+1 messagingConfirmer une commandecheckoutPOST /orders/{id}/confirm

    Send 12 messages as one batch instead of one publish per item

    412 000I/O évitablesnouveau ce mois-ci
  3. 3
    Redundant HTTPOuvrir les réglagesaccountGET /api/settings

    Identical operation executed 3 times: cache result or deduplicate

    96 000I/O évitablesmoins qu’en juin
Récap adapté de la démo du Hub, entreprise fictive. Les suggestions du moteur restent en anglais.
// l’angle mort

Le poids carbone du numérique,
et son angle mort : le code applicatif

Le numérique pèse déjà 1,8 % à 3,9 % des émissions mondiales de GES, à la hauteur de l’aviation civile et en croissance rapide. Mais la part due au code et aux applications web lourdes mal optimisées reste non quantifiée à l’échelle mondiale.

Le numérique pèse 1,8 % à 3,9 % des GES mondiaux
5 %4 %3 %2 %1 %0 %
1,8 %
3,9 % (dont ? %)
?
Estimation basse
Estimation haute
Mesuré : data centers, réseaux, terminaux
Zone non mesurée : manque d’optimisation des apps webs lourdes
Le code n’apparaît dans aucun chiffre

Les estimations publiées couvrent les data centers, les réseaux et les terminaux. Aucune ne descend jusqu’à une requête ou un endpoint.

72 %
de réduction d’émissions par visite après l’optimisation côté front par Jisc d’une page à fort trafic (1,09 g → 0,30 g CO₂)
// estimer par le bas, pas par le haut

L’approche bottom-up de Perf Sentinel face au top-down des outils actuels

Approche top-down
SI et outils carbone actuels
•Part de moyennes : consommation des data centers, ratios sectoriels.
•Estime une empreinte globale depuis la facture cloud ou les effectifs.
•Donne un chiffre annuel, mais pas le détail de ce qui pèse.
Résultat
Chiffre global, non attribuable et non actionnable.
Approche bottom-up
Perf Sentinel sur les apps web lourdes
✓Observe l’application réelle, requête par requête.
✓Traduit chaque traitement en énergie puis en carbone, selon la méthode SCI.
✓Pointe les gaspillages évitables et leur coût.
Résultat
Gisement chiffré, attribuable au code et directement actionnable.
// greenops

Chaque I/O évitable a un coût,
en temps, énergie et carbone

Réduire les N+1 et les appels redondants améliore à la fois les temps de réponse et la consommation d'énergie. co2.total suit le numérateur Software Carbon Intensity v1.0 (ISO/IEC 21031:2024) : l’énergie consommée (E) multipliée par l’intensité carbone du réseau électrique (I), plus les émissions matérielles embarquées (M), le tout sommé sur les traces analysées.

Réduire les N+1 et les appels redondants améliore à la fois les temps de réponse et la consommation d'énergie. co2.total suit la méthode Software Carbon Intensity v1.0 (ISO/IEC 21031:2024), sommée sur les traces analysées.

co2.total
Énergie
estimée par I/O, ou mesurée en mode daemon
Intensité carbone
par région, table embarquée ou Electricity Maps
Fabrication
part du matériel, par requête
bornes basse et haute dans chaque rapport
co2.avoidable : la part due aux I/O évitables, hors fabrication

Score d'intensité I/O (IIS)

Total des opérations I/O d'un endpoint divisé par son nombre d'invocations.

Ratio de gaspillage I/O

Opérations évitables sur opérations totales, la part directement récupérable.

co2.total multi-régions

Numérateur SCI v1.0, scoring par région automatique quand les spans portent cloud.region.

Estimation directionnelle, assez pour prioriser et comparer avant et après. Une source d’énergie mesuréeUne source d’énergie mesurée (mode daemon) affine E. Activity data pour Watershed · Sweep · Greenly · Persefoni ou une démarche RGESN. Rapports publics périodiques énergie et carbone en option (trimestriels ou annuels, en JSON et PDF/A-3b, signature Sigstore optionnelle, vérifiables par hash).

Une estimation directionnelle, assez pour prioriser et comparer avant et après. Une source d’énergie mesurée l’affine. Elle sert de donnée d’activité pour vos outils carbone ou une démarche RGESN, et peut être publiée en rapport périodique.

// sources de mesure

De l'estimation à la mesure,
quand votre infra le permet

Par défaut, l’énergie est estimée depuis les I/O : un chiffre directionnel, à 2× près. En mode daemon, elle peut venir d’une mesure, avec l’intensité carbone du réseau en temps réel. Le rapport JSON nomme sa source.

énergie, selon votre infrastructure
Mesure logicielle : processeur (RAPL)
Une des trois, Alumet en priorité. Requiert Linux x86 avec accès RAPL : bare metal, ou VM qui l'expose (rare dans le cloud).
Recommandé
Attribue l'énergie RAPL par conteneur. Peut aussi mesurer une base de données ou un broker auto-hébergés.
par conteneur
Attribue l'énergie RAPL par processus.
par processus
Attribue l'énergie RAPL par conteneur ou par processus. Pensé pour Kubernetes, sans l'exiger.
par conteneur ou processus
Mesure du serveur entier
Serveurs physiques dont le BMC vous est accessible, quelle que soit l'architecture
Puissance du serveur entier, lue sur son contrôleur (BMC) : ventilateurs et disques compris. Aucune VM cloud n'expose de BMC.
Aucune VM cloud n’expose de BMC.
Bare metal · BMC
intensité carbone en direct

Remplace l’intensité carbone embarquée par la valeur en direct de la zone où tournent vos services, le plus gros levier sur les gCO₂ quand le mix électrique varie.

Les opérateurs de réseauGratuit
La valeur que publie l’opérateur du réseau électrique de la zone, directement à la source.
FR
RTE
éCO2mix
GB
NESO
Carbon Intensity API
FI
Fingrid
Open Data
DK
Energinet
Energi Data Service
ES
REE
e·sios
AU
Open Electricity
NEM · WEM
HU
MAVIR
export XLSX
NZ
em6
Transpower
Intensité en direct pour la plupart des zones du monde, en analyse de cycle de vie.
Clé APIpayant en usage commercial

Indépendant de la source d’énergie : se combine avec n’importe quelle option ci-dessus, ou avec l’estimation par défaut. Là où les deux couvrent une zone, Electricity Maps l’emporte. Là où aucun ne la couvre, la table embarquée s’applique.

Une mesure logicielle n’est pas un compteur : RAPL ne voit que processeur et mémoire, la moitié aux deux tiers de la consommation à la prise. Seul Redfish voit aussi ventilateurs, disques et cartes réseau.

Sources de mesure et précision dans la doc →
// comment ça se compare

Léger, agnostique, CI-natif, carbon-aware

Capacité
APM commercial type
Perf Sentinel
Empreinte runtime
Agent par hôte ou dans chaque service (~130 Mo RSS pour l’Agent Datadog)
Un seul daemon pour toute la flotte, 17 Mo au repos, puis selon les findings retenus
Couverture langages
Agents par langage ou SDK
Tout runtime instrumenté OTel
Détection N+1 SQL & HTTP
Oui, liée à l’agent
Oui, au niveau protocole
Corrélation cross-service
Oui
Oui, via trace ID
Quality gate CI natif
Pas de gate sur les anti-patterns de traces
Oui, exit 1 sur seuil
Score GreenOps (IIS, gaspillage)
Non
Intégré
Attribution carbone par span
Non
Oui (aligné SCI, directionnel)
Licence & hébergement
SaaS propriétaire, à l’usage
AGPL-3.0, auto-hébergeable

« APM commercial type » : outils SaaS à agent, variables selon le produit, comme Datadog ou New Relic. Le chiffre d’agent, publié par Datadog pour l’Agent 7.34, exclut le traceur par service, comme celui de Perf Sentinel exclut l’instrumentation OTel qu’il lit. Pas un APM complet : il s’adosse à une suite d’observabilité sans la remplacer. Comparatif par outil (Sentry, Hypersistence, Digma, Pyroscope, OTJAE) dans la doc.

« APM commercial type » : outils SaaS à agent comme Datadog ou New Relic. Perf Sentinel s’adosse à une suite d’observabilité sans la remplacer.

Ce que Perf Sentinel n’est pas

✗Pas un remplacement d’APM complet. L’outil n’a ni RUM, ni agrégation de logs, ni interface d’alerting, que Datadog, New Relic et Sentry couvrent.Ni RUM, ni agrégation de logs, ni alerting.
✗Pas un profiler continu. L’outil observe les patterns d’I/O, pas le temps CPU ni les allocations, et se marie bien avec Grafana Pyroscope.Il observe les I/O, pas le CPU ni les allocations.
✗Pas une plateforme de monitoring. Un daemon garde un tampon borné de findings récents, et Perf Sentinel Hub ajoute l’historique à l’échelle de la flotte.Le daemon garde les findings récents, le Hub l’historique.
✗Pas (encore) une plateforme de comptabilité carbone réglementaire standalone. Un reporting CSRD ou GHG Protocol Scope 2/3 standalone exige une vérification tiers-partie qu’il n’a pas. Périmètre et couplages :Il lui manque la vérification tierce qu’exige un reporting CSRD ou GHG Protocol. Périmètre : voir la section GreenOps.
✗Pas un substitut à la mesure énergétique. Le modèle I/O-vers-énergie est une estimation directionnelle, affinée par Alumet, Scaphandre, Kepler, Redfish ou les API énergie des clouds. Ce que couvre l’attribution logicielle :Une estimation directionnelle, qu’une sonde affine. Ce qu’elle couvre : voir la documentation sur les limites.
✗Pas zéro-config. La détection au niveau protocole exige une instrumentation OTel dans vos apps.Il exige une instrumentation OTel dans vos apps.
✗Pas un plugin IDE. Pour du feedback in-IDE en JVM/.NET au fil de la frappe, Digma offre une expérience JetBrains bien intégrée.Pas de retour au fil de la frappe dans l’éditeur.
// publier et vérifier

Un rapport que chacun peut vérifier

Le daemon archive chaque fenêtre d’analyse. perf-sentinel disclose en tire un rapport trimestriel ou annuel, et disclose-pdf le rend en PDF/A-3b. Le Hub peut le recevoir et le partager, mais personne n’en a besoin pour le vérifier.

Première page du rapport d’exemple : énergie 18,42 kWh, carbone 1,91 kgCO₂eq, évitable 0,34 kgCO₂eq sur le premier trimestre 2026.

Un PDF de dix pages, lisible sans outil : les chiffres du trimestre et leur marge d’incertitude, le périmètre mesuré, les limites de la méthode, et une annexe de chaque champ du rapport. Le rapport source et sa signature voyagent en pièce jointe, et une commande suffit à tout revérifier.

  • PDF/A-3b
  • 10 pages
  • signé (Sigstore)
  • entreprise fictive

Vérifiez-le vous-même

Après le téléchargement, une commande recalcule le hash du rapport joint, vérifie que l’attestation le nomme et contrôle la signature, avec cosign dans le PATH.

Une commande, avec cosign dans le PATH, recalcule le hash du rapport joint et contrôle sa signature.

$ curl -fsSLO https://perf-sentinel.dev/exemple/disclosure/report.pdf
$ perf-sentinel verify-hash --report report.pdf \
$ perf-sentinel verify-hash --report report.pdf
--expected-identity https://github.com/Institut-du-Numerique-Responsable/perf-sentinel/.github/workflows/sample-disclosure.yml@refs/heads/main…/sample-disclosure.yml@refs/heads/main \
--expected-issuer https://token.actions.githubusercontent.com
Overall: TRUSTED
// licence

AGPL-3.0, ce que ça implique pour votre code

open source

Un résumé lisible par un service juridique, sans fouiller le dépôt. Perf Sentinel est sous licence GNU Affero General Public License v3.0.

✓
Vos services restent les vôtres

Faire tourner Perf Sentinel ne place pas vos propres services sous AGPL. C’est un processus autonome : vos applications lui envoient seulement des traces OpenTelemetry par le réseau (OTLP), une communication à distance et non un lien de compilation, qui ne crée donc aucune œuvre dérivée et n’impose aucune obligation de licence sur votre code.

✓
Binaires non modifiés, aucune obligation

L’AGPL couvre le code source de Perf Sentinel lui-même. Utiliser les binaires ou l’image officiels non modifiés n’entraîne aucune obligation de copyleft, d’aucune sorte.

La seule condition : si vous modifiez Perf Sentinel et proposez la version modifiée à des tiers via un réseau, l’article 13 vous oblige à mettre cette source modifiée à disposition de ces utilisateurs. Ceci est un résumé pratique et non un avis juridique. Consultez votre service juridique en cas de doute.

La seule condition : si vous modifiez Perf Sentinel et proposez cette version à des tiers par le réseau, l’article 13 vous oblige à en publier la source. Résumé pratique, pas un avis juridique.

// pour votre DSI

Ce que votre DSI vérifiera, et où le trouver

Perf Sentinel et son Hub s’installent sur votre infrastructure, sans SaaS. Ce qu’une revue de sécurité examine en général : actif par défaut, ou à votre charge.

DONNÉES

Requêtes normalisées en mémoire

Le moteur remplace en mémoire les valeurs SQL et les identifiants d’URL par des marqueurs, avec des exceptions documentées. Le Hub garde ces findings 180 jours par défaut, dans une base SQLite chez vous.

Valeurs SQL et identifiants d’URL remplacés, avec des exceptions documentées. Le Hub garde les findings 180 jours par défaut, chez vous.

FLUX

Aucune télémétrie

Le moteur ne contacte que ce que vous configurez, comme une source de mesure d’énergie. Le Hub vérifie chaque jour la dernière version sur GitHub, et un réglage le désactive.

Le Hub vérifie chaque jour la dernière version sur GitHub, et un réglage le désactive.

ACCÈS

Ce qui est ouvert, et comment le fermer

Le daemon écoute sur 127.0.0.1 par défaut, TLS en option. Ses lectures ne sont pas authentifiées : une NetworkPolicy ou votre ingress les filtre. Le Hub exige une clé par source et peut placer son interface derrière votre SSO.

Les lectures du daemon ne sont pas authentifiées : une NetworkPolicy ou votre ingress les filtre. Le Hub exige une clé par source.

CODE ET IMAGE

Rust sans unsafe, images sans root

Le cœur du moteur interdit le code unsafe à la compilation. Les deux images tournent sans root, FROM scratch pour le moteur et chiselée pour le Hub, en lecture seule dans leurs charts Helm.

FROM scratch pour le moteur, chiselée pour le Hub, en lecture seule dans leurs charts Helm.

APPROVISIONNEMENT

Tags signés, binaires traçables

Tags de release signés, provenance de build attestée via Sigstore et SBOM SPDX à chaque version. Actions épinglées par SHA, dépendances auditées chaque jour.

Provenance de build attestée via Sigstore et SBOM SPDX à chaque version.

SIGNALEMENT

Signalement privé, délais publiés

Les failles se signalent en privé via GitHub. Chaque dépôt publie ses délais de réponse et les versions qui reçoivent les correctifs.

Chaque dépôt publie aussi les versions qui reçoivent les correctifs.

Le dossier sécurité complet →

Posez la sentinelle dans votre pipeline

Démo intégrée sans rien installer côté apps, puis quality gate sur traces capturées ou daemon OTLP à côté de votre tracing.

# 1. les traces de vos tests d’intégration
$ perf-sentinel capture -o traces.json -- mvn verify
# 2. le gate : code de sortie 1 si un seuil est franchi
$ perf-sentinel analyze --input traces.json --ci
# 3. les findings dans Code scanning (SARIF)
$ perf-sentinel analyze --input traces.json --format sarif > findings.sarif
Modèles GitHub Actions, GitLab CI et Jenkins →
$ cargo install perf-sentinel --locked
$ perf-sentinel demo # rapport terminal
$ perf-sentinel demo --tui # TUI interactif
$ perf-sentinel demo --html demo.html # dashboard HTML
Binaires précompilés, image Docker et chart Helm dans le guide →
Le projet vous sert ? Une étoile l’aide à se faire connaître.Perf Sentinel43Perf Sentinel Hub1
Institut du Numérique ResponsableInstitut du Numérique Responsable
// gouvernance

Porté par l’Institut du Numérique Responsable

Né comme projet personnel, Perf Sentinel a rejoint l’INR, association loi 1901 issue du Club Green IT. Son créateur, Robin Trassard, continue de le diriger au sein de l’institut. Robin est par ailleurs développeur fullstack chez Onepoint, orienté back-end et spécialisé en performance et éco-conception. Le code reste sous AGPL-3.0 et se développe en public sur le GitHub de l’INR.

{{ skipLink }}
Perf SentinelPerf Sentinel
GitHub{{ psStarsN }}
{{ personaPrompt }} {{ personaHint }}
{{ spotTitle }}{{ spotSkip }}
{{ tipText }}
{{ dLead }}
{{ dHint }}
{{ eyebrowHero }}{{ eyebrowHeroGreen }}

{{ heroTitle }}

{{ heroSub }}

{{ inrBy }}
{{ inrArt }}{{ inrName }}
CRITN+1 HTTPGET /api/cart/enrich{{ dfCalls }} {{ dfLineA }}inventory/enrich.py:88{{ dfLineB }}
{{ dfBarsA }}GET catalog-svc/api/products/{id}{{ dfBarsB }}
{{ dfWhatT }}
{{ dfWhat }}
{{ dfCostT }}
{{ dfCost }}
{{ dfFixT }}
inventory/enrich.py:88
{{ dfFixA }}?ids=…{{ dfFixB }}
{{ dfTrace }} →
{{ embedLead }}
{{ embedOpen }}{{ embedOpenMobile }} ↗
{{ embedCaption }}
{{ embedCaptionSyn }}
{{ proofAvT }}{{ proofEq }}
{{ proofAvS }}
{{ proofFoot }}
{{ proofCalls }}
  • {{ c.t }}
{{ whyEyebrow }}

{{ whyT1 }}{{ whyTName }}{{ whyT2 }}

{{ whyP1 }}

{{ whyP2 }}

  1. {{ l.n }}{{ l.tag }}
    {{ l.title }}
    {{ l.sub }}

{{ lgcScope }}

{{ whyP3 }}

{{ whyP4 }}

{{ smpAlt }}

{{ smpT }}

{{ smpP }}

  • {{ f.t }}

{{ prereq1Label }} {{ prereq1Text }}

{{ prereq2Label }} {{ prereq2Text }}

{{ prereqNotLabel }} {{ prereqNotText }} {{ prereqNotLink }}.

{{ prereq3Label }} {{ prereq3Text }}

{{ prereqLink }}

{{ shrEyebrow }}

{{ shrT1 }}{{ shrTW }}

{{ shrIntro }}

{{ shrRecapHead }}{{ shrPeriod }}
{{ shrFixFirst }}
  1. {{ r.i }}
    {{ r.s }}
    {{ r.where }}
    {{ r.n }}{{ shrUnit }}{{ r.pill }}
{{ shrRecapCap }}
{{ shrBridge }}
{{ shrAlt }}
{{ shrCardCap }}{{ shrCo2 }}

{{ shrNeverT }}

  • {{ n.t }}
{{ detEyebrow }}

{{ detT1 }}{{ detWAnti }}{{ detT2 }}

{{ detIntro }}

{{ detMatrixLead }}

{{ c }}
{{ r.name }}
{{ r.rule }}
{{ r.ess }}
{{ r.sql }}
{{ r.http }}
{{ r.msg }}
{{ detExTitle }}{{ detExSub }}
{{ detExNeeded }}{{ detExAvoidable }}
{{ detExBefore }}
GET /api/cart/enrich
CartService::enrich
GET …/products/1
GET …/products/2
GET …/products/3
GET …/products/4
GET …/products/5
GET …/products/6
GET …/products/7
GET …/products/8
GET …/products/9
GET …/products/10
GET …/products/11
GET …/products/12
{{ detExBeforeSum }}{{ detExBeforeNote }}
{{ detExAfter }}
GET /api/cart/enrich
CartService::enrich
GET …/products?ids=1,…,12
CRITN+1 HTTPGET /api/cart/enrich
{{ detExFix }}
{{ detExAfterSum }}{{ detExAfterNote }}

{{ detStructLead }}

{{ p.labels.0 }} {{ p.labels.1 }} ABC {{ p.labels.0 }} {{ p.labels.1 }}{{ p.labels.2 }} {{ p.labels.0 }} {{ p.labels.1 }} {{ p.labels.0 }} ABC {{ p.labels.1 }} ABC {{ p.labels.2 }}

{{ p.name }}

{{ p.badge }}
{{ p.trigger }}{{ p.ess }}

{{ detFoot }}

{{ detFootEss }}

{{ stackEyebrow }}

{{ stackTitle }}

{{ stackIntro }}

{{ stackLangs }}
{{ stackFws }}{{ stackOrm }}
{{ stackLangs }}
{{ stackFws }}{{ stackOrm }}
{{ stackLink }} →
{{ modEyebrow }}

{{ modTitle }}

{{ modSrc }}
{{ s }}
{{ l.tag }}
{{ l.title }}
{{ l.sub }}
{{ o }}{{ l.hl }}
{{ d.t }}
{{ d.s }}

{{ ccTitle }}

{{ ccLead }}

{{ ccAvailPre }} Claude Code.

  1. {{ r.tag }}{{ r.cmd }}

    {{ r.text }}

# {{ ccTermCmt }}
> /plugin marketplace add Institut-du-Numerique-Responsable/perf-sentinel-claude
> /plugin install perf-sentinel@perf-sentinel
{{ ccMore }} ↗

{{ ccNote }}

{{ perfEyebrow }}

{{ perfT1 }}{{ perfWRust }}{{ perfT2 }}

{{ perfBadge }}

{{ perfIntro }}

{{ s.value }}
{{ s.label }}
{{ perfMore }} →
{{ hubEyebrow }}

{{ hubTitleB1 }}{{ hubWCs }}{{ hubTitleB2 }}

.NET{{ hubBadge }}

{{ hubLeadA }}/api/findings{{ hubLeadB }}

{{ hubLeadEss }}

perf-sentinel · daemon 1
perf-sentinel · daemon 2
perf-sentinel · daemon 3
{{ hubDmnNote }}
{{ hubPush }}
{{ hubPull }}
Perf Sentinel Hub
{{ hubKeepA }}{{ hubKeepB }}{{ hubKeepC }}
{{ c }}
{{ hubBrowser }}{{ hubLauncher }}
{{ hubPick }}
{{ hubRun }}
{{ s.value }}
{{ s.label }}
{{ s.ess }}
{{ rvwEyebrow }}

{{ rvwT1 }}{{ rvwTW }}

{{ rvwIntro }}

{{ rvwHead }}{{ rvwPeriod }}
{{ rvwSub }}{{ rvwRank }}
  1. 1
    N+1 SQL{{ rvwR1Label }}shopGET /cart/{id}

    Use WHERE ... IN (?) to batch 41 queries into one

    {{ rvwR1N }}{{ rvwUnit }}{{ rvwR1Pill }}
    {{ rvwHow }}
    SELECT * FROM cart_item WHERE cart_id = ?
    {{ rvwFix }}java_jpa

    Use JOIN FETCH on the relationship or annotate the repository method with @EntityGraph to load associations in a single query.

    {{ rvwWhere }}
    CartItemRepository.findByCartId
    shop/src/main/java/acme/cart/CartItemRepository.java:31
    {{ rvwDet }}
    {{ rvwDetN }}
    {{ rvwConf }}
    daemon_production
    signature
    n_plus_one_sql:shop:GET__cart_{id}:09908701485122dcb9d5d84b7c653b7c
  2. {{ r.i }}
    {{ r.chip }}{{ r.label }}{{ r.svc }}{{ r.ep }}

    {{ r.sug }}

    {{ r.n }}{{ rvwUnit }}{{ r.pill }}
{{ carbonEyebrow }}

{{ carbonT1 }}{{ carbonTW }}{{ carbonT2a }}
{{ carbonT2b }}{{ carbonTW2 }}{{ carbonT3 }}

{{ carbonIntro }}

{{ carbonChartTitle }}
5 %4 %3 %2 %1 %0 %
{{ carbonAnnBasse }}
{{ carbonAnnHaute }} {{ carbonAnnHauteSubPre }}{{ carbonAnnHauteQ }})
?
{{ carbonBarBasse }}
{{ carbonBarHaute }}
{{ carbonLegMeasured }}
{{ carbonLegUnmeasured }}
{{ carbonChartSrc }}ITU 2025, IEA 2025, Freitag et al. 2021
{{ carbonNarrTitle }}

{{ carbonNarrText }}

{{ carbonStatNum }}
{{ carbonStatText }}
{{ carbonCmpTitle }}

{{ carbonCmpSub }}

{{ carbonTdEyebrow }}
{{ carbonTdTitle }}
•{{ pt.t }}
{{ carbonResultLabel }}
{{ carbonTdResultA }}{{ carbonTdResultB }}{{ carbonTdResultC }}{{ carbonTdResultD }}.
{{ carbonBuEyebrow }}
{{ carbonBuTitle }}
✓{{ pt.t }}
{{ carbonResultLabel }}
{{ carbonBuResultA }}{{ carbonBuResultB }}{{ carbonBuResultC }}{{ carbonBuResultD }}.
{{ goEyebrow }}

{{ goT1 }}{{ goWCost }},
{{ goT2 }}{{ goWEnergy }}{{ goT3 }}{{ goWCarbon }}

{{ goBodyA }}co2.total{{ goBodyB1 }}Software Carbon Intensity v1.0{{ goBodyB2 }}ISO/IEC 21031:2024{{ goBodyB3 }}

{{ goBodyA }}co2.total{{ goEssB1 }}Software Carbon Intensity v1.0{{ goEssB2 }}ISO/IEC 21031:2024{{ goEssB3 }}

{{ goEqTotal }}
{{ goEqET }}
{{ goEqES }}
{{ goEqIT }}
{{ goEqIS }}
{{ goEqMT }}
{{ goEqMS }}
{{ goEqBounds }}
{{ goEqAvLabel }}{{ goEqAvText }}

{{ g.title }}

{{ g.body }}

{{ goNoteA }}{{ goNoteLink }}{{ goNoteLink }}{{ goNoteB }}

{{ goEssNoteA }}{{ goNoteLink }}{{ goEssNoteB }}

{{ mesEyebrow }}

{{ mesT1 }}{{ mesTWord }},
{{ mesT2 }}

{{ mesIntro }}

{{ mesE }}
{{ mesSoft }}
{{ mesSoftNote }}
{{ mesBadge }}
{{ mesAlumet }}
{{ mesPerCont }}
{{ mesScaph }}
{{ mesPerProc }}
{{ mesKepler }}
{{ mesPerPod }}
{{ mesWall }}
{{ mesWallNote }}
{{ mesRedfish }}
{{ mesRedfishEss }}
{{ mesWallChip }}
{{ mesLive }}

{{ mesLiveIntro }}

{{ mesOpsTitle }}{{ mesOpsFree }}
{{ mesOpsDesc }}
FR
RTE
éCO2mix
GB
NESO
Carbon Intensity API
FI
Fingrid
Open Data
DK
Energinet
Energi Data Service
ES
REE
e·sios
AU
Open Electricity
NEM · WEM
HU
MAVIR
export XLSX
NZ
em6
Transpower
{{ mesOpsOpen }}{{ mesOpsTerms }}
{{ mesEmaps }}
{{ mesKey }}{{ mesPaid }}

{{ mesLiveNote }}

{{ mesCaveat }}

{{ mesMore }} →
{{ cmpEyebrow }}

{{ cmpT1 }}{{ cmpWCarbon }}

{{ cmpHCap }}
{{ cmpHApm }}
Perf Sentinel
{{ c.cap }}
{{ c.apm }}
{{ c.ps }}

{{ cmpFoot }}

{{ cmpFootEss }}

{{ cpNotTitle }}

✗{{ n.lead }} {{ n.body }}{{ n.ess }} {{ n.refText }}.
{{ pubEyebrow }}

{{ pubT1 }}{{ pubTWord }}{{ pubT2 }}

{{ pubIntroA }}perf-sentinel disclose{{ pubIntroB }}disclose-pdf{{ pubIntroC }}

{{ smpAlt }}

{{ smpP }}

  • {{ f.t }}

{{ pubVerT }}

{{ pubVerText }}

{{ pubVerEss }}

$ curl -fsSLO https://perf-sentinel.dev/exemple/disclosure/report.pdf
$ perf-sentinel verify-hash --report report.pdf \
$ perf-sentinel verify-hash --report report.pdf
--expected-identity https://github.com/Institut-du-Numerique-Responsable/perf-sentinel/.github/workflows/sample-disclosure.yml@refs/heads/main…/sample-disclosure.yml@refs/heads/main \
--expected-issuer https://token.actions.githubusercontent.com
Overall: TRUSTED
{{ licEyebrow }}

{{ licTitleA }}{{ licTitleB }}

open source

{{ licIntro }}

✓
{{ licC1Title }}

{{ licC1Body }}

✓
{{ licC2Title }}

{{ licC2Body }}

{{ licDisclaimer }}

{{ licDisclaimerEss }}

{{ secEyebrow }}

{{ secTitle }}

{{ secIntro }}

{{ s.tag }}

{{ s.title }}

{{ s.desc }}

{{ s.ess }}

{{ secMore }} →

{{ ctaTitle }}

{{ ctaText }}

# {{ ciCmt1 }}
$ {{ ciCmd1View }}
# {{ ciCmt2 }}
$ {{ ciCmd2View }}
# {{ ciCmt3 }}
$ {{ ciCmd3View }}
{{ ctaCiLink }} →
$ {{ installView }}
$ perf-sentinel demo # {{ demoCmt1 }}
$ perf-sentinel demo --tui # {{ demoCmt2 }}
$ perf-sentinel demo --html demo.html # {{ demoCmt3 }}
{{ ctaGuide }} →
Institut du Numérique ResponsableInstitut du Numérique Responsable
{{ govEyebrow }}

{{ govTitleA }}{{ govTitleB }}

{{ govBodyA }}Robin Trassard{{ govBodyB }}

{{ dotNav }}