Skip to main content

Monitoring Setup

Установка стека мониторинга: Prometheus, Grafana, Loki, Promtail, Tempo.


1. Обзор стека

СервисВнешний доступНазначение
Grafanagrafana.goloot.online (Traefik + SSL)Дашборды и визуализация
PrometheusНет (только внутри Docker)Сбор метрик (scrape)
LokiНет (только внутри Docker)Агрегация логов
PromtailНет (только внутри Docker)Сбор и отправка логов
TempoНет (только внутри Docker)Distributed tracing
Безопасность

Все сервисы кроме Grafana не имеют внешних портов. Grafana доступна через Traefik с SSL и защищена встроенной авторизацией. Прямые порты (9090, 3100, 3200) убраны — весь трафик идёт через Traefik (:80/:443).


2. Предварительные условия

  • Docker-сеть dokploy-network существует
  • Backend уже задеплоен
  • Docker log rotation настроена (см. Server Setup)

Проверить сеть:

docker network ls | grep dokploy
Обычно уже существует

Dokploy создаёт эту сеть при установке. Если по какой-то причине нет — она автоматически создастся при первом деплое сервиса.


3. Деплой мониторинга

Один проект для всего

Все сервисы (включая мониторинг) живут в одном проекте goLoot — так проще управлять и видеть общую картину.

  1. Dokploy UI → Projects → проект goLoot
  2. New ServiceDocker Compose
  3. Имя сервиса: monitoring
  4. Source: GitHub → репозиторий goLoot
  5. Compose Path: monitoring/docker-compose.yml
  6. Environment Variables:
GRAFANA_ADMIN_USER=admin
GRAFANA_ADMIN_PASSWORD=YOUR_SECURE_PASSWORD
  1. Deploy

4. Доступ к Grafana

Grafana доступна через Traefik: grafana.goloot.online

Домен настроен через Dokploy (Domains tab в monitoring compose). Прямой порт :3030 убран — весь трафик через Traefik с SSL.

Авторизация — встроенная Grafana auth (логин/пароль задаются через GRAFANA_ADMIN_USER / GRAFANA_ADMIN_PASSWORD в Environment).


5. Что мониторится

Логи (Loki + Promtail)

Promtail автоматически собирает логи из Docker-контейнеров. Фильтры настроены по паттернам имён контейнеров:

ФильтрОписание
goloot-.*Все сервисы goLoot
backend.*Backend API
frontend.*Frontend
admin.*Admin Panel
redirect.*Redirect Service
tip

Имена контейнеров генерируются Dokploy автоматически (например, goloot-backend-abc123). Фильтры используют regex, поэтому backend.* поймает любое имя, содержащее backend.

Пайплайн обработки:

  1. Парсинг Docker JSON → извлечение log, stream, time
  2. Парсинг Pino JSON → извлечение level, msg, requestId, userId, method, path, statusCode, duration
  3. Фильтрация шума: /health, /metrics, /favicon — отбрасываются

Retention: 7 дней (настраивается в loki-config.yml)

Метрики (Prometheus)

Prometheus scrape targets:

JobTargetInterval
backendgolootstaging-backend-z9c2jc:400015s
redirect-serviceredirect-service:300015s
prometheuslocalhost:909015s
Имя контейнера

Target Backend использует имя Dokploy-сервиса (стабильное). Найти его: docker ps | grep backend.

Кэш-метрики (Redis Cache Layer):

МетрикаТипLabelsОписание
cache_hit_totalCounterkey_prefixПопадания в кэш
cache_miss_totalCounterkey_prefixПромахи (запрос в БД)
cache_error_totalCounteroperationОшибки Redis

Полезные PromQL запросы:

# Cache hit rate (%)
cache_hit_total / (cache_hit_total + cache_miss_total) * 100

# Hits per second by prefix
rate(cache_hit_total[5m])

# Errors per second
rate(cache_error_total[5m])

Alert rules:

AlertУсловиеSeverity
HighErrorRateError rate > 5% за 5 минcritical
HighResponseTimep95 > 1s за 5 минwarning

Трейсы (Tempo)

Backend отправляет трейсы через OpenTelemetry:

ReceiverПортПротокол
OTLP gRPC4317gRPC
OTLP HTTP4318HTTP

Retention: 48 часов


6. Grafana: полезные запросы

LogQL (Loki)

# Все ошибки backend
{container=~".*backend.*"} | json | level = "error"

# Медленные запросы (>1s)
{container=~".*backend.*"} | json | duration > 1000

# По userId
{container=~".*backend.*"} | json | userId = "user-id-here"

# По requestId (трейсинг запроса)
{container=~".*backend.*"} | json | requestId = "req-id-here"

Pino Log Levels

LevelЧислоФильтр
fatal60level >= 60
error50level >= 50
warn40level >= 40
info30level >= 30
debug20level >= 20

7. Troubleshooting

Логи не появляются в Grafana

  1. Проверить Promtail:
