Alertes Sentry par appel pour les erreurs critiques

Sentry n'a pas d'action « appel ». Routez ses alertes via un webhook pour que seules les erreurs qui cassent la production fassent sonner votre téléphone.

Mis à jour

Table des matières

Sentry ne peut pas vous appeler. Il peut vous envoyer un e-mail, publier sur Slack ou transmettre l'alerte à PagerDuty — mais il n'existe aucune action vocale intégrée. Pour en obtenir une sans acheter une plateforme d'incidents, il faut envoyer l'alerte Sentry vers un webhook qui sonne : créez une intégration interne, pointez-la sur un canal d'appel Echobell, et placez un filtre devant pour que seules les erreurs qui cassent vraiment la production passent.

Ce guide couvre tout le chemin : l'intégration, la règle d'alerte, la charge utile que Sentry envoie réellement, les modèles qui la lisent, et les deux pièges qui font abandonner.

Pourquoi Sentry ne peut pas faire sonner votre téléphone

Les actions des alertes d'incident de Sentry couvrent les notifications (e-mail, Slack, Discord, Microsoft Teams), la création de tickets (Jira, GitHub, Azure DevOps) et le relais vers un produit d'astreinte (PagerDuty, Opsgenie). Toutes finissent sur un écran que vous devez être en train de regarder, ou sur un siège payant chez un autre éditeur.

À 14 h, aucun problème. À 3 h du matin, un message Slack est indiscernable du silence, et une notification push perd face au mode Ne pas déranger. Pour le petit ensemble d'erreurs où deux heures de retard coûtent de l'argent réel — le tunnel de paiement qui renvoie des 500, l'authentification qui rejette tout le monde, un worker qui perd des jobs en silence — il vous faut un appareil qui sonne.

Le webhook est la jointure. Sentry peut appeler n'importe quel endpoint HTTPS comme action de règle d'alerte ; Echobell transforme cette requête HTTP en alerte de type appel qui traverse le mode Concentration d'iOS.

Ce qu'il vous faut

  • Une organisation Sentry où vous pouvez atteindre Settings → Developer Settings (owner ou manager)
  • Echobell installé (App Store / Google Play)
  • Cinq minutes

Rien n'a besoin d'être joignable depuis internet de votre côté. C'est Sentry qui émet la requête sortante ; vous ne faites que la recevoir.

Étape 1 — Créer un canal qui sonne

Dans Echobell, créez un canal et réglez son type de notification sur Appel. C'est tout l'intérêt de l'exercice : un canal d'appel se comporte comme un appel entrant plutôt que comme un push, il traverse donc le mode Concentration et Ne pas déranger.

Donnez-lui des modèles compréhensibles à 3 h du matin. La charge utile de Sentry est profondément imbriquée, les chemins de variables sont donc plus longs que d'habitude :

Titre : {{data.event.level}}: {{data.event.metadata.type}}
Corps : {{data.event.title}} — {{data.event.culprit}}

Configurez le modèle de lien dans les réglages avancés pour qu'un appui sur la notification ouvre l'incident :

{{data.event.web_url}}

Copiez l'URL du webhook depuis la vue détaillée du canal. Elle ressemble à :

https://hook.echobell.one/t/<channel-token>

Étape 2 — Créer une intégration interne Sentry

Sentry ne propose un webhook comme action de règle qu'à travers une intégration : il faut donc en créer une. C'est un formulaire, pas un service — vous n'écrivez aucun code.

  1. Allez dans Settings → Developer Settings → Custom Integrations
  2. Create New Integration → Internal Integration
  3. Name : Echobell (c'est l'étiquette que vous choisirez dans la règle)
  4. Webhook URL : l'URL de votre canal, obtenue à l'étape 1
  5. Activez l'interrupteur Alert Rule Action
  6. Permissions : Issue & Event → Read suffit
  7. Sous Webhooks, laissez toutes les cases décochées — voir le piège plus bas
  8. Enregistrez

Une intégration interne est limitée à votre organisation et s'installe d'elle-même. Vous n'aurez jamais besoin du jeton qu'elle génère pour ce montage.

Étape 3 — Ajouter l'intégration comme action de la règle

Allez dans Alerts → Create Alert → Issue Alert, ou modifiez une règle existante.

