Aller au contenu
mcpd
aucun daemon
Source

Moniteurs et alertes

Une condition qui mérite d’être surveillée, surveillée. mcpd évalue à intervalle régulier, verrouille ce qu’il trouve, et vous le dit une fois.

Ce qu’est un moniteur

Un moniteur est une question enregistrée que mcpd se pose à intervalle régulier : le taux d’erreur de ce projet est-il au-dessus de cinq pour cent sur les cinq dernières minutes ? La moyenne de ce scorer est-elle en dessous du nombre convenu ? Il lit le même stockage que lit l’interface, si bien qu’un moniteur ne peut affirmer que ce que vous auriez pu chercher vous-même.

Les moniteurs sont inactifs tant que vous n’en configurez pas un. mcpd ne devine pas un seuil à votre place, parce qu’un seuil que personne n’a choisi est un seuil auquel personne ne se fie.

Monitor panel

6 watched · every 60s

Error rate P95 latency Hourly cost Run count No tool loop Not a refusal

Error rate

Threshold 5%

Two readings in the middle are —: too few runs in the window to judge. The lamp stays lit through them.

A monitor panel of six annunciator windows. The error-rate window lights when the measured rate crosses five percent, stays lit through two windows that hold too few runs to judge, and clears only when a later reading genuinely falls back under the threshold.

Il se verrouille

Un moniteur qui se déclenche à chaque évaluation tant qu’une condition dure est mis en sourdine en moins d’une journée, et un moniteur en sourdine est pire que pas de moniteur du tout, parce qu’il ressemble à une couverture. mcpd rapporte donc la transition et non l’état : une fois quand les ennuis commencent, une fois quand ils cessent, et rien entre les deux.

Le silence n’est pas un rétablissement

C’est la règle qui coûte des pannes aux gens. Quand le trafic s’arrête, la fenêtre tient trop peu d’exécutions pour juger, et l’implémentation évidente rapporte « rien d’anormal » et efface l’alerte. Or un agent qui a cessé de servir des requêtes est la panne, pas le rétablissement.

Une fenêtre qui contient trop peu d’exécutions laisse une alerte en cours exactement là où elle était. Un moniteur ne revient au nominal que lorsqu’une lecture appuyée sur assez d’échantillons repasse à l’intérieur du seuil.

Le même raisonnement fixe min_samples. Une exécution en échec dans une heure calme fait cent pour cent de taux d’erreur, et mcpd n’appellera pas cela une faute. Le défaut est vingt.

Ce qui peut être surveillé

GrandeurCe qu’elle mesure
error_rate Exécutions en échec sur le total des exécutions de la fenêtre.
latency_p95 Durée d’exécution au quatre-vingt-quinzième centile, en millisecondes.
cost Dépense totale sur la fenêtre, dans la devise de la grille tarifaire.
score_mean Moyenne d’un seul scorer, nommé par scorer_id. C’est celle qui attrape une régression de qualité qu’un graphe de latence ne peut pas voir.
trace_count Exécutions dans la fenêtre. Surveillez-la avec below pour attraper un pipeline devenu silencieux.
step_count_divergence Exécutions de la fenêtre qui ont pris un nombre d’étapes inhabituel pour leur propre définition. La seule surveillance ici sans seuil dans l’unité de ce qu’elle mesure. Elle lit les exécutions durables, pas les traces.
run_repetition À quel point une exécution se répète : la moyenne, sur les exécutions de la fenêtre, du plus grand nombre de tentatives que l’une d’elles a faites sur un même nœud de sa définition. 1 signifie qu’aucun nœud n’a tourné deux fois. Elle lit les exécutions durables, pas les traces.

Un objectif, quand un seuil est la mauvaise question

Un moniteur demande si le taux d’erreur est au-dessus de cinq pour cent en ce moment. Un SLO demande quelque chose de plus utile : allons-nous manquer la cible que nous avons promise, et à quelle vitesse y allons-nous ?

La différence compte parce qu’un seuil ne sait pas distinguer un soubresaut de deux minutes d’une fuite lente, et les deux appellent des réponses opposées. Réglez un seuil assez serré pour attraper la fuite et le soubresaut vous réveille à trois heures du matin. Réglez-le assez large pour dormir pendant le soubresaut et la fuite tourne une semaine.

Le budget, et la vitesse à laquelle il se consomme

Un objectif de 0.995 sur trente jours dit qu’un demi pour cent des exécutions peut échouer. Ce demi pour cent est le budget d’erreur. Une vitesse de consommation de 1 le dépense exactement sur les trente jours ; une vitesse de 10 le dépense en trois.

mcpd mesure la consommation sur deux fenêtres à la fois et ne déclenche que lorsque les deux s’accordent : plus vite que 14.4x sur la dernière heure et plus vite que 6x sur les six dernières. C’est ce qui sépare les deux cas. Une panne de cinq minutes déplace le nombre d’une heure et ne peut pas déplacer celui de six : elle ne réveille donc personne. Une fuite qui tourne depuis tout l’après-midi déplace les deux.

