# SES Monitor Система непрерывного мониторинга диалоговой сценарной машины **SES** (Service Engine Server). ## Что делает Watchdog-демон, который: - **Проверяет доступность** SES API каждые 30 секунд - **Имитирует диалоги пользователей** по сценариям, описанным в YAML-файлах - **Анализирует архив** диалогов на ошибки (unknown, not found, no data) - **Отправляет метрики в Zabbix** через `zabbix_sender` SES — универсальная сценарная машина, поэтому мониторинг не привязан к конкретному проекту. Один и тот же демон может обслуживать любой сценарий: голосового ассистента, чат-бота, IVR, диалогов МФЦ, медорганизаций и любых других. ## Архитектура ``` ┌─────────────────────────────────────────────────────┐ │ ses-monitor (watchdog-демон) │ │ │ │ ┌──────────────┐ ┌────────────────┐ ┌──────────┐│ │ │ LivenessCheck │ │ ScenarioRunner │ │ Archive ││ │ │ (30 сек) │ │ (по YAML) │ │ Auditor ││ │ │ │ │ │ │ (10 мин) ││ │ │ GET /hostname│ │ POST /ses/ask │ │ /archive ││ │ │ GET /license │ │ шаги+expect │ │ /list ││ │ └──────┬───────┘ └───────┬─────────┘ └────┬─────┘│ │ │ │ │ │ │ ┌──────▼──────────────────▼──────────────────▼─────┐│ │ │ ZabbixSender (zabbix_sender) ││ │ └──────────────────────┬───────────────────────────┘│ └─────────────────────────┼───────────────────────────┘ │ TCP 10051 ┌───────────▼───────────┐ │ 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/zbx_ses_template_5.0_up.xml` в Zabbix 2. Привязать шаблон к хосту (Configuration → Hosts → выберите хост → Templates) 3. В конфиге монитора `config/config.yaml` установить `mode: "userparameter"` 4. В `/etc/zabbix/zabbix_agentd.conf` добавить строку: ``` Include=/opt/ses-monitor/config/zbx_agentd_ses.conf ``` 5. Перезапустить Zabbix агента: `sudo systemctl restart zabbix-agent` ## Структура проекта ``` /opt/ses-monitor/ ├── ses_monitor/ # Python-пакет │ ├── __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 (zabbix_sender) │ └── utils.py # Утилиты (логирование, JSON-пути, проверки) ├── config/ │ ├── config.yaml # Основная конфигурация │ └── scenarios/ │ ├── example_liveness.yaml # Пример: быстрая проверка │ └── example_dialog.yaml # Пример: многошаговый диалог ├── zabbix/ │ ├── zbx_ses_template.xml # Шаблон Zabbix (импорт в frontend) │ └── zbx_ses_monitor.conf # UserParameter для Zabbix Agent (резерв) ├── systemd/ │ └── ses-monitor.service # Systemd unit ├── tests/ │ └── test_scenario_runner.py ├── pyproject.toml # Зависимости и метаданные пакета └── README.md ``` ## Установка на сервере ### 1. Требования - **Python 3.9+** - **Git** — для клонирования репозитория - **Zabbix Agent** с утилитой `zabbix_sender` - Доступ к SES API (`http://:6190`) - Доступ к Zabbix Server по порту 10051 - SSH-ключ, добавленный в Git-репозиторий (`git.totmin.ru`) ### 2. Установка пакета ```bash # Клонируем репозиторий на сервер git clone git@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://10.101.60.31:6190" # URL вашего SES API robot_id: "" # ID робота из GET /ses/robot/listall 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 1. Zabbix Frontend → **Configuration → Templates → Import** 2. Выбрать файл `zabbix/zbx_ses_template_5.0.xml` (для sender) или `zabbix/zbx_ses_template_5.0_up.xml` (для UserParameter) 3. Нажать Import 4. Привязать шаблон "SES Monitor" к нужному хосту ## Формат сценариев Сценарии описываются в YAML-файлах в каталоге `config/scenarios/`. Это гибкий DSL, который не зависит от конкретного проекта SES. ### Полный формат ```yaml # Имя сценария (используется в логах и ключах Zabbix) name: "example: проверка диалога" # Описание для документации description: "Проверяет что бот корректно отвечает на вопросы" # Включён ли сценарий (false — отключён) enabled: true # Интервал запуска в секундах interval: 300 # Таймаут HTTP-запроса в секундах timeout: 30 # ID робота (если не указан — берётся из config.yaml) 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/list ``` 2. **Пропишите robot_id** в `config/config.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. **Добавьте item в Zabbix** для вашего сценария (см. комментарий в `zbx_ses_template.xml`) 6. **Запустите демон** и проверьте что метрики идут в Zabbix ## Расширение системы ### Добавление нового сценария 1. Создать `config/scenarios/my_scenario.yaml` 2. Скопировать структуру из примеров 3. Описать шаги и ожидания 4. Сценарий автоматически подхватится через hot-reload (каждые 60 секунд) ### Добавление новой метрики 1. В нужном модуле добавить поле в датакласс-результат 2. В методе `to_zabbix_metrics()` добавить соответствующий ключ 3. В `main.py` вызвать `self._zabbix.add(key, value)` 4. Добавить item в Zabbix шаблон ### Мониторинг SEE, SMC, TTS, QAS, SPR Заложена возможность расширения для мониторинга внутренних сервисов SES. **SEE (распознавание намерений/сущностей):** ```python for entry in entries: for model in entry.models: if model.startswith("see:"): see_model = model.split(":", 1)[1] # Анализ точности распознавания ``` **SMC (классификация):** ```python if model.startswith("smc:"): # Отслеживание дрифта классификации ``` **TTS (синтез речи):** ```python # Проверка наличия голосовых ответов в реплаях if any(a.get("voice") for a in entry.raw.get("reply", {}).get("answers", [])): tts_ok_count += 1 ``` **QAS (вопросно-ответная система):** ```python # Поле qas в archive entry — проверка наполненности if not entry.raw.get("current", {}).get("qas"): qas_empty_count += 1 ``` **SPR (распознавание речи):** ```python # Косвенная проверка через тестовые сценарии, # которые отправляют аудио и проверяют текстовую расшифровку ``` ### Prometheus/Grafana При необходимости можно добавить экспорт метрик в Prometheus: ```python from prometheus_client import Gauge, start_http_server api_liveness = Gauge("ses_api_liveness", "SES API availability") ``` ## Мониторинг самого монитора - **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