Skip to content

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

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

Что heartbeat сообщает панели ​

Каждые 15 секунд каждый узел сообщает, запускает ли он то, что получил, число открытых соединений всего и по инбаундам, сколько раз перезапускалось его ядро и последнюю ошибку запуска, а также счёт соединений, которые отклонили его блокирующие аутбаунды. Панель держит это в памяти, пока узел продолжает отвечать. Узел, который перестал отвечать, показывает «нет данных», а не свои последние цифры.

История состояния ​

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

  • За последние 7 дней хранится каждый 5-минутный замер.
  • Более старые замеры сворачиваются в один на узел за час — среднее по замерам, в которых был каждый показатель.
  • История хранится 90 дней по умолчанию, до двух лет. 0 останавливает запись и очищает её.
  • Замер, в котором узел ничего не сообщил, никогда не сохраняется. У узла, который не может сообщать показатели хоста, нет истории, а не история из нулей.

Полоса доступности ​

Полоса на узле делит окно времени на три состояния:

СостояниеКак показаноЧто значит
РаботаетВ сетиу панели есть замер от узла за этот интервал
Не работаетНе отвечалпанель работала весь интервал, а узел не дал ни одного замера
НеизвестноНе наблюдалсяпанель не может сказать: она была выключена, узла ещё не было или узел никогда не давал замеров

Полоса никогда не рисует сбой, который не может доказать. Интервал считается нерабочим, только если один запуск панели наблюдал его целиком и ничего не услышал. Интервал рядом с перезапуском панели считается неизвестным, а не нерабочим. Узел, который вообще никогда не сообщал показатели хоста, потому что работает на платформе, где это невозможно, может отлично обслуживать, поэтому его полоса остаётся неизвестной, а не красной.

Чтобы отличить «панель была выключена» от «узел не работал», панель записывает каждый свой запуск: когда он начался, когда она последний раз была жива и остановилась ли она штатно. Полоса использует 5-минутные интервалы в пределах последних 7 дней и часовые дальше, в соответствии с хранимой историей.

Живые соединения по запросу ​

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

  • Счётчики для пользователя приходят со всех подключённых узлов сразу, из итогов, которые каждый узел поддерживает в актуальном состоянии, поэтому запрос дешёвый.
  • Строки (источник, назначение, правило, аутбаунд, сеть, возраст, байты) приходят с одного узла за раз, обновляются каждые 10 секунд, пока открыт диалог, новые сверху, не больше 500 строк. Счётчики остаются полными, даже когда строки обрезаны.
  • Назначение — это живое состояние, а не запись. Панель не записывает, куда подключаются пользователи.

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

Эндпоинт метрик ​

