GH GambleHub

Логирование и трассировка событий

Логирование и трассировка событий

1) Цель и рамка

Логи и трейсы — фундамент наблюдаемости.
Логи отвечают на «что произошло» и «с каким контекстом».
Трейсы отвечают на «где и почему медленно/ошибочно» в распределенном пути запроса.

Ключевые принципы:
  • Structured by default (JSON); Trace-first: каждый лог в горячем пути привязывается к `trace_id`/`span_id`.
  • Минимум шума, максимум сигнала: уровни, сэмплинг, анти-кардинальность.
  • Безопасность и приватность: маскирование, редактирование, разграничение доступа.
  • Версионированные схемы логов и событий.

2) Таксономия событий

Разделяйте потоки и индексы по назначению:

1. Технические логи (runtime, ошибки, сетевые таймауты, ретраи).

2. Бизнес-события (регистрация, депозит, ставка, вывод, KYC-этап) — пригодны для продуктовой аналитики и инцидентов по «денежным» путям.

3. Аудит (кто/когда что изменил: конфиги, доступы, флаги, лимиты) — неизменяемый журнал.

4. Безопасность (аутентификация, эскалации привилегий, санкционный/PEP-флаги).

5. Инфраструктура (K8s events, autoscaling, HPA/VPA, узлы/диск/сеть).

Для каждого потока — отдельные правила ретеншна, индексации и доступа.


3) Структурный лог (эталон JSON)

json
{
"ts": "2025-11-03T14:28:15.123Z",
"level": "ERROR",
"service": "payments-api",
"env": "prod",
"region": "eu-central-1",
"trace_id": "8a4f0c2e9b1f42d7",
"span_id": "c7d1f3a4b8b6e912",
"parent_span_id": "a1b2c3d4e5f60789",
"logger": "withdraw.handler",
"event": "psp_decline",
"msg": "PSP declined transaction",
"http": { "method": "POST", "route": "/withdraw", "status": 502, "latency_ms": 842 },
"user": { "tenant_id": "t_9f2", "user_key": "hash_0a7c", "vip_tier": 3 },
"payment": { "psp": "acme", "amount": 120.50, "currency": "EUR", "idempotency_key": "u123:wd:7845" },
"safe": true,         // пройдена проверка на секреты
"version": "1.14.2",     // версия сервиса (SemVer)
"build": "sha-1f2a3b4",
"kubernetes": { "pod": "payments-7cbdf", "node": "ip-10-0-2-41" }
}

Требования: плоская схема + вложения по доменам, обязательные поля (`ts, level, service, env, trace_id, msg`), числовые значения — числами, не строками.


4) Уровни, кардинальность и объем

Уровни: `DEBUG` (не в проде), `INFO` (бизнес-факты), `WARN` (аномалии), `ERROR` (ошибки), `FATAL` (краши).
Кардинальность: избегайте произвольных ключей/динамических label’ов. Никаких «id-в-ключе».
Сэмплинг логов: rate-limit повторяющиеся сообщения; включайте `DEBUG` только scoped и по времени (feature flag).
Идемпотентность: логируйте `idempotency_key`, чтобы подавлять дубликаты событий потребителями.


5) Приватность и безопасность

Маскируйте PII/секреты на агентах (Fluent Bit/Vector): карты маскирования по ключам (`email`, `card`, `token`, `authorization`).
Хешируйте `user_key`, удерживайте только необходимый контекст (страна, KYC-уровень, VIP-tier).
Разделите хранилища: теплые (оперативный поиск) и холодные (архив без PII/с урезанным контекстом).
Аудит — append-only, WORM-хранилище, доступ только по принципу least privilege.


6) Трассировка: стандарты и контекст

W3C Trace Context: заголовки `traceparent`/`tracestate`, плюс baggage для безопасных ключей (например, `tenant_id`, `region`).
Связь метрик и трейсов: Exemplars — передавайте `trace_id` в сэмплированные точки гистограмм (ускоряет RCA).
Sampling: базовый сэмплинг 1–5% + динамический «на ошибках/медленном p95» до 100% для проблемных запросов.
Links: для асинхронных очередей/саг связывайте спаны через `links`, а не только через `parent`.


