Политика уведомлений
Обещание DumbMonit в том, что уведомление стоит того, чтобы его прочитать. Движок оповещений снижает уровень шума до того, как оповещение может заговорить (подавление по зависимости, группировка, окна обслуживания); политика уведомлений снижает его после — по каждому каналу. Ничего не требует настройки: приведённые ниже значения по умолчанию работают из коробки.
Конвейер в одном списке
Заголовок раздела «Конвейер в одном списке»evaluate (hysteresis, per-device overrides) → deduplicate → suppress by dependency → silence → group by device → flap hold → channel severity filter → channel routing filter → resolved on/off → cooldown → quiet hours → batch window → hourly cap → send (+ deep link) ↘ nobody acknowledged → escalation channel| Этап | Где настраивается | По умолчанию |
|---|---|---|
| Порог очистки (гистерезис) | Редактор правил → Clear below / above | нет (CPU: 85 %, диск: 88 % во встроенных правилах) |
| Переопределения для монитора | Редактор правил → Per-device overrides | нет |
| Обнаружение дребезга | Параметры → Уведомления и отчёты → Политика уведомлений → Дополнительные параметры | 4 изменения за 30 мин, удержание 30 мин |
| Минимальная серьёзность | Канал → Параметры доставки → Send | все |
| Сообщать, когда прошло | Канал → Параметры доставки | включено |
| Минимальный интервал на оповещение | Канал → Параметры доставки | нет |
| Тихие часы | Канал → Параметры доставки | выключено |
| Фильтр маршрутизации (теги, тип, правило) | Канал → Параметры доставки → Only some alerts | выключено (канал слышит всё) |
| Эскалация, если никто не подтвердил | Параметры → Уведомления и отчёты → Политика уведомлений | выключено |
| Окно группировки | Параметры → Уведомления и отчёты → Политика уведомлений | 60 с |
| Сообщений на канал в час | Параметры → Уведомления и отчёты → Политика уведомлений | 20 |
| Публичный URL (глубокие ссылки) | Параметры → Уведомления и отчёты → Политика уведомлений, или DUMBMONIT_PUBLIC_URL | пусто |
Гистерезис и переопределения для монитора
Заголовок раздела «Гистерезис и переопределения для монитора»Правило, которое срабатывает выше 90 % и сбрасывается в момент, когда значение
опускается ниже 90 %, будет срабатывать и сбрасываться весь вечер при CPU,
колеблющемся в районе 89–91 %. Задайте ему порог очистки: после срабатывания
оповещение сбрасывается только когда значение опускается ниже него (для правил
«срабатывает выше») или поднимается выше него (для правил «срабатывает ниже»).
Поле API — clear_threshold у правила; сервер отклоняет порог очистки, заданный
с неверной стороны от порога срабатывания.
Переопределение для монитора меняет порог или порог очистки для одного монитора, или отключает правило для него, без дублирования самого правила:
PUT /api/alerts/rules/{id}/overrides/{target_id}{ "threshold": 97, "clear_threshold": 95 } # или { "enabled": false }GET /api/alerts/rules/{id}/overridesGET /api/alerts/overrides?target_id=7 # все переопределения одного монитораDELETE /api/alerts/rules/{id}/overrides/{target_id}Переопределение со всеми пустыми полями удаляется. Сообщения указывают порог, который был фактически применён.
Обнаружение дребезга
Заголовок раздела «Обнаружение дребезга»Независимо от правила, оповещение, чей отпечаток сработал или сбросился 4 раза
за 30 минут, считается дребезжащим: отправляется одно уведомление («дребезг:
4 изменения за 30 мин, уведомления удержаны на 30 мин»), и больше ничего об этом
оповещении не отправляется до конца удержания. Решение после окончания удержания
всё равно объявляется. Настройте или отключите это в Параметры → Уведомления и отчёты →
Политика уведомлений → Дополнительные параметры (flap_events,
flap_window_secs, flap_hold_secs; flap_events: 0 отключает функцию).
Параметры доставки для каждого канала
Заголовок раздела «Параметры доставки для каждого канала»Каждый канал решает, что он слышит (policy в данных канала):
min_severity—info,warning(Advisory и выше) илиcritical(только Warning). Канал на телефон обычно хочетcritical, чат — всё.notify_resolved—false, чтобы слышать только о проблемах.min_interval_secs— минимум столько времени между двумя сообщениями об одном и том же оповещении (повторные срабатывания и напоминания). Решения этим параметром никогда не задерживаются, а решение отправляется только тому каналу, который слышал о срабатывании.quiet_hours— еженедельное окно в вашем местном времени, той же формы, что еженедельное окно обслуживания. Во время тихих часов проходят только оповещенияcritical; остальные ждут и приходят единой сводкой по окончании, с заголовком «Тихие часы закончились — …». Оповещение, которое сработало и сбросилось во время тихих часов, упоминается в этой сводке только как «решено во время тихих часов».matcher— какие оповещения хочет канал, по тегу, типу монитора или правилу. Пусто (по умолчанию, и то, что сохраняют все существующие каналы) означает всё.
PUT /api/notify/channels/{id}{ "name": "Phone", "kind": "ntfy", "settings": {…}, "policy": { "min_severity": "critical", "min_interval_secs": 900, "quiet_hours": { "kind": "weekly", "days": [0,1,2,3,4], "start_minute": 1320, "end_minute": 420, "timezone": "Europe/Paris" } } }Если policy не указано при обновлении, сохранённое значение остаётся;
"quiet_hours": null очищает их, а "matcher": null очищает фильтр
маршрутизации.
Маршрутизация по тегу
Заголовок раздела «Маршрутизация по тегу»Монитора несут теги (site=cellar, role=storage) и тип (snmp, proxmox,
synology, agent…). Фильтр маршрутизации канала указывает, какие
оповещения он хочет:
{ "policy": { "min_severity": "warning", "matcher": { "include": [ { "field": "tag", "key": "site", "value": "cellar" } ], "exclude": [ { "field": "tag", "key": "role", "value": "lab" } ] } } }Три поля, и только точное равенство — без регулярных выражений, без скобок:
field | Сопоставляет по | Пример |
|---|---|---|
tag | Тегу на странице самого монитора | {"field":"tag","key":"site","value":"cellar"} |
kind | Коллектору, опрашивающему монитор | {"field":"kind","value":"proxmox"} |
rule | uid правила | {"field":"rule","value":"disk_full"} |
Как читаются списки:
- условия на одном и том же поле (тот же ключ тега, или
kind, илиrule) — это ИЛИ:site=cellarплюсsite=atticозначает любое из них; - условия на разных полях — это И:
site=cellarплюсrole=storageозначает оба; excludeвсегда выигрывает, даже против совпавшегоinclude.
Поэтому пример выше читается — и интерфейс произносит его именно этими словами: этот канал получает advisory и выше с мониторов с тегом site=cellar, кроме мониторов с тегом role=lab.
Под редактором предпросмотр показывает, какие из ваших текущих мониторов выбирает фильтр. Это не приближение: сервер запускает тот же самый фильтр, что и движок оповещений, сведённый к той части, которая зависит только от монитора. Условия правила применяются к оповещениям, а не к мониторам, поэтому предпросмотр называет их отдельно, а не делает вид, что считает их.
POST /api/notify/match-preview{ "matcher": { "include": [ { "field": "tag", "key": "site", "value": "cellar" } ] } }
→ { "devices": [ { "id": 3, "name": "nas", "kind": "synology", "tags": { "site": "cellar" }, "matched": true } ], "matched": 1, "total": 12, "rules": [], "excluded_rules": [] }Фильтр ограничен двенадцатью условиями. После этого второй канал яснее, чем ещё одно условие.
Эскалация: если никто не подтвердил
Заголовок раздела «Эскалация: если никто не подтвердил»Один дополнительный переход, и только один. Когда в политике заданы
escalate_after_secs и escalate_channel, оповещение, которое никто не
подтвердил в течение этой задержки, также отправляется —
один раз — на этот канал:
PUT /api/notify/policy{ "escalate_after_secs": 900, "escalate_channel": 4 }- Задержка отсчитывается с момента, когда первое сообщение действительно было отправлено, а не с момента срабатывания оповещения. Если тихие часы или неудачная доставка поглотили первое уведомление, эскалировать пока нечего, и переход ждёт.
- Подтверждение оповещения останавливает его, точно как останавливает напоминания; так же действует и сброс оповещения.
- Сообщение об эскалации идёт только на канал эскалации — каналы, которые уже слышали о срабатывании, не уведомляются повторно.
- Оно пересекает собственный порог серьёзности канала, фильтр маршрутизации и тихие часы: вы назвали этот канал, чтобы он разбудил кого-то, поэтому он не сдерживается в тот самый момент, когда это важно.
- В строке это отражено так:
🔴 Critical · Disk full — /data — 95 % … — still unacknowledged.
"escalate_channel": null отключает эскалацию; задержка 0 делает то же самое.
Нужны оба значения, чтобы переход существовал, и сервер отказывает в канале,
которого не существует, вместо того чтобы эскалировать в пустоту.
DumbMonit намеренно останавливается здесь: один переход, без ротации, без графика дежурств на неделю. Если вам нужно именно это, направьте канал эскалации на PagerDuty или Opsgenie, которые делают это по-настоящему.
Группировка сообщений и часовой лимит
Заголовок раздела «Группировка сообщений и часовой лимит»GET/PUT /api/notify/policy хранит глобальные настройки:
{ "batch_window_secs": 60, "max_per_hour": 20, "flap_events": 4, "flap_window_secs": 1800, "flap_hold_secs": 1800, "public_url": "https://monit.example.lan", "escalate_after_secs": 0, "escalate_channel": null }- Окно группировки — оповещения, сработавшие в пределах окна, уходят как
одно сообщение на канал, сгруппированное по монитору: «3 оповещения на
2 мониторах» с разделом на каждое монитор; решения едут вместе
(«2 решено»).
0отправляет на следующем цикле. Сводка показывает не более 12 строк, затем «…и ещё N оповещений». - Часовой лимит — как только канал получил
max_per_hourсообщений за последний час, дальнейшие оповещения ждут и приходят единой сводкой, когда освобождается слот.0убирает лимит. - Каналы дежурных служб (PagerDuty, Opsgenie) никогда не группируются между мониторами: они открывают и закрывают по одному инциденту на монитор, поэтому получают по одному сообщению на монитор без ожидания.
Сбои доставки оставляют строки в очереди; следующий цикл повторяет попытку.
Что говорит строка
Заголовок раздела «Что говорит строка»Каждое оповещение — одна строка, одинаковая в письме, ntfy, чате и переменной
{{message}} произвольного вебхука:
🔴 Critical · Disk full — /data — 95 % (threshold > 90 %), for 12 min⚠️ Warning · VM or container stopped — win11-desktop (101), for 59 s✅ Resolved · Service down — https://example.lan/- За значком следует слово состояния (Critical / Warning / Info, Resolved, Flapping), поэтому серьёзность читается без цвета или эмодзи.
- Правило, наблюдающее за несколькими рядами, называет тот, что сработал: ВМ и её id, точку монтирования, интерфейс, группу резервного копирования, URL проверки. Общедевайсные правила (недоступность) не называют ничего кроме монитора.
- Значение и порог показываются для измеряемых правил; правило «всё или ничего» на метрике 0/1 (на батарее, гостевая ВМ остановлена) не повторяет «1 (threshold > 0)».
Глубокие ссылки
Заголовок раздела «Глубокие ссылки»Каждое сообщение заканчивается ссылкой на монитор ({public_url}/targets/{id}),
если публичный URL известен — public_url политики или DUMBMONIT_PUBLIC_URL.
Произвольные вебхуки также получают её как переменную {{link}}, если у них не
задан собственный base_url.
В сообщениях намеренно нет ссылки «заглушить на 1 ч»: чат-сервисы запрашивают каждую ссылку, которую показывают, чтобы построить предпросмотр, что запустило бы заглушение в момент публикации сообщения. Заглушайте со страницы монитора или со страницы оповещений.
Что позаимствовано у Pulse, а что нет
Заголовок раздела «Что позаимствовано у Pulse, а что нет»Дизайн следует за Pulse там, где это подходит монитору для домашней лаборатории: пороги срабатывания/очистки, слой переопределений на ресурс, задержка между уведомлениями, окно группировки, часовой лимит, тихие часы, обнаружение дребезга с задержкой, «уведомлять при решении», и инструменты дежурных служб, не попадающие в сводки. Не позаимствовано: 24-часовой период наблюдения Pulse перед началом уведомлений (базовое правило DumbMonit уже учится молча; правила по порогу должны говорить с первого дня) и отложить/подтвердить из самого сообщения (см. выше). Маршрутизация по тегу на получателя была позаимствована, в виде описанного выше фильтра маршрутизации — выбор каналов в самом правиле оказался неверным местом для «всё из подвала идёт в эту комнату».