Коротко. Покрытие собирается по четырём слоям: хосты, платформа, хранилища состояния, прикладной слой; пропуск любого даёт «всё зелёное, а работать нельзя». Пороги снимаются с собственной системы, выдержка подбирается по штатному поведению, расписание учитывается в самом признаке, а не заглушкой. Мониторинг наблюдает и за собой: ошибки правил, доставка уведомлений и внешний сигнал живости обязательны, иначе его отказ выглядит ровно как тишина.

Проверить свой мониторинг можно одним вопросом: о скольких из последних пяти аварий он сообщил раньше пользователей. Если ответ «ни об одной» или «не знаю», дальше обычно обнаруживаются правила по несуществующим метрикам, серверы без экспортёров и заглушенный чат с сотней сообщений в сутки. Разбираем, что снимать с инсталляции RX по слоям, какие правила срабатывают по делу, а какие шумят или молчат годами, и как проверить всё это за один день.

Симптом

  • Об инциденте сообщают пользователи, а в мониторинге за это время не сработало ни одного правила.
  • В чате или почте десятки алертов в сутки, реакция — на единицы. Дежурный отключил уведомления, и формально мониторинг есть.
  • После разбора аварии выясняется, что правило на этот случай было, но ссылалось на метрику, которой в вашей сборке экспортёра нет: она переименована, отдаётся другим endpoint или у неё нет метки, по которой шёл фильтр. Правило не могло сработать ни разу за всё время.
  • Экспортёр на одном из серверов не отвечает несколько месяцев, и это обнаруживается случайно. По этому серверу мониторинг был слеп, но выглядел как зелёный: нет метрик — нет и превышений порога.
  • Первопричину аварии в метриках не видно вовсе, видны только следствия: перезапуски сервисов, таймауты, недоступность.

Почему так

Мониторинг это три разные задачи, которые обычно решают как одну.

Покрытие — что снимаем и с чего. Собирается снизу вверх по слоям, и на каждом слое свои инструменты. Пропущенный слой не виден по дашбордам: они показывают то, что есть, и молчат о том, чего нет.

Правила — когда будить. Метрика может быть, а правило по ней либо не срабатывает никогда (неверное выражение, несуществующая метка), либо срабатывает постоянно (порог взят «на глаз», не учтено штатное расписание). Оба состояния выглядят одинаково безобидно, пока не случится авария.

Доставка — кому, куда и с каким текстом. Алерт без указания влияния и первых шагов бесполезен ночью: получатель не может отличить «встал приём документов» от «сайдкар с метриками не отвечает».

И четвёртое, о чём вспоминают последним: мониторинг сам является системой, которая ломается. Экспортёр падает, конфигурация правил не перезагружается после ошибки, канал доставки отваливается, а сервер мониторинга живёт на той же площадке, что и наблюдаемый контур. Всё это выглядит как тишина, то есть как «всё хорошо».

Что снимать: четыре слоя

Слой Чем снимают Что ловит Чего в нём не видно
Хосты и ОС node_exporter (или аналог для Windows) CPU, память, диски, иноды, состояние служб, сеть, время что именно происходит внутри СУБД, брокера, сервисов
Платформа метрики кластера и планировщика, состояние узлов, обратный прокси перезапуски, нехватка лимитов, недоступность узла, доля ошибок на входе причина перезапуска
Хранилища состояния экспортёры СУБД, брокера, объектного хранилища, поискового движка блокировки, репликация, очереди, свободная ёмкость, состояние кластера связь с конкретной операцией пользователя
Прикладной слой конечные точки здоровья сервисов, метрики среды выполнения, логи как источник метрик долгие операции, ошибки методов, зависшие блокировки объектов инфраструктурная причина

Слои не заменяют друг друга. Инфраструктурные метрики отвечают на вопрос «почему», прикладные — на вопрос «что именно сломалось у людей». Мониторинг только снизу приводит к «всё зелёное, а работать нельзя»; мониторинг только сверху — к «плохо, а почему, непонятно».

Хосты

