Наблюдаемость: логи, метрики, трассировки
Наблюдаемость: логи, метрики, трассировки
1) Зачем это нужно
Наблюдаемость — способность системы отвечать на незапланированные вопросы о своем состоянии. Она опирается на три основных сигнала:- Метрики — компактные агрегаты для SLI/SLO и алертинга по симптомам.
- Трассировки — причинно-следственные цепочки запросов (end-to-end).
- Логи — детальные события для расследований и аудита.
Цель: быстрый RCA, превентивные алерты и управляемая надежность в рамках error budget.
2) Принципы архитектуры
Единый контекст: везде прокидываем `trace_id`, `span_id`, `tenant_id`, `request_id`, `user_agent`, `client_ip_hash`.
Стандарты: OpenTelemetry (OTel) для SDK/агентов, JSON-формат логов (канонический, со схемой).
Симптомы > причины: алертим по пользовательским симптомам (латентность/ошибки), а не по CPU.
Связь сигналов: от метрики → в спаны (exemplars) → в конкретные логи по `trace_id`.
Безопасность и приватность: маскирование PII в логах, шифрование in transit/at rest, неизменяемые журналы для аудита.
Многоарендность: разделение пространств имен/ключей/политик.
3) Таксономия сигналов и схемы
3.1 Метрики
RED (Rate, Errors, Duration) для сервисов и USE (Utilization, Saturation, Errors) для инфраструктуры.
Типы: counter, gauge, histogram/summary. Для латентности — histogram с фиксированными bucket’ами.
Exemplars: ссылка на `trace_id` в «горячих» бинах гистограммы.
name: http_server_duration_seconds labels: {service, route, method, code, tenant}
type: histogram buckets: [0. 01, 0. 025, 0. 05, 0. 1, 0. 25, 0. 5, 1, 2, 5]
exemplar: trace_id
3.2 Трассировки
Спан = операция с `name`, `start/end`, `attributes`, `events`, `status`.
W3C Trace Context для переносимости.
Сэмплирование: базовое (head) + динамическое (tail) + правила «важности» (ошибки, высокие p95).
3.3 Логи
Только структурированный JSON; уровни: DEBUG/INFO/WARN/ERROR.
Обязательные поля: `ts_utc`, `level`, `message`, `trace_id`, `span_id`, `tenant_id`, `env`, `service`, `region`, `host`, `labels{}`.
Запрещено: секреты, токены, PAN, пароли. PII — только токенизировано/маскировано.
json
{"ts":"2025-10-31T12:05:42. 123Z","level":"ERROR","service":"checkout","env":"prod",
"trace_id":"c03c...","span_id":"9ab1...","tenant_id":"t-42","route":"/pay",
"code":502,"msg":"payment gateway timeout","retry":true}
4) Сбор и транспорт
Агенты/экспортеры (daemonset/sidecar) → буфер на узле → шина/ингест (TLS/mTLS) → хранилища сигналов.
Требования: back-pressure, ретраи, дедупликация, ограничение кардинальности (labels!), защита от «log storms».
Метрики: pull (Prometheus-совместимо) или push через OTLP.
Трассировки: OTLP/HTTP(gRPC), tail-сэмплеры на коллекторе.
Логи: локальный сбор (journald/docker/stdout) → парсер → нормализатор.
5) Хранение и ретенция (tiered)
Метрики: горячие TSDB 7–30 дней (с downsample), агрегаты на более долгий срок (90–365 дней).
Трассировки: 1–7 дней полно, затем аггрегаты/спаны «важных» сервисов; хранить индексы по `service`, `status`, `error`.
Логи: горячий индекс 7–14 дней, теплый 3–6 мес, архив до 1–7 лет (комплаенс). Аудит — WORM.
Оптимизация затрат: downsampling, фильтрация DEBUG в проде, квоты на лейблы, sampling для трасс.
6) SLI/SLO, алертинг и дежурства
SLI: доступность (% успешных запросов), латентность (p95/p99), доля 5xx, свежесть данных, доля успешных джоб.
SLO: цель на SLI (например, 99.9% успешных ≤ 400 мс).
Error budget: 0.1% «права на ошибку» → правила фичфриз/экспериментов.
- `ALERT HighLatency` если `p99(http_server_duration_seconds{route="/pay"}) > 1s` 5мин.
- `ALERT ErrorRate` если `rate(http_requests_total{code=~"5.."}[5m]) / rate(http_requests_total[5m]) > 0.02`.
- Силос-алерты (CPU/Disk) — только как вспомогательные, без paging.
7) Корреляция сигналов
Метрика «красная» → кликаем в exemplar → конкретный `trace_id` → смотрим «медленный» спан → открываем логи по тому же `trace_id`.
Корреляция с релизами: атрибуты `version`, `image_sha`, `feature_flag`.
Для данных/ETL: `dataset_urn`, `run_id`, связь с lineage (см. соответствующую статью).
8) Семплирование и кардинальность
Метрики: ограничиваем лейблы (без `user_id`, `session_id`); квоты/валидация при регистрации.
Трассировки: комбинируем head-sample (на входе) и tail-sample (на коллекторе) с правилами: «все что 5xx, p99, ошибки — 100%».
Логи: уровни и дросселирование; для частых повторяющихся ошибок — агрегирующие события (dedupe ключ).
yaml processors:
tailsampling:
decision_wait: 2s policies:
- type: status_code status_code: ERROR rate_allocation: 1. 0
- type: latency threshold_ms: 900 rate_allocation: 1. 0
- type: probabilistic hash_seed: 42 sampling_percentage: 10
9) Безопасность и приватность
In Transit/At Rest: шифрование (TLS 1.3, AEAD, KMS/HSM).
PII/секреты: санитайзеры до отправки, токенизация, маскирование.
Доступ: ABAC/RBAC на чтение; разделение ролей producers/readers/admins.
Аудит: неизменяемый журнал доступа к логам/трассам; экспорт — в зашифрованном виде.
Многоарендность: namespaces/tenant-labels с политиками; изоляция ключей шифрования.
10) Профили конфигураций (фрагменты)
Prometheus (метрики HTTP + алертинг):yaml global: { scrape_interval: 15s, evaluation_interval: 30s }
scrape_configs:
- job_name: 'app'
static_configs: [{ targets: ['app-1:8080','app-2:8080'] }]
rule_files: ['slo. rules. yaml']
slo.rules.yaml (пример RED):
yaml groups:
- name: http_slo rules:
- record: job:http_request_duration_seconds:p99 expr: histogram_quantile(0. 99, sum(rate(http_server_duration_seconds_bucket[5m])) by (le,route))
- alert: HighLatencyP99 expr: job:http_request_duration_seconds:p99{route="/pay"} > 1 for: 5m
OpenTelemetry SDK (псевдокод):
python provider = TracerProvider(resource=Resource. create({"service. name":"checkout","service. version":"1. 8. 3"}))
provider. add_span_processor(BatchSpanProcessor(OTLPExporter(endpoint="otel-collector:4317")))
set_tracer_provider(provider)
with tracer. start_as_current_span("pay", attributes={"route":"/pay","tenant":"t-42"}):
business logic pass
Логи приложения (stdout JSON):
python log. info("gw_timeout", extra={"route":"/pay","code":502,"trace_id":get_trace_id()})
11) Данные/ETL и стриминг
SLI для данных: свежесть (max lag), полнота (rows vs expectation), «качество» (валидаторы/дупликаты).
Алерты: пропуск окна, лаг консьюмера, рост DLQ.
Корреляция: `run_id`, `dataset_urn`, события lineage; трассировки для пайплайнов (span на батч/partition).
Kafka/NATS: метрики продюсер/консьюмер, лаг/отказ; трассировки по headers (в т. ч. `traceparent`).
12) Профилировка и eBPF (доп. сигнал)
Низкоуровневые горячие пути CPU/alloc/IO; профили на инцидент.
eBPF-телеметрия (сетевые задержки, DNS, системные вызовы) с привязкой к `trace_id`/PID.
13) Тестирование наблюдаемости
Контракт сигналов: проверка экспорта метрик/лейблов/гистограмм в CI.
Synthetic probes: сценарии RUM/симулированные клиенты для внешних SLI.
Chaos/Fire drills: выключения зависимостей, деградация — смотрим, как алерты и дежурные реагируют.
Smoke в проде: пост-деплой проверка, что новые эндпоинты имеют метрики и трассировки.
14) Стоимость и контроль объемов
Бюджеты по сигналу/команде; дэшборд «cost per signal».
Кардинальность под бюджетом (SLO по cardinality), лимиты на новые лейблы.
Downsampling, ретенции по классам данных, «холодные» архивы и WORM для аудита.
15) Эксплуатация и SLO платформы наблюдаемости
SLO платформы: 99.9% успешных ингестов; задержка до индекса метрик ≤ 30 с, логов ≤ 2 мин, трасс ≤ 1 мин.
Алерты платформы: лаг инжеста, рост дропов, ошибка подписи/шифрования, переполнение буферов.
DR/HA: многозонность, репликация, резервные копии конфигов/правил.
16) Чек-листы
Перед продом:- Везде прокидывается `trace_id`/`span_id`; JSON-логи со схемой.
- RED/USE метрики с гистограммами; exemplar → трассы.
- Tail-sampling включен; правила 5xx/p99 = 100%.
- Алерты по симптомам + рунибуки; тихие часы/anti-flap.
- Санитайзеры PII; шифрование at rest/in transit; WORM для аудита.
- Ретенции и бюджеты на объемы/кардинальность.
- Ежемесячный обзор алертов (шум/точность), тюнинг порогов.
- Отчет по error budget и принятые меры (фичфриз, hardening).
- Проверка покрытий дашбордов/логов/трасс для критичных путей.
- Учебные инциденты и обновление runbook’ов.
17) Runbook’и
RCA: рост p99 /pay
1. Открыть дашборд RED для `checkout`.
2. Перейти по exemplar → медленная трасса → выявить «узкий спан» (напр., `gateway.call`).
3. Открыть логи по `trace_id` → посмотреть таймауты/ретраи.
4. Включить фича-флаг отката/лимит RPS, уведомить владельцев зависимости.
5. После стабилизации — RCA, тикеты на оптимизацию, тест воспроизведения.
1. SLI «свежесть» красный → трассы джоба → failing шаг.
2. Проверить лаг брокера/DLQ, ошибки коннектора.
3. Запустить reprocess, уведомить потребителей (BI/продукт) через статус-канал.
18) Частые ошибки
Логи без схемы и без `trace_id`. Расследования затягиваются в разы.
Алерты по инфраструктуре вместо симптомов. Paging уходит «в молоко».
Безграничная кардинальность метрик. Взрыв затрат и нестабильность.
Все трассы 100%. Дорого и не нужно; включайте умное семплирование.
PII/секреты в логах. Включайте санитайзеры и «красные списки».
«Немые» фичи. Новый код без метрик/трасс/логов.
19) FAQ
В: Нужно ли хранить сырой текст логов?
О: Да, но с ретенцией и архивами; для алертов и SLO достаточно агрегатов. Аудит — в WORM.
В: Что выбирать для трасс — head или tail sampling?
О: Комбинировать: head-probabilistic для базового покрытия + tail-rules для ошибок и аномалий.
В: Как связать пользовательские метрики и технические?
О: Через общий `trace_id` и бизнес-лейблы (`route`, `tenant`, `plan`), а также через события продукта (конверсии) с корреляцией к трассам.
В: Как не утонуть в алертах?
О: Бейте по симптомам, вводите тихие часы, дедупликацию, группировку, приоритизацию по SLO и владелец-по-умолчанию на каждый алерт.
- «Аудит и неизменяемые журналы»
- «Шифрование In Transit / At Rest»
- «Менеджмент секретов»
- «Происхождение данных (Lineage)»
- «Privacy by Design (GDPR)»
- «Гарантии доставки вебхуков»