Логирование & трассировка
Структурированное логирование
Все логи — в JSON-формате для машинной обработки.
Обязательные поля
json
{
"timestamp": "2025-01-01T00:00:00.000Z",
"level": "error",
"message": "payment processing failed",
"service": "payments",
"trace_id": "abc123",
"span_id": "def456",
"error": {
"type": "InsufficientFundsError",
"message": "balance 50.00 < requested 100.00"
},
"context": {
"user_id": "uuid",
"transaction_id": "uuid"
}
}Уровни логирования
| Уровень | Когда использовать |
|---|---|
error | Ошибка, требующая внимания. Система не смогла выполнить операцию |
warn | Нештатная ситуация, но система справилась |
info | Значимые бизнес-события (создание заказа, платёж) |
debug | Детали для отладки. Отключены в production |
Правила
- Не логируй PII — маскируй email, телефон, данные карт
- Не логируй секреты — токены, пароли, ключи
- Один event = одна строка лога — для парсинга
- Добавляй контекст — trace_id, user_id, request_id
OpenTelemetry
Архитектура
App (SDK) → OTel Collector → Backend (Jaeger / Tempo)
→ Metrics (Prometheus)
→ Logs (Loki / ELK)Distributed Tracing
Каждый входящий запрос получает trace_id, который пробрасывается через все сервисы:
Client → API Gateway → Service A → Service B → Database
│ │ │ │ │
└─────────┴──────────────┴────────────┴──────────┘
trace_id: abc123Что трейсить
- Все HTTP/gRPC входящие и исходящие запросы
- Запросы к БД
- Вызовы внешних сервисов
- Операции с кэшем
- Публикация/потребление событий
Span-naming
HTTP GET /api/v1/users/{id}
DB query users.find_by_id
Redis GET session:{id}
Kafka produce payments.transaction.createdХранение логов
| Окружение | Хранение | Уровень |
|---|---|---|
| Production | 30 дней (hot), 1 год (cold) | info+ |
| Staging | 7 дней | debug+ |
| Development | 1 день | debug+ |