Базовое покрытие очевидно; ниже — только то, что регулярно забывают:

  • Инодов может не хватить раньше, чем места. Каталоги с мелкими файлами, кешами и распакованными архивами выедают их незаметно.
  • Отдельные точки монтирования — отдельные правила. У раздела под архив журналов транзакций и у раздела под резервные копии другая логика заполнения и другая цена переполнения, чем у корневого раздела. Общее правило «мало места на диске» их размывает.
  • Состояние служб. Правило «любая служба в состоянии failed» ловит то, чего нет ни в одном белом списке: упавший агент сбора логов, отвалившийся экспортёр, сломанный таймер. Перед включением стоит расчистить те, что уже в failed, иначе алерт зависнет с первого дня.
  • Утилизация диска по операциям, а не только по объёму. Диск может быть наполовину пуст и при этом упираться в квоту по IOPS — для компонентов, чувствительных к задержке записи, это отказ. Метрика насыщения диска по времени обслуживания запросов показывает это раньше, чем начнут падать зависимые сервисы.
  • Расхождение времени. Ломает единый вход, подписи и корреляцию логов между узлами.
  • Steal в виртуальной среде. Показывает, что нагрузка не ваша, а на стороне гипервизора: разбор упрётся в облако, а не в код.

Платформа

В кластере минимальный набор такой: узлы и их готовность, контейнеры в состояниях ожидания запуска (недоступный образ, цикл падений, ошибка конфигурации), принудительные завершения по памяти, приближение к лимиту памяти, свободное место в томах, доля ошибок 5xx на входном прокси. Практический пример, почему нужен именно контейнерный слой: если публикующая сторона убирает теги образов из общедоступного реестра, поды не поднимаются после первого же перезапуска, а по инфраструктурным метрикам всё в порядке.

Отдельно — хранилище состояния кластера. Задержка синхронной записи журнала и времени фиксации транзакций у него читается как первопричина: когда диск под ним начинает отвечать за сотни миллисекунд вместо единиц, кластер теряет лидера и утаскивает за собой планировщик, контроллеры и операторов. В метриках при этом видны только следствия — циклы перезапусков подов, по которым причина не восстанавливается. Правило на задержку записи ставится сразу, с порогом, снятым с вашего же здорового кластера.

Без кластера роль этого слоя выполняют состояние служб, обратный прокси и его коды ответов.

СУБД, брокер, хранилище, поиск

PostgreSQL. Стандартный экспортёр даёт доступность, число соединений относительно предела, дедлоки, попадание в кеш, отставание реплики, состояние архивации журналов. Этого мало для документооборота, и обычно добавляют собственные запросы, отдающие метрики: возраст самой длинной открытой транзакции, длительность ожидания на тяжёлых блокировках, фактический состав репликации (кто реально подключён, а не кто должен быть), утилизацию журнала предзаписи, роль узла и верхушку pg_stat_statements. Три подводных камня:

  1. Тяжёлые коллекторы бьют по базе. Сбор размера каждой базы или обход всех таблиц на каждом опросе стоит дороже, чем даёт. Такие метрики снимают редко и кешируют на стороне экспортёра, а не опрашивают раз в пятнадцать секунд.
  2. Встроенные коллекторы отваливаются на новых мажорных версиях. Системные представления переименовываются, коллектор молча перестаёт отдавать метрику, правило по ней перестаёт срабатывать. После обновления СУБД правила по ней проверяют заново.
  3. Метка, которой нет. Классическая мёртвая проверка — правило по ожиданиям на блокировках, написанное по метрике, у которой нужной метки нет вовсе. Выражение синтаксически корректно, результат всегда пуст.

RabbitMQ. Глубина очередей, число потребителей, состояние блокировок по памяти и диску, число очередей, состав кластера. Подробный разбор — в отдельной статье «RabbitMQ в Directum RX: очередь растёт, задания не двигаются». Важная тонкость сбора: если экспортёр или сервер мониторинга ходят к кластеру через общий адрес, каждый опрос попадает на случайный узел, а метрики по конкретной очереди приезжают с провалами. Лечится не «убрать шумное правило», а взятием худшего значения за окно в несколько опросов.

