Легкая работа со сложными алертами. Или история создания Balerter

Легкая работа со сложными алертами. Или история создания Balerter

Все любят алерты.

Конечно, гораздо лучше получить уведомление когда что-то произошло (или починилось), чем сидеть, смотреть на графики и искать аномалии.

И инструментов для для этого создано немало. Alertmanager из экосистемы Prometheus и vmalert из группы продуктов VictoriaMetrics. Уведомления zabbix и алерты в Grafana. Самописные скрипты на bash и Telegram боты, которые периодически дергают какой-то URL и говорят, если что-то не так. Много всего.

Мы, в нашей компании, тоже использовали разные решения, пока не уперлись в сложность, или, скорее, невозможность создания сложных, составных алертов. Чего нам хотелось и что в итоге сделали — под катом. TLDR: Так появился open source проект Balerter

Довольно долго мы неплохо жили с алертами, настроенными в Grafana. Да, это не лучший путь. Всегда рекомендуется использовать какие-то специализированные решения, типа Alertmanager. И мы тоже не один раз смотрели в сторону переезда. А затем, потихоньку, нам захотелось большего.

Сказать, когда некий график упал/вырос на XX% и находится там уже N минут по сравнению с предыдущим периодом в M часов? Это, кажется, можно попробовать реализовать с Grafana или Alertmanager, но довольно не просто. (А может и нельзя, я сейчас и не скажу)

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

Проверяем данные из двух баз Clickhouse, далее сравниваем с некоторыми данными из Postgres, и принимаем решение об алерте. Сигнализировать либо отменить

Подобных хотелок у нас накопилось достаточно много, чтобы мы задумались о своем решении. И тогда попробовали составить первый список требований/возможностей этого, не созданного пока, сервиса

  • обращаться к разным источникам данных. Например, Prometheus, Clickhouse, Postgres

  • отправлять алерты в различные каналы — telegram, slack и т.д.

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

  • запуск скриптов по расписанию

  • легкое обновление скриптов без перезапуска сервиса

  • возможность как-то расширять функционал без пересборки сервиса из исходных кодов

Это список примерный и, скорее всего, не очень точный. Какие-то пункты видоизменялись, какие-то умирали. Все как обычно.

Собственно, именно так началась история Balerter.

Легкая работа со сложными алертами. Или история создания Balerter

Попробую описать коротко, что в итоге получилось и как это работает. (Да, конечно, это не финал. Много планов для развития продукта. Я просто остановлюсь на сегодняшнем дне)

Как это работает?

Вы пишите скрипт на Lua, где явно отправляете запросы (в Prometheus, Clickhouse и т.д). Получаете ответы и как-то их обрабатываете и сравниваете. После чего включаете/выключаете какой-то алерт. Balerter сам отправит уведомление в каналы, которые вы настроили (Email, telegram, slack и т.д.). Скрипт выполняется с заданной периодичностью. И… в общем-то это все)

Лучше всего показать на примере:

-- @interval 10s
-- @name script1

local minRequestsRPS = 100

local log = require("log")
local ch1 = require("datasource.clickhouse.ch1")

local res, err = ch1.query("SELECT sum(requests) AS rps FROM some_table WHERE date = now()")
if err ~= nil then
    log.error("clickhouse 'ch1' query error: " .. err)
    return
end

local resultRPS = res[1].rps

if resultRPS < minResultRPS then
    alert.error("rps-min-limit", "Requests RPS are very small: " .. tostring(resultRPS))
else
    alert.success("rps-min-limit", "Requests RPS ok")
end 

Что тут происходит:

  • указываем, что данный скрипт должен выполняться каждые 10 секунд

  • указываем имя скрипта (для API, для отображения в логах, для использования в тестах)

  • подключаем модуль для вывода логов

  • подключаем модуль для доступа к кликхаусу с именем ch1 (само подкчлючение настраивается в конфиге)

  • отправляем запрос в кликхаус

  • в случае ошибки — выводим сообщение в лог и выходим

  • сравниваем результат запроса с константой (в живом примере мы могли бы это значение получать, например, из базы Postgres)

  • включаем или выключаем алерт с ID rps-min-limit

  • вы получите уведомление, если статус алерта изменился

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

Поэтому созрело логичное желание — иметь возможность напистать тесты для своих скриптов. И в версии v0.4.0 это появилось.

Тестирование скриптов

Пример теста для нашего скрипта из примера выше:

-- @test script1
-- @name script1-test

test = require('test')

local resp = {
    {
        rps = 10
    }
} 

test.datasource('clickhouse.ch1').on('query', 'SELECT sum(requests) AS rps FROM some_table WHERE date = now()').response(resp)

test.alert().assertCalled('error', 'rps-min-limit', 'Requests RPS are very small: 10')
test.alert().assertNotCalled('success', 'rps-min-limit', 'Requests RPS ok')

По шагам:

  • указываем имя скрипта, для которого написан тест

  • имя теста (для логов)

  • подключаем модуль тестирования

  • говорим, какой результат надо вернуть при определенном запросе к кликхаусу ch1

  • проверяем, что был вызван алерт (error) rps-min-limit с указанным сообщением

  • проверяем, что алерт rps-min-limit не был отключен (success)

Что еще умеет Balerter?

Я попробую коснуться самых важных, по поему мнению, умениях Balerter. Подробно все посмотреть можно на официальном сайте https://balerter.com

  • получать данные из

    • clickhouse

    • postgres

    • mysql

    • prometheus

    • loki

  • отправлять уведомления к каналы

    • slack

    • telegram

    • syslog

    • notiify (UI уведомления на вашем компьютере)

    • email

    • discord

  • строить графики по вашим данным, загружать изображение в S3 совместимое хранилище и прикреплять к уведомлениям (Пример с картинками)

  • позволяет обмениваться данными между скриптами — глобальное Key/Value хранилище

  • писать свои библитеки на Lua и использовать их в скриптах (по-умолчанию поставляются lua-библиотеки для работы с json, csv)

  • отправлять HTTP запросы из ваших скриптов (ну и получать ответы, разумеется)

  • предоставляет API (пока еще не такое функциональное, как хотелось бы)

  • экспортирует метрики в формате Prometheus

А что хотелось бы уметь еще?

Уже понятно, что пользователи и мы хотим возможность управлять запуском скриптов с помощью синтаксиса cron. Это будет сделано до версии v1.0.0

Хочется поддержать больше источников данных и каналов доставки уведомлений. Например, кому-то точно не будет хватать MongoDB. Кому-то Elastic Search. Отправлять SMS и/или делать дозвон на мобильный. Хотим уметь получать скрипты не только из файлов, но и, например, из базы данных. В конце концов хотим для проекта более удобный сайт и более хорошую документацию.

Всегда кому-то чего-то не хватает) Здесь мы надеемся на запрос сообщества, чтобы правильно выстроить приоритеты. И на помощь сообщества, чтобы все реализовать

В заключение

Мы используем Balerter у себя уже довольно давно. Десятки скриптов стоят на страже нашего спокойствия. Надеюсь, эта работа станет полезна кому-то еще.

И добро пожаловать с вашими Issue и PR.

Источник: habr.com