# SES Monitor Система непрерывного мониторинга диалоговой сценарной машины **SES** (Service Engine Server). ## Что делает Watchdog-демон, который: - **Проверяет доступность** SES API каждые 30 секунд - **Имитирует диалоги пользователей** по сценариям, описанным в YAML-файлах - **Отправляет метрики в Zabbix** через zabbix_sender или UserParameter SES — универсальная сценарная машина, поэтому мониторинг не привязан к конкретному проекту. Один и тот же демон может обслуживать любой сценарий: голосового ассистента, чат-бота, IVR, диалогов поддержки и любых других. ## Архитектура ``` ┌─────────────────────────────────────────────────────┐ │ ses-monitor (watchdog-демон) │ │ │ │ ┌──────────────┐ ┌────────────────┐ │ │ │ LivenessCheck │ │ ScenarioRunner │ │ │ │ (30 сек) │ │ (по YAML) │ │ │ │ │ │ │ │ │ │ GET /hostname│ │ POST /ses/ask │ │ │ │ GET /license │ │ шаги+expect │ │ │ └──────┬───────┘ └───────┬─────────┘ │ │ │ │ │ │ ┌──────▼──────────────────▼──────┐ │ │ │ Zabbix (sender / UP) │ │ │ └──────────────┬─────────────────┘ │ └─────────────────┼────────────────────────────────────┘ │ TCP 10051 / JSON file ┌───────────▼───────────┐ │ Zabbix Server │ │ (триггеры, алерты) │ └───────────────────────┘ ``` ## Режимы доставки в Zabbix Монитор поддерживает два режима отправки метрик: ### sender (по умолчанию) — zabbix_sender (активный push) Монитор запускает утилиту `zabbix_sender` и передаёт метрики через stdin. Данные отправляются на Zabbix сервер или прокси (порт 10051, trapper). В Zabbix элементы данных имеют тип "Zabbix траппер". Требуется: установленный zabbix_sender на сервере с монитором. ### userparameter — Zabbix агент (пассивный опрос) Монитор пишет JSON со всеми метриками в файл (`/var/tmp/ses_monitor/metrics.json`). Zabbix агент по запросу сервера запускает скрипт `scripts/zbx_get.py`, который возвращает содержимое JSON-файла. В Zabbix используется master-элемент `ses.metrics` (тип "Zabbix агент", текст) и зависимые элементы с препроцессингом JSONPath. Настройка: 1. Импортировать шаблон в Zabbix: - Zabbix 6.4: `zabbix/zbx_ses_template_up.xml` - Zabbix 5.0: `zabbix/zbx_ses_template_5.0_up.xml` 2. Привязать шаблон к хосту (Configuration → Hosts → выберите хост → Templates) 3. В конфиге монитора `config/config.yaml` установить `mode: "userparameter"` 4. При старте демон автоматически создаёт конфиг агента: `/opt/ses-monitor/config/zbx_agentd_ses.conf` 5. В `/etc/zabbix/zabbix_agentd.conf` добавить строку (или скопировать конфиг в `/etc/zabbix/zabbix_agentd.d/`): ``` Include=/opt/ses-monitor/config/zbx_agentd_ses.conf ``` 6. Перезапустить Zabbix агента: `sudo systemctl restart zabbix-agent` ## Структура проекта ``` /opt/ses-monitor/ ├── src/ │ └── ses_monitor/ # Python-пакет (src-layout) │ ├── __init__.py # Версия, метаданные │ ├── __main__.py # Точка входа: python -m ses_monitor │ ├── main.py # Главный asyncio watchdog-цикл │ ├── config.py # Загрузка YAML-конфигурации │ ├── checker.py # Liveness-проверки (API, лицензия, роботы) │ ├── session_client.py # HTTP-клиент для SES API │ ├── scenario_runner.py # Движок выполнения сценариев │ ├── log_client.py # Чтение логов SES (задел на будущее) │ ├── zabbix.py # Интеграция с Zabbix (sender / UserParameter) │ └── utils.py # Утилиты (логирование, JSON-пути, проверки) ├── config/ │ ├── config.yaml.example # Шаблон конфигурации (скопировать в config.yaml) │ └── scenarios/ │ ├── example_liveness.yaml # Пример: быстрая проверка │ └── example_dialog.yaml # Пример: многошаговый диалог ├── zabbix/ │ ├── zbx_ses_template.xml # Шаблон Zabbix 6.4 для sender (trapper) │ ├── zbx_ses_template_up.xml # Шаблон Zabbix 6.4 для UserParameter │ ├── zbx_ses_template_5.0.xml # Шаблон Zabbix 5.0 для sender (trapper) │ ├── zbx_ses_template_5.0_up.xml # Шаблон Zabbix 5.0 для UserParameter │ └── zbx_ses_monitor.conf # Резервный конфиг UserParameter ├── scripts/ │ └── zbx_get.py # Скрипт чтения JSON для UserParameter ├── systemd/ │ └── ses-monitor.service # Systemd unit ├── tests/ │ ├── __init__.py │ └── test_scenario_runner.py # 48 тестов ├── pyproject.toml # Зависимости и метаданные пакета └── README.md ``` ## Установка на сервере ### 1. Требования - **Python 3.9+** - **Git** — для клонирования репозитория - **Zabbix Agent** с утилитой `zabbix_sender` - Доступ к SES API (`http://:6190`) - Доступ к Zabbix Server по порту 10051 ### 2. Установка пакета ```bash # Клонируем репозиторий на сервер git clone https://git.totmin.ru/en2zmax/ses-monitor.git /opt/ses-monitor # Переходим в каталог проекта cd /opt/ses-monitor # Создаём виртуальное окружение и устанавливаем пакет python3 -m venv .venv source .venv/bin/activate pip install -e . # Создаём каталог для логов mkdir -p /var/log/ses-monitor ``` ### 3. Настройка конфигурации Скопируйте шаблон и отредактируйте: ```bash cp config/config.yaml.example config/config.yaml nano config/config.yaml ``` Основные поля: ```yaml ses: base_url: "http://YOUR_SES_HOST:6190" # URL вашего SES API channel: "monitoring" # Канал для мониторинговых сессий request_timeout: 30 zabbix: enabled: true mode: "userparameter" # или "sender" host: "my-server-name" # Имя хоста в Zabbix server: "127.0.0.1" # IP Zabbix сервера (только sender) port: 10051 sender_path: "/usr/bin/zabbix_sender" metrics_file: "/var/tmp/ses_monitor/metrics.json" # (только userparameter) ``` ### 4. Создание сценария Скопируйте пример и адаптируйте под ваш проект: ```bash cp config/scenarios/example_liveness.yaml config/scenarios/my_project.yaml ``` ### 5. Запуск ```bash # Проверка вручную: cd /opt/ses-monitor .venv/bin/python -m ses_monitor # Установка как systemd-сервиса: cp systemd/ses-monitor.service /etc/systemd/system/ systemctl daemon-reload systemctl enable --now ses-monitor # Просмотр логов: journalctl -u ses-monitor -f ``` ### 6. Импорт шаблона Zabbix В зависимости от версии Zabbix и режима доставки: | Zabbix | sender (trapper) | userparameter | |---|---|---| | 6.4 | `zabbix/zbx_ses_template.xml` | `zabbix/zbx_ses_template_up.xml` | | 5.0 | `zabbix/zbx_ses_template_5.0.xml` | `zabbix/zbx_ses_template_5.0_up.xml` | 1. Zabbix Frontend → **Configuration → Templates → Import** 2. Выбрать файл шаблона 3. Нажать Import 4. Привязать шаблон "SES Monitor" к нужному хосту ## Формат сценариев Сценарии описываются в YAML-файлах в каталоге `config/scenarios/`. Это гибкий DSL, который не зависит от конкретного проекта SES. ### Полный формат ```yaml # Имя сценария (используется в логах) name: "example: проверка диалога" # Описание для документации description: "Проверяет что бот корректно отвечает на вопросы" # Включён ли сценарий (false — отключён) enabled: true # Интервал запуска в секундах interval: 300 # Таймаут HTTP-запроса в секундах timeout: 30 # ID робота (обязательно). Узнать: GET /ses/robot/listall robot_id: "uuid-вашего-робота" # Канал (если не указан — берётся из config.yaml) channel: "monitoring" # Не переоткрывать закрытые сессии (false — создаём новую сессию каждый раз) restart_closed: false # Шаги сценария steps: - send: "Привет" expect: # Каждое ожидание проверяет значение в JSON-ответе - path: "error" equals: 0 - path: "answer[0].messages[0]" contains: "Здрав" - send: "Как дела?" expect: - path: "error" equals: 0 - path: "answer" not_empty: true ``` ### Условия проверки (expect) | Условие | Описание | Пример | |---|---|---| | `equals` | Точное совпадение | `equals: 0` | | `contains` | Подстрока содержится (без учёта регистра) | `contains: "здравствуйте"` | | `not_contains` | Подстрока отсутствует | `not_contains: "ошибка"` | | `not_empty` | Поле не пустое | `not_empty: true` | | `regex` | Регулярное выражение | `regex: "\\d{10,}"` | | `exists` | Поле существует и не None | `exists` (без значения) | ### Пути JSON (path) Формат: `ключ.подключ[индекс].поле` ```yaml # Корневое поле path: "error" # Массив → первый элемент → поле path: "answer[0].messages[0]" # Глубокая вложенность path: "request.data[0].reply.confidence" ``` ## Как адаптировать под ваш проект 1. **Узнайте robot_id** вашего сценария: ```bash curl -s http://:6190/ses/robot/listall ``` 2. **Пропишите robot_id** в файле сценария (поле `robot_id` в YAML) 3. **Создайте файл сценария**, описав шаги диалога: ```bash cp config/scenarios/example_liveness.yaml config/scenarios/$(hostname).yaml vim config/scenarios/$(hostname).yaml ``` 4. **Протестируйте вручную** шаги через curl: ```bash curl -X POST "http://:6190/ses/ask/?text=Привет&channel=monitoring" ``` 5. **Запустите демон** — метрики агрегируются автоматически (шаблон Zabbix универсален) ## Расширение системы ### Добавление нового сценария 1. Создать `config/scenarios/my_scenario.yaml` 2. Скопировать структуру из примеров 3. Указать `robot_id` вашего робота (узнать: `GET /ses/robot/listall`) 4. Описать шаги и ожидания 5. Сценарий автоматически подхватится через hot-reload (каждые 60 секунд) ### Добавление новой метрики 1. В нужном модуле добавить поле в датакласс-результат 2. В `main.py` вызвать `self._zabbix.add(key, value)` 3. Добавить item в Zabbix шаблон ## Мониторинг самого монитора - **systemd**: `systemctl is-active ses-monitor` - **Zabbix Active Agent**: `proc.num[python,root,ses_monitor]` - **Логи**: `journalctl -u ses-monitor --since "10 min ago" -o cat | grep ERROR` ## Отказоустойчивость - **Автоперезапуск**: systemd Restart=always, RestartSec=10 - **Graceful shutdown**: по SIGTERM отправляет последний батч метрик - **Таймауты**: все HTTP-запросы с ограничением по времени (по умолчанию 30с) - **Изоляция сценариев**: ошибка в одном сценарии не влияет на другие - **Hot-reload**: сценарии перечитываются без перезапуска демона ## Лицензия MIT