ses-monitor/README.md
Maksim Totmin 7394b14b52 Initial commit: ses-monitor watchdog for SES
Универсальный watchdog-мониторинг Service Engine Server (SES):
- Liveness-проверки (API, лицензия, роботы)
- Диалоговые сценарии из YAML с агрегацией в 6 фиксированных Zabbix-метрик
- Доставка: zabbix_sender (active push) или UserParameter (пассивный опрос)
- Поддержка Python 3.7+, Zabbix 5.0
2026-06-19 20:26:26 +07:00

364 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 # Движок выполнения сценариев
│ ├── archive_auditor.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+**
- **Zabbix Agent** с утилитой `zabbix_sender`
- Доступ к SES API (`http://<ses-host>:6190`)
- Доступ к Zabbix Server по порту 10051
### 2. Установка пакета
```bash
# Копируем проект на сервер
rsync -avz --exclude='.git' --exclude='__pycache__' ./ root@<ses-host>:/opt/ses-monitor/
# На сервере:
cd /opt/ses-monitor
# Создаём виртуальное окружение и устанавливаем зависимости
python3 -m venv .venv
source .venv/bin/activate
pip install -e .
# Устанавливаем zabbix_sender (если ещё не установлен)
apt update && apt install -y zabbix-sender
# Создаём каталог для логов
mkdir -p /var/log/ses-monitor
```
### 3. Настройка конфигурации
Отредактируйте `config/config.yaml`:
```yaml
ses:
base_url: "http://10.101.60.31:6190" # URL вашего SES API
robot_id: "" # ID робота из GET /ses/robot/list
channel: "monitoring" # Имя канала в архиве
request_timeout: 30
zabbix:
enabled: true
server: "127.0.0.1" # IP вашего Zabbix сервера
host: "my-server-name" # Имя хоста в Zabbix
port: 10051
sender_path: "/usr/bin/zabbix_sender"
```
### 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.xml`
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://<ses-host>: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://<ses-host>:6190/ses/ask/<robot_id>?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
# В archive_auditor.py можно добавить анализ confidence-оценок:
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