SIRINVIDEO Документация администратора и интегратора На сайт 2026.08

Мониторинг и метрики

Что показывает панель, метрики Prometheus на закрытом эндпоинте /metrics, поток событий SSE, журнал и показатели, за которыми стоит следить.

У сервера четыре независимых источника наблюдаемости, и выбирать между ними нужно осознанно:

Источник Формат Для чего
Панель управления веб-интерфейс глазами, здесь и сейчас
GET /metrics текст Prometheus внешняя система сбора метрик и оповещений
GET /api/v1/events Server-Sent Events живая лента изменений для своих панелей
GET /api/v1/logs JSON разбор конкретного инцидента

Все четыре читают одно и то же состояние; ничего не считается дважды.

Что показывает панель#

Раздел Overview — сводка узла. Шесть плиток вверху:

Плитка Значение Норма
Live streams сколько потоков сейчас принимается равно числу настроенных, если ни один не выключен
Live viewers зрителей живого видео
DVR viewers зрителей архива
All sessions всего сессий отдачи сумма двух предыдущих
Ingress входящая полоса от источников пропорциональна числу и битрейту потоков
Egress исходящая полоса к зрителям Ingress × число зрителей на поток

Ниже — панель Resource posture с четырьмя показателями: Process CPU (в ядрах), Host CPU, Process memory (RSS) и Host memory.

Раздел System разворачивает то же самое подробнее: загрузка по каждому ядру, аптайм, открытые дескрипторы, потери приёма UDP и тренды процессора и памяти за две минуты.

Индикатор в верхней панели говорит, откуда взяты цифры: Live telemetry / SSE live — данные идут потоком событий; Polling — поток недоступен, идёт периодический опрос; Data stale · 7s — показаны последние полученные данные и им столько-то секунд.

Раздел Overview: живые плитки, график раздачи и состояние ресурсов
Раздел Overview: живые плитки, график раздачи и состояние ресурсов

Колокольчик Alerts в верхней панели копит оповещения об ухудшении здоровья потоков. Оповещение приходит на переходе состояния — при деградации, при отказе, при появлении сразу нездорового потока и при восстановлении. Залпа оповещений при старте сервера не бывает.

Метрики Prometheus#

GET http://media.example.com:8080/metrics

Формат — text/plain; version=0.0.4. Обратите внимание: это корень хоста, а не /api/v1/metrics. Второй адрес тоже существует, но отдаёт JSON-дамп и служит другой задаче — см. GET /api/v1/metrics.

Эндпоинт закрыт и требует токена#

Без учётных данных /metrics отвечает 401 — всегда

Эндпоинт не публичный. Он принимает те же учётные данные, что и /api/v1, и без них отвечает 401 {"error":"unauthorized"}в том числе на сервере, где вообще не настроено ни одних учётных данных. Иначе и быть не может: тело экспозиции называет каждый поток, его здоровье и счётчики зрителей, то есть раскрывает ровно то, ради чего закрыт /api/v1.

Значит, сборщику метрик нужно выдать токен. Токен передаётся строго заголовком Authorization; строкой запроса — никогда.

# Без токена:
curl -sS -o /dev/null -w '%{http_code}\n' "$BASE/metrics"
401
# С токеном:
curl -sS "$BASE/metrics" -H "Authorization: Bearer $TOKEN" | head -3
# HELP hastreamer_process_cpu_cores Process CPU usage in cores (cputime-delta / cores).
# TYPE hastreamer_process_cpu_cores gauge
hastreamer_process_cpu_cores 0.1000

Токен для сборщика#

Выдавать системе мониторинга пароль администратора не нужно и не следует: сессия живёт 12 часов, а сборщик работает годами. Заведите статический токен чтения — учётную запись, которая ничего не может изменить.

auth {
  admin_password "пароль-администратора";
  api_read_token "не-короче-16-символов";
}
Параметр Тип и допустимые значения По умолчанию Применение
api_read_token строка, не короче 16 символов не задан горячее

