feat(observability): клиентский инцидент зовёт дежурного поимённо + чинит сломанное продолжение команды (#3078) #3128

Merged
lekss361 merged 1 commit from feat/3078-oncall-mention into main 2026-08-27 10:50:51 +00:00
Owner

Две вещи, и вторая — исправление ошибки, которую я сам внёс в #3127 час назад.

1. Дежурного зовут по имени

27.08 продукты лежали 10 часов, и в канале «диск занят на 86 %» и «клиенты не могут открыть сайт» выглядели бы одинаково. Разной настойчивости не было вообще.

Появился отдельный маршрут: severity = "critical" И host = "apps" — критично на продуктовой машине означает, что людям недоступны МЕРА и Site Finder, а не «где-то в инфраструктуре тесно».

обычное критичное клиентский инцидент
Текст 🔴 имя алерта 🚨 КЛИЕНТЫ ЗАТРОНУТЫ
Упоминание нет дежурный по имени
Повтор 3 часа 30 минут

Короткий repeat_interval намеренно неудобен: пока инцидент не погашен, напоминание должно мешать. Заглушить его — осознанное действие через Alertmanager, и оно же служит отметкой «принято».

Сужение по host=apps существенно. Без него дежурного звали бы на каждую инфраструктурную мелочь, и тег перестал бы что-либо значить за неделю.

Аккаунт в репозиторий не попадает — берётся из METRICS_TELEGRAM_ONCALL (секрет уже задан). Дежурный меняется, конфиг в git — нет. Пустая переменная = сообщение без тега: поведение не ломается, если её забыли задать, и деплой предупреждает об этом явно.

2. Починка: комментарий внутри продолжения команды

В #3127 блок rm -f вместе с комментарием встал между строками, каждая из которых заканчивалась обратным слешем:

METRICS_TELEGRAM_CHAT_ID="..." \
METRICS_TELEGRAM_TOPIC_LINE="..." \
# rm перед записью обязателен: ...     <- строки склеиваются
rm -f ops/metrics/alertmanager/alertmanager.yml
envsubst ... > alertmanager.yml        <- НИКОГДА не выполнялся

Конфиг Alertmanager перестал бы рендериться вовсе — при полностью зелёном деплое.

Дефект коварен формой: синтаксически это корректный шелл, bash -n его не ловит, а в диффе не видно — строки выглядят самостоятельными. Поэтому тест структурный и применяется ко всем shell-блокам workflow (run: и script:), а не только к месту ожога: после строки с продолжением не может идти комментарий.

Проверка

$ python -m pytest tests/ops/test_3078_oncall_route.py -q
7 passed

Покрыто: комментарий внутри продолжения (упал бы на версии из #3127); наличие приёмника и маршрута; порядок маршрутов — клиентский обязан стоять выше общего critical, иначе Alertmanager заберёт инцидент в общий и тег молча не сработает; параметризация упоминания и отсутствие конкретного аккаунта в git; сквозная цепочка «секрет → env шага → список envsubst» (рвётся молча в любом звене); оба условия сужения маршрута.

Чего здесь нет

Кнопки подтверждения. Alertmanager инлайн-клавиатуру не умеет — нужен свой обработчик, и у него есть развилка по месту жительства, которую стоит решать отдельно и осознанно. Опишу варианты в #3078; этот PR даёт вызов по имени, что закрывает бо́льшую часть задачи «не проспать».

Refs #3078, #3127, #3119

Две вещи, и вторая — исправление ошибки, которую я сам внёс в #3127 час назад. ## 1. Дежурного зовут по имени 27.08 продукты лежали 10 часов, и в канале «диск занят на 86 %» и «клиенты не могут открыть сайт» выглядели бы одинаково. Разной настойчивости не было вообще. Появился отдельный маршрут: `severity = "critical"` **И** `host = "apps"` — критично на **продуктовой** машине означает, что людям недоступны МЕРА и Site Finder, а не «где-то в инфраструктуре тесно». | | обычное критичное | клиентский инцидент | |---|---|---| | Текст | 🔴 имя алерта | 🚨 **КЛИЕНТЫ ЗАТРОНУТЫ** | | Упоминание | нет | дежурный по имени | | Повтор | 3 часа | **30 минут** | Короткий `repeat_interval` намеренно неудобен: пока инцидент не погашен, напоминание должно мешать. Заглушить его — осознанное действие через Alertmanager, и оно же служит отметкой «принято». **Сужение по `host=apps` существенно.** Без него дежурного звали бы на каждую инфраструктурную мелочь, и тег перестал бы что-либо значить за неделю. Аккаунт в репозиторий не попадает — берётся из `METRICS_TELEGRAM_ONCALL` (секрет уже задан). Дежурный меняется, конфиг в git — нет. Пустая переменная = сообщение без тега: поведение не ломается, если её забыли задать, и деплой предупреждает об этом явно. ## 2. Починка: комментарий внутри продолжения команды В #3127 блок `rm -f` вместе с комментарием встал **между** строками, каждая из которых заканчивалась обратным слешем: ```sh METRICS_TELEGRAM_CHAT_ID="..." \ METRICS_TELEGRAM_TOPIC_LINE="..." \ # rm перед записью обязателен: ... <- строки склеиваются rm -f ops/metrics/alertmanager/alertmanager.yml envsubst ... > alertmanager.yml <- НИКОГДА не выполнялся ``` Конфиг Alertmanager перестал бы рендериться **вовсе** — при полностью зелёном деплое. Дефект коварен формой: синтаксически это корректный шелл, `bash -n` его не ловит, а в диффе не видно — строки выглядят самостоятельными. Поэтому тест **структурный** и применяется ко **всем** shell-блокам workflow (`run:` и `script:`), а не только к месту ожога: после строки с продолжением не может идти комментарий. ## Проверка ``` $ python -m pytest tests/ops/test_3078_oncall_route.py -q 7 passed ``` Покрыто: комментарий внутри продолжения (упал бы на версии из #3127); наличие приёмника и маршрута; **порядок маршрутов** — клиентский обязан стоять выше общего `critical`, иначе Alertmanager заберёт инцидент в общий и тег молча не сработает; параметризация упоминания и отсутствие конкретного аккаунта в git; сквозная цепочка «секрет → env шага → список envsubst» (рвётся молча в любом звене); оба условия сужения маршрута. ## Чего здесь нет **Кнопки подтверждения.** Alertmanager инлайн-клавиатуру не умеет — нужен свой обработчик, и у него есть развилка по месту жительства, которую стоит решать отдельно и осознанно. Опишу варианты в #3078; этот PR даёт вызов по имени, что закрывает бо́льшую часть задачи «не проспать». Refs #3078, #3127, #3119
lekss361 added 1 commit 2026-08-27 10:06:07 +00:00
feat(observability): клиентский инцидент зовёт дежурного поимённо + чинит сломанное продолжение команды (#3078)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 10s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 1m59s
CI / backend-tests (pull_request) Successful in 17m26s
6f120c6605
Две вещи, вторая — исправление собственной ошибки из #3127.

## Дежурного зовут по имени

27.08 продукты лежали 10 часов, и в канале «диск занят на 86 %» и «клиенты
не могут открыть сайт» выглядели одинаково. Появился отдельный маршрут:
severity=critical И host=apps, то есть критично на ПРОДУКТОВОЙ машине —
значит людям недоступна МЕРА и Site Finder, а не «где-то в инфраструктуре
тесно».

У такого сообщения другой текст (🚨 КЛИЕНТЫ ЗАТРОНУТЫ), упоминание дежурного
и repeat_interval 30 минут против 3 часов у прочего критичного: пока
инцидент не погашен, напоминание должно быть неудобным.

Сужение по host=apps существенно. Без него дежурного звали бы на каждую
инфраструктурную мелочь, и тег перестал бы что-либо значить за неделю.

Сам аккаунт в репозиторий не попадает — берётся из METRICS_TELEGRAM_ONCALL.
Дежурный меняется, конфиг в git — нет. Пустая переменная = сообщение без
тега, поведение не ломается.

## Починка: комментарий внутри продолжения команды

В #3127 блок rm -f вместе с комментарием встал МЕЖДУ строками, каждая из
которых заканчивалась обратным слешем. Строки склеиваются, и весь вызов
envsubst уехал в комментарий — конфиг Alertmanager перестал бы рендериться
вовсе, при полностью зелёном деплое.

Синтаксически это корректный шелл, bash -n такое не ловит, а в диффе не
видно: строки выглядят как отдельные. Поэтому проверка структурная и
применяется ко ВСЕМ shell-блокам workflow, а не только к месту ожога.
lekss361 merged commit f0b03112fc into main 2026-08-27 10:50:51 +00:00
lekss361 deleted branch feat/3078-oncall-mention 2026-08-27 10:50:52 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#3128
No description provided.