Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Логирование

Лог (журнал) — записи о том, что делала программа: запустилась, приняла заказ, не смогла подключиться к базе. По логу разбираются, что пошло не так на сервере, где отладчик не запустишь. Можно писать такие записи через System.out.println, но у них нет ни времени, ни важности, их нельзя отключить без правки кода, и они смешиваются с обычным выводом программы. Для этого есть логгеры.

System.Logger

Встроенный в JDK логгер получают методом System.getLogger(имя). Имя обычно совпадает с пакетом или классом и помогает понять, откуда пришла запись. Метод log принимает уровень важности и сообщение:

void main() {
    System.Logger log = System.getLogger("shop");
    log.log(System.Logger.Level.INFO, "Заказ принят");
}

Результат (дата и время у вас будут другими):

окт. 04, 2026 10:30:02 AM Main main
INFO: Заказ принят

Логгер сам добавил время, класс и метод, откуда пришла запись. Пишет он в System.err, а не в System.out, поэтому записи можно перенаправить отдельно от вывода программы.

Формат записи

System.Logger по умолчанию передаёт записи стандартному логгеру JDK — java.util.logging. Его формат задаёт системное свойство java.util.logging.SimpleFormatter.format: в нём %1$s — дата, %3$s — имя логгера, %4$s — уровень, %5$s — сообщение, %6$s — исключение, %n — перевод строки. Свойство передают ключом -D или задают в начале программы:

void main() {
    System.setProperty("java.util.logging.SimpleFormatter.format", "[%4$s] %3$s: %5$s%6$s%n");
    System.Logger log = System.getLogger("shop");
    log.log(System.Logger.Level.INFO, "Заказ принят");
}

Результат:

[INFO] shop: Заказ принят

Уровни

У System.Logger.Level пять основных уровней — от самого подробного к самому важному: TRACE, DEBUG, INFO, WARNING, ERROR. По умолчанию выводятся записи от INFO и выше, а DEBUG и TRACE — подробности для отладки — скрыты. В выводе уровни называются по-своему: ERROR превращается в SEVERE, DEBUG — в FINE:

void main() {
    System.setProperty("java.util.logging.SimpleFormatter.format", "[%4$s] %5$s%6$s%n");
    System.Logger log = System.getLogger("shop");
 
    log.log(System.Logger.Level.DEBUG, "Корзина: 3 товара");
    log.log(System.Logger.Level.INFO, "Заказ принят");
    log.log(System.Logger.Level.WARNING, "Осталось мало товара");
    log.log(System.Logger.Level.ERROR, "Платёж отклонён");
}

Результат:

[INFO] Заказ принят
[WARNING] Осталось мало товара
[SEVERE] Платёж отклонён

Параметры и исключения

Значения в сообщение подставляют через {0}, {1} — строка собирается, только если запись действительно выводится. Исключение передают последним аргументом, и логгер напечатает его вместе со стеком вызовов:

void main() {
    System.setProperty("java.util.logging.SimpleFormatter.format", "[%4$s] %5$s%6$s%n");
    System.Logger log = System.getLogger("shop");
 
    log.log(System.Logger.Level.INFO, "Заказ {0} от {1}", 42, "Анна");
    try {
        Integer.parseInt("abc");
    } catch (NumberFormatException e) {
        log.log(System.Logger.Level.ERROR, "Не удалось прочитать количество", e);
    }
}

Результат (строки стека из JDK опущены):

[INFO] Заказ 42 от Анна
[SEVERE] Не удалось прочитать количество
java.lang.NumberFormatException: For input string: "abc"
	at Main.main(Main.java:7)

java.util.logging напрямую

Тот же механизм можно использовать и напрямую. Модуль java.logging не входит в java.base, поэтому нужен import. Методы называются по уровням: severe, warning, info, config, fine, finer, finest:

import java.util.logging.*;
 
void main() {
    System.setProperty("java.util.logging.SimpleFormatter.format", "[%4$s] %3$s: %5$s%6$s%n");
    Logger log = Logger.getLogger("shop.orders");
 
    log.info("Заказ принят");
    log.fine("Подробности для отладки");
    log.warning("Платёж задерживается");
}

Результат:

[INFO] shop.orders: Заказ принят
[WARNING] shop.orders: Платёж задерживается

В реальных проектах чаще всего используют библиотеку SLF4J с реализацией Logback (в Spring Boot они подключены по умолчанию): логгер создают через LoggerFactory.getLogger(...), а параметры подставляют через {}. Идеи те же — имя, уровни, параметры, — а настройки хранят в файле logback.xml.

Частая ошибка

Чтобы увидеть отладочные записи, логгеру ставят уровень FINE — но они всё равно не появляются. Дело в том, что фильтров два: у логгера и у обработчика (handler), который печатает записи в консоль. Обработчик по умолчанию пропускает только INFO и выше, поэтому понизить уровень нужно и ему:

import java.util.logging.*;
 
void main() {
    System.setProperty("java.util.logging.SimpleFormatter.format", "[%4$s] %5$s%6$s%n");
    Logger log = Logger.getLogger("shop.orders");
    log.setLevel(Level.FINE);
 
    log.fine("не видно: обработчик отсекает FINE");
 
    Logger.getLogger("").getHandlers()[0].setLevel(Level.FINE);
    log.fine("теперь видно");
}

Результат:

[FINE] теперь видно

Logger.getLogger("") — корневой логгер, у которого и есть консольный обработчик. В больших программах такие настройки выносят в файл logging.properties и передают его ключом -Djava.util.logging.config.file=logging.properties.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.