engineering7 min de lecture

Ce que Sentry a révélé : observabilité, stabilité et coût de la surveillance de son propre code

Des erreurs en production ont révélé un décalage de schéma, un échec de récupération de transaction et des journaux peu utiles. Comment une petite équipe a corrigé des pannes backend avec Sentry, préparé le monitoring navigateur et réduit le bruit des alertes.

K
Ken Jo

Autrefois, les équipes d’ingénierie investissaient soit trop dans l’observabilité — toute une équipe SRE configurant des tableaux de bord que personne ne consultait — soit pas du tout, et découvraient une panne lorsqu’un client leur écrivait. En 2026, aucun de ces extrêmes n’est acceptable. Il faut savoir ce qui casse, sans payer des tarifs de grande entreprise pour un produit indépendant.

Ce retour d’expérience montre comment notre intégration Sentry a révélé des erreurs de production, ce que nous avons changé ensuite et comment nous avons configuré le monitoring pour maîtriser le bruit et la consommation. Il examine aussi l’évolution des outils d’observabilité pour les petites équipes d’ingénierie.

Pourquoi les alertes ne signalaient pas les erreurs du navigateur

Notre backend est connecté à Sentry depuis mars. La DSN est stockée dans Google Secret Manager, le secret est monté dans Cloud Run et sentry_sdk.init s’exécute à chaque démarrage. Les alertes par e-mail arrivaient. De l’extérieur, tout semblait fonctionner.

En interne, ce n’était pas le cas. Le frontend n’était pas du tout relié à Sentry. Les exceptions du navigateur, les erreurs d’hydratation et les échecs de chargement de chunks étaient invisibles. De plus, les erreurs Python du backend arrivaient dans un projet nommé javascript-nextjs, le seul de l’organisation. Les traces s’accumulaient au mauvais endroit, leur regroupement ne servait à rien et le tableau de bord mélangeait des événements de plusieurs langages.

Avant de traiter chaque bug, il fallait séparer les erreurs du navigateur de celles du backend.

Ce que montraient les données

Nous avons extrait les événements d’erreur des 90 derniers jours. Quelques tendances se sont dégagées :

Un incident historique déjà corrigé

L’erreur la plus fréquente de la période était une StringDataRightTruncation de Postgres : 16 événements en 22 secondes, provenant du point de terminaison d’inscription sociale. La cause était un décalage de schéma classique : le modèle autorisait une biographie de 800 caractères, alors que la colonne de la base de production était toujours en VARCHAR(500), héritée d’une ancienne migration. Une personne a envoyé une biographie dépassant légèrement 500 caractères ; notre couche Pydantic l’a acceptée et l’INSERT a échoué.

La migration portant la colonne à 800 avait déjà été écrite et déployée le lendemain matin. Mais le problème de fond restait entier : le modèle et le schéma de la base peuvent diverger sans que personne le voie avant qu’un client ne tombe dessus.

Nous avons agi sur deux fronts. Premièrement, nous avons renforcé le schéma de requête de l’inscription sociale : une valeur max_length explicite pour l’adresse e-mail, le nom affiché et le jeton permet de renvoyer proprement 422 pour les entrées problématiques, avant qu’elles n’atteignent la base. Deuxièmement, nous avons étendu notre script d’intégrité DB afin de comparer information_schema.columns.character_maximum_length aux longueurs attendues par l’application. Si une future migration réduit une colonne en dessous de ce que le modèle peut produire, le prochain contrôle de déploiement échouera.

Une session qui ne voulait pas annuler la transaction

Plus bas dans la liste, nous avons trouvé cette séquence : un OperationalError: server closed the connection unexpectedly sur POST /v1/upload, suivi d’une série de PendingRollbackError sur le même chemin de code. Postgres avait coupé la connexion au milieu d’une requête, la session SQLAlchemy était devenue invalide et le service d’importation tentait d’enregistrer des résultats partiels malgré tout. Chaque opération suivante dans cette session propageait l’échec.

La correction est simple, mais facile à rater. Lorsque le pipeline d’importation intercepte une exception, il exécute désormais db.rollback() en tout premier — dans son propre bloc try/except afin qu’un échec du rollback ne masque pas l’erreur initiale. La logique d’enregistrement partiel s’exécute ensuite avec une session propre.

Des journaux qui s’effaçaient eux-mêmes

Le gestionnaire de fin WebSocket journalisait une exception interceptée avec err=%s. Pour la plupart des exceptions, cela fournit une information utile. Mais certains types renvoient une chaîne vide via __str__ : le journal affichait alors err= sans rien après. Les événements Sentry nous disaient qu’un enregistrement avait échoué, sans en donner la raison.

Passer à logger.exception(...) et err=%r n’a rien coûté et a rendu chaque événement futur explicite.

Un bruit pour lequel nous ne voulions pas payer