Sous Then perform these actions, ajoutez Send a notification via an integration et choisissez Echobell.

Réglez Action interval — le limiteur « si cette alerte s'est déclenchée plus d'une fois » — sur au moins 30 minutes. Par défaut, chaque déclenchement envoie, et une erreur qui part 400 fois par minute composera votre numéro jusqu'à ce que vous coupiez tout.

Enregistrez, puis lancez le test de la règle pour voir arriver une vraie charge utile avant de lui faire confiance.

Étape 4 — Savoir ce qui arrive réellement

C'est là que la plupart des montages cassent, parce que la charge utile n'a pas la forme qu'on imagine. Sentry emballe tout :

{
  "action": "triggered",
  "actor": { "id": "sentry", "name": "Sentry", "type": "application" },
  "data": {
    "event": {
      "event_id": "e4874d664c3540c1a32eab185f12c5ab",
      "level": "error",
      "title": "ReferenceError: heck is not defined",
      "culprit": "?(<anonymous>)",
      "platform": "javascript",
      "project": 1,
      "release": null,
      "metadata": { "type": "ReferenceError", "value": "heck is not defined" },
      "tags": [["level", "error"], ["browser", "Chrome 75.0.3770"]],
      "issue_id": "1117540176",
      "issue_url": "https://sentry.io/api/0/issues/1117540176/",
      "web_url": "https://sentry.io/organizations/test-org/issues/1117540176/events/e4874.../"
    },
    "triggered_rule": "Very Important Alert!"
  },
  "installation": { "uuid": "a8e5d2..." }
}

Quatre choses à savoir avant d'écrire le moindre modèle :

  • Tout ce qui est utile se trouve sous data.event. {{title}} ne rend rien ; {{data.event.title}} rend l'erreur.
  • data.event.project est un ID numérique, pas un slug. Pour un nom de projet lisible dans la notification, écrivez-le en texte littéral dans le modèle de titre et utilisez un canal par projet.
  • Il n'y a pas de champ environment. L'environnement arrive dans data.event.tags sous forme de paire ["environment", "production"], et sa position dans le tableau n'est pas stable — n'y accédez donc pas par index. Filtrez l'environnement dans la règle Sentry (étape 5).
  • data.triggered_rule est le nom de la règle. Utile dans le corps quand un canal sert plusieurs règles.

L'en-tête Sentry-Hook-Resource vaut event_alert pour les alertes d'incident. Vous pouvez l'exiger dans une condition de canal pour que rien d'autre ne puisse le faire sonner :

header["sentry-hook-resource"] == "event_alert"

Étape 5 — Filtrer jusqu'à ce qui mérite un appel

Un canal d'appel qui sonne à chaque nouvel incident est pire que pas de canal du tout : en une semaine vous l'aurez coupé, et il ne sonnera donc pas pour celui qui comptait. Filtrez à deux endroits.

Dans Sentry, avec les conditions et filtres de la règle :

ObjectifConfiguration de la règle
Production uniquementMettez l'Environment de la règle sur production
Seulement les vraies cassesFiltre : The event's level equals fatal (ou error)
Pas pour un soubresautCondition : The issue is seen more than 25 times in 1 hour
Un seul chemin critiqueFiltre : The event's tags match transaction contains /checkout
Seulement les régressionsCondition : A resolved issue changes state from resolved to unresolved

Dans Echobell, utilisez une condition de canal comme filet pour ce que Sentry ne sait pas exprimer, ou pour un changement que vous ne pouvez pas livrer aujourd'hui :

data.event.level == "fatal" || data.event.level == "error"

Filtrer la sévérité dans la règle Sentry est généralement préférable, car c'est aussi là que vit la limitation de fréquence. Le faire dans Echobell est préférable quand vous voulez deux niveaux d'urgence à partir d'une seule règle.

Étape 6 — Une porte plus discrète pour les avertissements

L'intérêt du classement par niveaux, c'est que l'appel garde son sens. Créez un second canal Echobell de type Sensible au temps, ajoutez une seconde règle Sentry avec un seuil plus bas et pointez-la vers une seconde intégration interne (une intégration ne porte qu'une URL de webhook, un second canal demande donc une seconde intégration).

Un montage qui survit à une vraie semaine ressemble à ceci :

