Maksim Totmin 6d8bf29045 refactor: migrate to src-layout (PEP 517/518)
Move ses_monitor package into src/ directory for proper
Python packaging standards (src-layout).

- src/ses_monitor/ — package source
- pyproject.toml: [tool.setuptools.packages.find] where = ["src"]
- pyproject.toml: [tool.pytest.ini_options] pythonpath = ["src"]
- 59 tests pass unchanged
2026-06-19 20:29:22 +07:00

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. Установка пакета

# Копируем проект на сервер
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:

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. Создание сценария

Скопируйте пример и адаптируйте под ваш проект:

cp config/scenarios/example_liveness.yaml config/scenarios/my_project.yaml

Формат сценария описан ниже.

5. Запуск

# Проверка вручную:
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.

Полный формат

# Имя сценария (используется в логах и ключах 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 вашего сценария:

    curl -s http://<ses-host>:6190/ses/robot/list
    
  2. Пропишите robot_id в config/config.yaml

  3. Создайте файл сценария, описав шаги диалога:

    cp config/scenarios/example_liveness.yaml config/scenarios/$(hostname).yaml
    vim config/scenarios/$(hostname).yaml
    
  4. Протестируйте вручную шаги через curl:

    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 (распознавание намерений/сущностей):

# В archive_auditor.py можно добавить анализ confidence-оценок:
for entry in entries:
    for model in entry.models:
        if model.startswith("see:"):
            see_model = model.split(":", 1)[1]
            # Анализ точности распознавания

SMC (классификация):

if model.startswith("smc:"):
    # Отслеживание дрифта классификации

TTS (синтез речи):

# Проверка наличия голосовых ответов в реплаях
if any(a.get("voice") for a in entry.raw.get("reply", {}).get("answers", [])):
    tts_ok_count += 1

QAS (вопросно-ответная система):

# Поле qas в archive entry — проверка наполненности
if not entry.raw.get("current", {}).get("qas"):
    qas_empty_count += 1

SPR (распознавание речи):

# Косвенная проверка через тестовые сценарии,
# которые отправляют аудио и проверяют текстовую расшифровку

Prometheus/Grafana

При необходимости можно добавить экспорт метрик в Prometheus:

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

Description
Система непрерывного мониторинга диалоговой сценарной машины SES (Service Engine Server).
Readme 310 KiB
Languages
Python 100%