Введение в Log4j2 - Appenders, Layouts и Filters
1. обзор
Регистрация событий является критическим аспектом разработки программного обеспечения. Несмотря на то, что в экосистеме Java доступно множество платформ, Log4J был самым популярным в течение десятилетий благодаря гибкости и простоте, которую он обеспечивает.
Log4j 2 - это новая улучшенная версия классической платформы Log4j.
В этой статье мы познакомим вас с наиболее распространенными приложениями, макетами и фильтрами на практических примерах.
В Log4J2, appender - это просто пункт назначения для событий журнала; он может быть таким же простым, как консоль, и может быть сложным, как любая СУБД. Макеты определяют, как будут представлены журналы, и фильтруют данные по различным критериям.
2. Настроить
Чтобы понять несколько компонентов журналирования и их конфигурацию, давайте настроим различные тестовые сценарии использования, каждый из которых состоит из файла конфигурацииlog4J2.xml и тестового классаJUnit 4.
Две maven-зависимости являются общими для всех примеров:
org.apache.logging.log4j
log4j-core
2.7
org.apache.logging.log4j
log4j-core
2.7
test-jar
test
Помимо основного пакетаlog4j-core нам нужно включить «test jar», принадлежащий пакету, чтобы получить доступ к контекстному правилу, необходимому для тестирования файлов конфигурации с необычными именами.
3. Конфигурация по умолчанию
ConsoleAppender - это конфигурация по умолчанию основного пакетаLog4J 2. Он записывает сообщения в системную консоль в виде простого шаблона:
Давайте проанализируем теги в этой простой конфигурации XML:
-
Configuration: Корневой элемент файла конфигурацииLog4J 2 и атрибутstatus - это уровень внутренних событий Log4J, которые мы хотим регистрировать.
-
Appenders: Этот элемент содержит один или несколько дополнений. Здесь мы настроим приложение, которое выводит на системную консоль в стандартном режиме.
-
Loggers: Этот элемент может состоять из нескольких настроенных элементовLogger. С помощью специального тегаRoot вы можете настроить безымянный стандартный регистратор, который будет получать все сообщения журнала от приложения. Каждый регистратор может быть установлен на минимальный уровень журнала
-
AppenderRef: Этот элемент определяет ссылку на элемент из разделаAppenders. Следовательно, атрибут «ref» связан с атрибутом appenders «name».
Соответствующий модульный тест будет таким же простым. Получим ссылкуLogger и напечатаем два сообщения:
@Test
public void givenLoggerWithDefaultConfig_whenLogToConsole_thanOK()
throws Exception {
Logger logger = LogManager.getLogger(getClass());
Exception e = new RuntimeException("This is only a test!");
logger.info("This is a simple message at INFO level. " +
"It will be hidden.");
logger.error("This is a simple message at ERROR level. " +
"This is the minimum visible level.", e);
}
4. ConsoleAppender сPatternLayout
Давайте определим новый консольный аппендер с индивидуальным цветовым шаблоном в отдельном XML-файле и включим его в нашу основную конфигурацию:
Этот файл использует некоторые переменные шаблона, которые во время выполнения заменяются наLog4J 2:
-
%style\{…}{colorname}: Это напечатает текст в первой паре скобок (…) заданным цветом (colorname).
-
%highlight\{…}\{FATAL=colorname, …}: Это похоже на переменную style. Но разные цвета могут быть заданы для каждого уровня журнала.
-
%date{format}: Заменяется текущей датой в указанномformat. Здесь мы используем формат DateTime «DEFAULT»,‘yyyy_-MM-dd HH: mm: ss, SSS'_.
-
%-5level: Печатает уровень сообщения журнала с выравниванием по правому краю.
-
%message: Представляет необработанное сообщение журнала
Но есть еще много переменных и форматирования вPatternLayout.. Вы можете сослаться на них в официальной документацииLog4J 2.
Теперь мы включим определенный консольный аппендер в нашу основную конфигурацию:
Модульный тест:
@Test
public void givenLoggerWithConsoleConfig_whenLogToConsoleInColors_thanOK()
throws Exception {
Logger logger = LogManager.getLogger("CONSOLE_PATTERN_APPENDER_MARKER");
logger.trace("This is a colored message at TRACE level.");
...
}
5. Приложение Async File сJSONLayout иBurstFilter
Иногда бывает полезно писать сообщения журнала асинхронным способом. Например, если производительность приложения имеет приоритет над доступностью журналов.
В таких случаях мы можем использоватьAsyncAppender.
В нашем примере мы настраиваем асинхронный файл журналаJSON. Кроме того, мы включим пакетный фильтр, который ограничивает вывод журнала с заданной скоростью:
...
...
Заметить, что:
-
JSONLayout настроен таким образом, что записывает одно событие журнала на строку
-
BurstFilter отбрасывает каждое событие с уровнем «INFO» и выше, если их больше двух, но не более 10 отброшенных событий.
-
AsyncAppender установлен в буфер на 80 сообщений журнала; после этого буфер сбрасывается в файл журнала
Давайте посмотрим на соответствующий модульный тест. Мы заполняем добавленный буфер в цикле, позволяем ему записывать на диск и проверяем количество строк в файле журнала:
@Test
public void givenLoggerWithAsyncConfig_whenLogToJsonFile_thanOK()
throws Exception {
Logger logger = LogManager.getLogger("ASYNC_JSON_FILE_APPENDER");
final int count = 88;
for (int i = 0; i < count; i++) {
logger.info("This is async JSON message #{} at INFO level.", count);
}
long logEventsCount
= Files.lines(Paths.get("target/logfile.json")).count();
assertTrue(logEventsCount > 0 && logEventsCount <= count);
}
6. RollingFile Appender иXMLLayout
Затем мы создадим непрерывный файл журнала. После настроенного размера файла файл журнала сжимается и поворачивается.
На этот раз мы используем макетXML:
Заметить, что:
-
ПриложениеRollingFile имеет атрибут «filePattern», который используется для именования файлов ротации журналов и может быть настроен с помощью переменных-заполнителей. В нашем примере он должен содержать дату и счетчик перед суффиксом файла.
-
В конфигурации по умолчаниюXMLLayout будут записываться отдельные объекты событий журнала без корневого элемента.
-
Мы используем политику на основе размера для ротации наших файлов журналов.
Наш класс модульного теста будет выглядеть так же, как и в предыдущем разделе:
@Test
public void givenLoggerWithRollingFileConfig_whenLogToXMLFile_thanOK()
throws Exception {
Logger logger = LogManager.getLogger("XML_ROLLING_FILE_APPENDER");
final int count = 88;
for (int i = 0; i < count; i++) {
logger.info(
"This is rolling file XML message #{} at INFO level.", i);
}
}
7. ПриложениеSyslog
Допустим, нам нужно отправить зарегистрированное событие на удаленный компьютер по сети. Самый простой способ сделать это с помощью Log4J2 - использоватьSyslog Appender:
...
...
Атрибуты в тегеSyslog:
-
name: определяет имя аппендера и должно быть уникальным. Поскольку у нас может быть несколько приложений Syslog для одного приложения и конфигурации
-
format: он может быть установлен как BSD или RFC5424, и записи системного журнала будут отформатированы соответствующим образом
-
host & port: имя хоста и порт удаленного сервера Syslog.
-
protocol:, использовать ли TCP или UPD
-
facility:, в какое средство системного журнала будет записано событие
-
connectTimeoutMillis: период ожидания установленного соединения, по умолчанию равен нулю
-
reconnectionDelayMillis: время ожидания перед повторной попыткой подключения
8. FailoverAppenderс
Теперь могут быть случаи, когда одному аппендеру не удается обработать события журнала, и мы не хотим потерять данные. В таких случаяхFailoverAppender пригодится.
Например, если приложениеSyslog не может отправлять события на удаленный компьютер, вместо потери этих данных мы можем временно вернуться кFileAppender.
FailoverAppender принимает первичный аппендер и количество вторичных добавлений. В случае сбоя основного он пытается обработать событие журнала с дополнительными по порядку, пока одно из них не преуспеет или не останется никаких второстепенных событий, которые можно было бы попробовать:
Давайте проверим это:
@Test
public void givenLoggerWithFailoverConfig_whenLog_thanOK()
throws Exception {
Logger logger = LogManager.getLogger("FAIL_OVER_SYSLOG_APPENDER");
Exception e = new RuntimeException("This is only a test!");
logger.trace("This is a syslog message at TRACE level.");
logger.debug("This is a syslog message at DEBUG level.");
logger.info("This is a syslog message at INFO level.
This is the minimum visible level.");
logger.warn("This is a syslog message at WARN level.");
logger.error("This is a syslog message at ERROR level.", e);
logger.fatal("This is a syslog message at FATAL level.");
}
9. Приложение JDBC
Приложение JDBC отправляет события журнала в RDBMS, используя стандартный JDBC. Соединение может быть получено с использованием любого источника данных JNDI или любой фабрики соединений.
Базовая конфигурация состоит изDataSource илиConnectionFactory, ColumnConfigs иtableName:
А теперь попробуем:
@Test
public void givenLoggerWithJdbcConfig_whenLogToDataSource_thanOK()
throws Exception {
Logger logger = LogManager.getLogger("JDBC_APPENDER");
final int count = 88;
for (int i = 0; i < count; i++) {
logger.info("This is JDBC message #{} at INFO level.", count);
}
Connection connection = ConnectionFactory.getConnection();
ResultSet resultSet = connection.createStatement()
.executeQuery("SELECT COUNT(*) AS ROW_COUNT FROM logs");
int logCount = 0;
if (resultSet.next()) {
logCount = resultSet.getInt("ROW_COUNT");
}
assertTrue(logCount == count);
}
10. Заключение
В этой статье приведены очень простые примеры того, как вы можете использовать различные приложения для ведения журналов, фильтрации и макетов с Log4J2 и способы их настройки.
Примеры, сопровождающие статью, доступныover on GitHub.