Logger.info: примеры (JAVA)
Logger.info(String msg): voidОбщее описание метода Logger.info()
Метод Logger.info() используется для записи сообщений журнала на уровне информационных сообщений (INFO). В Java этот метод встречается у разных реализаций логирования: у стандартного java.util.logging.Logger, у SLF4J (org.slf4j.Logger), у Log4j и у обёрток над ними. Назначение одно: фиксировать сообщения, важные для понимания нормального состояния приложения, но не являющиеся ошибками.
Основные свойства и поведение зависят от реализации, но общая модель следующая:
- уровень: INFO;
- возвращаемое значение: метод обычно возвращает
void; - основной аргумент: строка сообщения (
String); многие реализации поддерживают шаблонизацию и дополнительный параметрThrowableдля стек-трейса; - в некоторых API есть перегрузки с varargs для подстановки значений в шаблон, а также варианты с объектом-меткой (Marker) или ленивой генерацией сообщения через
Supplierили лямбду.
Перечень типичных перегрузок (на примере популярных API):
- java.util.logging:
info(String msg). Для ленивой генерации используетсяlog(Level.INFO, Supplier<String>); - SLF4J / Logback / Log4j2:
info(String msg)info(String format, Object arg)info(String format, Object arg1, Object arg2)info(String format, Object... arguments)info(String msg, Throwable t)- варианты с
Markerи контекстом MDC
Замечания по аргументам:
- шаблоны SLF4J используют плейсхолдеры
{}для замены аргументов; - последний аргумент varargs может интерпретироваться как
Throwable, если он является исключением и количество плейсхолдеров меньше числа аргументов; - в
java.util.loggingрекомендуется избегать дорогих вычислений сообщения без ленивой генерации, иначе накладные расходы выполнятся даже если уровень INFO отключён; - возвращаемого значения нет, информация выводится в конфигурируемые аппендеры/хендлеры.
Примеры конфигурации и поведение форматирования зависят от конкретной библиотеки и настроек аппендера/файла/консоли.
Короткие примеры использования
Ниже показаны минимальные примеры для стандартного логгера JDK и для SLF4J. В каждом примере код и ожидаемый результат.
java.util.logging.Logger - простое сообщение
import java.util.logging.Logger;
public class ExampleJUL {
private static final Logger logger = Logger.getLogger(ExampleJUL.class.getName());
public static void main(String[] args) {
logger.info("Приложение запущено");
}
}
Jul 21, 2024 10:00:00 AM ExampleJUL main INFO: Приложение запущено
SLF4J - параметризованное сообщение
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ExampleSlf4j {
private static final Logger logger = LoggerFactory.getLogger(ExampleSlf4j.class);
public static void main(String[] args) {
String user = "ivan";
logger.info("Пользователь {} вошёл в систему", user);
}
}
INFO com.example.ExampleSlf4j - Пользователь ivan вошёл в систему
SLF4J - сообщение с исключением
try {
throw new IllegalStateException("Непредвиденное состояние");
} catch (Exception e) {
logger.info("Обнаружено исключение при обработке", e);
}
INFO com.example.ExampleSlf4j - Обнаружено исключение при обработке
java.lang.IllegalStateException: Непредвиденное состояние
at ...Похожие методы в Java и их особенности
- Logger.log(Level.INFO, ...) - более гибкий метод в
java.util.logging, позволяет задать уровень и дополнительные параметры, в том числе ленивые поставщики сообщений. - Logger.fine / config / warning / severe - методы для других уровней логирования в JDK; выбирать по важности записи.
- org.slf4j.Logger.debug / warn / error - аналоги в SLF4J для соответствующих уровней. Для подробной отладки используется
debug, для ошибок -error. - System.out.println - не является методом логирования; подходит для простых выводов, но не поддерживает уровни, фильтрацию и форматирование.
Выбор зависит от потребностей: для гибкой маршрутизации и фильтрации предпочтение у лог-фреймворков (SLF4J + реализация). Для простых случаев можно временно использовать консоль, но это ухудшает последующий анализ.
Аналоги в других языках и отличия
- PHP:
error_log()или фреймворки типа Monolog.error_log("INFO: Пользователь вошёл");(запись в лог или syslog в зависимости от конфигурации)
Отличие: чаще используется централизованный компонент Monolog для уровней и обработчиков. - JavaScript (Node.js):
console.info()или библиотеки Winston, Bunyan.console.info('Пользователь %s вошёл', 'ivan');Пользователь ivan вошёл
Отличие: JSON-логирование и асинхронные передатчики у популярных библиотек. - Python: модуль
logging, методlogging.info().import logging logging.info('Пользователь %s вошёл', 'ivan')INFO:root:Пользователь ivan вошёл
Отличие: форматирование выполняется лениво, если используется параметризация через запятые. - SQL: в SQL-скриптах не предусмотрено стандартного логирования как в приложениях. В T-SQL используется
PRINTили запись в таблицу для логов. - C# (.NET): интерфейс
Microsoft.Extensions.Logging.ILogger, методLogInformation().logger.LogInformation("Пользователь {User} вошёл", "ivan");info: MyApp[0] Пользователь ivan вошёлОтличие: встроенная поддержка структурированного логирования и провайдеров. - Go: пакет
logсPrintlnили сторонние библиотеки (zap, logrus) с уровнями.log.Println("INFO: Пользователь", user)2009/11/10 23:00:00 INFO: Пользователь ivan
- Kotlin: использует Java-логгеры; часто применяет SLF4J с теми же методами
info(). Отличие: синтаксический сахар и расширения для удобства. - Lua: простая функция
printили библиотеки log4lua.print('INFO: Пользователь вошёл')INFO: Пользователь вошёл
В большинстве языков наблюдается одна общая задача: структурированное логирование и контроль уровней. Java предоставляет широкую экосистему совместимых библиотек (SLF4J + реализация), что обеспечивает переносимость кода и единую модель использования.
Типичные ошибки при использовании Logger.info()
- Дорогая конкатенация строк без проверки уровня. Пример:
logger.info("Результат: " + computeHeavy());(computeHeavy() выполнится даже если INFO отключён, что приведёт к потерям производительности)
Решение: использовать параметризованное логирование или ленивую генерацию. - Неверное число плейсхолдеров в SLF4J. Пример:
logger.info("Пользователь {} выполнил {} операций", user);INFO ... - Пользователь ivan выполнил {} операцийЗдесь второй плейсхолдер останется не заполненным. - Передача исключения как первый аргумент вместо последнего. Пример:
logger.info(e, "Ошибка при обработке: {}", id);(некорректный порядок аргументов, вызовет компиляционную ошибку или некорректный вывод в зависимости от API)
Следует передавать throwable последним:logger.info("...", id, e)илиlogger.info("...", e)согласно сигнатуре. - Использование нулевого экземпляра логгера. Пример:
Logger logger = null; logger.info("test");java.lang.NullPointerException
Проверка инициализации обязательна. - Ожидание возвращаемого значения. Все распространённые реализации возвращают void; попытка использовать значение приведёт к ошибке компиляции.
Изменения в поведении и новых возможностях
В развитии экосистемы логирования отмечаются следующие тенденции:
- в стандартной библиотеке Java добавлены возможности ленивой генерации сообщений через
Supplierв методахlog(Level, Supplier<String>), что снижает накладные расходы при отброшенных уровнях; - SLF4J и реализаций активно вводят поддержку параметризации и структурированного логирования; в новых версиях увеличено внимание к эффективной обработке varargs и безопасному логированию исключений;
- в современных реализациях растёт поддержка асинхронной записи (асинхронные аппендеры) и форматов JSON для централизованного сбора логов.
Конкретные изменения зависят от версии библиотеки: рекомендуется проверять заметки релиза используемой реализации (Logback, Log4j2, SLF4J).
Расширенные примеры использования
Дальше несколько продвинутых сценариев с пояснениями и примерным выводом.
Ленивая генерация сообщения в java.util.logging через Supplier
import java.util.logging.*;
public class LazyExample {
private static final Logger logger = Logger.getLogger(LazyExample.class.getName());
public static void main(String[] args) {
logger.log(Level.INFO, () -> "Дорогой расчёт: " + expensive());
}
private static String expensive() {
// эмуляция тяжёлой операции
try { Thread.sleep(100); } catch (InterruptedException ignored) {}
return "результат";
}
}
(если уровень INFO включён) INFO: Дорогой расчёт: результат (если уровень INFO отключён) (ничего не вычисляется)
Пояснение: Supplier вызывается только при необходимости, что экономит ресурсы.
Использование MDC с SLF4J для контекста запроса
import org.slf4j.MDC;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MdcExample {
private static final Logger logger = LoggerFactory.getLogger(MdcExample.class);
public static void main(String[] args) {
MDC.put("requestId", "req-123");
try {
logger.info("Обработка запроса");
} finally {
MDC.clear();
}
}
}
INFO com.example.MdcExample [requestId=req-123] - Обработка запроса
Пояснение: MDC добавляет контекст, автоматически включаемый в шаблон формата логов.
Структурированное логирование с параметрами и JSON-выводом
// Конфигурация Logback/Log4j2 для JSON + пример использования
logger.info("{\"event\":\"login\", \"user\":\"{}\"}", "ivan");
{"timestamp":"2024-07-21T10:00:00","level":"INFO","logger":"com.example.App","event":"login","user":"ivan"}
Пояснение: структурированное сообщение упрощает парсинг и последующий анализ в системах типа ELK или Splunk. Часто применяется форматтер на стороне аппендера.
Асинхронная запись логов для высокой нагрузки (пример архитектуры)
Конфигурация асинхронного аппендера (Log4j2 AsyncAppender или Logback AsyncAppender) позволяет писать логи в отдельном потоке, снижая влияние на latency основного потока. Код вызова остаётся прежним: logger.info(...), конфигурация отвечает за асинхронность.
Логирование больших объектов с безопасной сериализацией
// Лучше сериализовать выборочно, чтобы избежать утечки данных
logger.info("Профиль пользователя: id={}, имя={}", user.getId(), mask(user.getName()));
INFO ... - Профиль пользователя: id=42, имя=iv***
Пояснение: при логировании объектов следует избегать вывода чувствительных данных и больших бинарных полей; применять маскирование и ограничение размера.