Мониторинг и логи¶
Что наблюдать у работающей платформы DataHUB, какие healthcheck-эндпоинты доступны, как устроены логи и какие алерты стоит настроить в системе мониторинга. Конкретный стек мониторинга (Prometheus, Zabbix, Grafana, Loki, ELK) — на стороне инфраструктуры заказчика; здесь — что именно ему отдавать.
Healthcheck-эндпоинты¶
Сводно — все точки, по которым можно судить о состоянии платформы.
| Эндпоинт | Источник | Что проверяет |
|---|---|---|
https://lk.<your-domain>/healthz |
nginx | nginx жив и отвечает |
https://lk.<your-domain>/api/actuator/health |
backend (через nginx) | backend жив; общий статус без токена, подробности — с токеном администратора |
https://lk.<your-domain>/api/actuator/health/liveness |
backend (Spring Actuator) | приложение живо; от базы и внешних систем не зависит |
https://lk.<your-domain>/api/actuator/health/readiness |
backend (Spring Actuator) | приложение готово принимать трафик |
Docker (healthy) status в docker ps |
контейнеры | внутренний HEALTHCHECK каждого блока |
nginx /healthz¶
Возвращает 200 OK\n. Не зависит от состояния backend — это «жив ли сам reverse proxy». Если nginx не работает (сбой контейнера, неверный конфиг) — этот эндпоинт недоступен.
Базовая проба:
Spring Actuator /api/actuator/health¶
Единственный эндпоинт actuator, открытый без токена. Остальные (info, metrics,
mappings, env) требуют роль администратора и анониму отвечают 401.
Без токена отдаётся общий статус и список включённых групп проб — и ничего больше:
Этого достаточно и мониторингу, и пробе контейнера: UP — HTTP 200, DOWN — HTTP 503.
Состав проверок видит только администратор (management.endpoint.health.show-details: when-authorized
плюс roles: ADMIN). С токеном администратора ответ такой:
{
"status": "UP",
"components": {
"db": { "status": "UP", "details": { "database": "PostgreSQL", "validationQuery": "isValid()" } },
"diskSpace": { "status": "UP", "details": { "total": ..., "free": ..., "threshold": ... } },
"ping": { "status": "UP" }
}
}
В агрегированный статус входит только база данных (плюс свободное место и сама живость приложения). Два индикатора отключены конфигурацией намеренно:
rabbit(management.health.rabbit.enabled: false) — слишком чувствителен к коротким обрывам и давал ложныеDOWNпри штатной работе. Состояние брокера наблюдается через сам RabbitMQ Management API;mail(management.health.mail.enabled: false) — почтовый сервер внешний, и его недоступность не должна делать backend «нездоровым»: иначе проба контейнера получала бы 503 из-за чужого SMTP.
Базовая проба:
Состава проверок в этом ответе нет — только статус и имена групп; jq нужен разве что для читаемости.
Пробы liveness и readiness¶
Два отдельных пути, оба без токена:
/api/actuator/health/liveness— приложение живо. В группу входит толькоlivenessState, поэтому недоступная база или брокер её не роняют:DOWNздесь означает, что приложение нужно перезапускать, а не что сломался сосед. По этой пробе проверяется контейнер backend;/api/actuator/health/readiness— приложение готово принимать трафик, то есть стартовая инициализация завершена.DOWNсразу после запуска — норма;DOWNнадолго — проблема.
Состав групп Spring Boot не показывает никому, даже администратору, — у проб всегда только
статус. Поэтому ?show-details и токен к ним ничего не добавляют.
Вне Kubernetes эти пути включаются настройкой: management.endpoint.health.probes.enabled: true
в application.yml backend. Если она выключена, пути отвечают 404, и мониторинг приходится
строить на сводном /api/actuator/health — но тогда недоступная база делает «нездоровым» само
приложение.
Docker HEALTHCHECK¶
У большинства блоков платформы внутри образа определён HEALTHCHECK, который Docker опрашивает с заданным интервалом и помечает контейнер (healthy) / (unhealthy) / (starting).
| Блок | Что проверяет | Интервал | Что значит unhealthy |
|---|---|---|---|
postgres |
pg_isready |
10s | БД не отвечает на подключения |
rabbitmq |
rabbitmq-diagnostics check_running, check_port_connectivity, check_local_alarms |
30s | узел не загружен, порты не принимают соединения или сработал аларм памяти/диска |
frontend |
GET http://localhost:<порт>/healthz |
30s | Next.js не отдаёт healthz |
backend |
GET http://localhost:<порт>/actuator/health/liveness |
30s | приложение не живо: не отвечает или отдаёт не 2xx |
nginx |
— | — | (используйте /healthz) |
flyway |
— (одноразовый контейнер) | — | (после Exited (0) — успех) |
dh_initializer |
— (одноразовый контейнер) | — | (после Exited (0) — успех) |
Проба backend идёт к liveness, а не к сводному /actuator/health, именно поэтому: статус DOWN
из-за недоступной базы — нездоровье базы, а не контейнера приложения, и помечать unhealthy надо
не его. При этом проба строгая — любой ответ не 2xx считается отказом. Порт в пробах backend и
frontend берётся из настроек установки, а не вписан числом.
Сводка состояния:
В колонке STATUS должно быть Up <время> (healthy) для всех «живых» блоков. Up <время> без (healthy) — у блоков без HEALTHCHECK (это нормально).
Что должен мониторить production¶
Минимальный набор алертов:
1. Доступность платформы¶
https://lk.<your-domain>/healthzне возвращает 200 более 1 минуты → CRITICAL.https://lk.<your-domain>/api/actuator/healthвозвращает не 200 более 5 минут → CRITICAL.https://exchange.<your-domain>/api/exchange/...возвращает 5xx более X% за окно → WARN.
2. Состояние контейнеров¶
- Любой контейнер платформы (
postgres,rabbitmq,backend,frontend,nginx,pg-admin) не в состоянииrunning→ CRITICAL. - Любой контейнер с HEALTHCHECK в состоянии
unhealthyболее 5 минут → CRITICAL. - Контейнер перезапускался N раз за последний час → WARN (признак нестабильности).
Сбор статусов:
sudo docker inspect --format '{{.Name}} {{.State.Status}} {{.State.Health.Status}}' $(docker ps -aq)
3. Дисковое пространство¶
/etc/datahub/postgres/data/— свободно менее 10 GB → WARN, менее 1 GB → CRITICAL. При исчерпании PostgreSQL перестаёт принимать write-операции./etc/datahub/rabbitmq/data/— то же по принципу. При нехватке RabbitMQ блокирует приём сообщений (free disk space alarm)./var/lib/docker/— общее место под образы и логи контейнеров. Свободно менее 20% → WARN.
4. RabbitMQ¶
- Длина любой очереди растёт без снижения более 30 минут → WARN (потребитель отстаёт или недоступен).
- Алармы RabbitMQ (memory/disk) активны → CRITICAL. Проверяются через Management API:
GET /api/aliveness-test/%2F. - Число коннекшенов резко выросло → WARN (возможна утечка).
Метрики достаются через RabbitMQ Management API (/api/overview, /api/queues).
5. PostgreSQL¶
- Подключения близки к
max_connections→ WARN. - Долгие запросы (> 30 сек) → WARN.
- Размер БД растёт неожиданно быстро → WARN.
Доступно через pg_stat_activity, pg_stat_database.
6. TLS-сертификаты¶
- Срок действия сертификата < 30 дней → WARN, < 7 дней → CRITICAL.
Проверка:
echo | openssl s_client -servername lk.<your-domain> -connect lk.<your-domain>:443 2>/dev/null \
| openssl x509 -noout -enddate
7. Backend-метрики (через Spring Actuator)¶
Spring Actuator выставляет метрики Micrometer на /actuator/metrics и в формате Prometheus — на /actuator/prometheus (если включён micrometer-registry-prometheus). Оба пути закрыты ролью администратора: без токена — 401, поэтому сборщику метрик нужны учётные данные.
Полезные метрики для алертов:
hikaricp_connections_active/hikaricp_connections_max— насыщение пула БДhttp_server_requests_seconds_count+ tagstatus— счётчики ответов 4xx/5xxjvm_memory_used_bytes— использование heapprocess_cpu_usage— CPU контейнераcache_sizeдля именованных кэшей Caffeine
Логи: где, что, как читать¶
Логи контейнеров (Docker json-file)¶
Все блоки логируют через Docker json-file driver с ротацией 100 МБ × 10 файлов на сервис (~1 GB на блок). Логи доступны через docker logs:
Физическое расположение на хосте — /var/lib/docker/containers/<id>/<id>-json.log. При централизованном сборе логов агенты (Promtail, Filebeat, Vector) подхватывают эти файлы напрямую.
Логи nginx (отдельный том)¶
Nginx, в отличие от остальных, дополнительно пишет логи в bind-mount /etc/datahub/nginx/log/:
/etc/datahub/nginx/log/
├── access.log # общий access-лог
├── error.log # error-лог
├── access_api.log # обращения к /api/* на личном кабинете
├── access_auth.log # обращения к /api/auth/*
├── access_auth_session.log # обращения к /api/auth/session*
├── access_docs.log # обращения к документации backend
├── access_exchange_log.log # обращения к exchange API
├── access_log_80.log # запросы на порт 80 до редиректа
└── access_log_15432.log # обращения к pgAdmin и RabbitMQ Management
Формат datahub_format — единый для всех виртуальных серверов:
<ISO-время> status=<код> request="<метод> <URL>" http_referer="<...>" body_bytes_sent=<N> ip=<IP> ua="<...>" http_x_forwarded_for="<...>"
Раздельные логи по серверам помогают быстро локализовать проблему: «5xx на exchange API» → access_exchange_log.log, «brute-force на login» → access_auth.log.
Ротация nginx-логов¶
Nginx не делает ротацию сам. На production надо настроить logrotate:
sudo tee /etc/logrotate.d/datahub-nginx >/dev/null <<'EOF'
/etc/datahub/nginx/log/*.log {
daily
rotate 30
compress
missingok
notifempty
sharedscripts
postrotate
docker exec nginx nginx -s reopen
endscript
}
EOF
nginx -s reopen переоткрывает дескрипторы логов после ротации, иначе nginx продолжит писать в уже переименованный файл.
Логи backend (прикладные)¶
Backend пишет логи через стандартный logback Spring Boot — в stdout/stderr контейнера. Дополнительно том ./log/:/var/log/nginx/:rw (путь исторический), но в дефолтной конфигурации Spring туда не пишет.
Уровни логирования по умолчанию — INFO. Уровни на профиле dev — DEBUG для com.datahub. Подробнее — в Сервер DataHUB / Логирование.
Логи PostgreSQL и RabbitMQ¶
Эти блоки пишут только в stdout/stderr своих контейнеров (доступно через docker logs postgres и docker logs rabbitmq). Отдельных томов для логов на хосте нет — это упрощает развертывание и снимает заботу о ротации.
При диагностике через docker logs можно фильтровать:
sudo docker logs postgres 2>&1 | grep -i error
sudo docker logs rabbitmq 2>&1 | grep -i 'error\|alarm'
Централизованный сбор логов¶
При наличии в инфраструктуре заказчика централизованной системы сбора логов (Loki, Elasticsearch, Splunk, Vector → S3) — настроить отправку из двух источников:
- Docker контейнеры через файлы
/var/lib/docker/containers/<id>/<id>-json.logили через docker logging driver (fluentd,gelf,syslog). - Nginx-логи через файлы
/etc/datahub/nginx/log/*.log.
Готовых интеграций «из коробки» в платформе нет — конфигурация агентов на стороне заказчика.
При наличии Loki:
- Лейблы —
container_name,compose_project,compose_service(Docker logging driver их сам добавит). - Парсинг nginx — через готовый pipeline для
combined-формата плюс кастомные поля изdatahub_format.
Метрики уровня платформы (Prometheus)¶
Backend не выставляет endpoint /actuator/prometheus в дефолтной поставке (нет зависимости micrometer-registry-prometheus). При необходимости — собрать backend с этой зависимостью и включить:
Альтернатива — снимать стандартные метрики /actuator/metrics периодически своими средствами (exporter, скрипт), но это менее удобно.
Метрики RabbitMQ Management — доступны напрямую: GET https://lk.<your-domain>:15672/api/.... Существуют готовые Prometheus-exporters для RabbitMQ.
Метрики PostgreSQL — снимаются postgres_exporter, подключается отдельным контейнером в dh_network.
Тонкие моменты¶
- Backend не выставляет HEALTHCHECK в docker-compose — это сделано осознанно, статус определяется через Spring Actuator. Если ваша система мониторинга ожидает
(healthy)вdocker psдля backend — придётся добавить custom HEALTHCHECK в локальную копиюdocker-compose.yml. - Frontend HEALTHCHECK строгий — при недоступности
/healthz5 минут (5 проб × 30s × 1 retry) контейнер уходит вunhealthy. Это может ложно срабатывать при тяжёлых server-side операциях. - Логи RabbitMQ содержат много WARN-сообщений в штатном режиме (соединения коннектятся-дисконнектятся, каналы открываются-закрываются). Не реагируйте на каждый WARN — алерты ставьте только на ERROR и алармы.
Что дальше¶
- Сервер DataHUB / Логирование — настройка уровней логов backend.
- Reverse Proxy — детали формата
datahub_formatи раздельные логи по виртуальным серверам. - Диагностика / Анализ логов — как читать логи при разборе инцидентов.
- Production-настройка — где мониторинг входит в общий чек-лист готовности.