Blog ·
Un incident qui ne se ferme jamais sur un silence
Un incident de supervision doit s’ouvrir sur une mesure et se fermer sur une mesure. Voici ce qui casse quand l’absence de données vaut bonne nouvelle.
Par Provibr
Tout système de supervision finit par affronter la même question dans un costume légèrement différent : que faites-vous quand les mesures cessent d’arriver ?
La réponse tentante consiste à traiter cela comme un rétablissement. Plus rien n’échoue, la ligne rouge disparaît, le tableau de bord est calme. C’est aussi le mensonge le plus coûteux que le système puisse dire, car le moment où vous cessez de pouvoir regarder quelque chose est exactement le moment où vous ne devez pas affirmer que tout va bien.
Voici la conception à laquelle nous sommes arrivés pour les incidents, et l’essentiel consiste à garder « nous avons mesuré que c’est cassé », « nous avons mesuré que c’est réparé » et « nous ne pouvons pas le voir en ce moment » comme trois affirmations distinctes qui ne deviennent jamais discrètement l’une l’autre.
Pourquoi l’incident est un objet
Auparavant, une panne était une série de lignes dans une table de transitions d’état. C’est assez pour tracer un graphique et pas assez pour dire quoi que ce soit. Trois choses n’existent qu’à partir du moment où il y a un objet.
Une durée. Le message de rétablissement ne portait jusqu’ici aucune durée, parce qu’il n’y avait rien pour remplir le paramètre. Un incident a un début : la durée est donc une mesure et non une estimation.
Une couche humaine. Acquitter, assigner et fermer à la main sont des choses que font des personnes, et elles ne doivent pas toucher à l’état mesuré. Une colonne acknowledged_at sur une mesure brouillerait exactement la ligne sur laquelle toute cette fonctionnalité est construite.
La déduplication dans le temps. Une notification à l’ouverture, des rappels sur leur propre horloge, au plus une escalade. Sans objet, il n’y a rien à quoi accrocher le « je vous l’ai déjà dit », et alors chaque battement est une nouvelle occasion de vous le redire.
La déduplication est un index
L’unicité qui empêche deux incidents d’exister pour une seule règle est un index unique partiel sur la règle, là où l’horodatage de résolution est nul. Deux passerelles traitant la même transition produisent un seul incident par construction ; la seconde reçoit une violation d’unicité et passe à autre chose.
Du code qui vérifie s’il en existe déjà un puis insère, ce sont deux instructions, donc deux occasions pour que quelque chose se glisse entre les deux. C’est la même forme que l’index de créneaux du planificateur et que l’index d’occupation des baies ailleurs dans ce produit, et pour la même raison.
Il y a eu ici un bogue franchement gênant, qui mérite d’être écrit parce qu’il est invisible en relecture. La clé de déduplication de la notification était construite à partir de la règle, du nouvel état et de l’horodatage courant. Une clé qui contient l’horodatage courant ne déduplique rien, par construction, et elle a l’air tout à fait raisonnable à l’écran. C’est désormais l’identifiant de l’incident. Mesuré ensuite : trois échecs consécutifs produisent un incident et une notification, et trois de plus ne changent rien.
Trois façons de terminer un incident, et une seule est une mesure
| Résolution | Ce qu’elle affirme | Ce qui est enregistré avec elle |
|---|---|---|
recovered | nous avons de nouveau mesuré un état sain | le résultat qui l’a fermé, stocké sur la chronologie |
configuration_retired | la règle qui a ouvert ceci ne mesure plus rien | aucune, et aucune n’est revendiquée |
manual | une personne l’a fermé | qui, et éventuellement pourquoi |
Celle du milieu est la raison d’être de la liste. Une règle remplacée par une révision de modèle doit fermer ses incidents ouverts, et elle doit le faire sans fausse mesure de rétablissement. Si la seule résolution disponible était recovered, remplacer un modèle écrirait silencieusement « ceci est remonté » dans l’historique de chaque service qui était en panne à ce moment-là.
Il n’y a délibérément pas de résolution stale. Que les mesures aient cessé d’arriver ne dit rien sur la cible.
Quelles transitions touchent un incident
Un incident est accroché à une affirmation sur la cible. Une transition vers « source indisponible », c’est-à-dire notre propre agent qui a disparu, n’ouvre donc rien et, plus important encore, ne ferme rien. Si un agent qui s’en va pouvait fermer un incident, une panne en cours disparaîtrait du champ de vision au moment exact où nous perdons la capacité de la regarder.
Une transition vers « erreur de configuration » se comporte de la même façon : la règle ne décrit plus rien de mesurable, ce qui est une affirmation sur nous et pas sur le service.
« Dégradé » ferme bien un incident. Le service répond, la condition compte comme saine, seule la latence est élevée. Laisser l’incident ouvert ferait d’un service lent une panne ouverte en permanence, rappels compris.
En dessous de tout cela, venue d’une manche antérieure, se trouve une distinction dure entre une source injoignable et une cible qui est tombée. Une vérification dont l’agent n’est pas connecté produit « source indisponible » et jamais « hors service ». Tout ce qui précède est cette même règle, un étage plus haut.
La maintenance fait taire les notifications et continue de mesurer
Une fenêtre de maintenance supprime les notifications. Elle ne supprime pas la mesure. L’incident s’ouvre quand même, la chronologie continue de tourner, et seul le message reste dans le tiroir.
Ce n’est pas un détail. La question que les gens posent après une fenêtre de maintenance, c’est « est-ce revenu à temps », et cette question est sans réponse si vous avez cessé de mesurer au moment où cela comptait. Il existe une case à cocher distincte et explicite qui met bien les vérifications en pause, et elle est désactivée par défaut ; avec elle, le planificateur renonce à réclamer le créneau, si bien que rien ne devient exigible et rien n’est manqué. Ce qui reste ensuite est un unique marqueur de trou, le même que pour n’importe quel autre trou. Il n’y a pas de rattrapage.
La fenêtre elle-même est stockée comme un intervalle absolu avec un fuseau horaire IANA à côté. Le client saisit une heure murale et veut la relire comme la même heure murale, même si le panneau rend l’affichage dans un fuseau fixe. Stocker plutôt l’heure murale plus le fuseau obligerait chaque lecteur, planificateur, ingestion et écran confondus, à refaire la conversion, et alors un changement d’heure devient une heure de désaccord entre deux d’entre eux.
Là où deux fenêtres se chevauchent, c’est celle qui met les vérifications en pause qui l’emporte. Quand un client a fait explicitement un choix plus strict quelque part, c’est ce choix-là qu’il faut honorer.
Rappels, escalade et l’ordre de deux instructions
L’intervalle de rappel comme le délai d’escalade vivent sur la révision de la règle et non sur l’incident, parce que ce sont des réglages et que les réglages appartiennent à la révision qui les a enregistrés. Changez la politique pendant une panne et l’incident en cours reste sous la politique sous laquelle il s’est ouvert.
Les deux sont désactivés par défaut. Un réglage par défaut qui réveille des gens la nuit est une décision que le client n’a pas prise.
Acquitter fait taire les rappels, et c’est là toute la fonction de l’acquittement. Quelqu’un qui dit « je m’en occupe » ne devrait pas être interrompu toutes les quelques minutes. La notification de rétablissement arrive quand même, parce que c’est la réponse à la question qu’il était en train de regarder. L’horloge des rappels part en outre du dernier rappel plutôt que du début, si bien qu’un processus de fond qui rattrape son retard après une heure ne livre pas douze rappels d’un coup.
Le processus écrit l’horodatage d’abord et envoie le message ensuite, et la mise à jour exige que l’état soit encore celui qu’il a lu. Perdez cette course et il ne se passe rien ici. Dans l’autre ordre, une course perdue produit un message dont il n’existe aucune trace, et le message arrive alors de nouveau au tour suivant.
L’escalade se produit au plus une fois par incident, et le contrôle correspondant vit dans la règle partagée plutôt que dans le processus de fond. Sans lui, chaque passage écrirait un nouvel événement d’escalade aussi longtemps que dure la panne : trente par heure avec un sondage de deux minutes.
Le flapping est l’exception, et il se décide au moment où l’incident s’ouvre : trois incidents sur la même règle en une heure. Une vérification qui flappe n’a par définition jamais d’incident qui reste ouvert longtemps, si bien que toute escalade fondée sur le temps le manque pour toujours. Trois et pas deux, parce que deux fois c’est de la malchance et qu’un seuil de deux qualifierait de flapping le moindre redémarrage de service ordinaire. Une heure et pas un jour, parce que trois pannes réparties sur une journée de travail sont trois pannes.
La durée est un nombre et une unité
Le message de rétablissement porte la durée qu’a duré la panne, comme une valeur et une unité, jamais comme une phrase. Si le processus composait lui-même « 1 hour 12 minutes », ce fragment anglais se retrouverait au milieu d’une phrase traduite dans huit autres langues. Ce qui voyage à la place, c’est une unité sur laquelle la traduction fait sa sélection, avec un pluriel à l’intérieur de chaque branche.
Une seule unité, pas de composés : un composé exige un séparateur et un ordre, et ceux-ci diffèrent d’une langue à l’autre. Les secondes en dessous d’une minute, les minutes jusqu’à deux heures, les heures jusqu’à deux jours, les jours ensuite. Quatre-vingt-dix minutes se lit plus nettement que deux heures, et arrondir vers le haut ferait durer deux heures une panne de 89 minutes.
Deux conséquences honnêtes que nous n’avons pas corrigées
La panne, le rétablissement et le rappel partagent une clé de groupe de notification, parce qu’un rappel est littéralement le même sujet à nouveau et qu’il doit mettre à jour la ligne existante plutôt que d’en ajouter une à chaque déclenchement de l’horloge. Le coût, c’est qu’un rappel met à jour une ligne que quelqu’un a déjà lue, et lui est donc invisible. L’escalade reçoit son propre groupe pour exactement cette raison : le message qui doit frapper le plus fort ne doit pas être celui qui est écrasé en premier. Les notifications de supervision ne partent pas par courriel aujourd’hui.
Ce que nous retiendrions
- Ne laissez jamais l’absence de données fermer quoi que ce soit. Donnez à « nous ne pouvons pas le voir » son propre état et assurez-vous qu’il n’ouvre ni ne ferme aucun incident.
- Donnez un objet à l’incident dès que vous voulez une durée, un acquittement ou un second message sur la même chose.
- Mettez la déduplication dans un index unique, et vérifiez que votre clé de notification ne contient pas l’heure courante.
- Énumérez les façons dont un incident peut se terminer, et n’exigez une preuve que là où une preuve est revendiquée.
- Supprimez les notifications pendant la maintenance, pas les mesures, et faites de la mise en pause des vérifications un choix distinct, explicite et désactivé par défaut.
- Mettez l’état à jour, puis envoyez le message. L’autre ordre perd des messages en silence.
Ce travail se trouve derrière un indicateur de déploiement désactivé par défaut : rien de tout cela n’est donc quelque chose que vous pouvez acheter aujourd’hui. C’est écrit comme une méthode et non comme une annonce. La couche de mesure qui se trouve en dessous, y compris la raison pour laquelle un agent injoignable n’est pas un service en panne, est une histoire à part, et la question voisine de savoir quand une plateforme a le droit d’énoncer une durée est dans une barre de progression qui refuse de deviner.
Issu du travail de plateforme sur Provibr.