Règle SentryNiveau / seuilCanal EchobellComportement
prod-fatalfatal, productionAppelSonne à travers Concentration
prod-error-spikeerror, plus de 100 en 1 hSensible au tempsS'affiche sur l'écran verrouillé, sans sonner
new-issue-digesttout nouvel incidentNormalPush ordinaire, lu plus tard

Ne sonner qu'en dehors des heures de travail

En journée, vous regardez déjà Sentry. Echobell expose aux conditions des variables de temps système en UTC : un même canal peut donc se comporter différemment selon l'heure, sans seconde règle Sentry.

data.event.level == "fatal" && (hour >= 17 || hour < 9)

Ajoutez un test de jour si votre week-end est vraiment libre :

data.event.level == "fatal" && (hour >= 17 || hour < 9 || dayOfWeek == 0 || dayOfWeek == 6)

Tout cela est en UTC : convertissez depuis votre fuseau avant de figer les chiffres. La référence des conditions donne la liste complète des variables.

Les deux pièges

Piège 1 : cocher les cases Webhooks. Une intégration interne a deux chemins de webhook indépendants. L'interrupteur Alert Rule Action rend l'intégration sélectionnable dans les règles — c'est celui que vous voulez. Les cases Webhooks (issue, error, comment) vous abonnent à chaque événement de cette ressource : chaque incident créé, résolu, assigné, archivé ou ignoré, dans toute l'organisation. Cochez issue et votre téléphone sonnera quand un collègue résout quelque chose. Laissez-les toutes décochées et seules vos règles déclencheront le webhook.

Piège 2 : utiliser l'ancien plugin Webhooks. Le vieux plugin par projet Legacy Integrations → WebHooks existe toujours et fonctionne toujours, et il ressemble à un raccourci puisqu'on colle une URL sans créer d'intégration. Sa charge utile a une forme différente, plus plate, ses requêtes ne sont pas signées, et Sentry oriente les nouveaux montages ailleurs. Si vous l'utilisez, vos modèles auront besoin d'autres chemins de variables que ceux ci-dessus. Utilisez l'intégration interne.

Taille de charge utile, tempêtes et troncature

Trois limites à connaître avant que quelque chose casse à grande échelle :

  • 1 Mio de corps. Echobell rejette avec un HTTP 413 les corps de plus de 1 Mio. Une charge Sentry transporte la pile complète et le contexte de la requête, ce qui fait habituellement quelques dizaines de kilo-octets — mais un événement avec un gros corps de requête peut s'en approcher. Sentry n'a pas de réglage max_alerts : la parade est de nettoyer les gros corps dans le beforeSend de votre SDK, ce que vous voulez de toute façon pour la confidentialité.
  • 120 requêtes par minute et par jeton. Au-delà, le déclencheur répond 429 avec RATE_LIMIT_EXCEEDED et un Retry-After. C'est l'action interval de Sentry qui vous maintient en dessous ; 30 minutes suffit largement.
  • 1500 octets de corps de notification. Au-delà, le rendu est tronqué avant d'atteindre l'appareil. data.event.title plus culprit tient confortablement ; déverser data.event.exception, non — et c'est de toute façon illisible sur un écran verrouillé. Laissez le détail derrière le modèle de lien.

Partager avec l'équipe

Plusieurs personnes peuvent s'abonner à un canal Echobell, et chacune choisit son propre type de notification. La même règle Sentry peut donc faire sonner le téléphone de la personne d'astreinte tout en arrivant comme push ordinaire chez les autres — sans tarif par siège ni configuration de rotation.

Ce n'est pas pour autant une politique d'escalade. Il n'y a pas de « si personne n'acquitte en cinq minutes, appelle le suivant ». Si vous avez besoin de ça, il vous faut une vraie plateforme d'astreinte ; Echobell couvre la couche de livraison en dessous.

Ce que ce montage ne vous donne pas

Autant le dire clairement :

  • Pas d'acquittement. Répondre à l'appel ne dit rien à Sentry et n'arrête pas les téléphones des autres abonnés.
  • Pas de rotation ni d'escalade. Tous les abonnés reçoivent, ou personne.
  • Pas de déduplication au-delà de celle de Sentry. Le regroupement et la limitation se font dans la règle ; Echobell livre ce qui arrive.
  • Pas de synchronisation bidirectionnelle. Résoudre l'incident dans Sentry n'efface rien sur votre téléphone.

