Suppression des erreurs bruyantes
La suppression est destructrice par nature : les événements correspondants sont supprimés à l'ingestion et ne deviennent jamais des issues. Une mauvaise règle élimine silencieusement les vrais bugs. Cette skill existe pour s'assurer que la suppression n'est appliquée qu'aux motifs véritablement inactionables, avec des filtres suffisamment précis pour éviter d'avaler des erreurs sans rapport.
Quand la suppression est l'outil approprié
La suppression est l'outil approprié quand une erreur est :
- Inactionable depuis votre code — extensions de navigateur, scripts tiers, bloqueurs de publicités, balises réseau se déclenchant après la navigation. Vous ne pouvez pas la corriger car vous ne l'avez pas écrite.
- Particularités du moteur de navigateur —
ResizeObserver loop limit exceeded,Script error.,Non-Error promise rejection capturedavec des payloads vides. - Trafic bot ou crawler — erreurs se déclenchant uniquement depuis des navigateurs headless ou depuis des user agents de crawler connus.
- Échantillonnage déjà suffisant — pour les erreurs à fort volume mais réelles, atténuez avec
sampling_rateplutôt qu'une suppression complète pour garder une visibilité sans payer le coût complet.
La suppression n'est pas l'outil approprié quand :
- L'erreur est inactionable aujourd'hui mais pourrait devenir actionable après une correction — utilisez plutôt le statut
archivedouresolvedpour qu'elle réapparaisse si elle revient. - Vous voulez juste étouffer les notifications — assignez l'issue à un utilisateur, changez son statut, ou utilisez les règles de notification.
- L'erreur est un doublon d'une autre — fusionnez ou créez une règle de groupement (
grouping-noisy-errors).
Outils disponibles
| Outil | Objectif |
|---|---|
posthog:query-error-tracking-issues-list |
Trouver des candidats à suppression par volume et impact ; dry-run un filtre candidat via filterGroup |
posthog:query-error-tracking-issue-events |
Inspecter les événements $exception échantillonnés pour confirmer le motif |
posthog:execute-sql |
Dry-run de secours pour les filtres nécessitant des groupes OR ou des opérateurs hors de la liste autorisée filterGroup |
posthog:error-tracking-suppression-rules-list |
Vérifier les règles de suppression existantes |
posthog:error-tracking-suppression-rules-create |
Créer la règle de suppression |
posthog:error-tracking-issues-partial-update |
Masquer les données passées via le statut de l'issue sans supprimer les événements à l'ingestion |
Workflow
Étape 1 — Identifier les candidats
Un fort nombre d'occurrences avec peu d'utilisateurs distincts est le signal de bruit le plus fort — un utilisateur (ou un bot) produisant de nombreux événements.
posthog:query-error-tracking-issues-list
{
"status": "active",
"orderBy": "occurrences",
"orderDirection": "DESC",
"dateRange": { "date_from": "-7d" },
"limit": 30,
"volumeResolution": 0
}
Cherchez :
- Un ratio
occurrences/usersélevé / faible (par ex., 50 000 occurrences, 3 utilisateurs → probablement une boucle bot ou extension) - Des messages d'exception correspondant aux motifs de bruit connus :
ResizeObserver loop,Script error., espaces de noms d'extension (chrome-extension://,moz-extension://,safari-extension://) - Des stack traces dominées par des domaines tiers que l'utilisateur ne contrôle pas
Étape 2 — Confirmer le motif
Pour chaque candidat, tirez un échantillon d'événements $exception et vérifiez que le motif correspond à ce que vous avez l'intention de supprimer :
posthog:query-error-tracking-issue-events
{
"issueId": "<candidate_issue_id>",
"limit": 10,
"verbosity": "stack"
}
onlyAppFrames vaut par défaut true, mais pour une investigation de bruit vous voulez généralement voir les frames tiers — passez onlyAppFrames: false pour que les URLs d'extension et les domaines tiers apparaissent dans la stack.
Vérifiez :
- Le type d'exception ou le texte du message est cohérent dans l'échantillon
- Les URLs / user agents / navigateurs n'incluent pas de trafic utilisateur réel mélangé au bruit
- Supprimer ce motif ne cachera pas un futur bug réel qui partagerait le même type
Si un échantillon ne correspond pas, réduisez le filtre ou ignorez le candidat.
Étape 3 — Affiner le filtre
Les règles de suppression sont configurées avec la même forme de filtre que les règles de groupement. La description de l'outil error-tracking-suppression-rules-create avertit explicitement : ne créez pas de règles match-all et ne créez pas de règles trop larges. Faites correspondre la combinaison de propriétés la plus spécifique possible :
| Motif de bruit | Filtre recommandé |
|---|---|
| Erreurs d'extension Chrome | $exception_sources icontains "chrome-extension://" |
| Erreurs d'extension Firefox | $exception_sources icontains "moz-extension://" |
| Erreurs d'extension Safari | $exception_sources icontains "safari-extension://" |
| Boucle ResizeObserver | $exception_values icontains "ResizeObserver loop" (le message est spécifique ; un filtre de type est optionnel) |
| "Script error." cross-origin | $exception_values icontains "Script error." AND $exception_types exact "Error" |
| User agents bot | $raw_user_agent regex "(?i)bot" pour un seul terme ; voir le motif d'alternation ci-dessous pour faire correspondre plusieurs marqueurs bot/crawler dans une seule règle |
| Échecs de balises réseau tiers | $exception_sources icontains "<vendor-domain>" AND un filtre de type (par ex., $exception_types exact "TypeError") |
Les propriétés d'exception canoniques ($exception_types, $exception_values, $exception_sources, $exception_functions) sont des tableaux au moment de la capture. Le compilateur de filtre de propriété les traite comme un cas spécial — il analyse la colonne matérialisée JSON et enveloppe le filtre dans arrayExists(v -> ..., JSONExtract(...)), donc tous les opérateurs standards (exact, is_not, icontains, not_icontains, regex, not_regex) fonctionnent contre les éléments individuels avec la valeur brute : exact "TypeError", 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 elles produit une règle qui ne correspond silencieusement jamais.
Notez que l'opérateur regex sur les règles de suppression et de groupement compile en Operation::Regex HogVM, qui est sensible à la casse. Utilisez le flag inline (?i) pour une correspondance insensible à la casse (par ex., (?i)headlesschrome).
Pour faire correspondre plusieurs termes bot ou crawler, utilisez des barres nues pour l'alternation. Passez cela comme le champ value du filtre regex lors de l'appel de l'API ($raw_user_agent est plus fiable que le $user_agent analysé, que certains parseurs normalisent loin des marqueurs crawler) :
(?i)(HeadlessChrome|bot|crawler|spider)
Autant que possible, combinez avec AND deux ou plusieurs conditions — type plus message, ou message plus motif d'URL — pour que la règle soit spécifique au bruit réel.
Étape 4 — Décider : supprimer ou échantillonner
Si vous voulez garder une certaine visibilité, utilisez sampling_rate entre 0 et 1 :
sampling_rate: 1— supprimer tout ce qui correspond (suppression complète)sampling_rate: 0.95— supprimer 95 % des événements correspondants, garder 5 % comme données sentinellessampling_rate: 0.5— demi-débit, utile pour les erreurs à fort volume mais réelles
Défaut à un taux d'échantillonnage non-1.0 quand il y a un doute que le motif est du pur bruit. Vous pouvez serrer à 1.0 plus tard une fois que les données montrent que la règle ne capture pas de vrais problèmes.
Étape 5 — Dry-run le filtre contre les données en direct
Avant de demander une confirmation, exécutez le filtre candidat contre la liste des issues pour que vous (et l'utilisateur) voyiez exactement quelles issues la règle aurait attrapées au cours des 7 derniers jours. query-error-tracking-issues-list accepte la même forme de filtre de propriété que les règles de suppression utilisent via son paramètre filterGroup, donc pour une règle AND-only typique vous pouvez passer les filtres feuilles de la règle directement — pas de traduction HogQL nécessaire :
posthog:query-error-tracking-issues-list
{
"filterGroup": [
{ "type": "event", "key": "$exception_types", "operator": "exact", "value": "Error" },
{ "type": "event", "key": "$exception_values", "operator": "icontains", "value": "ResizeObserver loop" }
],
"dateRange": { "date_from": "-7d" },
"status": "all",
"filterTestAccounts": false,
"orderBy": "occurrences",
"limit": 25
}
Défauts importants à surcharger pour l'aperçu de suppression :
status: "all"— la suppression s'applique quel que soit le statut de l'issue, donc ne laissez pas le filtre par défautactivemasquer le bruit déjà archivé.filterTestAccounts: false— la règle ne respectera pas le toggle de compte de test à l'ingestion. L'aperçu doit correspondre à la réalité de la production.
Chaque ligne est une issue que la règle attrapperait : name (type d'exception), description (message échantillon), source, library, plus aggregations.occurrences et aggregations.users. La liste des issues est la ventilation par issue — lisez chaque ligne.
La vérification de sécurité la plus importante : scannez le résultat pour toute issue dont le name / description / source ressemble à un vrai bug que l'équipe voudrait corriger, pas du bruit. Un filtre qui semble précis par le texte du message correspondra régulièrement à des issues sans rapport qui partagent une phrase, et c'est le mode d'échec qui détruit silencieusement les vraies données une fois que la règle est en direct. Si vous voyez quelque chose de suspect, réduisez le filtre (étape 3) et relancez cette étape jusqu'à ce que seul le vrai motif de bruit soit dans la liste.
Additionnez aggregations.occurrences et aggregations.users sur les lignes pour les totaux du rayon d'impact que vous présenterez à l'utilisateur à l'étape 6. Si vous avez besoin de totaux exacts sur plus d'issues que la limit, paginÿez avec offset ou retombez sur l'agrégat HogQL à la fin de cette étape.
Pour un ou deux événements échantillons concrets avec des stack traces complètes, relancez sur l'issue qui semble la plus suspecte avec query-error-tracking-issue-events :
posthog:query-error-tracking-issue-events
{
"issueId": "<id from the list>",
"limit": 3,
"verbosity": "stack",
"onlyAppFrames": false
}
Quand vous devez tomber à execute-sql
filterGroup est AND seul et plat. Passez à HogQL quand :
- La règle utilise
type: "OR"au groupe extérieur ou tout OR imbriqué. - La règle utilise des opérateurs non supportés par
filterGroup(par ex.,between,in,semver_*). - Vous voulez un compte exact au niveau de l'événement plutôt que des agrégats par issue.
La forme HogQL reflète ce que le bytecode de la règle de suppression compile. La colonne de propriété matérialisée est nullable, donc le wrapper coalesce(..., '[]') est requis — sans lui ClickHouse rejette la requête avec « Nested type Array(String) cannot be inside Nullable type » :
SELECT
count() AS matched,
count(DISTINCT distinct_id) AS users,
count(DISTINCT properties.$exception_issue_id) AS issues
FROM events
WHERE event = '$exception'
AND timestamp > now() - INTERVAL 7 DAY
AND arrayExists(
v -> ifNull(ilike(v, '<pattern>'), 0),
JSONExtract(coalesce(properties.$exception_values, '[]'), 'Array(String)')
)
Utilisez ilike pour icontains, l'égalité ordinaire pour exact, match(v, '<pattern>') pour regex. Le regex de la règle est sensible à la casse — ajoutez (?i) inline si nécessaire.
Étape 6 — Confirmer avec l'utilisateur avant de créer
La suppression est destructrice par nature bien que l'API la marque destructive: false. Montrez à l'utilisateur avant de créer :
- Le filtre exact que vous prévoyez d'envoyer
- La liste des issues de l'étape 5 avec leurs
occurrencesetusers, plus les totaux agrégés — signalez toute ligne qui ressemble à un vrai bug - Qu'elle chevauche des règles de suppression existantes (
posthog:error-tracking-suppression-rules-listd'abord)
Attendez une confirmation explicite. Puis créez :
posthog:error-tracking-suppression-rules-create
{
"filters": {
"type": "AND",
"values": [
{
"type": "event",
"key": "$exception_types",
"operator": "exact",
"value": "Error"
},
{
"type": "event",
"key": "$exception_values",
"operator": "icontains",
"value": "ResizeObserver loop"
}
]
},
"sampling_rate": 0.95
}
Commencez à 0.95 (supprimer 95 %, garder 5 % comme données sentinelles) pour pouvoir confirmer que la règle n'attrape pas les vrais erreurs avant de serrer à 1.0.
Étape 7 — Surveiller la règle pendant 24-48h
Après avoir créé la règle :
- Confirmez que les événements correspondants ne sont plus capturés en exécutant le même filtre sur une fenêtre courte limitée à après la création de la règle (par ex.,
WHERE timestamp > now() - INTERVAL 1 HOURune fois qu'une heure a passé). Ne relancez pas l'estimation sur 7 jours de l'étape 5 — la suppression ne s'applique qu'aux nouveaux événements, donc les événements historiques dans la fenêtre seront toujours là et le compte ne baissera pas. - Surveillez les issues actives connexes sur la fenêtre post-création — si leur volume baisse tandis que les issues sans rapport restent stables, la règle était correctement délimitée
- Si le volume d'une vraie issue connexe baisse aussi (faux positif), demandez à l'utilisateur de désactiver la règle via Paramètres du projet → Suivi des erreurs → Règles de suppression immédiatement et réduisez le filtre avant de le recréer. Les outils MCP pour éditer ou supprimer une règle (
error-tracking-suppression-rules-partial-update,-destroy) ne sont pas activés — l'agent n'a aucun moyen de récupérer programmatiquement.
Si vous voyez des signes de faux positifs (un vrai problème devenant silencieux au moment où la règle a été créée), préférez désactiver la règle plutôt que de la supprimer — cela préserve la configuration de la règle pour un examen post-mortem.
Conseils
- Paramètres du projet → Suivi des erreurs → Règles de suppression montre les mêmes données ; mentionnez cela quand l'utilisateur demande où vivent les règles dans l'interface utilisateur.
- La suppression s'applique à l'ingestion. Les issues existantes d'événements passés gardent leurs données ; seuls les nouveaux événements sont supprimés.
- Pour un changement de statut seul (ne supprimez pas les données, cachez-la juste de la liste active), préférez
error-tracking-issues-partial-updateavecstatus: "suppressed"plutôt qu'une règle de suppression. - Le schéma avertit explicitement le modèle de ne pas créer de règles match-all. Si l'utilisateur demande « supprimer tout depuis les extensions », délimitez toujours par stack trace ou URL — ne laissez jamais
filtersvide. - Une règle de suppression trop précise est inoffensive (du bruit fuit). Une règle trop large détruit silencieusement les vraies données — penchez vers la précision.