7) Сбор и маршрутизация

Агенты: Fluent Bit/Vector для логов; OTLP-экспорт в OpenTelemetry Collector.
Collector: центральный шлюз (batch/transform/filter/routing).

Рекомендуемый конвейер:

App → (OTLP logs/traces/metrics) → OTel Collector
→ logs: redact → route(security    audit    tech    biz) → hot index / cold archive
→ traces: tail_sampling(errors    p95>threshold) → APM backend
→ metrics: Prometheus exporter (for SLO/alerts)
OTel Collector (фрагмент):
yaml processors:
batch: {}
attributes:
actions:
- key: env value: prod action: insert filter/logs:
logs:
include:
match_type: strict resource_attributes:
- key: service.name value: payments-api exporters:
otlp/traces: { endpoint: "apm:4317", tls: { insecure: true } }
loki: { endpoint: "http://loki:3100/loki/api/v1/push" }
prometheus: {}
service:
pipelines:
logs: { receivers: [otlp], processors: [attributes,batch], exporters: [loki] }
traces: { receivers: [otlp], processors: [batch], exporters: [otlp/traces] }
metrics: { receivers: [otlp], processors: [batch], exporters: [prometheus] }

8) Инструментирование: примеры SDK

8.1 Node.js (Pino + OTel)

js import pino from "pino";
import { context, trace } from "@opentelemetry/api";

const logger = pino({ level: process.env.LOG_LEVEL          "info" });

function log(info) {
const span = trace.getSpan(context.active());
const base = span? { trace_id: span.spanContext().traceId, span_id: span.spanContext().spanId }: {};
logger.info({...base,...info });
}

// пример log({ event: "deposit.created", amount: 50, currency: "EUR", user: { user_key: "hash_0a7c" } });

8.2 Java (SLF4J + OTel)

java
MDC.put("trace_id", Span.current().getSpanContext().getTraceId());
MDC.put("span_id", Span.current().getSpanContext().getSpanId());
log.info("psp_response status={} latency_ms={}", status, latency);

8.3 Python (structlog + OTel)

python import structlog from opentelemetry import trace log = structlog.get_logger()

def log_json(event, kwargs):
span = trace.get_current_span()
ctx = {}
if span and span.get_span_context().is_valid:
ctx = {"trace_id": span.get_span_context().trace_id, "span_id": span.get_span_context().span_id}
log.msg(event=event, ctx, kwargs)

8.4 NGINX → трассировка заголовков

nginx proxy_set_header traceparent $http_traceparent;
proxy_set_header tracestate $http_tracestate;

9) Логи как сигнал для алертов и авто-действий

Ошибочные паттерны (`psp_decline`, `fraud_flag`) агрегируйте и коррелируйте с SLO.
Алерты на pattern-rate: «5xx по /withdraw > 0.5% за 10м», «fraud_flag spike > +200% от базовой».
Авто-действия: при логе `withdrawals_manual_mode=true` включайте kill-switch через платформу флагов.

Пример правила (псевдо-экспрессия):

rate(count_over_time({service="payments-api", level="ERROR", event="psp_decline"}[5m])) > 5

10) Ретеншн, индексация, хранение

Горячее: 7–14 дней (оперативное расследование).
Теплое: 30–90 дней (тренды, RCA).
Холодное: 180–365+ (архив, аудит) — сжатие, дешевые классы, возможно без полнотекстового поиска.
Индексация: фиксированные ключи (`service, env, level, event, trace_id, user.tenant_id`), запрет на индекс «всего подряд».
Лимиты на размер события (например, ≤ 32KB), трим/снизу: «лишнее в storage — враг MTTR».


11) Аудит и неизменяемость

События аудита пишите отдельным потоком с подписями/хэшами, серверным временем, `who/what/when/why`, ссылкой на тикет.
«Кто включил флаг бонусов на 100% в DE?» — ответ должен быть в 1-2 запроса.

