Программная конфигурация с Log4j 2

Программная конфигурация с Log4j 2

1. Вступление

В этом руководстве мы рассмотрим различные способы программной настройки Apache Log4j 2.

2. Начальная настройка

Чтобы начать использовать Log4j 2, нам просто нужно включить зависимостиlog4j-core иlog4j-slf4j-impl в нашpom.xml:


    org.apache.logging.log4j
    log4j-core
    2.11.0


    org.apache.logging.log4j
    log4j-slf4j-impl
    2.11.0

3. ConfigurationBuilderс

После того, как мы настроили Maven, нам нужно создатьConfigurationBuilder, который является классом, который позволяет нам настраиватьappenders, filters, layouts, иloggers.

Log4j 2 предоставляет несколько способов получитьConfigurationBuilder.

Начнем с самого прямого пути:

ConfigurationBuilder builder
 = ConfigurationBuilderFactory.newConfigurationBuilder();

И чтобы начать настройку компонентов,ConfigurationBuilder снабжен соответствующим методомnew, напримерnewAppender ornewLayout, для каждого компонента.

Некоторые компоненты имеют разные подтипы, напримерFileAppender илиConsoleAppender,, и в API они обозначаются какplugins.

3.1. Настройка Appenders

Давайте сообщимbuilder, куда отправлять каждую строку журнала, настроивappender:

AppenderComponentBuilder console
  = builder.newAppender("stdout", "Console");

builder.add(console);

AppenderComponentBuilder file
  = builder.newAppender("log", "File");
file.addAttribute("fileName", "target/logging.log");

builder.add(file);

Хотя большинство методовnew не поддерживают это,newAppender(name, plugin) позволяет нам дать приложению имя, которое впоследствии окажется важным. Эти дополнения мы назвалиstdout иlog, , хотя могли бы назвать их как угодно.

Мы также сообщилиbuilder, какой appenderplugin  (или, проще говоря, какой тип appender) использовать. Console иFile относятся к дополнениям Log4j 2 для записи в стандартный выход и файловую систему соответственно.

ХотяLog4j 2 supports several appenders,configuring them using Java can be a bit tricky since AppenderComponentBuilder is a generic class for all appender types.

Это делает его такими методами, какaddAttribute иaddComponent  вместоsetFileName иaddTriggeringPolicy:

AppenderComponentBuilder rollingFile
  = builder.newAppender("rolling", "RollingFile");
rollingFile.addAttribute("fileName", "rolling.log");
rollingFile.addAttribute("filePattern", "rolling-%d{MM-dd-yy}.log.gz");
rollingFile.addComponent(triggeringPolicies);

builder.add(rollingFile);

И, наконец,don’t forget to call builder.add to append it to the main configuration!

3.2. Настройка фильтров

Мы можем добавить фильтры для каждого из наших дополнений, которые определяют для каждой строки журнала, должен ли он быть добавлен или нет.

Давайте воспользуемся плагиномMarkerFilter в нашем консольном приложении:

FilterComponentBuilder flow = builder.newFilter(
  "MarkerFilter",
  Filter.Result.ACCEPT,
  Filter.Result.DENY);
flow.addAttribute("marker", "FLOW");

console.add(flow);

Обратите внимание, что этот методnew не позволяет нам присвоить имя фильтру, но он просит нас указать, что делать, если фильтр проходит или не работает.

В данном случае мы не усложнили задачу, заявив, что еслиMarkerFilter проходит, тоACCEPT лог-линия. В противном случаеDENY сидят.

Обратите внимание, что в этом случае мы добавляем это не кbuilder, а к добавляемым элементам, которые мы хотим использовать этот фильтр.

3.3. Настройка макетов

Затем давайте определим макет для каждой строки журнала. В этом случае мы будем использовать плагинPatternLayout:

LayoutComponentBuilder standard
  = builder.newLayout("PatternLayout");
standard.addAttribute("pattern", "%d [%t] %-5level: %msg%n%throwable");

console.add(standard);
file.add(standard);
rolling.add(standard);

Опять же, мы добавили их непосредственно в соответствующие приложения, а не вbuilder напрямую.

3.4. Настройка Root Logger

Теперь, когда мы знаем, куда будут отправляться журналы, мы хотим настроить, какие журналы будут отправляться в каждый пункт назначения.

Корневой регистратор - это самый верхний регистратор, вродеObject в Java. Этот регистратор будет использоваться по умолчанию, если не переопределен.

Итак, давайте воспользуемся корневым регистратором, чтобы установить уровень ведения журнала по умолчанию наERROR и добавить по умолчанию для нашего приложенияstdout сверху:

RootLoggerComponentBuilder rootLogger
  = builder.newRootLogger(Level.ERROR);
rootLogger.add(builder.newAppenderRef("stdout"));

builder.add(rootLogger);

Чтобы указать нашему регистратору на конкретное приложение, мы не передаем ему экземпляр конструктора. Вместо этогоwe refer to it by the name that we gave it earlier.

3.5. Настройка дополнительных регистраторов

Дочерние регистраторы могут использоваться для определения конкретных пакетов или имен регистраторов.

Давайте добавим регистратор для пакетаcom в наше приложение, установив уровень ведения журнала наDEBUG и направив его в нашlog appender:

LoggerComponentBuilder logger = builder.newLogger("com", Level.DEBUG);
logger.add(builder.newAppenderRef("log"));
logger.addAttribute("additivity", false);

builder.add(logger);

