Aller au contenu

Observabilité des erreurs de production

Rendre a.js:1:4523 utile à nouveau

Rendre les incidents de production exploitables grâce aux mappages de sources téléversés, à un tunnel Sentry de même origine, au contexte des erreurs, au filtrage et à la relecture de session.

4 min de lecturePar

Deux façons de perdre l’erreur

Nous avions deux angles morts distincts. Les erreurs reçues pointaient vers du code minifié tel que a.js:1:4523 en raison de l’absence de mappages de sources. D’autres événements n’arrivaient jamais, car les requêtes directes vers sentry.io pouvaient être bloquées.

Il s’agissait de deux défaillances indépendantes. Les mappages de sources déterminent si une pile reçue peut être résolue vers le code source. Le transport détermine si l’événement atteint Sentry. N’en corriger qu’une laisse toujours l’incident illisible ou invisible.

Téléverser les mappages de sources sans les publier

@sentry/nextjs enveloppait la construction avec withSentryConfig. La CI fournissait SENTRY_AUTH_TOKEN, SENTRY_ORG et SENTRY_PROJECT. Le plugin de construction téléversait les mappages, élargissait le téléversement des fichiers clients pour améliorer les traces et utilisait deleteSourcemapsAfterUpload afin que ces mappages ne soient pas servis dans la sortie publique.

export default withSentryConfig(nextConfig, {
  org: process.env.SENTRY_ORG,
  project: process.env.SENTRY_PROJECT,
  authToken: process.env.SENTRY_AUTH_TOKEN,
  sourcemaps: {
    disable: process.env.NODE_ENV === 'development',
    deleteSourcemapsAfterUpload: true
  },
  widenClientFileUpload: true,
  disableLogger: true,
  tunnelRoute: '/t'
})

La résolution des symboles restait ainsi intégrée à la construction normale du déploiement. Aucun ingénieur n’avait à se souvenir d’une commande de téléversement sentry-cli distincte après la publication.

Utiliser l’origine de l’application comme transport

Le premier point de terminaison de même origine était /monitoring, mais les bloqueurs le reconnaissaient encore. J’ai raccourci la route en /t. Les événements du navigateur ciblaient alors l’origine de l’application, et le serveur Next.js les transférait à Sentry.

Le déploiement initial a consigné une capture complète après cette modification. C’était le résultat observé pendant la fenêtre de déploiement, pas la promesse que chaque bloqueur ou réseau livrerait toujours chaque événement.

Une incompatibilité silencieuse de la chaîne d’outils nécessitait sa propre correction

Next.js 15 a déplacé la configuration du navigateur dans instrumentation-client.ts. Avec Turbopack activé, le projet est resté sur Sentry v9 et le téléversement des mappages de sources s’est arrêté sans défaillance évidente de l’application. Le passage à Sentry v10 a rétabli une chaîne de téléversement compatible.

L’application initialisait aussi Sentry dans les environnements navigateur, serveur et périphérie, et ajoutait des limites d’erreur globales et au niveau des routes. La résolution des symboles concernait la construction. La capture des erreurs React, de requête et d’exécution concernait séparément l’application.

Lisible ne veut pas automatiquement dire utile

La fonction beforeSend ajoutait le chemin de la page, les informations du navigateur, la fenêtre d’affichage et une étiquette de version de l’application. Elle classait les défaillances d’API, de délai d’attente et de réseau, puis filtrait les restrictions d’appel Twilio connues avant l’ingestion.

Session Replay échantillonnait 5 % des sessions normales et toutes les sessions comportant une erreur en production. Le traçage fonctionnait initialement à 100 % en préproduction et à 10 % en production, puis a été désactivé parce qu’il consommait trop de quota. L’échantillonnage est un réglage d’exploitation, pas une valeur à recopier sans réflexion.

  • Téléversez des mappages de sources privés pendant la construction.
  • Envoyez les événements du navigateur par un tunnel de même origine.
  • Distinguez les restrictions produit attendues des défaillances de l’application.
  • Ajoutez le contexte de route et de relecture afin qu’un numéro de ligne lisible possède aussi le contexte du parcours utilisateur.