Regrouper les erreurs bruyantes
La même erreur peut être signalée sous la forme de douzaines de problèmes distincts lorsque les stack frames ou les messages contiennent des données volatiles — IDs aléatoires, chemins de fichiers dynamiques, hashes de build, noms de fonctions anonymes. La solution en deux étapes : fusionner les problèmes existants dans une cible, puis créer une règle de regroupement afin que les futurs événements du même call site partagent une seule empreinte canonique au lieu d'en générer de nouvelles.
Important au préalable : « même erreur » ici est étroit. Deux problèmes qui partagent un nom ou une phrase de message mais proviennent de chemins de code différents, de SDKs différents ou de runtimes différents sont des erreurs différentes et doivent rester séparés, même si l'utilisateur les considère comme « le même type de bug ». Regrouper une TypeError frontend avec une TypeError backend parce que les deux messages contiennent « undefined » détruit le signal qui permet à l'équipe d'en trouver chacune. Les critères à l'étape 1 existent pour l'empêcher.
Outils disponibles
| Outil | Objectif |
|---|---|
posthog:query-error-tracking-issues-list |
Trouver les problèmes potentiels en doublon |
posthog:query-error-tracking-issue |
Récupérer les détails compacts d'un problème individuel |
posthog:query-error-tracking-issue-events |
Événements $exception échantillonnés avec stack et message |
posthog:error-tracking-issues-merge-create |
Fusionner les problèmes existants dans une cible |
posthog:error-tracking-issues-split-create |
Diviser chirurgicalement les empreintes si une fusion échoue |
posthog:error-tracking-grouping-rules-create |
Regrouper automatiquement les futurs événements dans un problème |
posthog:error-tracking-grouping-rules-list |
Vérifier les règles de regroupement existantes avant d'en ajouter |
posthog:error-tracking-issues-partial-update |
Renommer ou redécrire la cible après une fusion |
Fusion vs règle de regroupement
Les deux outils résolvent des moitiés différentes du problème :
- Fusion est ponctuelle. Elle réduit les problèmes existants en une cible et réattache leurs événements. Les futurs événements se regroupent toujours selon leurs empreintes originales — si le même motif bruyant continue de produire de nouvelles empreintes, la fusion est un tapis roulant.
- Règle de regroupement est durable. Elle réécrit l'empreinte de tout événement correspondant en
custom-rule:<rule_id>au moment de l'ingestion, de sorte que tous les futurs correspondances partagent une seule empreinte canonique plutôt que de générer de nouvelles. Le premier correspondance crée soit un nouveau problème basé sur cette empreinte, soit achemine vers le problème déjà lié à celle-ci.
Utilisez les deux ensemble quand le problème est récurrent : fusionnez les doublons historiques dans une cible issue, puis créez la règle. L'API de règle n'accepte pas un ID de problème cible — une fois que la règle commence à s'activer, le problème résultant custom-rule:... peut être fusionné dans la même cible pour que la consolidation persiste. Utilisez fusion seule pour la prolifération historique que vous ne vous attendez pas à voir se répéter. Utilisez une règle de regroupement seule pour un nouveau motif que vous obtenez en avance, quand vous n'avez pas besoin de consolider avec un problème existant.
Workflow
Étape 1 — Confirmer les doublons
Recherchez par type d'exception ou message pour trouver des candidats :
posthog:query-error-tracking-issues-list
{
"searchQuery": "TypeError: Cannot read property",
"status": "active",
"limit": 50,
"orderBy": "occurrences",
"dateRange": { "date_from": "-30d" }
}
Pour chaque candidat, récupérez un événement d'exception échantillonné pour comparer le stack, le type et le message :
posthog:query-error-tracking-issue-events
{
"issueId": "<candidate_issue_id>",
"limit": 1,
"verbosity": "stack"
}
Exécutez ceci une fois par candidat. L'outil par défaut à onlyAppFrames: true, ce qui fait ressortir le top frame in-app d'un coup d'œil. Si deux candidats partagent le même top frame et le même type d'exception, c'est probablement la même erreur — mais vérifiez par rapport à la liste de contrôle complète ci-dessous avant de fusionner.
Sont-elles la même erreur ?
Traitez deux problèmes comme des doublons uniquement quand chacun de ceux-ci correspond :
$libest le même SDK (posthog-js,posthog-python,posthog-node,posthog-android, etc.). Les erreurs de SDKs différents proviennent presque toujours de chemins de code différents même quand le type d'exception correspond.- Le type d'exception est identique (
$exception_types). - Le top frame in-app de la stack pointe vers le même fichier et la même fonction. Les numéros de ligne et les petits décalages au sein de cette fonction vont bien ; un fichier différent ou une fonction différente en haut signifie un bug différent.
- Le message suit le même template, avec les différences limitées aux données volatiles — IDs, hashes, timestamps, chemins dynamiques. Si la différence est un verbe, un objet ou une opération différents, c'est un bug différent.
$exception_handleds'accorde (les deux gérés ou les deux non gérés). Une variante capturée et une variante non capturée sont des chemins de code différents et bénéficient de rester séparés.
Si un seul de ceux-ci diffère, ce ne sont pas des doublons — enquêter séparément (investigating-error-issue).
Quoi NE PAS regrouper ensemble
Ce sont les modes d'échec qui détruisent le signal de débogage. Ne groupez pas à travers l'un d'eux, même quand l'utilisateur les décrit comme « le même type de bug » :
- Variantes frontend et backend du même type d'exception. Une
TypeErrord'un bundle navigateur et uneTypeErrord'un service Node partagent un nom et souvent un mot de message, mais le stack, le runtime et le fix diffèrent tous. - SDKs / plateformes différents.
posthog-jsvsposthog-pythonvsposthog-androidsont des call sites différents. - Même type, fichier ou fonction différents en haut de la stack. Une
NullPointerExceptionlevée depuisOrderService.canceln'est pas le même bug que celle levée depuisPaymentService.refund, même si les deux messages disent « user was null ». - Capturé vs non capturé. Deux problèmes qui diffèrent uniquement par
$exception_handledsont généralement un chemin de code qui avale l'erreur à un endroit et la laisse se propager ailleurs — les garder séparés rend cela visible. - Bugs conceptuellement similaires qui partagent une phrase par chance. « Cannot read property of undefined » apparaît dans de nombreux bugs indépendants. Sans stack frames correspondants, la similarité de message seule ne suffit pas.
Étape 2 — Choisir le problème cible
Choisissez le problème qui devrait absorber les autres :
- Plus d'occurrences — garde le problème dominant afin que les tableaux de bord restent continus
- Meilleur nom et description — si l'utilisateur a annoté un, le préférer
- Plus ancien
first_seen— préserve la chronologie originale
Notez l'ID de la cible. Les autres candidats deviennent ids à fusionner.
Étape 3 — Fusionner les doublons existants
posthog:error-tracking-issues-merge-create
{
"id": "<target_issue_id>",
"ids": ["<duplicate_id_1>", "<duplicate_id_2>", "..."]
}
La fusion est destructrice (annotation destructive: true) — une fois les problèmes fusionnés dans une cible, les problèmes source disparaissent de la liste active. Confirmez la cible avec l'utilisateur avant d'appeler. Limitez chaque appel de fusion à environ 50 IDs source pour garder les défaillances localisées ; pour un étalement plus grand, traitez par lots.
Les modifications fusionnées peuvent ne pas apparaître immédiatement dans la liste des problèmes — relister juste après l'appel peut toujours montrer les problèmes source pour une courte fenêtre. Si un appel ultérieur error-tracking-issues-list semble inchangé, attendez quelques secondes et réinterrogez plutôt que de rééditer la fusion.
Si après la fusion les métadonnées de la cible semblent incorrectes (un doublon avait un meilleur nom), utilisez error-tracking-issues-partial-update pour corriger le nom ou la description sur la cible plutôt que de refusionner.
Étape 4 — Décider si une règle de regroupement est justifiée
Une règle de regroupement vaut la peine d'être créée quand les deux sont vrais :
- Le motif continue de produire de nouvelles empreintes (vous avez vu de nouveaux doublons apparaître depuis la dernière fusion)
- Vous pouvez décrire le motif avec des filtres de propriété qui n'avaleront pas accidentellement des erreurs non liées
Les propriétés d'exception canoniques ($exception_types, $exception_values pour les messages, $exception_sources pour les chemins de fichiers, $exception_functions pour les noms de fonction) sont des tableaux au moment de la capture. Le compilateur de filtre de propriété les traite spécialement — il analyse la colonne matérialisée en JSON et enveloppe le filtre dans arrayExists(v -> ..., JSONExtract(...)), de sorte que tous les opérateurs standard (exact, is_not, icontains, not_icontains, regex, not_regex) travaillent contre les éléments individuels avec la valeur brute : exact "TypeError", non pas exact '["TypeError"]' ou regex '"TypeError"'.
Les formes singulières ($exception_type, $exception_message) et $exception_stack_trace_raw sont émises sur une fraction de pour cent d'événements ; filtrer sur eux produit une règle qui ne correspond silencieusement jamais.
Si la volatilité est dans le message (p. ex., TypeError at /static/main.<hash>.js), un filtre regex sur $exception_values fonctionne. Si la volatilité est dans les numéros de ligne au sein d'un fichier connu, icontains sur $exception_sources le fait. $exception_handled est également une dimension de restriction utile — séparez géré vs non géré plutôt que de les mélanger.
Ignorez la règle de regroupement quand :
- Les doublons sont historiques (remplissage ponctuel, pas de nouvelles occurrences) — fusion suffisante
- Vous ne pouvez pas écrire un filtre assez étroit pour être sûr — élargissez plutôt la cadence de fusion et revisitez plus tard
Étape 5 — Créer la règle de regroupement
Traduisez la liste de contrôle « même erreur » de l'étape 1 en filtres de règle. Une règle qui correspond plus librement que la liste de contrôle fusionnera silencieusement des bugs non liés pour toujours — la règle est plus dangereuse que la fusion parce qu'elle s'exécute par rapport à chaque événement futur. À minima, établissez l'étendue par SDK et type d'exception, et ajoutez une troisième dimension (chemin de fichier via $exception_sources, ou une phrase de message spécifique via $exception_values) pour épingler le call site :
posthog:error-tracking-grouping-rules-create
{
"filters": {
"type": "AND",
"values": [
{
"type": "event",
"key": "$lib",
"operator": "exact",
"value": "posthog-js"
},
{
"type": "event",
"key": "$exception_types",
"operator": "exact",
"value": "TypeError"
},
{
"type": "event",
"key": "$exception_sources",
"operator": "icontains",
"value": "/static/checkout/"
},
{
"type": "event",
"key": "$exception_values",
"operator": "icontains",
"value": "Cannot read property"
}
]
},
"description": "Cleanup: collapse noisy checkout TypeError fingerprints (posthog-js)"
}
Les règles sont évaluées dans l'ordre. Listez d'abord les règles existantes (posthog:error-tracking-grouping-rules-list) — si une règle couvre déjà partiellement le motif, préférez ajuster son filtre à empiler un quasi-doublon.
Le champ assignee optionnel attribue automatiquement les problèmes créés par la règle. Ignorez-le à moins que l'utilisateur ne veuille explicitement la propriété intégrée à la règle.
Étape 6 — Vérifier et consolider
Échantillonnez les événements récents du problème fusionné pour confirmer que la fusion a réussi. Surveillez l'empreinte custom-rule:<rule_id> de la règle pour commencer à correspondre aux événements — le premier correspondance crée un nouveau problème (ou achemine vers celui qui était déjà lié à cette empreinte). Pour garder les événements sous votre cible historique plutôt que dispersés dans le nouveau problème custom-rule, exécutez une deuxième fusion pliant le problème custom-rule dans la cible.
Si de nouvelles empreintes (non-rule) continuent d'apparaître malgré la règle, son filtre est trop étroit — élargissez-le.
Conseils
- L'utilisateur confond souvent les règles de regroupement avec les règles d'attribution. Les règles de regroupement décident lequel problème un événement atterrit. Les règles d'attribution décident qui possède le problème résultant.
- Ne fusionnez pas les problèmes qui « semblent similaires » sans inspecter les événements. Deux
TypeErrors dans des fichiers différents sont des bugs différents. - Les stack frames sont le signal de regroupement canonique — l'ingestion crée déjà une empreinte sur le stack, donc un stack stable se regroupe lui-même. Une règle de regroupement concerne les cas où l'empreinte naturelle s'étale (noms de fichiers volatiles, noms de fonction hashés, numéros de ligne dynamiques) et vous avez besoin de la remplacer.
- La désactivation ou le resserrement d'une règle de regroupement ne dégroupent pas rétroactivement les événements existants ; les futurs événements itinent correctement, les événements passés restent où ils sont. Utilisez
error-tracking-issues-split-createsi vous avez besoin de diviser chirurgicalement les empreintes hors d'un problème fusionné. - Les règles de regroupement sont visibles dans l'interface sous Paramètres du projet → Suivi des erreurs → Règles de regroupement ; mentionnez ceci quand l'utilisateur demande où les règles se trouvent.