Optimisation des performances : pourquoi nous utilisons Pyroscope
Dans notre quête d'observabilité unifiée, nous avons adopté Pyroscope, une solution de profiling open-source, pour analyser en continu les performances de nos produits. Cet article de blog décrit d'abord comment nous avons structuré un flux de données centralisé, depuis la collecte des profils de toutes les instances clientes jusqu'à leur visualisation dans Grafana. Ensuite, nous expliquons comment cet outil nous a permis d'optimiser les performances de nos produits.
TL;DR
- Nous avons implémenté Pyroscope pour le profiling continu de toutes les instances de nos produits.
- Un cluster d'observabilité centralisé collecte les profils, logs et métriques des environnements Kubernetes distribués.
- L'intégration Grafana nous permet de visualiser les flame graphs et d'analyser les tendances de performance au fil du temps.
- Le profiling nous aide à détecter les goulots d'étranglement, optimiser le code et garantir des performances système élevées.
- Cas d'usage réel : nous avons identifié et résolu des fonctions gourmandes en CPU dans OpenCTI grâce aux informations fournies par Pyroscope.
Qu'est-ce que le profiling ?
Le profiling est le processus de collecte et d'analyse d'informations détaillées sur la façon dont un programme consomme des ressources (telles que le CPU, la mémoire ou les E/S) au fil du temps. Contrairement aux métriques traditionnelles, qui fournissent des informations agrégées, le profiling offre une vue granulaire, au niveau du code, du comportement du système. Il permet aux équipes d'identifier les inefficacités, les goulots d'étranglement et les régressions qui seraient autrement difficiles à détecter.
Une plateforme d'observabilité centralisée
Bien que nos produits (OpenCTI, OpenBAS) fonctionnent sur des clusters Kubernetes distribués dans différentes régions, nous avons mis en place un seul cluster d'observabilité centralisé dédié à la collecte et au traitement de tous les logs, métriques et données de profiling. Cette approche centralisée garantit une vue globale cohérente de la santé du système sans multiplier les points d'entrée ni augmenter la complexité de maintenance.
Chaque composant de la plateforme intègre le package de profiling Pyroscope Node.js, qui génère des profils à intervalles réguliers et les envoie à Alloy, notre collecteur unifié. Déployé sur chacun de nos clusters de production, Alloy reçoit les données de profiling, applique un étiquetage approprié et les transmet de manière sécurisée (via HTTPS et authentification) au serveur Pyroscope hébergé sur le cluster d'observabilité. Les profils y sont conservés pendant sept jours dans des volumes persistants avant d'être automatiquement purgés.

Vue d'ensemble de l'architecture
Visualisation et analyse dans Grafana
Pour rendre ces informations exploitables, nous avons intégré le plugin Pyroscope dans Grafana. Nos équipes peuvent accéder aux flame graphs, comparer l'évolution des performances entre les services et identifier rapidement les goulots d'étranglement. Cette intégration transparente nous permet de guider et de prioriser nos optimisations dès qu'une anomalie de profiling est détectée.
Profiling pour vos instances
Que vous ayez une instance OpenCTI de production ou de développement, vous pouvez maintenant activer le profiling sur celle-ci. Il suffit d'ajouter :
- Un service Pyroscope à votre déploiement compose :
Copied!
1pyroscope:2 image: grafana/pyroscope3 restart: unless-stopped4 ports:5 - "4040:4040"
- Des variables d'environnement pour le processus OpenCTI :
Copied!
1APP__TELEMETRY__PYROSCOPE__IDENTIFIER=opencti2APP__TELEMETRY__PYROSCOPE__ENABLED=true3APP__TELEMETRY__PYROSCOPE__EXPORTER="http://docker-pyroscope-1:4040"
Vous devriez pouvoir afficher les flame graphs en accédant à localhost:4040 :