Этот токен открывает только безопасные методы (GET, HEAD, OPTIONS) на /api/v1/* и GET /metrics. Любая попытка что-либо изменить получает 403 {"error":"forbidden","reason":"read_token_cannot_write"}, а чтение конфигурации целиком — 403 … "reason":"read_token_cannot_read_config". Подробнее — Введение и аутентификация.

Настройка сборщика — обычная авторизация bearer:

scrape_configs:
  - job_name: sirinvideo
    metrics_path: /metrics
    scheme: https
    authorization:
      type: Bearer
      credentials: "не-короче-16-символов"
    static_configs:
      - targets: ["media.example.com:8080"]

Что экспортируется#

Процесс и хост

Серия Тип Смысл
hastreamer_process_cpu_cores gauge потребление CPU процессом в ядрах
hastreamer_worker_cores gauge сколько ядер отведено под медиа
hastreamer_process_rss_bytes gauge резидентная память процесса
hastreamer_host_cpu_busy_ratio gauge занятость процессора хоста, доля 0…1
hastreamer_host_cpus gauge логических ядер на хосте
hastreamer_mem_total_bytes gauge всего памяти на хосте
hastreamer_mem_available_bytes gauge доступно памяти на хосте
hastreamer_open_fds gauge открытых файловых дескрипторов
hastreamer_uptime_seconds gauge время работы процесса

Нагрузка

Серия Тип Смысл
hastreamer_streams gauge работающих потоков на узле
hastreamer_sessions gauge активных сессий отдачи

Приём по UDP

Серия Тип Смысл
hastreamer_udp_ingest_kernel_drops_total counter датаграмм отброшено буфером сокета ядра
hastreamer_udp_ingest_queue_dropped_total counter датаграмм отброшено очередью приёма
hastreamer_udp_ingest_recv_errors_total counter ошибок чтения сокета

По потокам (метка stream)

Серия Тип Смысл
hastreamer_stream_no_data_seconds{stream} gauge секунд с момента последних данных от источника
hastreamer_stream_ingest_latency_ms{stream} gauge задержка приёма, миллисекунды
hastreamer_streams_omitted gauge сколько потоков не попало в экспозицию из-за ограничения
Ограничение количества рядов по потокам

Серии с меткой stream выгружаются не более чем для 500 потоков. Если потоков больше, лишние молча не попадают в экспозицию, а их число видно в hastreamer_streams_omitted. Проверяйте эту серию на больших установках: ненулевое значение означает, что часть потоков вы не видите.

Готовые правила оповещения#

groups:
  - name: sirinvideo
    rules:
      - alert: StreamSourceSilent
        expr: hastreamer_stream_no_data_seconds > 30
        for: 1m
        annotations:
          summary: "Поток {{ $labels.stream }} не получает данных 30+ секунд"

      - alert: UdpIngestDrops
        expr: rate(hastreamer_udp_ingest_kernel_drops_total[5m]) > 0
        for: 5m
        annotations:
          summary: "Ядро отбрасывает датаграммы приёма  мал буфер сокета"

      - alert: StreamMetricsTruncated
        expr: hastreamer_streams_omitted > 0
        annotations:
          summary: "Метрики по потокам обрезаны ограничением на 500 рядов"

      - alert: WorkerCoresNearLimit
        expr: hastreamer_process_cpu_cores / hastreamer_worker_cores > 0.85
        for: 10m
        annotations:
          summary: "Занято более 85% отведённых ядер"

Поток событий (SSE)#

GET /api/v1/events?topics=<темы через запятую>

Единственный живой канал: text/event-stream, без буферизации на прокси. Пока подписчиков нет, сервер не выполняет для него никакой работы.

Авторизация. Обычный заголовок Authorization: Bearer, и только этот маршрут дополнительно принимает тот же токен в параметре ?token= — потому что браузерный EventSource не умеет задавать заголовки. Строкой запроса принимается лишь сессионный токен; статические токены — никогда.

curl -sN "$BASE/api/v1/events?topics=totals,alerts" -H "Authorization: Bearer $TOKEN"
id: 2614
data: {"payload":{"bytes_in":6735178851,"bytes_out":117270589,"dvr_bytes_out":24412877,
       "dvr_sessions":0,"live_bytes_out":92857712,"live_sessions":1,"sessions":1,"streams":10},
       "seq":2614,"topic":"totals","ts":1787143322623}

: hb

Формат кадра. Строки event: не бывает никогда — всё едет обычным сообщением SSE, а клиент маршрутизирует по полю topic внутри конверта:

{"topic":"…","seq":123,"ts":1787092182193,"payload":{}}

Не реже чем раз в 10 секунд приходит сердцебиение : hb — даже если все темы отфильтрованы.

Темы#

Тема Когда приходит Полезная нагрузка
totals каждую секунду те же поля, что у GET /totals
sessions каждую секунду sessions, dvr_sessions, live_sessions, joined, left
alerts только на переходе здоровья id, kind, severity, title, detail, stream, core, ts, from, to, reasons, alive, viewers
sessions-audit на открытии и закрытии сессии событие open / close / checkpoint с ключом сессии, протоколом и адресом
stream:<id> каждую секунду по каждому подписанному потоку alive, health, health_reasons, viewers, dvr_viewers, fps, bitrate, packets_in_per_s, source_error, reconnects

Отсутствие параметра topics означает все темы. Тема logs принимается в списке, но пока молчит.

Значения alerts.kind: degraded, failing, absent, recovered, removed. Значения severity: info для восстановления, warn для деградации, error для остального.

# Следить за здоровьем одного потока
curl -sN "$BASE/api/v1/events?topics=stream:cam1,alerts" -H "Authorization: Bearer $TOKEN"
Переподключение не теряет события

Если заголовок Last-Event-ID попадает в окно кольца (512 кадров), сервер дословно повторит пропущенные кадры. Если не попадает или подключение новое — сразу присылает снимок: один кадр totals, один sessions и по одному alerts на каждый нездоровый поток. Кадры stream:<id> не несут идентификатора и потому никогда не переигрываются.

sessions-audit — единственный способ увидеть каждое подключение

Тема отдаёт события открытия и закрытия отдельных сессий, но только пока подписчик подключён: за прошедшее время она ничего не покажет. Если нужен учёт всех просмотров, держите подписчика постоянно и складывайте события в своё хранилище.

Журнал#

Операционный журнал живёт в кольцевом буфере в памяти процесса (до 4096 записей) и доступен в разделе Logs панели и через GET /api/v1/logs.

curl -sS "$BASE/api/v1/logs?level=warn&limit=5" -H "Authorization: Bearer $TOKEN"
{"capture_level":"info","head_seq":17,
 "entries":[{"seq":17,"ts_ms":1787143225999,"level":"warn","target":"source",
             "stream":"cam1","msg":"[cam1] source stopped: error: Timeout"}]}

Порог записи задаётся директивой log_level:

Параметр Тип и допустимые значения По умолчанию Применение
log_level debug | info | warn | error info горячее
Понизить порог задним числом невозможно

Записи ниже capture_level в кольцо никогда не попадали. Запрос ?level=debug на сервере с порогом info вернёт пусто, и это не ошибка. Поднимите подробность (директива применяется сразу) и дождитесь новых событий; уже накопленное кольцо не пересобирается.

Для постоянного хранения журнал нужно снимать наружу: сервер пишет структурированный вывод в стандартный поток, который забирает журнал системы инициализации.

journalctl -u hastreamer -f

За чем следить#

Порядок — по частоте, с которой эти показатели действительно спасают.

Показатель Где смотреть Тревожно, когда
Секунды без данных от источника hastreamer_stream_no_data_seconds, колонка Health больше 30 с подряд: камера отвалилась или закрыт порт
Здоровье потоков вкладки Degraded и Failing, тема alerts ненулевое число дольше нескольких минут
Переподключения источника reconnects в карточке потока, вкладка Source растёт постоянно: нестабильная сеть или перегруженная камера
CPU в долях отведённых ядер hastreamer_process_cpu_cores ÷ hastreamer_worker_cores стабильно выше 0,85: пора добавлять ядра или сервер
Свободное место архива раздел Storage, строка прогноза прогноз заполнения короче срока хранения, который вам нужен
Потери приёма UDP hastreamer_udp_ingest_*_total счётчик растёт: мал буфер сокета, см. udp_ingest_rcvbuf
Потери у зрителей раздел Sessions, фильтр Loss > 0 доля потерь растёт у многих сессий сразу: узкая исходящая полоса
Задержки доставки колонка Lag в Sessions ненулевая у многих: сервер не успевает отдавать
Открытые дескрипторы hastreamer_open_fds приближается к системному пределу
Обрезка метрик hastreamer_streams_omitted больше нуля: часть потоков не видна системе мониторинга
Не сравнивайте Process CPU с %cpu из top

Показатель считается как дельта процессорного времени, делённая на число ядер, и выражается в ядрах: 0.12 — примерно одна восьмая ядра. Мгновенная выборка top — другая величина, и совпадать они не обязаны.

Куда дальше#