Введение в Log4j2 - Appenders, Layouts и Filters

Введение в 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.

Related