Qu'est-ce qu'un flame graph et comment l'utilisons-nous ?
Les flame graphs fournissent une représentation intuitive et hiérarchique des appels de fonction et de leur consommation de ressources (principalement le temps CPU). La largeur de chaque barre dans le flame graph indique la proportion de temps passé dans cette fonction.
Nous utilisons ce flame graph généré par Pyroscope pour :
- Identifier les goulots d'étranglement de performance CPU : Identifier les lignes exactes de code consommant le plus de ressources.
- Comprendre le comportement de l'application au fil du temps : Le profiling continu fournit une vue historique des performances, aidant à détecter les régressions et à comprendre l'impact des modifications de code.
- Identifier une consommation mémoire anormale : Identifier les lignes exactes de code qui retiennent le plus l'utilisation de la mémoire par l'application.
Exemple concret
Depuis l'implémentation de Pyroscope pour tous nos déploiements, nous avons pu améliorer significativement les performances de nos produits. Mais prenons un exemple concret pour vous donner une meilleure idée de la façon dont nous l'avons utilisé récemment.
Contexte pour OpenCTI
OpenCTI utilise nodejs comme backend pour traiter la charge d'ingestion, et nodejs n'est pas une technologie multi-thread, elle est basée sur une boucle d'événements. Vous pouvez trouver plus d'informations ici https://nodejs.org/en/learn/asynchronous-work/event-loop-timers-and-nexttick.
En raison de cette architecture, une règle très importante doit être respectée : ne bloquez pas la boucle d'événements plus de 40 ms 😇.
C'est une règle vraiment importante à suivre car bloquer la boucle d'événements empêche nodejs d'exécuter correctement des blocs importants et de "simuler" plusieurs opérations s'exécutant en même temps.
Pyroscope à la rescousse
Développer de nouvelles fonctionnalités dans OpenCTI tout en respectant cette règle peut parfois s'avérer difficile. Le produit peut avoir besoin de gérer de très grandes quantités de données dans la même fonction de traitement. Imaginez un rapport contenant 50 000+ éléments qui doivent être traités afin de valider les données, transformer certaines entrées et manipuler les informations à plusieurs niveaux. À un moment donné, vous risquez de créer une fonction qui bloquera la boucle d'événements et perturbera les performances globales de la plateforme.
Dans le cas où vous avez déployé les mises à jour en production mais n'avez pas pris en compte ce type de volumétrie dans vos procédures de test, Pyroscope vous donnera une vue magique de la pile d'appels et de la ligne de code qui consomme le CPU pour une plage de temps spécifique.
Malheureusement, nous ne conservons pas les captures d'écran de nos dernières investigations où l'on peut voir un problème spécifique, nous allons donc expliquer un exemple sur une plateforme saine.
Vous pouvez voir ci-dessous un extrait de 1 minute de surveillance d'un OpenCTI.

Nous pouvons en apprendre beaucoup.
- Pour 1 minute de surveillance CPU, nous n'utilisons que 1,13 seconde de temps de calcul. Donc l'instance est actuellement tranquille 😉
- La fonction la plus utilisée pendant cette période est elDataConverter, qui est une fonction interne d'OpenCTI utilisée pour analyser les résultats de données que nous récupérons dans la base de données.
Cliquez sur cette fonction et vous verrez la position de la pile d'appels dans le graphique ainsi que la ligne de code responsable. Dans ce cas, c'est la définition de la fonction, car tout ce qui est à l'intérieur est traité de manière synchrone.

Maintenant, imaginez que Pyroscope affiche que la fonction "elDataConverter" occupe 55 secondes de CPU sur la dernière minute. Comment cette information vous indiquera-t-elle exactement ce qu'il faut chercher et où exactement cela pourrait se trouver dans votre code ? Je pense que vous pouvez voir le gain de temps que représente cette capacité de surveillance directe de votre production. 😉
Conclusion
En conclusion, Pyroscope comme solution de profiling a été un changement majeur dans la façon dont nous surveillons et optimisons les performances des produits Filigran. En intégrant Pyroscope dans notre plateforme d'observabilité centralisée et en visualisant les données via Grafana, nous obtenons non seulement des informations détaillées sur la consommation de ressources, mais nous identifions et résolvons également de manière proactive les goulots d'étranglement potentiels.
Cette approche nous a permis de maintenir des normes de performance élevées et de prendre des décisions éclairées concernant les améliorations des produits. Par conséquent, nous continuons à fournir des solutions robustes et efficaces à nos clients et à notre communauté.
Si vous avez des questions, demandes, commentaires ou retours à partager avec nous, n'hésitez pas à nous rejoindre sur Slack !
Lire la suite
Explorez des sujets et analyses associés
Votre SOC n'a pas de problème de données. Il a un problème de coordination.

Workflows d'approbation de l'intelligence : garantir la qualité des données et rationaliser les processus