Si ce sont des blocages, ce n'est pas le bon outil. Si ce qu'il vous faut, c'est « réveille-moi quand le paiement casse », c'est sans doute le moyen fiable le moins cher d'y arriver.

Dépannage

La règle se déclenche mais rien n'arrive. Vérifiez que Alert Rule Action est activé dans l'intégration. S'il est désactivé, l'intégration n'apparaît même pas dans la liste des actions — et une règle enregistrée avant l'activation garde une action obsolète.

Une notification arrive mais elle est vide. Votre modèle lit des clés de premier niveau. Sentry imbrique tout sous data.event.

Ça sonne pour des choses inattendues. Vérifiez les cases Webhooks de l'intégration (piège 1), puis si l'environnement de la règle est resté sur « All Environments ».

Ça sonne en boucle pour une même erreur. Augmentez l'action interval de la règle. Le réessai d'Echobell est autre chose : Réessayer l'appel échoué, dans les réglages, recompose un appel que vous avez manqué.

Rien n'arrive jamais, même le test. Déclenchez d'abord le canal avec curl pour écarter le côté Echobell :

curl -X POST https://hook.echobell.one/t/<channel-token> \
  -H 'Content-Type: application/json' \
  -d '{"data":{"event":{"level":"fatal","title":"Test error","culprit":"manual test","metadata":{"type":"TestError"}}}}'

Si ça sonne et que Sentry ne sonne pas, le problème est dans l'intégration, pas dans le canal.

Questions fréquentes

Sentry peut-il passer un appel nativement ?

Non. Les actions d'alerte de Sentry sont des notifications, de la création de tickets et des intégrations avec des produits d'astreinte. Un appel vocal exige un service externe : soit une plateforme comme PagerDuty, soit un récepteur de webhook qui sonne, comme Echobell.

Une alerte Sentry traverse-t-elle Ne pas déranger ?

Seulement si elle arrive comme alerte de type appel. Un canal Echobell de type appel se comporte comme un appel entrant, ce que le mode Concentration et Ne pas déranger d'iOS laissent passer. Un push ordinaire, non.

Faut-il un plan Sentry payant pour les webhooks ?

Les intégrations internes et les actions de règle sont disponibles à partir du plan Developer de Sentry. Le webhook lui-même ne coûte rien de plus.

Pourquoi ma variable de modèle est-elle vide ?

Presque toujours parce que le chemin est trop court. La charge d'alerte imbrique l'événement sous data.event : c'est donc {{data.event.title}}, pas {{title}}. Déclenchez le canal une fois et regardez le corps de requête enregistré dans l'app pour voir la forme exacte reçue.

Comment alerter sur un seul environnement ?

Renseignez le champ Environment de la règle d'alerte Sentry. N'essayez pas de le lire depuis data.event.tags : c'est un tableau de paires [clé, valeur] dont l'ordre n'est pas garanti.

Deux personnes peuvent-elles être appelées pour la même erreur ?

Oui. Partagez le canal et laissez chacun s'abonner avec le type de notification voulu. Comme il n'y a pas d'acquittement, toutes les personnes ayant choisi « appel » sont appelées.

Faut-il filtrer dans Sentry ou dans Echobell ?

Dans Sentry quand c'est possible — la règle porte aussi la limitation de fréquence et l'environnement. Dans Echobell quand vous voulez deux niveaux d'urgence à partir d'une règle, quand il vous faut une fenêtre horaire, ou quand la règle ne peut pas changer aujourd'hui.

Pour finir

Le montage tient en quatre choses : un canal d'appel, une intégration interne avec Alert Rule Action activé et les cases Webhooks décochées, une règle d'alerte assez étroite pour mériter un appel, et des modèles qui lisent data.event. Tout le reste de cette page sert à la garder assez étroite pour que, dans un mois, la sonnerie veuille encore dire quelque chose.

Téléchargez Echobell pour iPhone ou obtenez-le sur Google Play, puis envoyez le curl ci-dessus avant de confier quoi que ce soit d'important à ce chemin.

Articles connexes