Maksim Totmin 763a1a2a16 cleanup: remove dead archive_auditor module
archive_auditor.py not imported or used by main.py since archive
metrics were removed from the monitoring loop. Remove the dead
module along with its 10 tests and dead imports (ModelsMonitoringConfig,
AppConfig, ArchiveEntry).

Tests: 59 -> 48 (all pass)
2026-06-19 20:36:34 +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%