JavaRush /Курсы /JAVA 25 SELF /Основы логирования: java.util.logging, Log4j, SLF4J

Основы логирования: java.util.logging, Log4j, SLF4J

JAVA 25 SELF
63 уровень , 0 лекция
Открыта

1. Зачем нужно логирование

Логирование ≠ вывод в консоль

Когда вы только начинаете программировать, кажется, что для поиска проблем достаточно вставить везде System.out.println("Вот тут я был!"). Это работает, пока программа маленькая и запускается у вас на компьютере. Но представьте себе большой проект, сервер, который работает 24/7, или приложение, которым пользуются тысячи людей — вы же не будете сидеть у каждого пользователя за плечом и смотреть на его консоль?

Логирование — это не просто вывод сообщений. Это систематизированная запись информации о работе приложения: ошибок, предупреждений, бизнес-событий, технических деталей. Логи сохраняются в файлы, базы данных, могут отправляться по сети — и позволяют анализировать работу программы после её выполнения или прямо в процессе.

Для чего нужны логи

  • Диагностика проблем: если что-то пошло не так, логи — ваш главный помощник. По ним можно понять, где и почему возникла ошибка.
  • Аудит и безопасность: логи фиксируют важные действия пользователей, что помогает расследовать инциденты.
  • Отладка: иногда баги проявляются только в определённых условиях, и без логов их не поймать.
  • Мониторинг: по логам можно отслеживать состояние приложения, его производительность и «здоровье».

Пример из жизни

Если бы у самолётов не было «чёрных ящиков» (логи полёта), расследовать причины аварий было бы почти невозможно. В программировании логи — это ваши чёрные ящики.

2. Базовые уровни логирования

В логировании принято использовать уровни (levels) сообщений. Это как светофор: красный — опасно, жёлтый — осторожно, зелёный — всё хорошо.

Основные уровни (от самого «громкого» к самому «тихому»):

Уровень Описание
ERROR
Критическая ошибка, приложение не может продолжать работу
WARN
Предупреждение: что-то пошло не так, но программа работает
INFO
Информационное сообщение о штатных событиях
DEBUG
Подробная информация для отладки (видно только разработчикам)
TRACE
Самая подробная информация — для глубокой диагностики

Пример:

  • Пользователь не смог войти из-за неправильного пароля — это WARN.
  • Сломалась база данных — это ERROR.
  • Приложение стартовало — это INFO.
  • Вывод значения переменной в цикле — это DEBUG или TRACE.

Как выбирать уровень

Не стоит всё подряд писать на уровне ERROR — иначе в реальных ошибках вы утонете. Используйте уровни осознанно: только действительно критические сбои должны быть ошибками.

3. Стандартное логирование в Java (java.util.logging)

Java поставляется со встроенной системой логирования — пакет java.util.logging (сокращённо JUL). Это «родной» инструмент, который есть всегда, даже если вы не подключали никаких библиотек.

Основные классы:

  • Logger — главный класс для записи логов.
  • Level — перечисление уровней логирования (SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST).
  • Handler — обработчик, указывающий, куда писать логи (файл, консоль и т.д.).
  • Formatter — отвечает за формат сообщений.

Пример использования JUL

import java.util.logging.Logger;
import java.util.logging.Level;

public class LoggingExample {
    // Получаем логгер по имени класса
    private static final Logger logger = Logger.getLogger(LoggingExample.class.getName());

    public static void main(String[] args) {
        logger.info("Приложение стартовало");
        logger.warning("Это предупреждение!");
        logger.severe("А это уже ошибка!");

        int x = 42;
        logger.fine("Отладочная переменная x=" + x); // По умолчанию не выводится
    }
}

Важный момент: по умолчанию JUL выводит только уровни INFO и выше. Чтобы увидеть fine и другие подробные сообщения, нужно настроить уровень логирования.

Конфигурация через файл

JUL можно настраивать через файл logging.properties (обычно лежит в папке JRE). Там можно указать:

  • Минимальный уровень для логгера
  • Куда писать логи (файл, консоль)
  • Форматирование сообщений

Пример строки в logging.properties:

.level=INFO

4. Внешние библиотеки логирования

Log4j (Apache)

Log4j — одна из самых известных библиотек логирования для Java. Она гибкая, мощная, поддерживает разные форматы, асинхронную запись, ротацию файлов и многое другое.

Пример простейшей конфигурации Log4j 2 (XML):

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

Пример использования Log4j 2 в коде:

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class Log4jExample {
    private static final Logger logger = LogManager.getLogger(Log4jExample.class);

    public static void main(String[] args) {
        logger.info("Hello from Log4j!");
        logger.error("Это ошибка через Log4j");
    }
}

Чтобы это работало, нужно добавить зависимости Log4j в ваш проект (например, через Maven или Gradle).

SLF4J: фасад логирования

SLF4J (Simple Logging Facade for Java) — это не отдельная система логирования, а «прослойка» между вашим кодом и конкретной реализацией (Log4j, Logback, JUL и др.).

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

Пример использования SLF4J:

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

public class Slf4jExample {
    private static final Logger logger = LoggerFactory.getLogger(Slf4jExample.class);

    public static void main(String[] args) {
        logger.info("Привет, логирование через SLF4J!");
        logger.warn("Внимание: что-то может пойти не так");
        logger.error("Ошибка через SLF4J");
    }
}

Как это работает?

  • Вы пишете код через SLF4J.
  • В classpath добавляете нужную реализацию (например, Logback или Log4j).
  • SLF4J сам «прокидывает» вызовы к выбранной реализации.