Объектное или файловое хранилище. Диски вне строя, свободная полезная ёмкость (не сырая), ошибки репликации между площадками. Нередко правила на такое хранилище написаны по метрикам, которых нет: их отдаёт не тот endpoint, который добавили в сбор. Проверяется за минуту — запросом метрики в интерфейсе мониторинга.

Полнотекстовый поиск. Состояние кластера, заполнение кучи, свободное место. При достижении порога свободного места поисковый движок переводит индексы в режим только для чтения, и индексация останавливается тихо.

Резервные копии. Возраст последней успешной копии — метрика, а не строчка в журнале задания. Реализуется маленьким экспортёром или файлом с метриками, который читает агент. Без неё сломанное копирование обнаруживается в день, когда оно понадобилось.

Сервисы RX и пользовательский опыт

  • Живость каждого сервиса по его конечной точке здоровья, а не по факту «процесс запущен». Процесс живой и не работающий — штатное состояние при потере доступа к базе или брокеру.
  • Метрики среды выполнения .NET (сборка мусора, потоки, память) — не для алертов, а для разбора жалоб на «тормозит». Если снимаются сайдкаром, стоит помнить, что после релиза они ломаются пачкой: это один инцидент, а не двадцать.
  • Входной прокси: доля 5xx и задержка по маршрутам. Ближайшая к пользователю числовая характеристика.
  • Логи как источник метрик. Длительность прикладных операций, доля неуспешных вызовов интеграционных методов, блокировки объектов, висящие часами, ошибки фоновых заданий. Именно эти сигналы совпадают с формулировками пользовательских жалоб, и по ним имеет смысл строить два-три прикладных правила.
  • Синтетическая проверка: раз в несколько минут логин и открытие карточки. Отвечает на вопрос «система работает?» одним числом.

Какие алерты будят не зря

Набор, который закрывает большую часть реальных отказов. Формулировки словами, пороги подбираются под инсталляцию.

Правило Почему срабатывает по делу
Цель сбора не отвечает дольше нескольких минут самое дешёвое и самое пропускаемое правило; без него слепые пятна живут месяцами
Служба в состоянии failed ловит то, что не попало ни в один явный список
Свободного места меньше порога и отдельно: раздел вырос больше чем на N за час порог даёт часы, скорость роста даёт сутки
СУБД недоступна; соединения у предела; архивация журналов падает каждая из трёх приводит к остановке работы целиком
Транзакция открыта дольше N минут; ожидание на блокировке дольше N предшествует жалобам на «зависло сохранение»
Всплеск дедлоков относительно обычного уровня показывает, стало ли лучше после правок
Отставание реплики по времени и по объёму одно без другого врёт при простое записи
У рабочей очереди нет потребителей; очередь растёт непрерывно; активна блокировка брокера см. статью про очередь
Возраст последней успешной резервной копии больше N единственный способ узнать о сломанном копировании заранее
Задержка синхронной записи на узлах хранилища состояния кластера первопричина, а не следствие
Доля 5xx выше X при потоке запросов не ниже Y нижняя планка трафика убирает ночной шум от единичных ошибок
Ошибки вычисления правил и перезагрузки конфигурации мониторинга правило с ошибкой молчит и выглядит как «всё хорошо»
Сервер уведомлений недоступен; ошибки доставки иначе о поломке канала узнают, когда он понадобится

Приёмы, которые убирают ложные срабатывания

Порог считают от измеренного фона, а не назначают. Неделя наблюдений даёт нормальный диапазон; порог ставится заметно выше него, но заметно ниже уровня, на котором система разрушается. Пороги «90% CPU» и «10% диска» из чужих наборов правил — только стартовая точка.

Выдержку (for) подбирают по штатному поведению компонента. Очередь без потребителя пару минут — норма, полчаса — уже нет. Слишком короткая выдержка даёт шум на каждом всплеске, слишком длинная — опоздание к моменту, когда уже позвонили пользователи.

Сравнивают с порогом, а не с абсолютным значением. Правило «занято больше 80% от лимита» переживает изменение лимита, правило «занято больше N гигабайт» — нет, и однажды тихо перестаёт значить то, что задумано.

