Отправляем уведомления в определенный топик в чате Telegram
В этой статье я рассказываю, как настроить уведомления в вашем приложении на Python или в Alertmanager таким образом, чтобы сообщения приходили в определенный Telegram топик.
Некоторые топики в чате команды разработки
TL; DR
curl-запрос для отправки сообщений в определенный telegram топик:
curl -X POST -H 'Content-Type: application/json' \
-d '{"reply_to_message_id": "2", "chat_id": "-1001927109642_2", "text": "This is a test message from the alert system. Do not pay attention on it"}' \
https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendMessage
Ссылка на fork python_telegram_handler репозитория с поддержкой топиков
Ссылка на fork alertmanager репозитория с поддержкой топиков
Задача
Мое имя Вадим Резвов, я начинающий системный администратор.
В мои обязанности входит: мониторинг состояния всех основных сервисов и систем проекта, создание бэкапов, поддержка ключевых компонентов сервера.
В одном из моих текущих рабочих проектов, появились задачи, настроить систему регулярных бэкапов для DB PostgreSQL и настроить мониторинг компонентов системы.
Команда разработки выдвинула следующие требования:
Сообщения об ошибках при создании бэкапов и сообщения об успешно созданных бэкапах, о сбоях в работе компонентов, должны приходить в определенный telegram топик — «Support», чтобы не засорять другие топики «General».
Отправка в топик Telegram curl запросом
Решение задачи я начал с составления curl запроса, который будет отправлять сообщения в определенный telegram топик.
Этот шаг можно пропустить, curl запрос нужен, чтобы проверить корректность используемых данных: bot token, chat id, message id.
Отдельный топик в группе идентифицируется в Telegram Bot API с помощью id первого сообщение в топике.
Чтобы получить id первого сообщения в топике, в Telegram десктоп клиенте кликните правой кнопкой мыши по первому сообщению в топике, выберите «Copy Message Link».
Вы получите подобную ссылку:
https://t.me/c/-1001234567/1234/1235
Первая часть ссылки — это id чата -1001234567
Вторая часть ссылки — это id первого сообщения в топике: 1234
Извлекаем параметры для curl запроса:
reply_to_message_id: 1234
chat_id: -1001234567890_1234
Для отправки сообщения в топик нам потребуется:
Зарегистрировать бота в BotFather и получить его токен:
https://core.telegram.org/bots/tutorial#obtain-your-bot-tokenДобавить бота в чат как обычного пользователя.
Теперь можно делать curl запрос
# Перед отправкой curl, нужно установить bot token:
export TELEGRAM_BOT_TOKEN=1234567890:aBCd_eFGHjk_etc
# Отправляем curl запрос:
curl -X POST -H 'Content-Type: application/json' \
-d '{"reply_to_message_id": "2", "chat_id": "-1001927109642_2", "text": "This is a test message from the alert system. Do not pay attention on it"}' \
https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/sendMessage
Должны увидеть такое сообщение в нужном топике
Отправка в топик Telegram с помощью python logger
Проект python logger позволяет отправлять уведомления из логгера в Telegram.
Однако в нем нет возможности отправлять сообщения в определенный топик.
Для поддержки отправки в топики, я сделал fork этого репозитория.
и дописал пару строчек кода:
https://github.com/sashgorokhov/python-telegram-handler/compare/master…oktend: python-telegram-handler: master#diff-e5c391ada5f2b1d85ca23fc08080d0d01b7e19ab6cae725398a945aca8eb7309
Для демонстрации я сделал репозиторий с скриптом для отправки сообщений в топик группы в Telegram:
https://github.com/oktend/python-telegram-topic-notification-example
Ключевой код из примера:
telegram_handler = TelegramHandler(
level=logging.WARNING,
token="1234567890:aBCd_eFGHjk_etc",
reply_to_message_id="1234",
chat_id="-1001234567890_1234"
)
telegram_handler.setLevel(logging.WARNING)
log.addHandler(telegram_handler)
Теперь все сообщения из лога уровнем warning и выше будут отправляться в топик чата Telegram.
Я это использую и для отправки сообщений об успешно созданном бэкапе:
log.warning(f"Backup prod data script was successfully ended. timestamp: {now_str}")
Отправка в топик Telegram с помощью alertmanager
При настройке мониторинга мне потребовалось настроить отправку уведомлений в топик, но в стандартном alertmanager не был поддержан параметр reply_to_message_id, который нужен для отправки в топик.
Я решил это созданием fork alertmanager.
и отправил pull request в основной репозиторий alertmanager
Пока PR не принят, я использую сборку из своего репозитория:
https://github.com/oktend/alertmanager/releases/tag/v0.26.0-tg-topic
Для демонстрации я сделал репозиторий.
Здесь вы найдете docker образ с модифицированным alertmanager и инструкцию по запуску.
Здесь ключевой момент это настройка отправки уведомлений в топик в чате Telegram:
receivers:
- name: 'telegram'
telegram_configs:
- bot_token: 1234567890:aBCd_eFGHjk_etc
api_url: https://api.telegram.org
chat_id: -1001234567890_1234
reply_to_message_id: 1234
В своем проекте я использовал Ansible для установки alertmanager, подобный этому:
https://github.com/MiteshSharma/PrometheusAlertManagerWithAnsible
Но для того, чтобы alertmanager умел отправлять сообщения в топик, нужно поменять ссылку на сборку в файле:
https://github.com/MiteshSharma/PrometheusAlertManagerWithAnsible/blob/master/roles/alertmanager/tasks/main.yml#L17
таким образом:
- name: Download alertmanager
unarchive:
# src: "https://github.com/prometheus/alertmanager/releases/download/v{{ version }}/alertmanager-{{ version }}.linux-amd64.tar.gz"
src: "https://github.com/oktend/alertmanager/releases/download/v0.26.0-tg-topic/alertmanager-0.26.0.linux-amd64.tar.gz"
dest: /tmp/
remote_src: yes
Заключение
Надеюсь, моя статья будет полезна тем, кто столкнется с подобной проблемой.
Буду рад любой критике, советам, рекомендациям.