Взаимодействие SLF4J с другими логгерами: SLF4J может работать поверх JUL, Log4j, Logback и др., что позволяет легко мигрировать без переписывания кода.

5. Практика: сравниваем System.out.println и логирование

Пример 1: System.out.println

public class PrintlnExample {
    public static void main(String[] args) {
        System.out.println("Приложение стартовало");
        System.out.println("Произошла ошибка: что-то пошло не так");
    }
}

Что не так:

  • Нет уровня сообщения (ошибка, информация, предупреждение — всё одинаково).
  • Нет времени, имени класса, потока.
  • Все сообщения идут в одну кучу.
  • Нельзя гибко настроить вывод (например, писать только ошибки).

Пример 2: Логирование через SLF4J + Logback

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

public class LoggingVsPrintln {
    private static final Logger logger = LoggerFactory.getLogger(LoggingVsPrintln.class);

    public static void main(String[] args) {
        logger.info("Приложение стартовало");
        logger.error("Произошла ошибка: что-то пошло не так");
    }
}

Преимущества:

  • Каждое сообщение сопровождается временем, уровнем, именем класса, потоком.
  • Можно фильтровать сообщения по уровню.
  • Можно писать логи в файл, отправлять по сети, форматировать, архивировать.
  • Логирование потокобезопасно (актуально для многопоточных приложений).

Демонстрация разницы

System.out.println
Логирование (SLF4J/Logback)
Приложение стартовало 12:34:56 [main] INFO LoggingVsPrintln - Приложение стартовало
Произошла ошибка: что-то пошло не так 12:34:56 [main] ERROR LoggingVsPrintln - Произошла ошибка: что-то пошло не так

6. Как добавить логирование в свой проект

Для стандартного логгера (JUL)

Всё уже есть в JDK, можно сразу использовать:

import java.util.logging.Logger;

public class MyApp {
    private static final Logger logger = Logger.getLogger(MyApp.class.getName());

    public static void main(String[] args) {
        logger.info("Это инфо-сообщение");
    }
}

Для Log4j или SLF4J

  1. Добавьте зависимости (например, через Maven).

    Для Log4j 2:

    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.20.0</version>
    </dependency>
    

    Для SLF4J + Logback:

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>2.0.7</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.4.7</version>
    </dependency>
    
  2. Создайте конфигурационный файл (например, logback.xml для Logback или log4j2.xml для Log4j).
  3. Используйте логгер в своём коде (см. примеры выше).

7. Мини-приложение: добавляем логирование

Допустим, у нас есть простое приложение — калькулятор командной строки. Добавим к нему логирование.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Scanner;

public class CalculatorApp {
    private static final Logger logger = LoggerFactory.getLogger(CalculatorApp.class);

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        logger.info("Калькулятор запущен");

        try {
            System.out.print("Введите первое число: ");
            int a = Integer.parseInt(scanner.nextLine());
            logger.debug("Введено первое число: {}", a);

            System.out.print("Введите второе число: ");
            int b = Integer.parseInt(scanner.nextLine());
            logger.debug("Введено второе число: {}", b);

            int sum = a + b;
            logger.info("Сумма чисел: {}", sum);
            System.out.println("Результат: " + sum);
        } catch (NumberFormatException ex) {
            logger.error("Ошибка ввода числа", ex);
            System.out.println("Ошибка: введите корректное число!");
        } catch (Exception ex) {
            logger.error("Неизвестная ошибка", ex);
            System.out.println("Произошла ошибка!");
        }
        logger.info("Калькулятор завершил работу");
    }
}

Что здесь происходит:

  • Все ключевые события фиксируются в логе.
  • Ошибки логируются с уровнем ERROR и полным стек-трейсом.
  • Вся информация доступна для анализа после работы программы.

8. Типичные ошибки при работе с логированием

Ошибка №1: Использование только System.out.println для отладки и диагностики.
Это удобно на старте, но совершенно не подходит для реальных приложений. Вы не сможете управлять уровнем сообщений, не увидите время, не сможете анализировать логи, если программа работает на сервере.

Ошибка №2: Логирование слишком большого объёма информации на уровне ERROR.
Если всё подряд писать как ошибку, вы перестанете различать, что действительно важно, а что — просто информация для отладки.

Ошибка №3: Логирование чувствительных данных (пароли, токены, номера карт).
Логи должны быть безопасными! Не пишите туда то, что не должны видеть другие.

Ошибка №4: Отсутствие конфигурации логирования.
Если не настроить уровни, формат, место хранения логов — можно неожиданно «утонуть» в гигабайтах ненужной информации или не увидеть ошибку вовсе.

Ошибка №5: Неиспользование фасада логирования (SLF4J) в крупных проектах.
Если ваш проект будет расти, переходить с одной библиотеки на другую — без фасада это будет больно. SLF4J позволяет легко менять «движок» логирования без переписывания кода.

1
Задача
JAVA 25 SELF, 63 уровень, 0 лекция
Недоступна
Инженер на заводе
Инженер на заводе
1
Задача
JAVA 25 SELF, 63 уровень, 0 лекция
Недоступна
Новый разработчик
Новый разработчик
Комментарии (3)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Ioanna Polyak Уровень 44
10 декабря 2025
lvl UP! lvl = 63!
Anton Pohodin Уровень 27
27 ноября 2025
Level 63!!!
Andrey Уровень 1
21 ноября 2025
63