Учитывают расписание, иначе оно даёт ложные срабатывания по дизайну. Пример: если инкрементные копии делаются шесть дней в неделю, а на седьмой вместо них полная, то правило «возраст последней инкрементной копии больше суток» будет гореть каждые выходные, даже когда всё отработало штатно. Лечится не заглушкой на выходные, а сменой признака: смотреть возраст свежайшей копии любого типа. Такая же ловушка — регламентные окна обновлений и ночные задания.

Фильтруют структурно, а не списком имён. Временные очереди, короткоживущие поды и служебные объекты отсекаются по форме имени (суффикс-хеш, идентификатор экземпляра), а не перечислением. Список стендов и сервисов устаревает через неделю, форма имени — нет.

Ставят условие живости соседа. Не будить по компоненту выключенного контура: правило срабатывает, только если рядом есть хоть что-то живое. Контур включили — алерты вернулись сами, править ничего не нужно. То же самое делает метка «мониторинг отключён» на узле, который гасят намеренно: она честнее, чем закомментированное правило.

Сводят однотипное в один алерт. Двадцать одинаковых сообщений после релиза — это один инцидент. Сводное правило («недоступно N целей такого-то типа») читается, двадцать отдельных — нет.

Особая осторожность у правил о самом канале доставки. Они доставляются тем же каналом, о поломке которого сообщают, поэтому цена ложного срабатывания у них выше обычной: одна медленная отправка при коротком дедлайне уведомления способна раскрутиться в петлю на несколько часов и сотни неудачных доставок. Порог здесь — «больше нескольких неудач за окно», а не «любая одна».

Текст правила пишется для того, кого разбудят. Три обязательные части: что именно произошло, на что это влияет для пользователей, первые три шага. Без второй части ночной дежурный не отличит остановку приёма документов от неработающего сайдкара с метриками.

Информационные уведомления живут отдельно. «Копия создана», «релиз выкачен» — это отдельный маршрут и отдельный канал, причём без сообщений о «восстановлении»: то, что никогда не было проблемой, не может разрешиться.

Диагностика: аудит своего мониторинга за один день

Проверка не требует доступа к прикладной части и делается по существующей установке.

1. Слепые пятна. Сколько целей сбора не отвечает прямо сейчас и сколько заданий сбора не покрыто ни одним правилом доступности.

# цели, которые не отвечают
curl -s --data-urlencode 'query=up == 0' "$PROM/api/v1/query" \
  | jq -r '.data.result[] | "\(.metric.job) \(.metric.instance)"' | sort -u

Если веб-интерфейс закрыт базовой аутентификацией, добавляется -u; выражение передаётся через --data-urlencode, иначе сравнение в строке запроса придётся экранировать вручную.

Ответ «ноль недоступных» ничего не доказывает, пока не сверен список того, что вообще должно опрашиваться, со списком серверов и сервисов в инвентаре. Отсутствие цели выглядит точно так же, как её исправная работа.

2. Мёртвые правила. Прогнать выражения всех правил на здоровой системе и выписать те, что возвращают пустоту всегда. Пустой результат сам по себе нормален (условие не выполняется), поэтому кандидатов проверяют вручную: существует ли метрика, есть ли у неё метки, по которым идёт фильтр. Быстрый способ отсечь заведомо мёртвые — проверить, что метрика без условий вообще возвращает серии. Это находка номер один почти в каждом аудите.

3. Здоровье самого мониторинга. Есть ли правила на ошибки вычисления правил, на неудачную перезагрузку конфигурации, на недоступность сервера уведомлений и на ошибки доставки. Ошибка в одном правиле способна ронять вычисление целой группы, и без такого метаправила это остаётся незамеченным.

4. Тест по прошлым инцидентам. Взять три-пять последних аварий и по каждой ответить: какое правило должно было сработать, сработало ли, за сколько до жалобы пользователей. Единственный честный тест покрытия.

5. Топ шума. Ранжировать алерты за месяц по числу срабатываний и сверить с тем, на какие реально реагировали.

