Logger.warning: примеры (JAVA)

Разбор Logger.warning() в Java
Раздел: Логирование
Logger.warning(String msg): void

Общее описание метода Logger.warning()

Метод Logger.warning() из пакета java.util.logging предназначен для записи сообщений уровня WARNING. Обычно используется для логирования опасных, но не критичных ситуаций, требующих внимания администратора или разработчика, но не приводящих к немедленному завершению работы приложения.

Основная сигнатура:

public void warning(String msg)

Параметры и поведение:

  • msg - текст сообщения типа String. Теоретически может быть null, но некоторые форматтеры или обработчики могут не ожидать null и вызвать исключение при обработке.
  • Возвращаемое значение - void. Метод не возвращает результата; он отправляет сообщение логирующей подсистеме.
  • Фактическая запись сообщения зависит от конфигурации Logger, его уровня и подключённых Handler. Сообщение будет обработано только если logger.isLoggable(Level.WARNING) возвращает true.
  • Сообщение передаётся далее в зарегистрированные обработчики (Handler), где применяется форматтер (Formatter) и производятся действия вывода (консоль, файл и т.п.).

Связанные возможности (помимо простого warning(String)):

  • Общие методы записи уровня: log(Level.WARNING, ...), позволяющие указывать форматированные сообщения, параметры, исключения и ленивые поставщики сообщений через Supplier<String> (в более новых версиях JDK).
  • Фильтры (Filter) на уровне логгера и обработчика, управляющие тем, какие записи будут допущены к выводу.

Типичные сценарии применения: предупреждения о некритичных ошибках, проблемах конфигурации, о пропущенных значениях, связанных с поведением, которое может привести к ошибкам в будущем.

Небольшие примеры использования

Базовый пример логирования предупреждения:

import java.util.logging.Logger;

public class Main {
    private static final Logger logger = Logger.getLogger(Main.class.getName());
    public static void main(String[] args) {
        logger.warning("Критерий X нарушен, проверка обязательна");
    }
}

Возможный результат в консоли (зависит от конфигурации форматтера):

Apr 22, 2026 12:34:56 PM Main main
WARNING: Критерий X нарушен, проверка обязательна

Проверка уровня перед формированием тяжёлого сообщения:

if (logger.isLoggable(java.util.logging.Level.WARNING)) {
    String details = heavyComputation();
    logger.warning("Проблема: " + details);
}

Если требуется ленивое вычисление и JDK предоставляет log(Level, Supplier<String>), можно использовать обёртку:

logger.log(java.util.logging.Level.WARNING, () -> "Проблема: " + heavyComputation());

Использование log для передачи исключения и форматируемых параметров:

Exception ex = new IllegalStateException("state");
logger.log(java.util.logging.Level.WARNING, "Ошибка при обработке параметра {0}", new Object[]{param});
logger.log(java.util.logging.Level.WARNING, "Ошибка во время операции", ex);

Результат зависит от форматтера и может включать стек исключения:

WARNING: Ошибка во время операции
java.lang.IllegalStateException: state
    at ...

Похожие методы в Java и их особенности

  • Logger.severe() - для критичных ошибок, когда требуется отметить событие уровня ERROR или выше.
  • Logger.info() - для обычной информативной записи; менее приоритетен, чем warning.
  • logger.fine()/finer()/finest() - для отладочных сообщений с разной степенью подробности; часто отключены в рабочем окружении.
  • Logger.log(Level, ...) - универсальный метод, позволяющий передавать параметры, исключения и использовать ленивые поставщики сообщений; предпочтителен при необходимости гибкости.
  • logger.logp(), logger.logrb() - версии с указанием источника (class/method) или с учетом ресурсных пакетов для локализации.

Выбор зависит от семантики события: для ошибок, приводящих к краху, предпочтительна severe; для информационных записей - info; для предупреждений о потенциальных проблемах - warning. Если требуется локализация или уточнение источника, подходят logrb и logp.

Аналоги в других языках и отличия

PHP (встроенная и популярные библиотеки):

// встроенная
error_log("Warning: something unusual");

// Monolog
$logger->warning('Warning: something unusual');
// Встроенная - запись в системный лог или в файл, в зависимости от конфигурации
// Monolog - форматируемый вывод, множество обработчиков (файлы, Slack, и т.д.)

JavaScript:

console.warn('Warning: possible problem');

// с библиотекой winston
logger.warn('Warning: possible problem');
// console.warn выводит в консоль браузера/Node.js
// winston - настраиваемые уровни и транспорт

Python:

import logging
logging.warning('Warning: value missing')
WARNING:root:Warning: value missing

SQL:

В SQL нет встроенного уровня логирования наподобие Logger.warning. Часто логирование выполняется на уровне приложения или СУБД через служебные журналы.

C#:

// System.Diagnostics
System.Diagnostics.Trace.TraceWarning("Warning: check config");

// Serilog/NLog
logger.Warn("Warning: check config");
// TraceWarning выводит в зарегистрированные слушатели
// Serilog/NLog дают гибкую маршрутизацию и форматирование

Lua:

print("WARNING: value may be null") -- простая реализация
-- можно реализовать модуль логирования с уровнями
WARNING: value may be null

Go:

import "log"
log.Printf("WARNING: %s", "disk space low")

// Более гибкие библиотеки: logrus, zap
WARNING: disk space low

Kotlin:

Kotlin обычно использует те же Java-библиотеки (SLF4J, Logback, java.util.logging). Пример с SLF4J:

