Модуль 5.3. Наблюдаемость и эксплуатация
Темы: логирование, метрики, трассировки, алерты, feature flags, конфигурации. Артефакт: спецификация observability. Практика: SLI/SLO для 2 сервисов.
Системный аналитик (SA) формулирует измеримые требования к качеству сервиса и делает так, чтобы их можно было проверить без «ручной магии». Наблюдаемость — это не «графики», а способ отвечать на неизвестные вопросы про систему в проде: «почему вырос p99?», «какой флаг сломал конверсию?», «где теряются события?». В модуле — процесс, артефакты и готовые шаблоны: лог-схема, метрики/алерты, трассировки, политика фичефлагов и конфигураций.
Базовые принципы (к исполнению)
- Golden Signals: Latency, Traffic, Errors, Saturation.
- RED (для API): Rate, Errors, Duration.
- USE (для инфраструктуры): Utilization, Saturation, Errors.
- SLI (измеряем), SLO (цель), SLA (договор).
- Чёрный ящик (synthetic/пользовательский сценарий) + белый ящик (внутренние метрики).
- Корреляция: везде trace_id/span_id/correlation_id, service, version, env, tenant.
- Кардинальность: лейблы метрик должны быть ограничены (никаких raw userId в label).
Архитектура observability-стека (референс)
Приложения (OTel SDK) → OTel Collector → ├─ Метрики → Prometheus / VictoriaMetrics / облачный бэкенд ├─ Трейсы → Tempo/Jaeger/Cloud APM ├─ Логи → Loki/ELK/Cloud Logs └─ Алерты → Alertmanager/PagerDuty/Slack
Политики (глобально):
- Ресурсные атрибуты (service.name, service.version, deployment.environment, region, team).
- Сэмплинг: для горячих путей — 5–20% head+tail; ошибки — всегда.
- Ретенция: логи 7–30 дней (горячие), трейсы 3–7 дней, метрики 13 мес агрегированные.
Логирование (structured logs)
Обязательная схема логов (JSON)
- ts (UTC ISO8601), level (info/warn/error), service, env, version,
- trace_id, span_id, correlation_id, user_id?, tenant?,
- msg, error.code?, error.kind?, http.method?, http.path?, http.status?, duration_ms?.
Пример записи:
{
"ts": "2025-08-20T14:02:11.381Z",
"level": "error",
"service": "payments-api",
"env": "prod",
"version": "1.12.3",
"trace_id": "a9f1...e2",
"span_id": "1b3c...",
"correlation_id": "ord-8d2c...",
"http.method": "POST",
"http.path": "/v1/payments",
"http.status": 502,
"duration_ms": 2410,
"error.code": "PSP_UNAVAILABLE",
"msg": "PSP gateway timeout"
}
Политики логирования
- PII-masking (allowlist полей; regex-редакторы для email/телефонов/PAN).
- Уровни: debug выключен в prod; info — бизнес-факты и жизненный цикл; warn — нестабильность; error — отказ/потеря ценности.
- Сэмплинг логов (не ошибок) при высокой частоте.
- WORM и неизменяемость для аудит-логов.
Метрики (Prometheus/OpenMetrics)
Нейминг и типы
- service_subsystem_metric{label="value"}; единицы — в названии: _seconds, _bytes.
- Типы: counter (монотонный), gauge, histogram (с bucket-ами), summary (реже).
Набор по умолчанию (API)
- http_requests_total{service, method, route, code} (counter)
- http_request_duration_seconds_bucket{le, service, method, route} (histogram)
- http_inflight_requests{service} (gauge)
- errors_total{service, code} (counter)
Примеры SLI (PromQL):
-- Error rate (5m)
sum(rate(http_requests_total{service="payments-api",code=~"5.."}[5m]))
/
sum(rate(http_requests_total{service="payments-api"}[5m]))
-- p95 latency (5m)
histogram_quantile(0.95, sum by (le) (rate(http_request_duration_seconds_bucket{service="payments-api"}[5m])))
-- Availability как 1 - error_rate (с учётом 4xx по политике)
1 - (
sum(rate(http_requests_total{service="payments-api",code=~"5.."}[5m]))
/
sum(rate(http_requests_total{service="payments-api",code!~"4.."}[5m]))
)
Очереди/воркеры
-
queue_depth, queue_lag_seconds, jobs_processed_total, job_duration_seconds_bucket.
SLI: p95 queue_lag < 5s; Throughput ≥ N jobs/s.
Профили «жизненно важно»
- БД: соединения, блокировки, медленные запросы, реплика лаг.
- Кэш: hit_ratio, errors, evictions.
- GC/Runtime: паузы, heap, goroutines/threads.
Трассировки (OpenTelemetry)
Политики
- Везде Trace Context (traceparent, tracestate), плюс собственный X-Correlation-Id.
- Атрибуты спанов: db.system, db.statement (с санитайзом), http.route, peer.service, messaging.system, messaging.operation, feature_flags.
- Сэмплинг: head 10% + принудительное 100% для error=true и медленных спанов (tail).
- Async-связи: для очередей — messaging.message_id в атрибуты, линковать parent span (links).
Анти-паттерны
- Лить в спан PII/секреты;
- Слишком длинные события/лог-«простыни»;
- Отсутствие пропагации между сервисами/воркерами.
Алерты (SRE-подход)
Принципы
- Алерт — симптом боли пользователя/бизнеса (не «низкий CPU»).
- Каждому алерту — владелец, ранбук, канал и тайм-аут эскалации.
- Мультиокно/multi-burn для SLO (быстрые и медленные прожиги бюджета).
Пример правил (YAML, Alertmanager/Prometheus):
groups:
- name: payments-slo
rules:
- alert: PaymentsHighErrorBurnRate
expr: |
(sum(rate(http_requests_total{service="payments-api",code=~"5.."}[5m]))
/ sum(rate(http_requests_total{service="payments-api"}[5m]))) > 0.02
or
(sum(rate(http_requests_total{service="payments-api",code=~"5.."}[1h]))
/ sum(rate(http_requests_total{service="payments-api"}[1h]))) > 0.005
for: 10m
labels: {severity: "sev2", team: "payments"}
annotations:
summary: "Burning error budget on payments-api"
runbook: "https://runbooks/payments/high-error"
Что ещё мониторим
- Lag очередей / DLQ рост;
- p99 latency ключевых методов;
- Критические бизнес-ивенты/метрики (успешные оплаты RPS);
- Деградации: включился ли fallback, сработали ли фичефлаги-кнопки.
Feature Flags & Конфигурации (как часть эксплуатации)
Типы флагов
- Release (раскатка), Ops (kill switch), Permission (роли), Experiment (A/B).
- Требования: аудит изменений, безопасная деградация при недоступности флаг-сервиса (кэш/дефолты), экспозиция состояния флагов в метрики/логи/трейсы.
Полезные AC:
- AC-FF-1: при падении FlagService — все флаги в безопасном дефолте ≤ 100 мс.
- AC-FF-2: изменения флага логируются (кто/что/когда/причина), метрика feature_flag_changes_total++.
Конфигурации
- Единый источник (SSM/Consul/Vault/ConfigMap) + схема/валидация.
- Версионирование и canary-прокат (1% → 10% → 50% → 100%).
- Доступ — по ролям; аудит; откат (rollback) одним действием.
Схема конфига (пример JSON Schema):
{
"title": "payments-config",
"type": "object",
"properties": {
"psp_timeout_ms": {"type": "integer", "minimum": 100, "maximum": 10000},
"retry_attempts": {"type": "integer", "minimum": 0, "maximum": 5}
},
"required": ["psp_timeout_ms","retry_attempts"]
}
Артефакт: Спецификация Observability (шаблон)
# Observability Spec vX.Y.Z — <Сервис/Система>
Owner: <Team/Contacts> | SA: <ФИО> | Env: prod/stage
## 1. Инвентарь
Сервисы: payments-api, checkout-api, orders-worker
Релизы: semver; атрибуты ресурса OTel: service.name, service.version, deployment.environment, region
## 2. SLI/SLO
- Payments API:
- Availability: 99.9%/квартал (исключая planned 30мин/мес)
- Latency: p95 < 2.5s 08:00–23:00, p99 < 5s
- Error rate: < 0.5% (5xx)
- Orders Worker:
- Queue Lag p95 < 5s (09:00–22:00)
- DLQ = 0 (скользящее окно 1ч)
## 3. Метрики
Нейминг: `<service>_<subsystem>_<name>`, единицы в названии.
Обязательные:
- http_requests_total{method,route,code}
- http_request_duration_seconds_bucket{le,route}
- queue_depth, queue_lag_seconds
- db_connections, cache_hit_ratio
## 4. Логи
Формат: JSON; поля: ts, level, service, env, version, trace_id, span_id, correlation_id, user_id?, tenant?, msg, error.code.
Маскирование: email/phone/PAN — редактируются; запрет PII в событиях.
## 5. Трейсинг
OTel, пропагация TraceContext; head 10% + errors 100%; tail-sampling slow spans > 2s.
Атрибуты: http.*, db.*, messaging.*, feature_flags.
## 6. Алерты
- Multi-burn SLO (5m/1h окна)
- Queue Lag > 15s 10m — sev2
- DLQ > 0 5m — sev2
- p99 latency > 5s 5m — sev2
Runbooks: ссылки; Эскалация: дежурный → тимлид → платформа.
## 7. Дашборды
- RED: per route (RPS, error%, p95)
- Queue: depth, lag, processed/s, DLQ
- Infra: db, cache, runtime
## 8. Ретенция/стоимость
Логи: 14 дней (горячие), 90 дней архив; Трейсы: 7 дней; Метрики: сырье 15 дней, аггрегаты 13 мес.
Кардинальность: лимиты; ревью ежемесячно.
## 9. Безопасность/Приватность
PII-редакторы; аудит доступа к логам; WORM для audit.
## 10. Тесты/Приёмка
Chaos: отключение PSP; Spike x2; проверка алертов; трассировка сквозная через 3 сервиса.
Практика (90–120 мин): SLI/SLO для 2 сервисов
Сервисы: payments-api (синхронный HTTP) и orders-worker (очередь).
Определите SLI/SLO
Payments API
- Availability (request-based): 1 - 5xx_rate ≥ 99.9%/кв.
- Latency: p95 < 2.5s (08:00–23:00, Europe/Stockholm), p99 < 5s.
- Error rate: < 0.5% (5xx из total без 4xx).
Orders Worker
- Queue Lag: p95 lag < 5s (09:00–22:00).
- Throughput: ≥ 50 jobs/s при depth ≤ 500.
- DLQ: = 0 (rolling 1h).
Напишите запросы SLI (PromQL)
-- Availability payments-api (квартальное окно берётся из дашборда агрегатом)
1 - (sum(rate(http_requests_total{service="payments-api",code=~"5.."}[5m]))
/ sum(rate(http_requests_total{service="payments-api",code!~"4.."}[5m])))
-- p95 latency
histogram_quantile(0.95, sum by (le) (rate(http_request_duration_seconds_bucket{service="payments-api"}[5m])))
-- Queue lag p95
histogram_quantile(0.95, sum by (le) (rate(queue_lag_seconds_bucket{service="orders-worker"}[5m])))
-- DLQ count
sum(increase(dlq_messages_total{service="orders-worker"}[5m]))
Заложите алерты (multi-burn)
- Быстрый прожиг: ошибка > 2% за 5 минут → sev2.
- Медленный прожиг: ошибка > 0.5% за 1 час → sev3.
- queue_lag_p95 > 15s 10m → sev2, runbook: увеличить воркеры + проверить PSP задержки.
Дашборды
- Payments API RED: RPS, error%, p50/p95/p99, по роутам.
- Orders Worker: depth, lag p50/p95, processed/s, DLQ, retries.
Критерии зачёта
- SLI описаны формально (метрика, окно, фильтры, TZ).
- SLO достижимы и связаны с алертами.
- Есть дашборды и runbooks.
- В RTM добавлены acceptance-пункты: trace_id в логи, обязательные метрики/лейблы.
Типовые риски и как их гасить
|
Риск |
Симптом |
Меры |
|---|---|---|
|
Взрыв кардинальности метрик |
Падает TSDB/счёт |
Лимиты лейблов, дроп-правила в Collector, ревью |
|
Нет корреляции лог↔трейс |
«Не склеиваются» расследования |
Везде trace_id/span_id/correlation_id, мидлвары |
|
Шумные алерты |
Дежурные «горят» |
Multi-window burn, deadman’s switch, тюнинг порогов, аннотации и авто-тикеты |
|
PII в логах/спанах |
Риски приватности |
Маски/allowlist, линтеры/сканеры в CI, ревью схем |
|
Сломанная пропагация |
Трейсы «обрываются» |
Тест «сквозной trace» в приёмке, автотест с проверкой заголовков |
|
Затраты (storage) |
Счета за облако |
Сэмплинг, агрегации, ретенция по классам данных, бюджет/квоты |
|
Разные env смешаны |
Неправильные графики |
Лейбл deployment.environment, изоляция источников |
Вопрос–Ответ
В: Почему p95/p99, а не среднее?
О: Пользователь страдает от хвостов; среднее скрывает пики.
В: Как измерять доступность: по логам или счётчикам?
О: По счётчикам запросов (white-box) + чёрный ящик (synthetic). Логи — вторично.
В: Сколько хранить трейсы?
О: Обычно 3–7 дней; длиннее — дорого. Делайте агрегации метрик и храните экземпляры (exemplars) для «прыжка» из метрики в конкретный трейс.
В: Нужны ли логи, если есть трейсы?
О: Да. Логи фиксируют контекст и ошибки, которые не всегда попадают в спаны; и часто хранятся дольше.
В: Как не «утопить» прод логами?
О: Сэмплинг info, строгая схема, запрет на «болтливые» циклы, ретенция и бюджеты.
В: Можно ли алертить по инфраструктуре (CPU)?
О: Только как supporting alerts. Главные — по SLO (симптомы). CPU — для диагностики.
Шпаргалка
- RED/USE + Golden Signals — базовая канва.
- Везде trace_id/correlation_id, единые атрибуты ресурса.
- Метрики: счётчики/гистограммы, PromQL для p95/p99, error-rate.
- Алерты: multi-burn, владелец, ранбук, эскалация.
- Логи — структурированные, без PII, с масками.
- Трейсы — OTel, head+tail сэмплинг, атрибуты http/db/messaging/feature_flags.
- Фичефлаги/конфиги — аудит, дефолты, метрики, canary.
- Ретенция и кардинальность — держите в бюджете.



