Log4j 2 / SLF4J для Java: полное руководство с примерами

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Что это за библиотека и зачем нужна

Log4j 2 и SLF4J — это две взаимосвязанные библиотеки для логирования в Java, которые являются стандартом де-факто в мире корпоративной разработки. SLF4J (Simple Logging Facade for Java) — это фасад (абстракция), который предоставляет единый API для различных фреймворков логирования. Log4j 2 — это одна из самых мощных и производительных реализаций этого API.

Зачем это нужно? Логирование — это процесс записи информации о работе приложения: ошибки, предупреждения, информационные сообщения, отладочная информация. Без системы логирования разработчики вынуждены использовать System.out.println(), что приводит к:

  • Невозможности гибко управлять выводом (включить/выключить логи для разных частей приложения)
  • Отсутствию уровней логирования (INFO, WARN, ERROR, DEBUG)
  • Проблемам с производительностью (конкатенация строк даже когда логи отключены)
  • Отсутствию форматов вывода (дата, время, имя класса, поток)

Log4j 2 решает все эти проблемы. Он поддерживает асинхронное логирование, фильтры, аппендеры (вывод в файл, консоль, базу данных, сеть), ротацию логов, и множество других продвинутых функций. SLF4J позволяет при необходимости переключиться с Log4j 2 на Logback или java.util.logging без изменения кода.

Установка

Для Java проектов установка производится через системы сборки Maven или Gradle. В отличие от Python (pip) или Node.js (npm), в Java используется управление зависимостями через файлы конфигурации.

Maven (pom.xml)

<!-- SLF4J API + Log4j 2 как реализация -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>2.20.0</version>
</dependency>

<!-- Основной API Log4j 2 (если не используете SLF4J) -->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.20.0</version>
</dependency>

Gradle (build.gradle)

dependencies {
    implementation 'org.apache.logging.log4j:log4j-slf4j-impl:2.20.0'
    implementation 'org.apache.logging.log4j:log4j-core:2.20.0'
}

После добавления зависимостей, создайте файл конфигурации log4j2.xml в папке src/main/resources:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

Быстрый старт с примером кода

Создайте простой Java класс для демонстрации:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class QuickStart {
    // Создаем логгер для текущего класса
    private static final Logger logger = LoggerFactory.getLogger(QuickStart.class);

    public static void main(String[] args) {
        logger.info("Приложение запущено");
        logger.debug("Это отладочное сообщение");
        logger.warn("Предупреждение: ресурсы заканчиваются");
        logger.error("Критическая ошибка: {}", "деление на ноль");

        try {
            int result = 10 / 0;
        } catch (ArithmeticException e) {
            logger.error("Ошибка при вычислении", e);
        }
    }
}

Вывод в консоль будет выглядеть так:

14:30:15.123 [main] INFO  QuickStart - Приложение запущено
14:30:15.125 [main] WARN  QuickStart - Предупреждение: ресурсы заканчиваются
14:30:15.125 [main] ERROR QuickStart - Критическая ошибка: деление на ноль
14:30:15.125 [main] ERROR QuickStart - Ошибка при вычислении
java.lang.ArithmeticException: / by zero
    at QuickStart.main(QuickStart.java:15)

Основные методы/функции

1. LoggerFactory.getLogger()

Что делает: Создает или получает существующий экземпляр логгера для указанного класса или имени. Это точка входа в систему логирования.

Параметры:

  • Class<?> clazz — класс, для которого создается логгер (обычно передают MyClass.class)
  • String name — строковое имя логгера (позволяет создавать иерархию)

Рабочий пример:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class UserService {
    private static final Logger log = LoggerFactory.getLogger(UserService.class);
    // или с именем:
    private static final Logger auditLog = LoggerFactory.getLogger("AUDIT_LOGGER");
}

2. Logger.info()

Что делает: Записывает информационное сообщение уровня INFO. Используется для логирования важных событий в работе приложения (запуск, остановка, успешные операции).

Параметры:

  • String message — сообщение для записи
  • Object... args — аргументы для форматирования (опционально)

Рабочий пример:

logger.info("Пользователь {} успешно авторизован", username);
logger.info("Загружено {} записей из базы данных", count);