Пример аудита:
json
{
"ts": "2025-11-03T14:00:00.000Z",
"actor": "alice@company",
"action": "feature_flag.update",
"target": "bonus.enable_vip",
"old": {"rollout": 10},
"new": {"rollout": 100},
"reason": "campaign_2311",
"ticket": "OPS-3481",
"trace_id": "cf12ab.."
}

12) Бизнес-события и модель данных

Бизнес-события — не «текст в логах», а контракт:
  • `event_type`, `event_id`, `occurred_at`, `actor`, `subject`, `amount`, `currency`, `status`, `idempotency_key`.
  • Используйте Outbox и «at-least-once» с идемпотентными потребителями.

13) Kubernetes и pipeline логов

Sidecar/DaemonSet агенты с буфером на диск (при сетевых перерывах).
Аннотации подов для маршрутизации (`log.type`, `retention.tier`).
Логи K8s-контроллеров собирайте отдельно (кластерный индекс).

Fluent Bit (маскирование, фрагмент):
ini
[FILTER]
Name     modify
Match
Remove    authorization, password, card_number

14) Анти-паттерны

Строковые логи «как придется», отсутствие `trace_id`.
PII/секреты в логах, дампы payload целиком.
Миллионы уникальных ключей → «взорванная» индексация.
DEBUG в проде 24/7.
Смешивание аудита, безопасности и техлогов в один индекс.
Нет ретеншн-политики и теста восстановления из архива.


15) Чек-лист внедрения (0–45 дней)

0–10 дней

Включить W3C Trace Context в gateway/клиентах, проброс заголовков.
Перевести приложенческие логи на JSON, добавить `trace_id`/`span_id`.
Запретить PII/секреты (маскирование на агенте), утвердить список полей.

11–25 дней

Развести потоки: tech/biz/audit/security/infra, задать ретеншн и ACL.
Включить OTel Collector, сделать tail-sampling ошибок/медленных запросов.
Дашборды «Log Rate/Error by route» + Jump-to-trace (Exemplars).

26–45 дней

Алерты по шаблонам событий и корреляция с SLO.
Архив/восстановление (DR-тест) для холодных логов.
Линтер схем логов в CI, контракт для бизнес-событий.


16) Метрики зрелости

Покрытие запросов `trace_id` ≥ 95%.
Доля логов JSON ≥ 99%.
Инциденты, найденные via «jump-to-trace», решены < 15 мин (p50).
0 случаев PII в логах (сканер утечек).
Ретеншн соблюден по всем потокам (аудит доказываем автоматически).


17) Приложения: мини-сниппеты

W3C traceparent генерация (псевдо)

txt traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01

PromQL — связка логов и SLO (пример)


high_error_logs = rate(log_events_total{service="payments-api",level="ERROR"}[5m])
5xx_rate = sum(rate(http_requests_total{service="payments-api",status=~"5.."}[5m])) / sum(rate(http_requests_total{service="payments-api"}[5m]))
alert if high_error_logs > 10 and 5xx_rate > 0.005

OpenAPI — кореляционные заголовки

yaml components:
parameters:
Traceparent:
name: traceparent in: header required: false schema: { type: string }

18) Заключение

Сильный контур логирования и трассировки — это соглашения + дисциплина: структурные JSON-логи, единый `trace_id`, безопасная обработка PII, маршрутизация и ретеншн по потокам, а также тесная связка с SLO, алертингом и откатами. Сделайте переход от «свалки текстов» к контрактам событий и трассам, и диагностика прод-инцидентов станет быстрой, предсказуемой и проверяемой.

Contact

Свяжитесь с нами

Обращайтесь по любым вопросам или за поддержкой.Мы всегда готовы помочь!

Начать интеграцию

Email — обязателен. Telegram или WhatsApp — по желанию.

Ваше имя необязательно
Email необязательно
Тема необязательно
Сообщение необязательно
Telegram необязательно
@
Если укажете Telegram — мы ответим и там, в дополнение к Email.
WhatsApp необязательно
Формат: +код страны и номер (например, +380XXXXXXXXX).

Нажимая кнопку, вы соглашаетесь на обработку данных.