05. Observability-стек локально¶
Как работать с Prometheus / Grafana / Loki / Tempo в локальном docker-
compose: куда заходить, какие базовые запросы, как связать три
сигнала. Reference по инструментации — в
../conventions/observability.md.
Полный debugging flow production-инцидента — там же в разделе
«Debugging production issue».
Содержание¶
- Доступ
- Grafana
- Prometheus
- Loki
- Tempo
- Связка трёх сигналов
- Типовые сценарии
- pprof
- Troubleshooting самого стека
- См. также
Доступ¶
Все компоненты поднимаются docker compose up в сервис-репо
(см. 03-local-stack.md):
| Компонент | URL | Login |
|---|---|---|
| Grafana | http://localhost:3000 | admin / admin (при первом входе смена) |
| Prometheus | http://localhost:9090 | — |
| Loki | http://localhost:3100 | — (через Grafana) |
| Tempo | http://localhost:3200 | — (через Grafana) |
| pprof (сервис) | http://localhost:\<service-port>/debug/pprof/ | BasicAuth из .env |
Datasource'ы в Grafana уже настроены в compose-конфиге: Prometheus
как default, Loki и Tempo как дополнительные. Проверить — Grafana →
Connections → Data sources.
Grafana¶
Дашборды per-сервис¶
Открой Grafana → Dashboards. Там предзаливаются типовые dashboard'ы:
- HTTP API — RPS, latency p50/p95/p99, error rate per route.
- Kafka — lag, publish/consume rate, DLQ size.
- Runtime — goroutines, heap, GC, FD count.
- Outbox — unpublished rows, forwarder lag (если сервис использует outbox).
Если dashboard'а нет — создай через Import из infra-репо или
собери «с нуля» (Add new panel → выбираешь metric).
Explore¶
Compass icon слева → Explore. Это interactive query UI, быстрее
дашборда, когда копаешь конкретный запрос.
- Data source dropdown вверху — Prometheus / Loki / Tempo.
- Split view (кнопка справа) — два запроса рядом, например, logs + traces одного запроса.
Дата-пикер¶
Стандартно — Last 15m, Last 1h, Last 24h. Для инцидентов —
точные границы (Custom range → окно инцидента ±10 минут).
Prometheus¶
UI¶
http://localhost:9090 — graph, alerts, targets, rules.
- Status → Targets — все ли scrape-endpoint'ы отвечают зелёным?
Красный таргет = сервис не доступен /
/metricsне отвечает / wrong port. - Graph — вводишь PromQL, получаешь график + table.
- Alerts — какие alert-rule'ы сейчас
firingилиpending.
Базовые PromQL-запросы¶
Rate запросов за 5 минут:
Error rate:
sum(rate(http_requests_total{service="review",code=~"5.."}[5m]))
/ sum(rate(http_requests_total{service="review"}[5m]))
p99 latency:
histogram_quantile(0.99,
sum by (le, route) (
rate(http_request_duration_seconds_bucket{service="review"}[5m])
)
)
Top-5 endpoint'ов по ошибкам:
Goroutines:
Kafka lag:
Outbox:
Подробнее — ../conventions/observability.md
и ../conventions/slo-and-budget.md.
Интерпретация графиков¶
- Плоский
0— метрика не экспонируется. Проверь/metricsвручную:curl http://localhost:<port>/metrics | grep <metric>. - Плоский
NaN— делитель нулевой. Обычно: error rate при 0 RPS. - Пилообразный график — counter пересобран (pod рестарт). Используй
rate, он сглаживает. - Лестница — точная фиксация между scrape-интервалами. Ничего
страшного,
rate[5m]размажет.
Loki¶
Loki — log aggregation, доступ через Grafana Explore → Loki datasource.
LogQL: основные запросы¶
Все логи сервиса:
Логи одного request'а по correlation:
Только errors:
Error с подстрокой в message:
Группировка ошибок за окно (top error-messages):
Grafana Explore → «Explain query» объясняет план выполнения и рекомендует индексы.
Особенности¶
- Поиск идёт по label'ам → всегда начинай с
{service="..."}. - Фильтр
|= "..."— поиск подстроки в теле. | json— парсит JSON-поля как структурные.- Ретенция — 7 дней локально.
Подробнее — ../how-to/read-logs.md.
Tempo¶
Tempo — distributed tracing, доступ через Grafana Explore → Tempo datasource.
Поиск trace¶
Варианты ввода:
- TraceID — если знаешь, вводишь в «Trace ID» поле. Быстрее всего.
- TraceQL — язык запросов:
Найдёт trace'ы handler'а POST /v1/reviews.
- Фильтры в UI — service name, span name, min duration — для случаев «покажи медленные запросы к review».
Чтение waterfall¶
Trace = дерево span'ов. В Grafana видишь:
- Horizontal bar — длительность span'а.
- Nested — parent/child span'ы (HTTP-handler → service → pgx → Kafka-publish).
- Logs (справа при клике на span) — span events,
errorесли был. - Node graph — топология сервисов, через какие прошёл запрос.
Типичный debugging: открыть trace проблемного запроса → найти самый длинный span → понять, где время проводится (SQL / внешний HTTP / Kafka).
Retention¶
Локально — 24 часа. В prod — зависит от Tempo-tier, обычно 7 дней.
Подробнее — ../how-to/read-traces.md.
Связка трёх сигналов¶
Через общий trace_id и correlation_id можно прыгать между
системами:
- Prometheus alert сработал → ссылка «runbook» в alert → соответствующий troubleshooting/runbook.
- Grafana Dashboard → аномалия на графике → клик на точку → «View logs in Loki» / «View traces in Tempo» (если включены derived links в datasource).
- Tempo trace → в span'е есть лог event → клик → Loki с тем же
trace_id. - Loki лог → содержит
trace_id→ клик в Grafana → Tempo.
Derived links настраиваются в Grafana → Connections → Data sources → Loki / Tempo → Derived fields / Trace to logs.
Типовые сценарии¶
«5xx на endpoint'е»¶
- Grafana → Review Dashboard → panel «Error rate by route»: где именно?
- Explore → Loki:
{service="review"} | json | level="error"за 15 минут до пика. - В логе находим
request_id,trace_id. - Explore → Tempo → вставить trace_id → waterfall. Какой span упал?
- Если SQL — §§
db-slow-query.md. Если внешний HTTP —retry-and-circuit-breaker.md. Если panic — smoke test и фикс.
«Latency выросла»¶
- Dashboard → panel p99 latency per route: какой route?
- Explore → Prometheus:
- Tempo → выбрать медленный trace в окне.
- Какой span дольше обычного? (pgx / HTTP / Redis).
- Troubleshooting по конкретному span'у.
«Consumer лаг растёт»¶
- Dashboard → panel
kafka_consumer_lag→ какой topic/group. - Prometheus: Упал до 0 — consumer стоит; колеблется — rebalance.
- Loki:
{service="notification"} | json | level="error"— что в логах? ../troubleshooting/kafka-consumer-stuck.mdили../troubleshooting/kafka-rebalancing.md.
«Память растёт»¶
- Dashboard runtime → panel
heap_inuse+go_goroutines. - Если растёт — см.
../troubleshooting/memory-leak.md.
pprof¶
Локально pprof открыт без auth (за loopback):
# heap snapshot
go tool pprof -http=:8080 http://localhost:<port>/debug/pprof/heap
# goroutine текстом
curl -s 'http://localhost:<port>/debug/pprof/goroutine?debug=1' | less
# CPU profile (30 секунд сбора)
go tool pprof -http=:8081 http://localhost:<port>/debug/pprof/profile?seconds=30
Подробнее — ../how-to/profile-service.md и
../troubleshooting/memory-leak.md.
Troubleshooting самого стека¶
Grafana показывает «no data»¶
- Сервис не экспортирует метрику:
curl http://localhost:<port>/metrics | grep <metric_name>. - Prometheus не скрейпит: Status → Targets → твой сервис «DOWN»?
- Неправильный PromQL: синтаксис, label'ы.
Tempo не показывает trace'ы¶
OTEL_EXPORTER_OTLP_ENDPOINTне указывает на Tempo:docker compose logs <service> | grep otel.- Tempo не поднялся:
docker compose ps tempo→ healthy? SampleRateв конфиге слишком маленький (1%): подними до 100% локально.
Loki не видит логи¶
- Сервис пишет в stdout? (Правильно.) JSON-format? (Правильно.)
- Promtail (log-shipper) работает?
docker compose ps promtail/docker compose logs promtail.
Графики «трудно читать» — нет цветов / делений¶
Grafana 10+ default-theme иногда кривой. Settings → Preferences → Theme
→ Dark / Light, Refresh dashboard.
См. также¶
../conventions/observability.md— три сигнала, correlation, OpenTelemetry setup.../conventions/slo-and-budget.md— как определять SLO и alert-rule'ы.../how-to/read-logs.md— LogQL шпаргалка.../how-to/read-traces.md— Tempo workflow.../how-to/profile-service.md— pprof guide.../how-to/add-metric-and-alert.md— как добавить новую метрику и alert.03-local-stack.md— как поднять стек локально.