Une trace vous dit que le service de paiement a mis 800 ms à répondre. Une métrique vous dit que le CPU du pod était à 95 %. Un log vous dit que la requête a fini en succès. Et après ? Aucun des trois ne vous dit quelle fonction, quelle ligne de code a cramé ces 95 % de CPU. Vous savez qu'il y a un problème, vous savez où, mais pas pourquoi dans le code. C'est exactement le trou que le profiling continu vient boucher.
Les trois piliers classiques de l'observabilité s'arrêtent à la frontière du processus. Le profiling, lui, entre dans le processus et regarde ce que le CPU exécute réellement, ligne par ligne, en continu, en production. C'est le quatrième signal, et il devient accessible sans le surcoût qui le rendait impraticable il y a encore quelques années.
Le signal qui regarde dans le processus
Profiler, c'est échantillonner la pile d'appels d'un programme à intervalle régulier. À chaque échantillon, on capture quelles fonctions sont en cours d'exécution. Sur des milliers d'échantillons, une statistique émerge : les fonctions qui apparaissent le plus souvent sont celles qui consomment le plus. On obtient une carte du temps CPU réparti dans le code.
Le mot qui compte, c'est continu. Le profiling traditionnel, on le lançait à la main, sur un poste de dev, pendant un test de charge, sur une fenêtre de quelques minutes. Le profiling continu tourne en permanence en production, tout le temps, sur tous les processus. La différence est opérationnelle : quand un incident de latence frappe à 3 h du matin, vous avez déjà le profil de la fenêtre concernée. Pas besoin de reproduire, le signal était déjà capturé.
Ce qui rend ça viable, c'est l'échantillonnage à faible fréquence. On ne trace pas chaque appel de fonction, ce qui plomberait les performances. On échantillonne quelques dizaines de fois par seconde, ce qui suffit statistiquement et reste sous le seuil de surcoût acceptable en prod. Parca, par exemple, attache son programme eBPF à un perf_event de type PERF_COUNT_SW_CPU_CLOCK et déclenche la capture 19 fois par seconde. Le profiler eBPF de OpenTelemetry échantillonne lui à 97 fois par seconde sur tous les processus de l'hôte. Faible surcoût, toujours actif.
eBPF : profiler sans réinstrumenter
L'approche qui a débloqué le profiling en production, c'est eBPF. Plutôt que d'instrumenter chaque application, on charge un programme dans le noyau Linux qui lit les piles d'appels de tous les processus de la machine. Pas de modification du code applicatif, pas de redéploiement, pas de SDK à embarquer. Le profiler système voit tout ce qui tourne sur l'hôte, y compris les binaires qu'on n'a pas écrits.
La mécanique repose sur les perf_events du noyau et le déroulé de pile. À chaque échantillon, eBPF capture la stack du processus actif et la remonte image par image. Le profiler eBPF de OpenTelemetry déroule les piles via les données .eh_frame, ce qui lui permet de profiler des binaires compilés sans frame pointers : C, C++, Go, Rust, Zig. Pour le code natif, c'est le moyen le plus propre d'obtenir un profil sans toucher au build.
Cette capacité à observer le noyau et l'espace utilisateur sans instrumentation, c'est le même mécanisme que celui qui a transformé l'observabilité réseau et système. On a creusé le sujet dans notre analyse sur la révolution eBPF dans l'observabilité Linux.
Le revers : eBPF profile le CPU natif très bien, mais les runtimes managés avec des piles virtuelles (JVM, Python) demandent un travail de déroulé supplémentaire pour relier la pile native aux symboles du langage. C'est là que les agents spécifiques au langage gardent leur place.
Pyroscope et Parca : les deux moteurs open source
Côté outils, deux projets dominent. Grafana Pyroscope, né de la fusion avec Phlare, est une base de données de profiling continu intégrée à l'écosystème Grafana. Parca, créé par Polar Signals et des contributeurs venus de Prometheus et Thanos, est un système de profiling à l'échelle de l'infrastructure, profondément lié à eBPF.
Les deux convergent sur le format pprof, le format de profil hérité de l'écosystème Go. Parca produit du pprof avec son profiler eBPF et ingère n'importe quel profil pprof, ce qui ouvre le support à un large éventail de langages et l'interopérabilité avec l'outillage existant. Pyroscope collecte les profils via ses SDK par langage, via Grafana Alloy, ou en OTLP depuis des sources compatibles OpenTelemetry comme le profiler eBPF d'OTel. Pyroscope est passé en version 2.0 en avril 2026, une réarchitecture qui vise à réduire les coûts de stockage et la complexité d'exploitation, signe que le sujet sort de la niche.
Côté langages, le terrain se répartit comme ça. Go expose nativement un endpoint pprof, c'est le cas le plus simple. La JVM et Python ont leur instrumentation dédiée. Et pour tout ce qui est natif compilé, eBPF prend le relais sans rien réinstrumenter. La règle qu'on applique : eBPF pour le balayage système large et le code natif, SDK par langage quand on veut des symboles précis sur un runtime managé.
Lire un flamegraph
Le rendu d'un profil, c'est le flamegraph. Chaque barre horizontale est une fonction, sa largeur est proportionnelle au temps passé dedans, et l'empilement vertical montre la chaîne d'appels : qui appelle qui. Une fonction large tout en haut de la pile, c'est du temps CPU brûlé directement dans cette fonction. Une fonction large en bas qui se ramifie, c'est un point d'entrée coûteux par ses descendants.
Les flamegraphs ne servent pas qu'au CPU. On profile aussi l'allocation mémoire et le heap, pour traquer les fonctions qui allouent trop et nourrissent le garbage collector ou la fragmentation. Sur une fuite mémoire lente, le flamegraph d'allocation pointe la fonction responsable là où une métrique de RSS ne montre qu'une courbe qui monte sans dire d'où ça vient.
Corréler trace et profil
Le saut qualitatif, c'est la corrélation entre une trace et le profil correspondant. Une trace distribuée vous mène au span lent. Le profil lié à ce span vous montre le code qui a tourné pendant ce span précis. Vous passez de « ce service est lent » à « cette fonction dans ce service a pris le CPU sur cette requête ». C'est le chaînon manquant entre l'observabilité inter-services et le diagnostic dans le code.
Cette corrélation est précisément ce que vise le nouveau signal profiling d'OpenTelemetry. Le signal Profiles est passé en alpha publique en 2026, inspiré au départ du format pprof puis refondu en standard indépendant. Le modèle de données OTLP partage les piles d'appels entre échantillons, réutilise les conventions sémantiques d'OpenTelemetry, et surtout relie les profils aux autres signaux via les trace_id et span_id. Autrement dit, la corrélation trace vers profil devient native dans le standard, pas un bricolage propriétaire. Un profil pprof se convertit vers OTLP et inversement sans perte d'information.
Pour relier ce signal au tracing distribué qui l'alimente, notre guide sur Grafana Tempo couvre la brique traces. Et pour une plateforme qui rassemble déjà les signaux corrélés, on a comparé l'approche tout-en-un dans notre article sur SigNoz et l'observabilité OpenTelemetry.
Coût, rétention et quand dégainer le profiling
Le profiling continu produit du volume. Moins qu'on ne le craint, parce que l'échantillonnage à faible fréquence et la déduplication des piles compressent bien, mais il faut quand même décider d'une rétention. Comme pour les autres signaux, on garde rarement les profils bruts longtemps : l'intérêt d'un profil décroît vite après l'incident qu'il documente. Pyroscope 2.0 a justement travaillé le coût de stockage et la performance de requête pour rendre la rétention plus soutenable à l'échelle.
Le moment où le profiling paie vraiment. Quand vous avez de la latence ou une consommation CPU inexpliquée en production, et que les métriques et les traces vous ont mené au bon service sans expliquer le pourquoi dans le code, le profiling continu est le signal qui tranche. C'est l'outil qui transforme « le pod est à 95 % de CPU » en « voici la fonction à optimiser ». Si votre stack tourne déjà autour de Grafana, Pyroscope s'intègre directement. Si vous voulez un profiling système large piloté par eBPF, Parca est taillé pour ça. Dans les deux cas, le coût d'entrée a chuté assez pour que le profiling ne soit plus réservé aux équipes de performance dédiées.
Pour le contexte performance Linux où ce signal s'insère, notre guide sur l'analyse de performance Linux pose les fondations côté système.
Sources
- What is continuous profiling ? (Grafana Pyroscope) : définition du signal, principe de l'échantillonnage continu en production.
- OpenTelemetry Profiles signal : le signal profiling dans OTel, modèle de données, corrélation via trace_id et span_id.
- OpenTelemetry Profiles enters public Alpha : passage en alpha publique, relation au format pprof, conventions sémantiques.
- Parca documentation : profiler eBPF par échantillonnage, perf_event PERF_COUNT_SW_CPU_CLOCK, format pprof.
- OpenTelemetry eBPF profiler (Pyroscope) : profiling système via eBPF, déroulé via .eh_frame, support C/C++/Go/Rust/Zig.
- Pyroscope 2.0 makes continuous profiling practical at scale (InfoQ) : réarchitecture 2.0, coûts de stockage et complexité d'exploitation.