Панель публикует свои показатели по адресу /metrics в формате Prometheus, для ваших собственных Prometheus и Grafana. Их настройка, готовый дашборд Grafana и имена всех метрик описаны ниже.

  • Нужен токен. Используйте API-токен только с областью stats:read. Документ называет каждый узел и его адрес, поэтому открытого режима нет.
  • Всё — по узлу, по фиксированной категории или по всему парку. Ничего не размечено по пользователям: одна метка на учётную запись — это один ряд на учётную запись, хранимый весь срок хранения. Вопросы об одной учётной записи решает API отчётов панели (/api/reports/*) за выбранный вами период.
  • Отсутствует, а не ноль. У показателя, который узел не сообщил (диск, память, нагрузка, соединения, перезапуски, пользователи онлайн), ряда нет вовсе. Разрыв на графике значит, что панель не знает, а не что число упало.
  • Единственное исключение — число доставок событий по состоянию, которое экспортируется всегда, чтобы могло сработать оповещение о мёртвых доставках.
  • Отклонённые соединения экспортируются по узлу и по блокирующему аутбаунду.

Каждый опрос вычисляется из базы данных и живых показателей в этот момент, поэтому при интервале опроса 60 секунд ничего не теряется.

Prometheus и Grafana ​

Репозиторий панели содержит конфигурацию опроса Prometheus, дашборд Grafana и дополнительный compose-файл, который запускает оба рядом с панелью в Docker.

С Docker ​

Дополнительный файл подключается к compose-сети панели и обращается к панели по имени сервиса; панели не нужен дополнительный опубликованный порт.

bash
# 1. Fetch the monitoring directory next to your docker-compose.yml
curl -fsSL https://github.com/nexora-vpn/panel/archive/refs/heads/main.tar.gz \
  | tar -xz --strip-components=1 panel-main/monitoring

# 2. Put a token with the stats:read scope where Prometheus reads it
printf '%s' 'PASTE-THE-TOKEN' > monitoring/prometheus/token

# 3. Set Grafana's password
cp monitoring/.env.example .env      # or merge its lines into your .env
nano .env

# 4. Start everything
docker compose -f docker-compose.yml -f monitoring/docker-compose.monitoring.yml up -d

С этого момента всегда указывайте оба файла -f, иначе обычный docker compose up -d снова удалит два сервиса. Чтобы это происходило автоматически:

bash
echo 'COMPOSE_FILE=docker-compose.yml:monitoring/docker-compose.monitoring.yml' >> .env

Grafana слушает только loopback сервера. Подключайтесь к ней через SSH:

bash
ssh -L 3000:localhost:3000 you@your-server
# then open http://localhost:3000 and sign in with GRAFANA_PASSWORD

Дашборд Nexora fleet уже там. Prometheus не публикуется вовсе: у него нет собственного входа, а хранит он всю вашу эксплуатационную картину.

  • Панель сама обслуживает HTTPS: в monitoring/prometheus/prometheus.yml задайте scheme: https и tls_config: { insecure_skip_verify: true }. Сертификат панели называет ваше публичное имя хоста, а не имя сервиса panel, к которому подключается Prometheus.
  • У панели есть базовый путь: задайте metrics_path: /your-base-path/metrics.
  • У панели задано имя хоста: /metrics отвечает только на этом имени. Дайте сервису панели это имя как сетевой псевдоним в своём compose-файле (networks: { default: { aliases: [panel.example.com] } }) и опрашивайте panel.example.com:2095.

Без Docker ​

yaml
scrape_configs:
  - job_name: nexora-panel
    scheme: https
    metrics_path: /metrics
    authorization:
      type: Bearer
      credentials_file: /etc/prometheus/nexora-token
    static_configs:
      - targets: ['panel.example.com']

Для Grafana импортируйте monitoring/grafana/dashboards/nexora-fleet.json из репозитория панели. Он ожидает источник данных Prometheus с uid nexora-prometheus.

Токен ​

Создайте его на странице токенов API с областью stats:read и ничем больше и храните в отдельном файле, а не внутри prometheus.yml, который часто вставляют в чаты. Отзыв токена сразу останавливает опрос.

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

МетрикаЗначение
nexora_panel_build_info1, с работающей версией в метке
nexora_panel_start_time_secondsкогда запустился процесс панели; time() - this — время работы
nexora_license_valid1, пока лицензия действительна, иначе 0
nexora_license_expires_at_secondsсрок действия лицензии; отсутствует, если лицензия бессрочная
nexora_license_limit{resource}, nexora_license_used{resource}предел и текущее число для user и node (−1 = без ограничений)
nexora_users_total{status}учётные записи по состоянию: active, disabled, expired, limited, pending
nexora_users_onlineучётные записи с трафиком в окне онлайна
nexora_nodes_totalузлы, известные панели
nexora_node_up, nexora_node_enabledпо узлу: отвечает и включён
nexora_node_traffic_bytes_total{direction}трафик, учтённый на узле
nexora_node_online_usersучётные записи с трафиком на этом узле в окне онлайна
nexora_node_connections, nexora_node_engine_restarts_totalоткрытые соединения; перезапуски с момента запуска узла
nexora_node_rejected_connections_total{outbound}соединения, отклонённые блокирующим аутбаундом
nexora_node_disk_bytes, nexora_node_disk_used_bytes, nexora_node_memory_bytes, nexora_node_memory_used_bytes, nexora_node_load1хост узла
nexora_event_deliveries{status}, nexora_event_subscribersдоставки событий по состоянию (pending, delivered, dead) и включённые подписчики

Каждая метрика узла несёт метки node (его имя) и id.

Полезные оповещения ​

yaml
groups:
  - name: nexora
    rules:
      - alert: NexoraPanelDown
        expr: up{job="nexora-panel"} == 0
        for: 5m
      - alert: NexoraNodeDown          # a switched-off node is not an outage
        expr: nexora_node_up == 0 and nexora_node_enabled == 1
        for: 10m
      - alert: NexoraNodeDiskFilling
        expr: nexora_node_disk_used_bytes / nexora_node_disk_bytes > 0.9
        for: 30m
      - alert: NexoraEventDeliveriesDead
        expr: increase(nexora_event_deliveries{status="dead"}[1h]) > 0

Если вы продаёте по лицензии, добавьте nexora_license_expires_at_seconds - time() < 7 * 86400.

Оповещения как события ​

Несколько вещей панель оценивает сама и создаёт событие, когда они меняются, один раз при пересечении порога и ещё раз при восстановлении:

СобытиеКогда
node.disconnected, node.connectedузел перестаёт или начинает отвечать
node.disk_high, node.disk_recoveredзаполнение диска пересекает порог, по умолчанию 90%; восстановление — на пять пунктов ниже
node.memory_high, node.memory_recoveredто же для памяти
node.rejections_highотказы через один блокирующий аутбаунд превышают частоту в час, по умолчанию 100
node.limit_reachedпериодический лимит трафика узла отключил его

Пороги задаются на странице Вебхуки; 0 отключает оповещение. Частота отказов измеряется за скользящий час по тому, что наблюдала сама панель, поэтому большой счёт, присланный в первом heartbeat после перезапуска панели, — это история, а не всплеск. События доходят до вебхуков, Telegram, почты и дополнений; см. Шина событий.

Текст и изображения — CC BY 4.0.