Руководство по Log4j и log4j.properties в Java
Log4J — это популярный фреймворк для логирования с открытым исходным кодом, написанный на Java. Log4j широко используется в различных приложениях на Java. Более того, он является потокобезопасным, быстрым и предоставляет иерархию именованных логгеров. Log4j распространяется под лицензией Apache Software License с открытым исходным кодом.
Версия Log4j 1.x достигла конца своего жизненного цикла 5 августа 2015 года. Поэтому на сегодняшний день Log4j2 является последним обновлением Log4j.
В этом руководстве мы изучим Log4j и как настроить основные компоненты Log4j с помощью файла log4j.properties в Java.
1. Настройка Maven
Для начала нам понадобится зависимость log4j-core в нашем файле pom.xml:
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.24.1</version>
</dependency>
2. API Log4j
API Log4j предоставляет механизм для передачи информации о логировании на основе различных уровней приоритетов и направления её в различные назначения, такие как файлы, консоли, базы данных и т. д. Он также поддерживает фильтрацию лог-событий перед их передачей логгерам или аппендерам.
API Log4j имеет многослойную архитектуру, которая предоставляет два типа объектов в фреймворке Log4j — основные объекты и вспомогательные объекты.
3. Компоненты Log4j
Существует три основных компонента Log4j — логгеры, аппендеры и макеты — которые могут использоваться вместе для вывода настраиваемых лог-сообщений в нужные назначения. Давайте рассмотрим их кратко.
4.1. Логгер
Объект Logger отвечает за представление информации о логировании. Это первый обязательный уровень в архитектуре Log4j. Класс Logger определён в пакете org.apache.log4j.
Как правило, мы создаём один экземпляр Logger для каждого класса приложения, чтобы логировать важные события, относящиеся к этому классу. Также мы обычно создаём этот экземпляр в начале класса, используя статический фабричный метод, который принимает имя класса в качестве параметра:
private static final Logger logger = Logger.getLogger(JavaClass.class.getName());
Затем мы можем использовать различные методы класса Logger для логирования или вывода важных событий в зависимости от их категорий. Эти методы включают trace(), debug(), info(), warn(), error(), fatal(). Эти методы определяют уровень запроса на логирование.
Приоритетный порядок методов Logger: TRACE < DEBUG < INFO < WARN < ERROR < FATAL. Таким образом, эти методы выводят лог-сообщения в зависимости от уровня логгера, установленного в файле log4j.properties. Это означает, что если мы установим уровень логгера как INFO, то все события INFO, WARN, ERROR и FATAL будут записаны в лог.
4.2. Аппендер
Аппендер обозначает назначение вывода логов. Мы можем выводить логи в несколько предпочтительных мест с помощью Log4j, таких как консоль, файлы, удалённый сокет-сервер, база данных и т. д. Мы называем эти выходные назначения аппендерами. Более того, мы можем прикрепить несколько аппендеров к логгеру.
Аппендеры работают в соответствии с правилом аддитивности аппендеров. Это правило гласит, что вывод лог-сообщения любого логгера будет направлен ко всем его аппендерам и его предкам — аппендерам, которые находятся выше в иерархии.
Log4j имеет несколько аппендеров, определённых для файлов, консольных выводов, GUI-компонентов, удалённых сокет-серверов, JMS и т. д.
4.3. Макет
Мы используем макеты для настройки формата лог-сообщений. Мы можем сделать это, ассоциировав макет с уже определённым аппендером. Таким образом, комбинация макета и аппендеров помогает нам отправлять отформатированные лог-сообщения в нужные назначения.
Мы можем указать формат лог-сообщений, используя шаблоны преобразования. Класс PatternLayout объясняет больше о символах преобразования, которые мы можем использовать в зависимости от наших нужд.
Мы также рассмотрим несколько символов преобразования через примеры в следующих разделах.
5. Файл log4j.properties
Мы можем настроить Log4j с помощью XML или файла свойств. Файл log4j.properties хранит конфигурации в виде пар “ключ-значение”.
Имя файла конфигурации свойств log4j по умолчанию — log4j.properties. Логгер ищет это имя файла в CLASSPATH. Однако, если нам нужно использовать другое имя конфигурационного файла, мы можем установить его с помощью системного свойства log4j.configuration.
Файл log4j.properties содержит спецификации аппендеров, их имена и типы, а также шаблоны макетов. Он также содержит спецификации о корневом логгере по умолчанию и его уровнях логирования.
6. Синтаксис файла log4j.properties
В общем файле log4j.properties мы определяем следующие конфигурации:
- Корневой логгер и его уровень. Мы также предоставляем имя для аппендера здесь.
- Затем мы назначаем действительный аппендер для определённого имени аппендера.
- Наконец, мы определяем макет, цель, уровень и т. д. для определённого аппендера.
Давайте посмотрим на синтаксис общего файла log4j.properties:
# Корневой логгер с именем аппендера
log4j.rootLogger = DEBUG, NAME
# Назначаем NAME действительный аппендер
log4j.appender.NAME = org.apache.log4j.FileAppender
# Определяем макет для NAME
log4j.appender.NAME.layout=org.apache.log4j.PatternLayout
log4j.appender.NAME.layout.conversionPattern=%m%n
Здесь NAME — это имя аппендера. Как уже обсуждалось ранее, мы можем прикрепить несколько аппендеров к логгеру, чтобы направлять логи в разные назначения.
7. Примеры
Теперь давайте разберём конфигурации файла log4j.properties для различных аппендеров с помощью нескольких примеров.
7.1. Пример программы
Давайте начнём с примерного приложения, которое логирует некоторые сообщения:
import org.apache.log4j.Logger;
public class Log4jExample {
private static Logger logger = Logger.getLogger(Log4jExample.class);
public static void main(String[] args) throws InterruptedException {
for(int i = 1; i <= 2000; i++) {
logger.info("This is the " + i + " time I say 'Hello World'.");
Thread.sleep(100);
}
}
}
Приложение простое — оно записывает некоторые сообщения в цикле с короткой задержкой между итерациями. В нём 2,000 итераций, и в каждой итерации есть пауза в 100 мс. Таким образом, выполнение должно занять около трёх с половиной минут. Мы будем использовать это приложение в наших примерах ниже.
7.2. Логирование в консоль
Консоль является местом по умолчанию для логирования сообщений, если конфигурационный файл не найден. Давайте создадим конфигурацию log4j.properties для ConsoleAppender с корневым логгером и также определим уровень логирования для него:
# Корневой логгер
log4j.rootLogger=INFO, stdout
# Направляем лог-сообщения в stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
Здесь мы определили файл log4j.properties со следующими спецификациями:
- Мы установили уровень корневого логгера как INFO. Это означает, что все лог-события с уровнем INFO и выше будут записываться. Мы также задали имя для аппендера как stdout.
- Поскольку мы хотим направить логи в консоль, мы назначили аппендер как org.apache.log4j.ConsoleAppender и цель как System.out.
- Наконец, мы указали формат для PatternLayout, в котором хотим выводить логи, используя ConversionPattern.
Давайте также разберём значение каждого из символов преобразования в ConversionPattern, которые мы использовали:
- %d добавляет временную метку в заданном формате.
- %-5p добавляет информацию об уровне логирования к каждому лог-сообщению. Это означает, что приоритет события логирования должен быть выровнен по левому краю с шириной в пять символов.
- %c{1} выводит квалифицированное имя класса, опционально за которым следуют имена пакетов (квалификатор точности), то есть логирует конкретное лог-сообщение.
- %L выводит номер строки конкретного лог-события.
- %m выводит фактическое лог-сообщение.
- %n добавляет новую строку после каждого лог-сообщения.
Таким образом, когда мы запускаем наше примерное приложение, мы получаем следующие строки, напечатанные в консоли:
2023-08-01 00:27:25 INFO Log4jExample:15 - This is the 1 time I say 'Hello World'.
...
...
2023-08-01 00:27:25 INFO Log4jExample:15 - This is the 2000 time I say 'Hello World'.
Документация для класса PatternLayout объясняет больше о символах преобразования, которые мы можем использовать в зависимости от наших нужд.
7.3. Несколько назначений
Как уже обсуждалось ранее, мы можем перенаправлять лог-события в несколько назначений:
# Корневой логгер
log4j.rootLogger=INFO, file, stdout
# Перенаправление в файл
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=C:\\Baeldung\\app.log
log4j.appender.file.MaxFileSize=5KB
log4j.appender.file.MaxBackupIndex=2
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
# Перенаправление в консоль
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
Здесь мы использовали два аппендера, чтобы перенаправить лог-сообщения как в файл, так и в консоль. Также мы назначили RollingFileAppender для нашего файлового аппендера. Мы используем RollingFileAppender, когда знаем, что лог-файлы могут со временем увеличиваться в размере.
В нашем примере выше мы использовали RollingFileAppender, который прокручивает лог-файлы на основе как размера, так и количества лог-файлов, используя параметры MaxFileSize и MaxBackupIndex. Таким образом, лог-файл будет прокручиваться, когда его размер достигнет 5 КБ, и мы будем хранить максимум два прокрученных лог-файла в качестве резервной копии.
Когда мы запускаем наше приложение, мы получаем следующие файлы, содержащие те же лог-сообщения, что и в предыдущем примере:
31/01/2024 10:28 138 app.log
31/01/2024 10:28 5.281 app.log.1
31/01/2024 10:28 5.281 app.log.2
8. Заключение
В этой статье мы рассмотрели Log4j и его три компонента — логгеры, аппендеры и макеты. Мы также поняли синтаксис файла log4j.properties и некоторые простые примеры конфигурации файла log4j.properties.