# самые шумные алерты за неделю
curl -s --data-urlencode 'query=sort_desc(count by (alertname) (count_over_time(ALERTS{alertstate="firing"}[7d])))' \
  "$PROM/api/v1/query" | jq -r '.data.result[] | "\(.value[1])\t\(.metric.alertname)"' | head -20

Две оговорки, без которых список врёт. Первая: окно не должно превышать реальную глубину хранения. Если она задана размером, а не временем, фактический горизонт обычно заметно меньше номинального и меняется вместе с объёмом метрик; запрос за 30 дней при десяти днях данных не выдаст ошибку — он молча посчитает по тому, что нашлось. Глубину стоит посмотреть отдельно, прежде чем выбирать окно. Вторая: считаются точки ряда, то есть суммарное время в состоянии firing, а не число отдельных срабатываний. Для ранжирования шума этого достаточно, для отчётности «сколько раз будили» — нет.

Первые пять строк этого списка и есть причина, по которой чат заглушен.

6. Доставка. Отправить тестовое уведомление по каждому маршруту. Отдельно ответить, кто получает сообщения ночью и в выходные и что он должен с ними делать.

7. Дрейф конфигурации. Сверить конфигурацию на сервере с тем, что лежит в репозитории. Типовая находка — живой конфиг на несколько месяцев старше репозитория, с ручной правкой, о которой никто не помнит, и первая же плановая раскатка её снимает.

Что сделать

  1. Составить карту покрытия по четырём слоям и отметить, чем снимается каждая клетка. Пустые клетки — это и есть план работ; их видно только на бумаге, дашборды о них молчат.
  2. Включить страховочное правило доступности целей для всех заданий сбора, у которых нет собственного правила. Пишется как исключение («все, кроме перечисленных»), а не перечислением: новое задание сбора попадает под наблюдение автоматически.
  3. Снять фон за неделю и расставить пороги от него. До этого момента любые пороги — чужие.
  4. Ограничить критический уровень. Десять-пятнадцать правил, каждое из которых означает «работа людей остановлена или скоро остановится». Всё остальное — предупреждения в отдельный канал и на дашборд разбора. Критическим считается то, ради чего допустимо разбудить.
  5. Дописать тексты правил: влияние на пользователей и первые три шага. Это самая дешёвая работа с самым заметным эффектом на скорость реакции.
  6. Закрыть метамониторинг и добавить внешний сигнал живости: постоянно активное правило, которое шлёт сигнал во внешний сервис. Пропал сигнал — упал сам мониторинг. Без этого отказ мониторинга неотличим от тишины.
  7. Держать конфигурацию мониторинга в репозитории и раскатывать её кодом. Правила, дашборды и маршруты доставки — такой же артефакт, как код; ручная правка на сервере теряется при следующей раскатке.
  8. Раз в квартал возвращаться к списку по инцидентам: что сработало, что промолчало, что шумит. Набор правил живёт вместе с системой, а не пишется один раз.

Чего не делать

  • Заглушать шумный алерт вместо исправления признака. Заглушка переживёт того, кто её поставил, и снимет наблюдение вместе с шумом.
  • Заводить правило, не проверив, что метрика существует в вашей сборке экспортёра. Правило по несуществующей метрике или метке не даёт ошибок и не срабатывает никогда — самый опасный вид тишины.
  • Делать всё критическим. Если критично всё, не критично ничего; через месяц канал заглушен, и это уже не вопрос дисциплины.
  • Строить дашборд вместо алерта. Дашборд нужен для разбора, алерт — для обнаружения. Ночью на дашборд никто не смотрит.
  • Мониторить факт запуска процесса и считать это проверкой сервиса. Процесс жив, база недоступна, пользователи не работают.
  • Держать мониторинг только внутри наблюдаемого контура. Отказ площадки уносит и наблюдаемую систему, и наблюдателя. Минимум — внешний сигнал живости.
  • Копировать чужой набор правил целиком. Половина не сработает из-за других версий и метрик, вторая половина будет шуметь из-за чужих порогов, и разбираться в этом придётся во время аварии.