Наблюдаемость
Метрики, трассировка и журналы установки на своих серверах: что отдают сервисы, что из наблюдаемости приходит в комплекте и на какие показатели смотреть первыми.
На этой странице
Установка отдаёт три независимых сигнала: метрики Prometheus, трассы OTLP и журналы в JSON. Ниже — что именно отдаёт каждый сервис, что из обвязки уже лежит в комплекте, а что нужно настроить самому, и какие показатели стоит вывести на первый экран дежурного.
Что отдают сервисы
Четыре приложения — query-api, ingest-api, ch-writer и worker — поднимают
отдельный HTTP-листенер с единственным путём /metrics в формате Prometheus.
Адрес задаётся переменной METRICS_ADDR, по умолчанию порт
9090 у каждого бинарника. Это не тот порт, на котором сервис
обслуживает запросы: основной API слушает 8080, приём событий —
8081.
Посмотреть метрики живого сервиса, ничего не публикуя:
# из каталога комплекта
docker compose -f docker-compose.onprem.yml --env-file .env \
exec query-api wget -qO- http://localhost:9090/metrics | grep '^pp_'
Кроме прикладных рядов pp_* там же отдаются стандартные метрики Go-процесса
(память, горутины, GC) — они полезны, когда сервис ведёт себя странно, а
прикладные счётчики выглядят нормально.
Что поставляется в комплекте
Наблюдаемость в on-prem не отдельный профиль: перечисленные ниже контейнеры
поднимаются обычным up -d вместе с приложением. Пароли Grafana и Elastic
проверяет preflight.sh, поэтому запустить установку и «настроить мониторинг
потом» не получится — это осознанное решение поставки.
| Что | Контейнеры | Файл в комплекте |
|---|---|---|
| Метрики и правила | prometheus |
observability/prometheus.yml, monitoring/prometheus/actionpulse.rules.yml |
| Маршрутизация оповещений | alertmanager |
observability/alertmanager/alertmanager.yml |
| Панели | grafana |
observability/grafana/provisioning/, observability/grafana/dashboards/ |
| Метрики хоста и файл-метрики | node-exporter |
— |
| Метрики хранилищ | postgres-exporter, redis-exporter, nats-exporter |
— |
| Журналы | elasticsearch, kibana, filebeat, filebeat-metrics |
observability/filebeat/filebeat.onprem.yml |
| Трассы | jaeger |
jaeger/config-memory.yaml |
Prometheus скрейпит приложения по именам сервисов Compose —
query-api:9090, ingest-api:9090,
ch-writer:9090, worker:9090 — плюс
node-exporter:9100, postgres-exporter:9187, redis-exporter:9121,
nats-exporter:7777 и собственный Prometheus-эндпоинт ClickHouse
clickhouse:9363. Интервал скрейпа — 15 секунд, таймаут — 10. Срок хранения
задаёт PROMETHEUS_RETENTION, в шаблоне это 15 дней. Имена job’ов
(query-api, ingest-api, ch-writer, worker) значимы: на них ссылаются
поставляемые правила, поэтому переименовывать их не нужно.
Панелей две: «ActionPulse — эксплуатация» (приём, отставание записи, DLQ, 5xx, p95, диск, состояние резервных копий) и «ActionPulse — хранилища и пулы» (PostgreSQL, Redis, ClickHouse, NATS и пулы соединений приложения). Обе приезжают через provisioning, отдельного импорта не требуют. В панели эксплуатации три текстовых блока честно отмечают участки без метрик — это не графики, а напоминание, что доставка вебхуков, воркер биллинга и задачи приватности пока не имеют счётчиков исполнения.
Что придётся настроить самому
- Оповещения никуда не уходят по умолчанию. В поставляемом
alertmanager.ymlмаршрут ведёт в приёмникnull: правила срабатывают, алерты видны в Prometheus и Grafana, но никому не отправляются. Добавьте свой приёмник (почта, вебхук, Telegram) и переключите на негоroute.receiver. Критичные правила должны идти в канал с дежурством. - Доступ к интерфейсам. У Grafana, Prometheus, Alertmanager, Kibana и
Jaeger нет портов на хосте: они доступны только из соответствующей сети
Compose, через VPN или контролируемый временный port-forward. Grafana требует
вход (анонимный доступ и саморегистрация выключены), пароль администратора —
GRAFANA_ADMIN_PASSWORD. - Ссылка на документацию в панели. Замените её на внутренний аутентифицированный адрес, иначе дежурный будет уходить из закрытого контура.
- Адреса интерфейсов для страницы состояния.
GRAFANA_URL,KIBANA_URL,JAEGER_URL— необязательные переменные: пустое значение просто убирает ссылку.
Что предназначено только для разработки и демонстрации
- В
observability/prometheus.ymlу каждого прикладного job’а два адреса: имя контейнера и адрес хоста для запуска сервисов локально из клона репозитория. В on-prem второй адрес всегда недоступен и остаётсяup=0— это ожидаемо и ни на что не влияет. - Хранилище трасс Jaeger — в памяти, не более 100 000 трасс, без постоянного тома. Перезапуск контейнера теряет всё. Этого достаточно, чтобы разобрать инцидент здесь и сейчас, но это не архив трасс: если трассы нужны надолго, отправляйте их в свой коллектор.
- Генераторы панелей и валидаторы правил в комплект намеренно не входят: они запускаются только из клона репозитория продукта при его разработке, и правила поставки уже проверены там. Оператору они не нужны, а без клона репозитория их и не запустить.
- Единственный файл развёртывания для установки на своих серверах —
docker-compose.onprem.ymlиз комплекта. Другие compose-файлы, которые могут попасться на глаза, относятся к разработке продукта и к облаку.
Трассировка
Трассировка включается одной переменной OTEL_EXPORTER_OTLP_ENDPOINT — это
адрес приёмника OTLP по HTTP. Пустое значение полностью выключает экспорт: код
инструментирования вырождается в бесплатные заглушки. В поставляемом Compose
переменная по умолчанию указывает на встроенный Jaeger, то есть трассы
собираются внутри установки и никуда из неё не уходят. В Helm тот же адрес
задаётся значением observability.otelEndpoint.
Что попадает в спан: имя сервиса и версия (query-api, ingest-api,
ch-writer, worker и PP_VERSION), метод HTTP, шаблон маршрута, статус
ответа и pp.request_id для обратного поиска в журналах. Путь запроса
заменяется на шаблон маршрута ещё до старта спана, а из инструментального
запроса вычищаются Authorization, Proxy-Authorization, Cookie, Referer,
X-Api-Key, X-Auth-Token, X-Forwarded-For и X-Real-IP — идентификаторы
клиентов и credential’ы в трассы не попадают.
Распространение контекста W3C traceparent включено всегда, даже когда экспорт
выключен: входящий контекст принимается и передаётся дальше между сервисами, но
никуда не отправляется. Что именно уезжает за периметр, если вы направите
трассы во внешний коллектор, разобрано в Телеметрии установки.
Журналы
Все сервисы пишут структурированный JSON в stdout, одна строка — одно
событие. Общие поля: time (RFC 3339 с наносекундами), level, service,
message. Уровень задаёт LOG_LEVEL, по умолчанию info.
На каждый HTTP-запрос пишется строка с сообщением http:
| Поле | Что в нём |
|---|---|
method |
метод HTTP |
path |
шаблон маршрута, а не реальный путь |
status |
код ответа |
duration |
длительность обработки |
bytes |
размер ответа |
request_id |
значение заголовка X-Request-ID, он же возвращается клиенту |
trace_id, span_id |
присутствуют, когда включена трассировка |
Читать журналы:
# из каталога комплекта
docker compose -f docker-compose.onprem.yml --env-file .env logs -f query-api
docker compose -f docker-compose.onprem.yml --env-file .env logs -f ch-writer
Дальше искать по request_id из ответа сервера — это самый короткий путь от
жалобы «запрос упал» до конкретной строки. При включённой трассировке из той же
строки берётся trace_id.
Filebeat забирает журналы контейнеров, разбирает вложенный JSON и складывает их
в Elasticsearch в поток данных logs-actionpulse-* по TLS и с отдельной
учётной записью с минимальными правами. Срок хранения задаёт политика
actionpulse-logs, её создаёт однократная задача настройки Elastic;
количество дней берётся из LOG_RETENTION_DAYS со значением по умолчанию 30.
В шаблоне .env этой переменной нет — если нужен другой срок, добавьте её
самостоятельно. Проверка контейнера Filebeat выполняет filebeat test output,
поэтому не выданная учётная запись видна как unhealthy-контейнер, а не как
тишина в Kibana.
На что смотреть первым
Пороги ниже — ровно те, что заданы в поставляемых правилах. Активных правил 23; ещё три шаблона в файле закомментированы и не действуют — не считайте их частью поставки.
| Показатель | Метрика | Порог из правил |
|---|---|---|
| Отклонения на приёме | pp_ingest_events_total{status="rejected"} |
больше 1/с в течение 10 минут |
| Отставание записи событий | pp_writer_lag |
больше 10 000 сообщений 10 минут |
| Отставание записи сессий | pp_replay_writer_lag |
больше 10 000 сообщений 10 минут |
| Недоставленные сообщения | pp_writer_dlq_total |
любой рост за 15 минут — критично |
| Ошибки вставки в ClickHouse | pp_writer_insert_errors_total |
любой рост за 5 минут — критично |
| Доля ответов 5xx | pp_http_request_duration_seconds_count{status} |
выше 5 % при потоке выше 0,1 запроса/с, 10 минут — критично |
| p95 отчётных запросов | pp_query_duration_seconds_bucket{type} |
больше 2 секунд 10 минут |
| Свободное место | node_filesystem_avail_bytes / node_filesystem_size_bytes |
ниже 15 % — предупреждение, ниже 5 % — критично |
| Возраст проверенной резервной копии | pp_backup_last_success_timestamp_seconds против pp_backup_rpo_target_seconds |
превышение заданного RPO 15 минут — критично |
| Очередь писем | pp_email_outbox_pending, pp_email_outbox_oldest_seconds |
больше 200 писем 15 минут; старейшее старше 900 секунд — критично |
| Доставка журналов | pp_logs_failed_events_total, pp_logs_last_publish_timestamp_seconds |
любой рост отказов 15 минут; отсутствие ряда 30 минут |
Первые три показателя отвечают на главный операционный вопрос — «доходят ли события до отчётов». Отставание записи растёт, когда ClickHouse не успевает или недоступен; рост очереди недоставленных сообщений означает, что часть событий не удалось записать вообще, и разбираться нужно немедленно.
Чего поставляемые правила не покрывают
- Доставку оповещений во внешние каналы. Счётчик срабатываний доказывает только вычисление правила, но не то, что вебхук дошёл.
- Исполнение задач приватности и фоновых задач биллинга — у них пока нет
метрик исполнения. Ищите терминальные задачи со статусом
failedв интерфейсе и в журналах воркера. - Свежесть проекции лицензии. Отдельной метрики нет, а зависимость жёсткая:
если контейнер
workerне работает больше двух минут, приём событий начинает отвечать отказом по лицензии. Держите живостьworkerв своём наборе проверок — подробности в Лицензии. - Готовность сервисов. Метрики не заменяют служебную проверку — см. Проверки работоспособности.
Что проверить
docker compose -f docker-compose.onprem.yml --env-file .env ps— все контейнеры в состоянии running, ни один не перезапускается по кругу.- В Prometheus (через port-forward или VPN) на странице целей приложения
query-api,ingest-api,ch-writer,workerимеют состояниеup, а правила загружены без ошибок. - В Alertmanager настроен реальный приёмник, и тестовое оповещение до него
дошло. Приёмник
nullиз поставки не оповещает никого. - В Grafana открываются обе панели, и на них есть данные за последний час.
- В Kibana есть свежие записи в потоке
logs-actionpulse-*, а контейнерfilebeatне в состоянии unhealthy. - Ни один порт, кроме
80и443, не опубликован на хост:docker compose -f docker-compose.onprem.yml --env-file .env psпоказывает публикацию только у Caddy.