본문으로 건너뛰기
mcpd
데몬 없음
소스

모니터와 알림

지켜볼 값이 있는 조건을 지켜봅니다. mcpd는 타이머로 평가하고, 찾아낸 것을 래치하고, 한 번만 알려 줍니다.

모니터란 무엇인가

모니터는 mcpd가 타이머에 맞춰 스스로에게 던지는, 저장된 질문입니다. 이 프로젝트의 오류율이 지난 5분 동안 5퍼센트를 넘었는가? 이 스코어러의 평균이 우리가 합의한 숫자 아래로 내려갔는가? 모니터는 인터페이스가 읽는 그 스토리지를 읽으므로, 직접 찾아볼 수도 있었던 것만 주장할 수 있습니다.

모니터는 하나를 구성하기 전까지 꺼져 있습니다. mcpd는 임계값을 대신 짐작하지 않습니다. 아무도 고르지 않은 임계값은 아무도 믿지 않는 임계값이기 때문입니다.

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.

모니터는 래치합니다

조건이 이어지는 동안 평가할 때마다 울리는 모니터는 하루 안에 음소거를 당하고, 음소거된 모니터는 감시가 되고 있는 것처럼 보이기 때문에 모니터가 없는 것보다 나쁩니다. 그래서 mcpd는 상태가 아니라 전이를 보고합니다. 문제로 들어갈 때 한 번, 빠져나올 때 한 번, 그 사이에는 아무것도 보내지 않습니다.

조용한 것은 회복이 아닙니다

이것이 사람들에게 장애의 대가를 치르게 하는 규칙입니다. 트래픽이 멈추면 구간 안에 판단할 만큼의 실행이 남지 않고, 뻔한 구현은 “문제 없음”이라고 보고하며 알림을 지웁니다. 그러나 요청을 처리하기를 멈춘 에이전트는 회복이 아니라 바로 그 실패입니다.

실행이 너무 적게 들어 있는 구간은 이미 떠 있는 알림을 있던 그대로 둡니다. 모니터는 충분한 표본을 등에 업은 값이 임계값 안으로 돌아왔을 때에만 정상으로 돌아갑니다.

min_samples를 두는 근거도 같습니다. 한산한 시간에 실행 하나가 실패하면 오류율은 100퍼센트이고, mcpd는 그것을 결함이라고 부르지 않습니다. 기본값은 스무 개입니다.

무엇을 지켜볼 수 있는가

감시 항목재는 것
error_rate 구간 안의 전체 실행 대비 실패한 실행.
latency_p95 실행 소요 시간의 95백분위수. 밀리초 단위입니다.
cost 구간 안의 총지출. 가격표의 통화 단위입니다.
score_mean scorer_id로 지목한 스코어러 하나의 평균. 지연 차트가 볼 수 없는 품질 회귀를 잡아내는 것이 이것입니다.
trace_count 구간 안의 실행 수. 조용해진 파이프라인을 잡으려면 below와 함께 지켜보십시오.
step_count_divergence 윈도우 안에서, 자기 정의에 비해 유별난 수의 스텝을 밟은 실행들. 재는 대상의 단위로 임계값을 두지 않는, 여기서 유일한 감시입니다. 트레이스가 아니라 지속 실행을 읽습니다.
run_repetition 실행이 얼마나 자기를 반복하는지. 윈도우 안의 각 실행에 대해 자기 정의의 한 노드에서 한 시도 횟수의 최댓값을 구하고, 그 평균을 읽습니다. 1은 어떤 노드도 두 번 돌지 않았다는 뜻입니다. 트레이스가 아니라 지속 실행을 읽습니다.

임계값이 잘못된 질문일 때의 목표

모니터는 지금 이 순간 오류율이 5퍼센트를 넘었는지 묻습니다. SLO는 더 쓸모 있는 것을 묻습니다. 우리가 약속한 목표를 놓치게 될 것인가, 그리고 그쪽으로 얼마나 빨리 가고 있는가.

이 차이가 중요한 이유는 임계값이 2분짜리 순간적인 흔들림과 느린 누수를 구별하지 못하는데, 그 둘은 정반대의 대응을 요구하기 때문입니다. 누수를 잡을 만큼 임계값을 조이면 흔들림이 새벽 세 시에 사람을 깨웁니다. 흔들림을 자면서 넘길 만큼 느슨하게 두면 누수가 일주일을 갑니다.

예산, 그리고 그것이 타는 속도

30일에 걸친 0.995라는 목표는 실행의 0.5퍼센트까지 실패해도 된다는 뜻입니다. 그 0.5퍼센트가 오류 예산입니다. 소모율 1은 예산을 30일에 딱 맞게 씁니다. 소모율 10은 사흘에 다 씁니다.