logger.warn("Warning: deprecated API")
// Вывод, зависящий от backend'а (Logback и т.д.)

Основные отличия от Java: часто более удобные API у сторонних библиотек (конфигурирование, асинхронность), разный формат вывода и поведение по умолчанию. В веб- или скриптовых средах встроенные функции просты, но менее гибки по сравнению с Java logging-фреймворками.

Типичные ошибки при использовании

  • Отсутствие вывода из-за уровня логирования. Если уровень логгера или обработчика выше WARNING, вызов не будет виден. Пример:
Logger logger = Logger.getLogger("MyLogger");
logger.setLevel(java.util.logging.Level.SEVERE); // WARNING будет игнорироваться
logger.warning("Это не появится");
// Ничего не выводится, так как уровень установлен на SEVERE
  • Тяжёлая конкатенация строк без проверки isLoggable ведёт к затратам ресурсов даже при отключённом уровне:
// Плохо
logger.warning("Данные: " + expensiveToString(obj));

// Лучше
if (logger.isLoggable(Level.WARNING)) {
    logger.warning("Данные: " + expensiveToString(obj));
}
  • Передача null в warning(null) может привести к неожиданному поведению в кастомных форматтерах или обработчиках; возможен NullPointerException в пользовательском коде форматтера.
  • Ожидание форматирования похожего на SLF4J. Методы уровня в java.util.logging не поддерживают плейсхолдеры вида "{}". Для форматирования используются отдельные перегрузки log с массивом параметров или MessageFormat.
  • Ошибки конфигурации Handler/Formatter. Неправильный форматтер или исключение в форматтере может заглушить вывод или привести к выбросу исключения при логировании.

Изменения в последних версиях JDK

Основные изменения, влияющие на логирование:

  • Появление API для ленивой генерации сообщений через log(Level, Supplier<String>), что позволяет избежать затрат на формирование строки, если запись не будет обработана.
  • Модульная система (Java Modules) ввела модуль java.logging, что изменяет способ доступа к пакету при использовании модульной упаковки приложения.
  • В остальном базовый API java.util.logging.Logger претерпел мало изменений; большинство новых функций реализуется внешними библиотеками (SLF4J, Logback, Log4j2 и т.д.).

Расширенные и нетипичные примеры использования

1) Настройка FileHandler и кастомного форматтера для предупреждений:

Пример java
import java.io.IOException;
import java.util.logging.*;

public class FileLogExample {
    private static final Logger logger = Logger.getLogger("app.logger");

    public static void main(String[] args) throws IOException {
        logger.setUseParentHandlers(false); // отключить консоль по умолчанию
        FileHandler fh = new FileHandler("app.log", true);
        fh.setLevel(Level.WARNING);
        fh.setFormatter(new SimpleFormatter() {
            @Override
            public synchronized String format(LogRecord lr) {
                return String.format("[%s] %s: %s\n", lr.getLevel(), lr.getLoggerName(), lr.getMessage());
            }
        });
        logger.addHandler(fh);

        logger.warning("Disk space low");
    }
}

Результат в файле app.log:

[WARNING] app.logger: Disk space low

2) Дедупликация повторяющихся предупреждений с помощью Filter:

Пример java
class DedupFilter implements Filter {
    private String last;
    @Override
    public boolean isLoggable(LogRecord record) {
        String msg = record.getMessage();
        if (msg.equals(last)) return false;
        last = msg;
        return true;
    }
}

// Привязка
Logger l = Logger.getLogger("app");
for (Handler h : l.getHandlers()) h.setFilter(new DedupFilter());

// Использование
l.warning("Repeated situation");
l.warning("Repeated situation");

Результат: первая запись появится, вторая будет отброшена.

3) Асинхронная отправка предупреждений в отдельный поток через кастомный обработчик:

Пример java
class AsyncHandler extends Handler {
    private final BlockingQueue q = new LinkedBlockingQueue<>();
    private final Thread t;
    public AsyncHandler(Handler delegate) {
        setLevel(delegate.getLevel());
        t = new Thread(() -> {
            try {
                while (!Thread.currentThread().isInterrupted()) {
                    LogRecord r = q.take();
                    delegate.publish(r);
                }
            } catch (InterruptedException ignored) {}
        });
        t.setDaemon(true);
        t.start();
    }
    @Override public void publish(LogRecord record) { q.offer(record); }
    @Override public void flush() {}
    @Override public void close() throws SecurityException { t.interrupt(); }
}

// Привязка
Logger root = Logger.getLogger("");
Handler console = new ConsoleHandler();
root.addHandler(new AsyncHandler(console));
root.warning("Async warning example");

Результат: предупреждение выводится в консоль асинхронно, основной поток не блокируется на форматирование/вывод.

4) Локализация сообщений через ResourceBundle и logrb (если требуется локализованный текст):

Пример java
ResourceBundle rb = ResourceBundle.getBundle("messages", new Locale("ru"));
Logger logger = Logger.getLogger("app");
logger.logrb(Level.WARNING, "MyClass", "myMethod", rb, "key.warning");

Результат: вывод локализованного сообщения из messages_ru.properties.

5) Использование поставщика сообщений для ленивого вычисления:

Пример java
logger.log(Level.WARNING, () -> "Expensive details: " + heavyComputation());

Появится вычисленное сообщение только если уровень WARNING включён.

джава Logger.warning function comments

En
Logger.warning Запись предупреждения