middle
Какие есть лучшие практики логирования?
Хорошее логирование — это баланс между достаточностью информации для диагностики и отсутствием шума. Логи должны быть полезны через 3 месяца, когда контекст забыт.
Что логировать
- Начало и завершение значимых бизнес-операций
- Ошибки и исключения (с полным стек-трейсом)
- Входящие запросы (метод, URL, ключевые параметры)
- Интеграционные вызовы (к другим сервисам, БД, очередям)
- Изменения состояния (статус заказа, роль пользователя)
Что НЕ логировать
- Пароли, токены, API-ключи, секреты
- Персональные данные (PII): номер карты, СНИЛС, паспорт
- Тела запросов/ответов целиком (могут содержать sensitive данные и быть огромными)
Как логировать правильно
Пример
// ПРАВИЛЬНО — параметризованные сообщения
log.info("Пользователь {} авторизован, роль: {}", userId, role);
// НЕПРАВИЛЬНО — конкатенация (выполняется всегда)
log.debug("Результат: " + expensiveOperation());
// ПРАВИЛЬНО — исключение как последний аргумент (стек-трейс автоматически)
log.error("Ошибка обработки заказа {}", orderId, exception);
// НЕПРАВИЛЬНО — стек-трейс потерян
log.error("Ошибка: " + exception.getMessage());
// ПРАВИЛЬНО — проверка уровня для дорогих операций
if (log.isDebugEnabled()) {
log.debug("Детали: {}", computeExpensiveDebugInfo());
}
Гайд по выбору уровня
| Уровень | Когда использовать | Пример |
|---|---|---|
| ERROR | Требуется реакция (алерт) | Сервис недоступен, данные повреждены |
| WARN | Потенциальная проблема, система справилась | Retry succeeded, deprecated API, fallback |
| INFO | Нормальные бизнес-события | Заказ создан, пользователь авторизован |
| DEBUG | Диагностика для разработчика | SQL, промежуточные данные, состояние кэша |
| TRACE | Максимальная детализация | Вход/выход из метода, значения переменных |
Золотые правила
- Один запрос = одна корреляция: всегда логируйте requestId/traceId для связывания записей
- Исключение — ВСЕГДА последним аргументом:
log.error("msg", arg1, exception) - В production: INFO + structured JSON + correlation ID
- Не логируйте в цикле — 10 000 итераций по одному логу = 10 000 записей; агрегируйте результат
- Не делайте catch + log + throw — двойное логирование; логируйте на верхнем уровне
Частые ошибки
log.error(exception.getMessage())— теряется стек-трейс; используйтеlog.error("msg", exception)- Логирование в цикле без агрегации — замедляет систему и засоряет логи
- Catch + log + throw — одно исключение логируется дважды
- ERROR для всех исключений —
NotFoundExceptionприGET /users/999— это не ERROR, а INFO или WARN
Как используется в 2026
- Lombok
@Slf4j— автоматическая генерацияprivate static final Logger log - IDE (IntelliJ) — live templates
logi,logd,logeдля быстрого логирования - Spring Boot Actuator — динамическое изменение уровней через HTTP
На собеседовании: перечислите конкретные антипаттерны: потеря стек-трейса через
getMessage(), логирование в цикле, catch-log-throw. Это показывает production-опыт. Частая ошибка — дать абстрактный ответ “логируйте всё важное” без конкретных примеров.