mcpd는 두 구간에서 소모를 동시에 재고, 둘이 함께 말할 때만 발동합니다. 지난 한 시간 동안 14.4x보다 빠르고 그리고 지난 여섯 시간 동안 6x보다 빠를 때입니다. 두 경우를 갈라 주는 것이 바로 그것입니다. 5분짜리 장애는 한 시간 숫자는 움직이지만 여섯 시간 숫자는 움직일 수 없으므로 호출을 보내지 않습니다. 오후 내내 이어진 누수는 둘 다 움직입니다.

여기에 기대기 전에 알아 둘 것이 있습니다. 99.5% 목표에서 그 임계값은 오류율로 약 7.2%입니다. 5%로 꾸준히 실패하면 예산을 열 배 빠르게 태워 일찍 바닥내지만, 아무도 깨우지 않습니다. 그것을 보려면 budget_remaining을 지켜보고, 더 일찍 알고 싶으면 score_mean이나 error_rate 모니터를 함께 두십시오.

{
  "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는 각 목표를 성공률, 남은 예산의 비율, 그리고 두 소모율과 함께 돌려줍니다. POST /v1/api/slos/{id}/ack은 하나를 확인 처리합니다. 목표는 모니터와 똑같이 래치하고 똑같이 확인 처리되며, 판단하기에 너무 얇은 구간은 떠 있는 알림을 절대 지우지 않습니다.

budget_remaining은 예산을 넘겨 쓰면 0에서 멈추는 대신 음수로 갑니다. 0과 "목표를 백 배로 놓쳤다"는 서로 다른 상황이고, 그 숫자가 어느 쪽인지 말해 줍니다.

모니터 구성하기

모니터는 명령줄이 아니라 JSON 파일에 삽니다. 임계값과 구간과 비교 방식은 플래그 하나에 담기지 않고, 코드처럼 리뷰되어야 하기 때문입니다. 이 파일은 Kubernetes ConfigMap으로 고칠 것 없이 그대로 마운트됩니다.

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

모니터를 걸어 둔 채로 시작하기

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

알 수 없는 키는 무시되는 대신 시작을 실패시킵니다. threshold의 오타 하나가 아무것도 감시하지 않게 만드는 것이 나올 수 있는 결과 가운데 가장 나쁘므로, mcpd는 소리 내어 거부합니다.

모니터의 정의는 남겨 두되 평가하지 않으려면 "enabled": false를 설정하십시오. mcpd config는 몇 개가 걸려 있는지 출력합니다.

전이는 어디로 가는가

모든 전이는 모니터 id, 프로젝트, 임계값, 측정값을 구조화된 필드로 담아 로그에 남으므로, 로그 파이프라인이 문장을 파싱하지 않고도 그것을 라우팅할 수 있습니다. 이미 파이프라인을 돌리고 있다면 그것으로 연동은 끝입니다.

모니터에 webhook을 주면 mcpd는 전이를 POST하기도 합니다. 본문이 일반적인 것은 의도한 것입니다. Slack, PagerDuty, Opsgenie를 비롯한 모든 워크플로 도구가 인바운드 웹훅을 받아들이며, 그중 하나에 맞춰 페이로드를 빚으면 낡아 가는 벤더 연동 묶음을 떠안게 됩니다.

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

전달에 실패하면 로그에 남기고 버립니다. 재시도는 평가 루프를 막거나 지속성 있는 발신 큐를 요구하게 되는데, 조용히 뒤처질 수 있는 알림 경로는 메시지 하나를 놓친 것이 눈에 보이는 경로보다 나쁩니다.

읽기와 확인 처리

GET /v1/api/monitors는 모든 모니터를 래치된 상태, 마지막 측정값, 그리고 언제 발동했는지와 함께 돌려줍니다.

POST /v1/api/monitors/{id}/ack은 하나를 확인 처리합니다. 확인 처리는 조건이 풀린 척하지 않으면서 전이만 조용하게 만듭니다. 모니터는 여전히 임계값을 넘고 있는 동안 확인 처리된 상태로 있다가, 숫자가 회복되면 스스로 정상으로 돌아갑니다. 음소거를 풀 것을 기억하고 있어야 하는 사람은 없습니다.

모니터의 상태는 메모리에 있고 시작할 때마다 측정값에서 다시 만들어집니다. 저장하지 않습니다. 이미 회복된 알림을 재시작이 되살리는 것은, 재시작이 다시 평가하는 것보다 나쁜 실패이기 때문입니다.

다음

  • score_mean 모니터가 지켜보는 스코어러: 회귀 테스트.
  • 어떤 모니터도 덮지 않는, mcpd 자신의 건강 상태: 운영하기.
  • 모든 플래그와 파일 설정: 설정.