› Архитектура логирования
В Java-экосистеме принято строго разделять API логирования (интерфейсы) и движок (реализацию). Это позволяет менять движок без переписывания кода приложения.
- SLF4J (Simple Logging Facade for Java): Стандартный фасад (API). Разработчик пишет код, используя только классы SLF4J (
LoggerFactory.getLogger()). Сам по себе SLF4J ничего не пишет на диск, он лишь делегирует вызовы подключенному движку. - Logback: Движок логирования по умолчанию в Spring Boot. Написан создателем Log4j, является его прямой, более быстрой эволюцией. Нативно реализует интерфейсы SLF4J.
- Log4j2: Альтернативный, высокопроизводительный движок. Поддерживает асинхронное логирование на базе LMAX Disruptor (обеспечивает минимальные задержки).
- JUL (Java Util Logging): Устаревший встроенный механизм из
java.util.logging. В современных проектах не используется.
› Интеграция со Spring Boot
- Spring Boot “из коробки” включает стартер
spring-boot-starter-logging. - По умолчанию используется связка SLF4J + Logback.
- Мосты (Bridges): Spring Boot автоматически перехватывает логи от сторонних библиотек, использующих старые фреймворки (JUL, Log4j, JCL), и перенаправляет их в единый поток SLF4J.
- Для замены Logback на Log4j2 необходимо исключить стандартный стартер логирования и добавить
spring-boot-starter-log4j2.
› Logging Levels
Определяют степень важности сообщения. Если установлен уровень INFO, будут выводиться логи INFO и все уровни выше (WARN, ERROR).
- TRACE: Максимально детальная трассировка (пошаговое выполнение алгоритмов).
- DEBUG: Отладочная информация, полезная при разработке (содержимое переменных, SQL-запросы).
- INFO: Информационные сообщения о нормальной работе приложения (старт сервиса, успешная обработка пакета).
- WARN: Предупреждения. Приложение продолжает работу, но произошла нештатная ситуация (использование deprecated API, ретрай запроса).
- ERROR: Ошибка, не позволяющая выполнить конкретную операцию (выброшено исключение, недоступна БД).
- FATAL: Критический сбой, ведущий к остановке всего приложения (в SLF4J явно не выделен, мапится на ERROR с маркерами).
› Appenders
Appender — это компонент движка логирования, отвечающий за доставку лог-события в целевое место назначения.
- ConsoleAppender: Вывод логов в стандартный поток вывода (
System.out/System.err). Используется при локальной разработке и в Docker-контейнерах (где логи собирает демон Docker). - FileAppender: Запись логов в единый файл.
- RollingFileAppender: Стандарт для Production (если логи не собираются из stdout). Поддерживает ротацию логов — автоматическое создание новых файлов при достижении лимита размера (например, 100 МБ) или по времени (каждый день), а также архивацию старых логов.
- AsyncAppender: Асинхронная обертка над другими аппендерами. Складывает логи в очередь (в памяти) и пишет их в фоновом потоке, чтобы не блокировать основной поток бизнес-логики.
- Network/Logstash Appender: Отправка логов напрямую по сети в системы агрегации (ELK Stack, Graylog) в формате JSON.
› Конфигурация логирования
- Базовая (через
application.yml): Подходит для простых настроек: изменение уровней логирования для пакетов, задание имени файла логов.logging: level: root: INFO com.myproject: DEBUG org.hibernate.SQL: DEBUG - Продвинутая (через
logback-spring.xml): Файл кладется в папкуsrc/main/resources. Суффикс-springважен: он позволяет использовать специфичные фичи Spring, например, тег<springProfile>, чтобы задавать разные аппендеры дляdevиprodсред. Здесь настраиваются паттерны вывода (PatternLayout), ротация и кастомные аппендеры.
› MDC (Mapped Diagnostic Context)
MDC — это контекст диагностики, представляющий собой Map<String, String>, который привязан к текущему потоку выполнения (использует ThreadLocal под капотом).
- Решаемая проблема: В микросервисной архитектуре один HTTP-запрос обрабатывается множеством методов и сервисов. В логах (где пишут сотни параллельных потоков) невозможно понять, какие строки относятся к одному конкретному запросу пользователя.
- Как работает:
- При поступлении HTTP-запроса (например, в Servlet Filter) генерируется уникальный идентификатор (
trace_idилиcorrelation_id). - Этот ID кладется в MDC:
MDC.put("trace_id", traceId). - В паттерне конфигурации логгера (в
logback.xml) указывается плейсхолдер:%X{trace_id}. - Движок логирования автоматически добавляет этот ID к каждой строке лога, сгенерированной в данном потоке.
- В блоке
finallyфильтра обязательно вызываетсяMDC.clear(), чтобы предотвратить утечки памяти и смешивание контекстов при переиспользовании потоков в пуле (Tomcat Thread Pool).
- При поступлении HTTP-запроса (например, в Servlet Filter) генерируется уникальный идентификатор (