Les autres éléments de la file n’étaient pas des bugs. Uvloop lève parfois RuntimeError: unable to perform operation on <TCPTransport closed=True> lorsqu’un client se déconnecte en plein échange SSL. C’est un comportement attendu, impossible à corriger côté application ; avec un quota gratuit de 5 000 erreurs par mois, ces événements auraient gaspillé le budget. Nous avons ajouté un filtre before_send qui écarte ces motifs précis d’exception et de valeur. Même principe côté frontend pour ResizeObserver loop limit exceeded et les bruits similaires du navigateur.

Régler le forfait gratuit

Au 13 octobre 2026, le forfait Developer de Sentry inclut gratuitement 5 000 erreurs, 5 millions de spans de traçage et 50 replays par mois. Le traçage se mesure en spans, et non selon l’ancien quota d’unités de performance. Vérifiez le forfait en vigueur et prévoyez un budget distinct pour le traçage ; activez-le avec un taux d’échantillonnage adapté. Tarifs Sentry

Nos réglages :

  • tracesSampleRate: 0 sur le backend et le frontend. Le traçage distribué est réellement utile, mais le volume de spans nécessite un budget distinct, établi à partir de l’usage mesuré. Nous pouvons l’activer avec un faible taux d’échantillonnage pour une investigation ciblée.
  • profilesSampleRate: 0 sur le backend, pour la même raison.
  • Session Replay désactivé sur le frontend. Le code d’intégration reste en place, mais les deux taux d’échantillonnage sont à zéro. Si un bug critique exige le contexte de replay, nous pouvons régler replaysOnErrorSampleRate à 0.05 pour une journée, puis le désactiver à nouveau.
  • Des filtres before_send dans les deux environnements éliminent les événements que nous savons déjà non exploitables.

Les changements backend ont réduit le bruit des erreurs exploitables, tandis que la configuration du SDK navigateur a été préparée pour une activation. Ce sont deux étapes différentes : ni le code ni les paramètres d’échantillonnage ne prouvent à eux seuls que les événements du navigateur arrivent dans le bon projet.

Ce qui change sur le marché de l’observabilité

Nous avons réglé notre configuration pour le forfait gratuit, particulièrement généreux pour un service hébergé. Mais les conditions économiques évoluent.

Plusieurs changements se sont dessinés au cours des douze à dix-huit derniers mois :

  • Les standards ouverts réduisent le travail de migration, sans l’éliminer. Une instrumentation compatible OTLP peut limiter la dépendance à un backend de monitoring. Les requêtes, tableaux de bord, règles d’alerte et fonctionnalités SDK propres à un fournisseur doivent toujours être planifiés et testés lors d’un changement.
  • L’auto-hébergement modifie le calcul des coûts. Des options comme GlitchTip et les stacks natives OTLP offrent d’autres possibilités. Comparez le stockage, les sauvegardes, les mises à niveau et le temps d’ingénierie avec le forfait hébergé, pas seulement une facture de VM avec un abonnement.
  • Le débogage assisté par IA prolonge le processus. Seer, de Sentry, propose des causes racines et des correctifs ; une intégration MCP autorisée peut transmettre le contexte d’erreur à un assistant de programmation. Tout correctif proposé doit toutefois être reproduit et couvert par des tests de régression avant sa publication.
  • Les limites des forfaits méritent autant d’attention que les fonctionnalités. Le volume d’erreurs, la conservation, l’échantillonnage et les accès d’équipe influent sur la facture. Commencez par les signaux nécessaires et un budget d’événements mesuré, puis comparez les offres à cette charge réelle.

À la date de ce snapshot de version, Sentry couvrait notre besoin immédiat de surveillance des erreurs. Les interfaces ouvertes offriront davantage de choix à l’équipe, mais changer de fournisseur imposerait tout de même de vérifier le routage des projets, les alertes, les données conservées et les fonctionnalités propres au prestataire.

Les contrôles de déploiement complètent le monitoring

À la date de référence de cet article, le 17 mai 2026, deux tâches de déploiement restaient à faire :

  1. Créer un projet Sentry Python dédié pour que les erreurs backend ne soient plus classées sous javascript-nextjs. La DSN sera remplacée dans la même entrée Secret Manager que celle déjà lue par le backend.
  2. Ajouter la DSN frontend aux paramètres du projet Vercel afin que les erreurs côté client commencent à remonter. Le code est déjà présent et son initialisation est conditionnelle ; seule la variable d’environnement manque.

Lors de tout déploiement de monitoring, envoyez un événement de test contrôlé depuis chaque environnement d’exécution, puis vérifiez son projet, son environnement, son regroupement et son contexte avant de déclarer l’intégration terminée. Des projets séparés et une variable d’environnement sont des étapes de configuration, pas la preuve que les événements sont bien arrivés.

Pourquoi est-ce important ?

Quand on ne voit pas ce qui casse, on surinvestit dans le code défensif ou on investit trop peu et on met des bugs en production. Les deux coûtent cher. Une observabilité fiable et abordable permet à une petite équipe de fonctionner comme une plus grande : repérer les régressions avant les clients, les corriger sans tâtonner et consacrer les heures d’ingénierie à de nouvelles fonctionnalités.

La leçon utile est de vérifier les deux côtés : les corrections apportées à l’application et le chemin de monitoring censé révéler la prochaine régression.


← Retour au blog