feat(observability): кнопка «Принял в работу» под клиентским инцидентом (#3078) #3136
No reviewers
Labels
No labels
Fable 5 ревью
GG-форсайт
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
feedback/max
generative
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
ИРД
вторичка
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#3136
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "feat/3078-alert-ack-button"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Вторая половина запроса владельца: тег дежурного уже в #3128, здесь — обратная связь «я отреагировал». Вариант размещения выбран владельцем: сервис на наблюдателе.
Как выглядит
Кнопка после нажатия снимается, отметка уходит ответом на само сообщение инцидента — в ту же тему «алерты».
Три решения, каждое с ценой
Живёт на инфраструктурной машине, рядом с Alertmanager. У бота МЕРЫ уже есть приём обновлений, и повесить обработку туда было бы дешевле по коду. Но он работает на продуктовом хосте: при падении продукта кнопка оказалась бы мёртвой ровно тогда, когда она нужна.
Ссылка, а не callback. Callback-кнопка требует, чтобы кто-то читал обновления бота. Бот один, и его обновления уже читает МЕРА — второй читатель получил бы
409 Conflictи отобрал бы сообщения у поддержки. URL-кнопка не требует обновлений вовсе./ack/*без пароля — осознанно. Кнопку жмут ночью с телефона, когда лежит прод; требование пароля в этот момент даст ноль нажатий и вернёт нас к вопросу «а кто-нибудь это читает». Защита — неугадываемость и одноразовость: 128-битный токен, выданный под конкретное сообщение и живущий сутки. Максимум, чего добьётся угадавший, — ложная отметка «принято» в чате, где сразу видно, что её поставил не человек. Прав в системе токен не даёт никаких.Через сервис идёт только клиентский маршрут
Прочие алерты сохраняют прямой путь в Telegram: чем меньше звеньев у алерта, тем он надёжнее, и терять это для инфраструктурных сообщений незачем.
Если сервис лёг — Alertmanager считает доставку неудачной, повторяет, а сам инцидент остаётся активным и переуведомляется каждые 30 минут. Алерт задерживается, но не теряется. Дублировать его вторым прямым каналом не стал: два уведомления на каждый инцидент — шум, а шум в канале тревог опаснее задержки.
Тесты
Девять новых дёргают настоящие функции сервиса, подменяя ровно один шов — вызов Bot API. Сеть не трогается, всё, что ушло бы в неё, проверяется.
Важнейший из них: при отказе отправки с клавиатурой сообщение уходит без неё — алерт важнее кнопки, молчание вместо сообщения было бы тем самым отказом, ради устранения которого весь стек и заводится. Плюс идемпотентность повторного нажатия (ссылка живёт сутки, по ней кликнут дважды), протухание токена, и то, что неизвестный токен ничего не отправляет в чат.
Обновлён тест из #3128: упоминание дежурного переехало из шаблона в сервис вместе с текстом сообщения — проверка та же по смыслу, но смотрит туда, где текст формируется теперь. Заодно добавлена проверка, что прямой канал у остальных маршрутов сохранён.
Без зависимостей
Только стандартная библиотека Python, образ без сборки: сервис обязан подниматься даже когда сломано всё остальное, и не тащить за собой установку пакетов.
Refs #3078, #3128, #3119