3. Logger.error()

Что делает: Записывает сообщение об ошибке уровня ERROR. Используется для критических ошибок, которые требуют внимания разработчика или администратора.

Параметры:

  • String message — сообщение об ошибке
  • Throwable t — объект исключения (опционально)
  • Object... args — аргументы для форматирования

Рабочий пример:

try {
    // опасный код
} catch (SQLException e) {
    logger.error("Ошибка базы данных при запросе: {}", query, e);
}
logger.error("Не удалось обработать заказ #{}: {}", orderId, errorMessage);

4. Logger.warn()

Что делает: Записывает предупреждение уровня WARN. Используется для потенциально опасных ситуаций, которые не являются ошибками, но требуют внимания.

Параметры:

  • String message — предупреждающее сообщение
  • Object... args — аргументы для форматирования

Рабочий пример:

if (diskSpace < 100) {
    logger.warn("Свободное место на диске критически мало: {} MB", diskSpace);
}
logger.warn("Используется устаревший API: метод {} будет удален в версии 2.0", methodName);

5. Logger.debug()

Что делает: Записывает отладочное сообщение уровня DEBUG. Используется разработчиками для детальной трассировки выполнения кода.

Параметры:

  • String message — отладочное сообщение
  • Object... args — аргументы для форматирования

Рабочий пример:

logger.debug("Вход в метод processOrder с параметрами: orderId={}, userId={}", orderId, userId);
logger.debug("Промежуточный результат: {}", intermediateResult);

6. Logger.trace()

Что делает: Самый детальный уровень логирования (TRACE). Используется для очень подробной отладки, обычно включается только при расследовании сложных проблем.

Параметры:

  • String message — сообщение трассировки
  • Object... args — аргументы для форматирования

Рабочий пример:

logger.trace("Вызов метода calculate с x={}, y={}", x, y);
logger.trace("Цикл итерация #{}: текущее значение {}", i, currentValue);

7. Logger.isDebugEnabled() и isTraceEnabled()

Что делает: Проверяет, включен ли соответствующий уровень логирования. Используется для оптимизации производительности, когда формирование сообщения требует ресурсоемких операций.

Параметры: Нет

Рабочий пример:

if (logger.isDebugEnabled()) {
    String complexData = expensiveOperation(); // ресурсоемкая операция
    logger.debug("Сложные данные: {}", complexData);
}
// Без проверки:
logger.debug("Сложные данные: {}", expensiveOperation()); // вызовется даже если DEBUG отключен

8. MDC.put() и MDC.remove()

Что делает: Управляет Mapped Diagnostic Context (MDC) — контекстом, который позволяет добавлять дополнительные данные к каждому лог-сообщению (например, ID пользователя, ID сессии, ID запроса).

Параметры:

  • String key — ключ контекста
  • String value — значение контекста

Рабочий пример:

import org.slf4j.MDC;

public void processRequest(String requestId, String userId) {
    MDC.put("requestId", requestId);
    MDC.put("userId", userId);
    
    try {
        logger.info("Начало обработки запроса");
        // ... логика обработки
        logger.info("Запрос успешно обработан");
    } finally {
        MDC.remove("requestId");
        MDC.remove("userId");
    }
}
// В конфигурации log4j2.xml нужно добавить %X{requestId} и %X{userId} в PatternLayout

9. Logger.atLevel()

Что делает: Создает поставщика сообщений с динамическим уровнем логирования. Позволяет программно выбирать уровень в зависимости от условий.

Параметры:

  • Level level — объект уровня логирования (Level.INFO, Level.ERROR и т.д.)

Рабочий пример:

import org.apache.logging.log4j.Level;

Level dynamicLevel = errorCount > 10 ? Level.ERROR : Level.WARN;
logger.atLevel(dynamicLevel).log("Обнаружено {} ошибок", errorCount);

10. Logger.log()

Что делает: Базовый метод для логирования с явным указанием уровня. Позволяет использовать кастомные уровни логирования.

Параметры:

  • Level level — уровень логирования
  • String message — сообщение
  • Object... args — аргументы

Рабочий пример:

import org.slf4j.event.Level;

logger.log(Level.WARN, "Пользователь {} превысил лими                    

Рекомендаций