docker logs $(docker ps -q -f name=promtail) --tail 20
  1. Проверить Loki:
curl http://localhost:3100/ready
# Should return "ready"
  1. Promtail может не видеть контейнеры — проверить Docker socket:
docker exec $(docker ps -q -f name=promtail) ls /var/run/docker.sock

Высокое потребление диска

# Проверить размер данных
du -sh /var/lib/docker/volumes/monitoring_*

# Очистить старые данные Loki
docker restart $(docker ps -q -f name=loki)

"Entry out of order" ошибки в Loki

Добавь в loki-config.yml:

limits_config:
reject_old_samples: true
reject_old_samples_max_age: 168h

8. Docker log rotation на сервере

Обязательно настроить

Без rotation Docker логи заполнят диск. Настройка описана в Server Setup → Docker log rotation.

Быстрая проверка что rotation уже настроена:

cat /etc/docker/daemon.json
# Должен содержать "max-size" и "max-file"

10. Grafana API для автоматизации

Service Account

Grafana поддерживает Service Accounts — специальные аккаунты для API-доступа без пароля. Используются для:

  • Автоматической диагностики (AI-агент запрашивает метрики и логи)
  • Скриптов мониторинга
  • Интеграции с внешними системами

Создание Service Account

  1. Grafana → AdministrationService Accounts
  2. Add Service Account → имя (например, AI-Diagnostics), роль: Viewer
  3. Add Service Account Token → скопировать токен (glsa_xxx...)
Токен показывается один раз

После закрытия окна токен нельзя посмотреть — только пересоздать. Сохрани сразу.

Viewer = read-only

Роль Viewer даёт только чтение — нельзя изменить dashboards, datasource или настройки. Безопасно для автоматизации.

Datasource UIDs

DatasourceUIDProxy URL
Prometheusprometheus/api/datasources/proxy/uid/prometheus/
Lokiloki/api/datasources/proxy/uid/loki/
Tempotempo/api/datasources/proxy/uid/tempo/

Примеры API-запросов

Prometheus (метрики):

TOKEN="glsa_xxx"
BASE="https://grafana.goloot.online/api/datasources/proxy/uid/prometheus"

# Текущие значения cache метрик
curl -s -H "Authorization: Bearer $TOKEN" "$BASE/api/v1/query?query=cache_hit_total"

# Cache hit rate (%)
curl -s -H "Authorization: Bearer $TOKEN" \
"$BASE/api/v1/query?query=cache_hit_total/(cache_hit_total%2Bcache_miss_total)*100"

# Статус всех targets (UP/DOWN)
curl -s -H "Authorization: Bearer $TOKEN" "$BASE/api/v1/targets"

Loki (логи):

TOKEN="glsa_xxx"
BASE="https://grafana.goloot.online/api/datasources/proxy/uid/loki"

# Ошибки backend за последний час
curl -s -G -H "Authorization: Bearer $TOKEN" "$BASE/loki/api/v1/query_range" \
--data-urlencode 'query={container=~".*backend.*"} | json | level >= 50' \
--data-urlencode "start=$(date -d '1 hour ago' +%s)" \
--data-urlencode "end=$(date +%s)" \
--data-urlencode "limit=20"

# Логи конкретного пользователя
curl -s -G -H "Authorization: Bearer $TOKEN" "$BASE/loki/api/v1/query_range" \
--data-urlencode 'query={container=~".*backend.*"} | json | userId = "USER_UUID"' \
--data-urlencode "start=$(date -d '1 hour ago' +%s)" \
--data-urlencode "end=$(date +%s)"

Grafana Health:

# Проверка что Grafana работает
curl -s -H "Authorization: Bearer $TOKEN" "https://grafana.goloot.online/api/health"

# Список datasources
curl -s -H "Authorization: Bearer $TOKEN" "https://grafana.goloot.online/api/datasources"

Хранение токена

Токен хранится вне git-репозитория:

# Для Claude Code (локальный проект)
~/.claude/projects/-root-goloot/grafana-token

# Для других инструментов — .env файл (gitignored)
echo "GRAFANA_SA_TOKEN=glsa_xxx" >> backend/.env
Безопасность
  • Токен НЕ коммитится в репозиторий
  • Роль Viewer — минимально необходимые права
  • Токен можно отозвать в любой момент (Grafana → Service Accounts → Delete Token)
  • При компрометации — удалить и пересоздать

11. Чеклист

  • dokploy-network существует
  • Monitoring stack задеплоен через Dokploy (Docker Compose сервис)
  • Grafana доступна через grafana.goloot.online
  • Нет прямых внешних портов (9090, 3030, 3100, 3200 закрыты)
  • Логи backend видны в Grafana → Explore → Loki
  • Метрики Prometheus собираются (backend target = UP)
  • Cache метрики видны: cache_hit_total, cache_miss_total
  • Docker log rotation настроена
  • Grafana Service Account создан (роль Viewer) для API-доступа