Коллеги, привет. Если вы когда-нибудь оказывались в ситуации, когда нужно срочно начать мониторить появление слова "CRITICAL" в логах приложения, а возиться с написанием экспортера для Prometheus совсем не хочется — этот пост для вас.

Сразу оговорюсь: я не призываю отказываться от Prometheus, сам его активно использую. Но иногда нужно просто и быстро, без лишних телодвижений. И тут старый добрый Zabbix со своим агентом выстреливает неожиданно метко.

Почему Zabbix, а не очередной экспортер

Давайте честно: Prometheus — штука классная, но его модель "pull" иногда заставляет нас изобретать велосипеды. Хотите ловить ошибки в логах? Варианты:

  1. Ищете готовый экспортер (и молитесь, чтобы он поддерживал ваш формат логов).

  2. Пишете свой на Go (с красивыми метками и прочими радостями).

  3. Подключаете Vector или Fluentd и начинаете строить пайплайн.

А теперь вспоминаем про Zabbix-агента. Он просто приходит на сервер, выполняет команду и отдает результат. Всё. Никаких экспортеров, ничего лишнего. Иногда старое — это новое хорошо забытое.

Что будем мониторить

Для примера возьмем три задачи, которые в Prometheus без плясок с бубном не решаются:

  1. Счетчик ERROR в логе — сколько раз приложение упало в ошибку.

  2. Количество PANIC в последних 200 строках — чтобы не долбить диск чтением гигабайтных логов, а смотреть только свежак.

  3. Uptime сервера в секундах — есть в node_exporter, ну да ничего страшного .

UserParameter: как это работает

Всё волшебство происходит через директиву UserParameter в конфиге агента. Синтаксис до безобразия прост:

UserParameter=<ключ>,<команда>

Агент выполняет команду, перехватывает stdout и отправляет на сервер. Если команда упала — можно вернуть 0, чтобы графики не дырявились.

Вот как выглядят наши метрики:

# /etc/zabbix/zabbix_agentd.d/userparameter_demo.conf

# Просто считаем ошибки во всем файле
UserParameter=demo.log.error.count,grep -c "ERROR" /var/log/demo/demo.log 2>/dev/null || echo 0

# Смотрим только хвост — бережем диски
UserParameter=demo.log.panic.recent,tail -n 200 /var/log/demo/demo.log 2>/dev/null | grep -c "PANIC" || echo 0

# Uptime из /proc — быстрее чем вызывать uptime
UserParameter=demo.cmd.uptime,cut -d. -f1 /proc/uptime

Обратите внимание на 2>/dev/null || echo 0. Это моя любимая фишка: если лога вдруг нет или он недоступен, мы не падаем с ошибкой, а возвращаем ноль. Серверу всё равно, а графики целы.

Поднимаем стенд за минуту

Теория — хорошо, но лучше один раз запустить, чем сто раз прочитать. Я набросал docker-compose, который поднимает всё хозяйство:

  • Zabbix-сервер с веб-мордой

  • Агента на отдельном контейнере

  • Генератор логов, который раз в 5 секунд кидает в лог INFO, WARNING, ERROR и изредка PANIC

Репозиторий с лабой: - https://gitflic.ru/project/yusmit/zabbix-lab

Запускается элементарно:

git clone https://gitflic.ru/project/yusmit/zabbix-lab
cd zabbix-lab
podman compose up -d

Не забудь вытереть мокрую спину.

После всех манипуляций у нас полностью рабочая система:

Zabbix на 8080 порту — можно смотреть графики.
Контейнер с агентом, который тащит метрики.
Генератор логов — пишет тестовые строки в /var/log/demo/demo.log.
Три свои метрики, которые сделаны за 5 минут без единой строчки на Go.

Настройка в веб-интерфейсе

Заходим в веб-морду на http://localhost:8080 (логин Admin, пароль zabbix). Дальше классика:

Configuration → Hosts → Demo Linux Host → Items → Create item

Создаем три элемента данных:

1. Количество ERROR:

  • Name: Number of ERROR in log

  • Key: demo.log.error.count

  • Type: Numeric (unsigned)

  • Update interval: 1m

2. PANIC в последни�� 200 строках:

  • Name: Recent PANIC count (last 200 lines)

  • Key: demo.log.panic.recent

  • Type: Numeric (unsigned)

  • Update interval: 1m

3. Uptime:

  • Name: System uptime (seconds)

  • Key: demo.cmd.uptime

  • Type: Numeric (unsigned)

  • Units: s

  • Update interval: 1m

Выглядит это примерно так

Проверяем, что всё работает

Самый надежный способ проверить метрику — дернуть её руками через zabbix_get. Лезем в контейнер с сервером и пробуем. Если видите числа — значит, агент исправно отдает данные. Если нет — смотрите права на файл лога и путь к командам, логи самого агента.

podman exec -it demo-linux sh
/var/lib/zabbix $ zabbix_agent2 -t demo.log.error_count
demo.log.error_count                          [s|69]
/var/lib/zabbix $ zabbix_agent2 -t demo.log.panic_recent
demo.log.panic_recent                         [s|17]
/var/lib/zabbix $ zabbix_agent2 -t demo.cmd.uptime_seconds
demo.cmd.uptime_seconds                       [s|18965]

Но не забываем наше любимое - у меня локально работает - надо протестировать на живом хосте, через кнопку Test.

Ежели не работает - ищем причину.

Триггер: чтобы не сидеть и не смотреть в графики

Ну и напоследок — алерт на PANIC. Потому что сидеть и смотреть на графики вручную может только очень фрустрированный админ.

Идем в Configuration → Hosts → Demo Linux Host → Triggers → Create trigger:

  • Name: PANIC detected in application log!

  • Severity: High (пусть будет красно)

  • Expression: min(/Demo Linux Host/demo.log.panic.recent,5m) > 0

Теперь если за последние 5 минут в логе промелькнула хоть одна PANIC (а это легко симулировать) — Zabbix заорёт. Красота.

Личные впечатления и рефлексия

Я использую Prometheus, и все равно его не брошу менять его на Zabbix не собираюсь. Но в некоторых ситуациях Zabbix оказывается просто незаменим. Особенно когда нужно быстро на коленке собрать метрику "здесь и сейчас", а времени на написание экспортера нет.

Из минусов:

  • Нагрузка на диск. Если забудете про tail и начнете раз в 10 секунд grep-ать логи за неделю — диск скажет спасибо.

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

Из плюсов:

  • Это работает всегда. Даже если всё вокруг упало, zabbix-agent держится молодцом.

  • Минимум кода. По сути, просто bash-скрипты.

В общем, инструмент должен быть удобным, а не модным. Держите в арсенале и Zabbix, он еще выручит не раз.