Ir al contenido
mcpd
sin daemon
Código

Monitores y alertas

Una condición que merece vigilancia, vigilada. mcpd evalúa con un temporizador, enclava lo que encuentra y te lo dice una vez.

Qué es un monitor

Un monitor es una pregunta guardada que mcpd se hace a sí mismo con un temporizador: ¿la tasa de error de este proyecto está por encima del cinco por ciento en los últimos cinco minutos? ¿La media de este evaluador está por debajo del número que acordamos? Lee el mismo almacenamiento que lee la interfaz, así que un monitor solo puede afirmar algo que podrías haber consultado tú.

Los monitores están apagados hasta que configuras uno. mcpd no adivina un umbral por ti, porque un umbral que no eligió nadie es un umbral en el que no confía nadie.

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.

Se enclava

Un monitor que se dispara en cada evaluación mientras persiste una condición acaba silenciado en un día, y un monitor silenciado es peor que no tener monitor, porque parece cobertura. Así que mcpd informa de la transición y no del estado: una vez al entrar en el problema, una vez al salir de él, y nada entre medias.

El silencio no es una recuperación

Esta es la regla que le cuesta caídas a la gente. Cuando el tráfico se detiene, la ventana tiene demasiado pocas ejecuciones para juzgar, y la implementación obvia informa de que «no pasa nada» y borra la alerta. Pero un agente que ha dejado de atender solicitudes es el fallo, no la recuperación de él.

Una ventana con demasiado pocas ejecuciones deja una alerta activa exactamente donde estaba. Un monitor vuelve a nominal solo cuando una lectura con suficientes muestras detrás vuelve a entrar dentro del umbral.

El mismo razonamiento fija min_samples. Una ejecución fallida en una hora tranquila es una tasa de error del cien por cien, y mcpd no va a llamar a eso un fallo. El valor por defecto es veinte.

Qué se puede vigilar

VigilanciaQué mide
error_rate Ejecuciones fallidas sobre el total de ejecuciones de la ventana.
latency_p95 Duración de las ejecuciones en el percentil noventa y cinco, en milisegundos.
cost Gasto total en la ventana, en la moneda del libro de precios.
score_mean Media de un evaluador, nombrado por scorer_id. Es la que atrapa una regresión de calidad que un gráfico de latencia no puede ver.
trace_count Ejecuciones en la ventana. Vigílala con below para atrapar un pipeline que se quedó en silencio.
step_count_divergence Ejecuciones de la ventana que dieron un número de pasos inusual para su propia definición. Es la única vigilancia de aquí sin umbral en la unidad de lo que mide. Lee ejecuciones duraderas, no trazas.
run_repetition Cuánto se repite una ejecución: la media, sobre las ejecuciones de la ventana, del mayor número de intentos que alguna de ellas hizo en un mismo nodo de su definición. 1 significa que ningún nodo se repitió. Lee ejecuciones duraderas, no trazas.

Un objetivo, cuando el umbral es la pregunta equivocada

Un monitor pregunta si la tasa de error está ahora mismo por encima del cinco por ciento. Un SLO pregunta algo más útil: ¿vamos a incumplir la meta que prometimos, y a qué velocidad nos dirigimos hacia ahí?

La diferencia importa porque un umbral no distingue un pico de dos minutos de una fuga lenta, y esas dos cosas piden respuestas opuestas. Pon un umbral lo bastante estrecho para atrapar la fuga y el pico te avisará a las tres de la mañana. Ponlo lo bastante holgado para dormir durante el pico y la fuga correrá una semana entera.

El presupuesto, y el ritmo al que se consume

Un objetivo de 0.995 a treinta días dice que puede fallar medio por ciento de las ejecuciones. Ese medio por ciento es el presupuesto de errores. Una tasa de consumo de 1 lo gasta exactamente a lo largo de los treinta días; una tasa de consumo de 10 lo gasta en tres.

mcpd mide el consumo en dos ventanas a la vez y solo se dispara cuando las dos coinciden: más rápido que 14.4x en la última hora y más rápido que 6x en las últimas seis. Eso es lo que separa los dos casos. Una caída de cinco minutos mueve el número de una hora y no puede mover el de seis, así que no avisa a nadie. Una fuga que lleva toda la tarde en marcha mueve los dos.

Conviene saberlo antes de apoyarse en ello: con un objetivo del 99.5%, esos umbrales son una tasa de error de alrededor del 7.2%. Una tasa de fallo constante del 5% consume el presupuesto diez veces demasiado deprisa y lo agotará antes de tiempo, pero no despierta a nadie. Vigila budget_remaining para eso, y mantén un monitor de score_mean o de error_rate si quieres enterarte antes.

{
  "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 devuelve cada objetivo con su tasa de éxito, la fracción de presupuesto que queda y las dos tasas de consumo. POST /v1/api/slos/{id}/ack reconoce uno. Se enclavan y se reconocen exactamente igual que los monitores, y una ventana demasiado fina para juzgar no borra nunca una alerta activa.

budget_remaining se vuelve negativo en cuanto el presupuesto se sobrepasa, en lugar de pararse en cero. Cero e «incumplir la meta por un factor de cien» son situaciones distintas y el número dice cuál de las dos es.

Configurar uno

Los monitores están en un archivo JSON y no en la línea de comandos, porque un umbral, una ventana y una comparación no caben en un flag y se deberían revisar como código. El archivo se monta tal cual como un ConfigMap de 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
    }
  ]
}

arrancar con los monitores armados

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

Una clave desconocida impide el arranque en lugar de ignorarse. Una errata en threshold que en silencio no vigila nada es el peor desenlace disponible, así que mcpd la rechaza en voz alta.

Fija "enabled": false para conservar la definición de un monitor sin evaluarlo. mcpd config imprime cuántos están armados.

A dónde va una transición

Cada transición se anota en el log con el id del monitor, el proyecto, el umbral y el valor medido como campos estructurados, para que un pipeline de logs pueda encaminarla sin analizar una frase. Si ya tienes uno, esa es toda la integración.

Dale a un monitor un webhook y mcpd envía además la transición por POST. El cuerpo es genérico a propósito: Slack, PagerDuty, Opsgenie y todas las herramientas de flujo de trabajo aceptan un webhook entrante, y dar forma al payload para una de ellas significaría mantener un conjunto de integraciones con proveedores que se quedan obsoletas.

{
  "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"
}

Una entrega fallida se anota y se descarta. Reintentar bloquearía el bucle de evaluación o necesitaría una cola de salida duradera, y un camino de alertas que puede quedarse atrás en silencio es peor que uno que ha perdido un mensaje a la vista de todos.

Leer y reconocer

GET /v1/api/monitors devuelve cada monitor con su condición enclavada, su última lectura y cuándo se disparó.

POST /v1/api/monitors/{id}/ack reconoce uno. Reconocerlo silencia la transición sin fingir que la condición se ha despejado: el monitor sigue reconocido mientras siga incumpliendo, y vuelve a nominal por su cuenta cuando el número se recupera. Nadie tiene que acordarse de quitarle el silencio.

El estado de un monitor se guarda en memoria y se reconstruye a partir de las lecturas en cada arranque. No se persiste, porque un reinicio que resucita una alerta que ya se ha recuperado es un fallo peor que un reinicio que vuelve a evaluar.

A continuación