Обратите внимание, что мы можем установитьadditivity w с нашими регистраторами, что указывает, должен ли этот регистратор наследовать свойства, такие как уровень ведения журнала и типы добавителей, от своих предков.

3.6. Настройка других компонентов

Не все компоненты имеют специальный методnew дляConfigurationBuilder.

Итак, в этом случае мы называемnewComponent.

Например, поскольку нетTriggeringPolicyComponentBuilder, нам нужно использоватьnewComponent  для чего-то вроде указания нашей политики запуска для сменных файловых добавлений:

ComponentBuilder triggeringPolicies = builder.newComponent("Policies")
  .addComponent(builder.newComponent("CronTriggeringPolicy")
    .addAttribute("schedule", "0 0 0 * * ?"))
  .addComponent(builder.newComponent("SizeBasedTriggeringPolicy")
    .addAttribute("size", "100M"));

rolling.addComponent(triggeringPolicies);

3.7. Эквивалент XML

ConfigurationBuilder comes оснащены удобным методом для распечатки эквивалентного XML:

builder.writeXMLConfiguration(System.out);

Выполнение вышеуказанной строки выводит:



   
      
         
         
      
      
         
         
            
            
         
      
      
         
      
   
   
      
         
      
      
         
      
   

Это удобно, когда мы хотим дважды проверить нашу конфигурацию или если мы хотим сохранить нашу конфигурацию, скажем, в файловой системе.

3.8. Собираем все вместе

Теперь, когда мы полностью настроены, давайте скажем Log4j 2 использовать нашу конфигурацию:

Configurator.initialize(builder.build());

После его вызоваfuture calls to Log4j 2 will use our configuration.

Обратите внимание, что это означает, что нам нужно вызватьConfigurator.initialize, прежде чем мы будем делать какие-либо вызовыLogManager.getLogger.

4. ConfigurationFactoryс

Теперь, когда мы увидели один способ получить и применитьConfigurationBuilder, давайте взглянем на еще один:

public class CustomConfigFactory
  extends ConfigurationFactory {

    public Configuration createConfiguration(
      LoggerContext context,
      ConfigurationSource src) {

        ConfigurationBuilder builder = super
          .newConfigurationBuilder();

        // ... configure appenders, filters, etc.

        return builder.build();
    }

    public String[] getSupportedTypes() {
        return new String[] { "*" };
    }
}

В этом случае вместо использованияConfigurationBuilderFactory мы создали подклассConfigurationFactory, абстрактный класс, предназначенный для создания экземпляровConfiguration.

Затем, вместо вызоваConfigurator.initialize, как в первый раз, нам просто нужно сообщить Log4j 2 о нашей новой фабрике конфигурации.

Есть три способа сделать это:

  • Статическая инициализация

  • Свойство времени выполнения или

  • Саннотации@Plugin 

4.1. Использовать статическую инициализацию

Log4j 2 поддерживает вызовsetConfigurationFactory  во время статической инициализации:

static {
    ConfigurationFactory custom = new CustomConfigFactory();
    ConfigurationFactory.setConfigurationFactory(custom);
}

Этот подход имеет то же ограничение, что и последний подход, который мы видели, а именно то, что нам нужно будет вызвать егоbefore any calls to LogManager.getLogger.

4.2. Используйте свойство времени выполнения

Если у нас есть доступ к команде запуска Java, то Log4j 2 также поддерживает указание использованияConfigurationFactory to с помощью параметра-D:

-Dlog4j2.configurationFactory=com.example.log4j2.CustomConfigFactory

Основное преимущество этого подхода заключается в том, что нам не нужно беспокоиться о порядке инициализации, как в случае с первыми двумя подходами.

4.3. Используйте аннотацию@Plugin 

И, наконец, в обстоятельствах, когда мы не хотим возиться с командой запуска Java, добавляя-D, мы можем просто аннотировать нашCustomConfigurationFactory с помощью саннотации Log4j 2@Plugin :

@Plugin(
  name = "CustomConfigurationFactory",
  category = ConfigurationFactory.CATEGORY)
@Order(50)
public class CustomConfigFactory
  extends ConfigurationFactory {

  // ... rest of implementation
}

Log4j 2 просканирует путь к классам для классов, имеющих саннотацию@Plugin , и, найдя этот класс в категорииConfigurationFactory , будет использовать его.

4.4. Сочетание со статической конфигурацией

Еще одно преимущество использования расширенияConfigurationFactory заключается в том, что мы можем легко комбинировать нашу настраиваемую конфигурацию с другими источниками конфигурации, такими как XML:

public Configuration createConfiguration(
  LoggerContext context,
  ConfigurationSource src) {
    return new WithXmlConfiguration(context, src);
}

Параметрsource представляет собой статический файл конфигурации XML или JSON, который Log4j 2 находит, если он есть.

Мы можем взять этот файл конфигурации и отправить его в нашу собственную реализациюXmlConfiguration, где мы можем разместить любую необходимую нам конфигурацию переопределения:

public class WithXmlConfiguration extends XmlConfiguration {

    @Override
    protected void doConfigure() {
        super.doConfigure(); // parse xml document

        // ... add our custom configuration
    }
}

5. Заключение

В этой статье мы рассмотрели, как использовать новый APIConfigurationBuilder, доступный в Log4j 2.

Мы также рассмотрели настройку комбинацииConfigurationFactory in сConfigurationBuilder для более сложных случаев использования.

Не забудьте просмотреть мои полные примерыover on GitHub.