À savoir avant de compter dessus : sur un objectif à 99.5 %, ces seuils correspondent à un taux d’erreur d’environ 7.2 %. Un taux d’échec constant de 5 % consomme le budget dix fois trop vite et l’épuisera en avance, mais il ne réveille personne. Surveillez budget_remaining pour cela, et gardez un moniteur score_mean ou error_rate si vous voulez le savoir plus tôt.

{
  "slos": [
    {
      "id": "support-availability",
      "name": "99.5% of support runs succeed over 30 days",
      "project": "support-desk",
      "objective": 0.995,
      "window_days": 30,
      "min_samples": 20,
      "webhook": "https://hooks.example.com/mcpd"
    }
  ]
}

GET /v1/api/slos rend chaque objectif avec son taux de réussite, la fraction de budget qui reste, et les deux vitesses de consommation. POST /v1/api/slos/{id}/ack en acquitte un. Ils se verrouillent et s’acquittent exactement comme les moniteurs, et une fenêtre trop maigre pour juger n’efface jamais une alerte en cours.

budget_remaining devient négatif une fois le budget dépassé, plutôt que de s’arrêter à zéro. Zéro et « la cible manquée d’un facteur cent » sont des situations différentes, et le nombre dit laquelle.

En configurer un

Les moniteurs vivent dans un fichier JSON plutôt que sur la ligne de commande, parce qu’un seuil, une fenêtre et une comparaison n’entrent pas dans une option et méritent d’être relus comme du code. Le fichier se monte tel quel en ConfigMap Kubernetes.

{
  "monitor_interval_seconds": 60,
  "monitors": [
    {
      "id": "support-error-rate",
      "name": "Support agent error rate above 5%",
      "project": "support-desk",
      "watch": "error_rate",
      "compare": "above",
      "threshold": 0.05,
      "window_seconds": 300,
      "min_samples": 20,
      "webhook": "https://hooks.example.com/mcpd"
    },
    {
      "id": "relevance-regression",
      "name": "Answer relevance fell below 0.8",
      "project": "support-desk",
      "watch": "score_mean",
      "scorer_id": "answer_relevance",
      "compare": "below",
      "threshold": 0.8,
      "window_seconds": 3600
    }
  ]
}

démarrer avec les moniteurs armés

mcpd serve --config-file ./mcpd.json

Une clé inconnue fait échouer le démarrage au lieu d’être ignorée. Une faute de frappe dans threshold qui ne surveille silencieusement rien est le pire résultat possible : mcpd la refuse donc à voix haute.

Posez "enabled": false pour garder la définition d’un moniteur sans l’évaluer. mcpd config affiche combien sont armés.

Où va une transition

Chaque transition est journalisée avec l’identifiant du moniteur, le projet, le seuil et la valeur mesurée en champs structurés, si bien qu’un pipeline de logs peut la router sans analyser une phrase. Si vous en exploitez déjà un, c’est toute l’intégration.

Donnez un webhook à un moniteur et mcpd poste aussi la transition. Le corps est générique à dessein : Slack, PagerDuty, Opsgenie et tous les outils de workflow acceptent un webhook entrant, et façonner le payload pour l’un d’eux voudrait dire entretenir un jeu d’intégrations propriétaires qui se périment.

{
  "monitor_id": "support-error-rate",
  "name": "Support agent error rate above 5%",
  "project": "support-desk",
  "condition": "tripped",
  "watch": "error_rate",
  "threshold": 0.05,
  "value": 0.5,
  "samples": 40,
  "detail": "error rate is 0.5000, threshold above 0.0500, over 40 run(s)",
  "at": "2026-08-28T02:13:54.687391446Z"
}

Une remise qui échoue est journalisée puis abandonnée. Réessayer bloquerait la boucle d’évaluation ou demanderait une file sortante durable, et un chemin d’alerte qui peut prendre du retard en silence est pire qu’un chemin qui a visiblement manqué un message.

Lire et acquitter

GET /v1/api/monitors rend chaque moniteur avec sa condition verrouillée, sa dernière lecture et le moment où il s’est déclenché.

POST /v1/api/monitors/{id}/ack en acquitte un. Acquitter fait taire la transition sans prétendre que la condition a disparu : le moniteur reste acquitté tant qu’il est encore en dépassement, et revient au nominal de lui-même quand le nombre se rétablit. Personne n’a à penser à le sortir de sourdine.

L’état d’un moniteur est tenu en mémoire et reconstruit depuis les lectures à chaque démarrage. Il n’est pas persisté, parce qu’un redémarrage qui ressuscite une alerte déjà rétablie est une panne pire qu’un redémarrage qui réévalue.

Ensuite