От бизнес-метрики до дежурного: как построить алертинг, от которого не страдают

В прошлой статье мы прошли путь одного события от метрики и PromQL до Alertmanager и nxs-anomaly: разобрали состояния pending и firing, группировку, webhook, расписание и цепочку эскалации. Но технически исправная доставка ещё не делает алерт полезным. Можно гарантированно разбудить нужного инженера из-за диска, заполненного на 51%, хотя кластер спокойно переживёт это еще месяц. А можно следить за тысячами инфраструктурных метрик и не заметить, что пользователи перестали оплачивать заказы.
Эта статья - о шаге, который предшествует настройке маршрутов: как выбрать сигнал, связать его с влиянием на бизнес, определить срочность и проверить, что вызов дежурного действительно оправдан. В качестве сквозного примера возьмём оформление заказа, а в конце свяжем правила детектирования с обработкой в nxs-anomaly.
Хороший мониторинг ещё не означает хороший алертинг
Мое знакомство с алертигом началось со статьи «Построение правильной системы алертинга — реагируй только на бизнес-критичные проблемы», в которой описана показательная история: после модернизации инфраструктуры команда имела 150 000 метрик, 30 000 триггеров и 5 000 правил, отправлявших события в PagerDuty. Новая отказоустойчивая платформа могла потерять несколько узлов без влияния на поток данных, но алертинг продолжал относиться к отказу отдельного сервера как к фатальной аварии.
Команда оставила для вызова дежурного только события, которые нельзя отложить до утра или понедельника. Число вызывающих дежурного триггеров сократилось с 5 000 до 250, а сверхурочная работа в первый месяц уменьшилась в четыре раза. Проблема была не в недостатке телеметрии, а в том, что прежняя модель алертинга перестала соответствовать архитектуре и реальному влиянию отказов.
Почти десять лет спустя крупные инженерные команды формулируют тот же принцип разными словами:
Google SRE предлагает вызывать человека только при срочном, требующем действий и уже заметном или неизбежном влиянии на пользователя. Причины полезны для диагностики, но вызов дежурного прежде всего должен реагировать на симптомы.
AWS Well-Architected рекомендует привязывать алерты к KPI, добавлять бизнес-контекст, объединять связанные сигналы и регулярно пересматривать правила.
LinkedIn ThirdEye разделяет обнаружение аномалий и отправку уведомлений. Для бизнес-метрик там учитывают тренды, сезонность, объём выборки, разрезы данных и праздничные периоды, а близкие аномалии объединяют.
Uber агрегирует детальные проверки в политики уведомлений. Например, состояние одного хоста может привести к письму, нескольких хостов — к вызову дежурного, а большая географическая проблема — к одному сводному событию вместо серии уведомлений по каждому городу.
GitLab группирует SLO-алерты по сервису и учитывает зависимости. Во время общего сбоя это сокращает каскад вызовов от всех нижестоящих симптомов.
Cloudflare сохраняет состояния алертов для анализа, ищет flapping, забытые правила и события без получателя, а затем использует эти данные на регулярных разборах.
Общий вывод простой: алертинг - это не набор порогов и не последняя стадия установки Prometheus. Это управляемая система принятия решений. Она должна ответить на четыре вопроса:
Что пострадало?
Насколько срочно нужно вмешаться?
Кто способен это исправить?
Как проверить, что сигнал остаётся полезным со временем?
Метрика, KPI, SLI и алерт решают разные задачи
Путаница начинается, когда любое число на дашборде называют бизнес-метрикой, а каждую бизнес-метрику пытаются превратить в срочный вызов. Давайте разберемся в определениях:
Метрика - это измерение: запросы в секунду, заполнение диска, число начатых оформлений заказа или сумма платежей.
KPI описывает результат, важный для компании или продукта: число завершённых заказов, конверсию оформления, выручку, долю активных клиентов. KPI помогает понять состояние бизнеса, но не всегда указывает на технический инцидент. Заказы могут просесть ночью, вырасти во время акции или измениться после отключения рекламной кампании.
SLI измеряет качество конкретного пользовательского опыта: долю успешных оплат среди валидных попыток, задержку подтверждения заказа или свежесть каталога.
SLO задаёт допустимый уровень этого качества за период.
Условие алерта превращает измерение в решение: какое отклонение считать значимым, как долго оно должно продолжаться и какие исключения применить.
Page - это уже обещание организации: событие срочное, у него есть владелец, а получатель может выполнить осмысленное действие прямо сейчас. Дальше будем называть такой сигнал вызовом дежурного.
Из этой последовательности следует важное ограничение:
Не каждая наблюдаемая метрика должна иметь алерт, не каждый алерт должен создавать уведомление и не каждое уведомление должно будить человека.
Дашборд подходит для исследования и долгосрочного тренда. Задача или тикет - для проблемы, которая требует работы, но может подождать. Вызов дежурного нужен, когда промедление увеличивает ущерб быстрее, чем команда успевает исправить его в рабочее время. Повторяемое и безопасное действие лучше автоматизировать, сохранив видимость результата автоматизации.
Сигнал | Пример | Реакция |
|---|---|---|
Пользовательский сценарий быстро деградирует | Ошибки оплаты расходуют месячный error budget за часы | Вызов дежурного |
Риск растёт медленно | Диск заполнится через несколько дней | Задача или рабочее уведомление |
Событие полезно только для диагностики | Перезапустился один pod один раз, сервис сохранил SLO | Дашборд или лог |
Ответ полностью детерминирован | Зависший stateless-процесс можно безопасно перезапустить | Автоматическое действие и аудит |
Начинаем не с серверов, а с пользовательского сценария
Рассмотрим сервис checkout. Бизнесу важно, чтобы покупатель мог оформить и оплатить заказ. Начать можно с карты результата:
```text
Пользователь начал checkout
|
v
Заказ создан -> платёж подтверждён -> заказ передан в исполнение
| | |
v v v
API платёжный шлюз очередь
| | |
+---------- PostgreSQL ----------------+Верхняя строка описывает результат для пользователя и бизнеса. Нижняя помогает искать причину. Если поменять их местами, получится десяток вызовов от CPU, pod, базы и очереди во время одного сбоя.
Для каждого критичного сценария полезно письменно ответить на вопросы:
Как выглядит успешная операция с точки зрения пользователя?
Что считать валидной попыткой, а что исключить: тестовый трафик, отмену самим клиентом, антифрод или некорректный запрос?
Какой объём ошибок допустим и за какой период?
Как быстро растёт ущерб при нарушении?
Какое действие может выполнить дежурный?
Кто владеет всем сценарием, если он проходит через несколько сервисов?
Ответы становятся контрактом SLI. Например:
checkout_success_ratio =
успешно оплаченные заказы / валидные попытки оформления
```Счётчик orders_per_minute тоже нужен, но сам по себе он хуже подходит для срочного алерта. Его значение зависит от времени суток, дня недели, рекламы и сезона. Отношение успехов к попыткам ближе к качеству сервиса, хотя и ему нужен минимальный объём выборки: одна неудача из одной попытки даст 100% ошибок.
Если попытки исчезли полностью, отношение вообще нельзя посчитать. Это отдельный класс события. Причиной может быть отсутствие спроса, сломанная телеметрия, недоступный frontend или сбой раньше в воронке. Поэтому рядом нужны проверка свежести данных и независимая синтетическая проверка критичного пути. Нулевое значение и отсутствие данных — разные состояния.
Порог выбирают по типу сигнала
Один способ детектирования не подходит для всех метрик.
Фиксированный порог
Он хорош там, где есть физическая или контрактная граница: свободное место, возраст очереди, срок действия сертификата, исчерпание пула соединений. Порог следует связывать со временем до ущерба. Формулировка «места осталось на четыре часа» полезнее, чем «диск заполнен на 80%»: четыре терабайта свободного места и четыре гигабайта требуют разной реакции.
Error budget и burn rate
Для пользовательской надёжности лучше оценивать скорость расходования допустимого бюджета ошибок. При SLO 99,9% за 30 дней постоянные 0,1% ошибок соответствуют burn rate 1: бюджет закончится ровно к концу периода. Burn rate 10 израсходует его примерно за три дня, а 1 000 — примерно за 43 минуты.
Google SRE Workbook предлагает как отправную точку несколько окон:
Расход error budget | Длинное окно | Короткое окно | Burn rate | Реакция |
|---|---|---|---|---|
2% | 1 час | 5 минут | 14,4 | Вызов дежурного |
5% | 6 часов | 30 минут | 6 | Вызов дежурного |
10% | 3 дня | 6 часов | 1 | Задача |
Для каждой строки порог одновременно проверяется на обоих окнах. Короткое окно позволяет быстро снять алерт после восстановления, длинное подтверждает значимый расход бюджета. Медленное, но устойчивое ухудшение создаёт задачу на рабочее время. Эти числа не являются универсальным стандартом: их нужно согласовать с SLO, трафиком и допустимой нагрузкой на дежурство.
Упрощённая запись SLI для Prometheus может выглядеть так:
groups:
- name: checkout-sli
rules:
- record: checkout:sli_errors_per_attempt:ratio_rate5m
expr: |
sum(rate(checkout_attempts_total{
environment="production", result="failed"
}[5m]))
/
sum(rate(checkout_attempts_total{
environment="production"
}[5m]))
- record: checkout:attempts:rate5m
expr: |
sum(rate(checkout_attempts_total{
environment="production"
}[5m]))В реальной конфигурации понадобятся такие же recording rules для остальных окон и защита минимального трафика. Смысл примера не в готовом пороге, а в порядке: сначала формализуем пользовательский результат, затем считаем долю неуспеха, после этого применяем окна и политику доставки.
Относительное изменение и аномалия
Для заказов, регистраций, поездок и других сезонных бизнес-метрик статический порог быстро устаревает. Здесь полезнее сравнивать значение с ожидаемым диапазоном для того же времени суток и дня недели, учитывать тренд, праздники, акции и размер выборки.
LinkedIn в ThirdEye отдельно фильтрует слишком малые и нерелевантные срезы, выбирает алгоритм под характер ряда и объединяет близкие аномалии. Это важнее конкретного алгоритма. Самая сложная модель будет шуметь, если ей передать смешанные регионы, неполные данные или не сообщить о запланированной акции.
Аномальность также не равна срочности. Необычно высокая выручка — аномалия, но обычно не авария. Падение конверсии на 20% может требовать вызова дежурного при достаточном трафике и подтверждении другими сигналами, а отклонение на редком региональном срезе — только задачи для аналитика.
Составное условие
Хороший бизнес-алерт часто объединяет несколько фактов:
конверсия ниже ожидаемого диапазона
AND попыток достаточно для вывода
AND отклонение длится 10 минут
AND данные свежие
AND сейчас нет согласованного maintenance или эксперимента
Составное условие уменьшает шум, но у него есть цена: чем больше фильтров, тем легче пропустить реальный инцидент. Поэтому его нужно проверять на истории, проигрывать на известных сбоях и отдельно наблюдать за качеством входных данных.
Причина должна помогать диагностике, а не создавать ещё один инцидент
Допустим, из-за отказа PostgreSQL одновременно выросли 5xx у checkout, задержка платежей, lag очереди и ошибки сервиса заказов. Четыре команды могут получить четыре вызова об одной причине.
Здесь нужны три разных механизма:
Агрегация определяет гранулярность проблемы. Если человек устраняет деградацию сервиса целиком, десятки экземпляров и региональных SLI следует показать внутри одной группы, а не как независимые вызовы.
Дедупликация не даёт повторным вычислениям одного правила создавать новые проблемы. Для неё идентифицирующие labels должны оставаться стабильными; текущий процент ошибок следует помещать в annotations.
Подавление по зависимостям убирает ожидаемые симптомы, когда известна первопричина. GitLab описывает, как зависимости сервисов используются для inhibition в Alertmanager: если деградировал patroni, отдельные вызовы от зависящих api и web-pages не помогают дежурному.
Подавление опасно настраивать слишком широко. Ошибка в базе и независимый баг API могут произойти одновременно. Поэтому зависимости должны храниться как код, проверяться и применяться только к понятным парам сигналов. В уведомлении о корневой проблеме при этом стоит показать затронутые пользовательские симптомы.
У алерта должен быть контракт
Перед включением вызова полезно заполнить короткую карточку. Если на половину вопросов нет ответа, правило пока готово для дашборда или тестового канала, но не для ночного дежурства.
Поле | Вопрос |
|---|---|
Пользовательское влияние | Какой сценарий нарушен и как это измерено? |
Срочность | Почему нельзя дождаться рабочего времени? |
Условие | Какие окно, порог, минимальный объём и |
Владелец | Какая команда способна выполнить первое действие? |
Действие | Что дежурный проверяет или меняет в первые пять минут? |
Контекст | Где дашборд, runbook, последние изменения и связанные сервисы? |
Завершение | Как понять, что пользователи восстановились и алерт должен закрыться? |
Исключения | Maintenance, тесты, drained-трафик, праздники, эксперименты? |
Проверка | На каких прошлых инцидентах и нормальных периодах правило проверено? |
Для передачи между системами контракт нужно выразить в стабильных полях. Минимальный набор labels обычно содержит service, team, environment, severity и alertname. Полезные annotations — краткое описание влияния, текущее значение, ссылки на дашборд и runbook.
labels:
severity: critical
service: checkout
team: commerce
environment: production
alert_class: slo_burn
annotations:
summary: "Checkout быстро расходует error budget"
description: "Доля неуспешных попыток превышает допустимый burn rate."
dashboard_url: "https://grafana.example.com/d/checkout"
runbook_url: "https://runbooks.example.com/checkout/slo-burn"Runbook не должен пересказывать устройство всей платформы. Для дежурного полезнее короткая последовательность: как подтвердить влияние, какие изменения и зависимости проверить, какое безопасное действие доступно, когда эскалировать и в каких известных случаях сигнал бывает ложным.
Где в этой схеме находится nxs-anomaly
nxs-anomaly не определяет, является ли падение конверсии аномалией, и не заменяет Prometheus, SLO-платформу или анализатор бизнес-рядов. Граница ответственности выглядит так:
Бизнес-события и технические метрики
|
v
Prometheus / SLO rules / anomaly detector
выбор сигнала, окна, порога и severity
|
v
Alertmanager
grouping, inhibition, silence, routing
|
v
nxs-anomaly
нормализация, группа, команда, расписание,
цепочка эскалации, ACK, доставка и история
|
v
Дежурный -> диагностика -> действие -> resolveВ предыдущей статье цикла мы подробно разобрали этот путь на примере Alertmanager webhook. Для методологии важны несколько границ.
Во-первых, признаки маршрутизации должны появиться до nxs-anomaly. Если team=commerce добавлен только преобразованием после выбора маршрута, он не сможет задним числом изменить уже сделанный выбор.
Во-вторых, группировка транспорта и группировка человеческой проблемы - не всегда одно и то же. Один webhook Alertmanager может содержать несколько элементов с разными fingerprints. Нужно заранее решить, ожидается ли одна проблема на сервис, регион, пользовательский сценарий или экземпляр.
В-третьих, repeat_interval не заменяет эскалацию. Повторная отправка снова обращается к тому же получателю, а цепочка эскалации меняет адресата: текущий дежурный, резервный инженер, затем команда. Для критичного checkout-сценария политика может выглядеть так:
T+0 уведомить дежурного Commerce
T+5 если нет ACK — уведомить резервного
T+15 если нет ACK — подключить всю команду
Расписание, каналы и сама цепочка тоже являются частью надёжности. У правила может быть идеальная precision, но это бесполезно, если смена не покрыта, Telegram-токен истёк или worker доставки остановился. Поэтому нужно отдельно мониторить heartbeat источников, покрытие расписаний, задержку первой успешной доставки и ошибки провайдеров.
Алертинг нужно измерять как продукт
Порог однажды попал в Git - работа только началась. Трафик меняется, сервисы переезжают, команды реорганизуются, а авария прошлого квартала превращается в штатно переживаемый отказ.
Cloudflare описывает полезный подход: сохранять жизненный цикл алертов, строить обзоры по командам и компонентам, искать флапинг метрик (состояние, когда значение метрики постоянно и быстро меняется, пересекая пороговое значение туда и обратно в течение короткого промежутка времени), правила без получателя, забытые проверки удалённых кластеров и ошибки метрик ингибирования (inhibition metrics errors - это погрешности, неточности или ложные результаты, которые возникают при измерении степени подавления (ингибирования) какого-либо процесса). Такой разбор превращает фразу «pager опять шумит» в список конкретных изменений.
В Community Edition nxs-anomaly для такого разбора доступны таймлайны групп, история доставки и аудит. Enterprise Edition может экспортировать события жизненного цикла через Kafka в аналитический контур. Но продуктовые SLI и независимый реестр пользовательских инцидентов всё равно должны приходить из своих источников: система реагирования не может восстановить их из факта отправки уведомления.
Для регулярного обзора полезны следующие показатели:
количество срочных вызовов на час дежурства и распределение по времени суток;
доля событий, после которых действительно потребовалось действие;
самые частые, долго активные и повторно открывающиеся группы;
доля эскалаций и время от первой успешной доставки до ACK;
задержки и ошибки каналов доставки;
пробелы в расписаниях и события без владельца;
правила без runbook и ссылки на дашборд;
инциденты, о которых сначала сообщил пользователь, а не мониторинг.
Последний пункт особенно важен. По одному журналу алертов нельзя посчитать recall: в нём нет инцидентов, которые система пропустила. Нужен независимый реестр пользовательских инцидентов или подтверждённых интервалов влияния. По той же причине время от открытия до закрытия группы нельзя автоматически называть временем восстановления сервиса. Группу мог закрыть оператор позже фактического восстановления или, наоборот, закрыть до того, как пользовательский SLI пришёл в норму.
Скорость ACK тоже не должна превращаться в рейтинг инженеров. Она помогает найти проблемы доставки, покрытия и эскалации. Качество технического решения оценивают по восстановлению пользовательского сценария и последующей работе с причиной.
Практический цикл обзора может быть таким:
Каждую неделю разобрать самые частые и самые дорогие вызовы.
Для каждого события отметить: реальная проблема, требовалось ли действие, помог ли runbook, была ли выбрана правильная команда.
Для ложного или несрочного вызова выбрать одно изменение: порог, окно, агрегация, inhibition, автоматизация либо перевод в задачу.
После каждого значимого инцидента проверить не только «почему не сработал алерт», но и «какие вызовы были лишними».
Удалять правила вместе с сервисами и пересматривать контракт при изменении архитектуры или SLO.
Если алерт регулярно получает один и тот же механический ответ, это кандидат на автоматизацию. Если его регулярно игнорируют как безопасный, это дефект правила. Если его нельзя связать с владельцем и действием, это пока диагностическая метрика, а не вызов дежурного.
Минимальный план внедрения
Необязательно переписывать все правила за один проект. Начать можно с одного критичного пользовательского пути.
Выберите сценарий с понятным бизнес-результатом, например оплату заказа.
Определите валидную попытку, успех и источник данных.
Задайте SLI и договоритесь о SLO с владельцем продукта и сервиса.
Добавьте проверку свежести данных и минимального трафика.
Разделите быстрый burn rate для вызова дежурного и медленный для задачи.
Сформируйте стабильные labels, runbook и дашборд.
Настройте группировку и зависимости, затем маршрут, расписание и эскалацию в nxs-anomaly.
Проверьте всю цепочку тестовым событием:
firing, доставка, ACK, эскалация иresolved.Через неделю и после первого инцидента пересмотрите фактический шум и полезность.
Такой подход не уменьшает наблюдаемость. Метрик, логов и трассировок может стать даже больше. Он уменьшает число решений, которые без необходимости перекладываются на сонного человека.
Правильный алерт сообщает не «на одном сервере что-то изменилось», а «критичный пользовательский результат под угрозой, ждать нельзя, вот команда и первое осмысленное действие». Prometheus и анализаторы аномалий находят отклонение, Alertmanager связывает события, а nxs-anomaly доводит проблему до конкретного дежурного и контролирует эскалацию. Доверие появляется, когда вся эта цепочка регулярно проверяется — от смысла метрики до факта человеческой реакции.
На этом все. В следующей статье мы подробно рассмотрим мы рассмотрим настройку всех элементов nxs-anomaly подробно, заверенем их в Terraform провайдер и получим наш первый алерт. Полезные ссылки:
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.