Как создать пользовательский аппендер в log4j2?
Как показано в этой ссылке: Как создать собственное приложение в log4j?
Для создания пользовательского приложения в log4j 1.x мы должны расширить класс AppenderSkeleton и реализовать его метод append.
Аналогично тому, как мы можем создать пользовательский аппендер в log4j2, поскольку у нас нет класса AppenderSkelton для расширения, а все остальные аппендеры расширяют класс AppenderBase .
2 ответа:
Это работает совершенно иначе в log4j2, чем в log4j-1.2.
В log4j2 вы создадите плагин для этого. Руководство имеет объяснение с примером для пользовательского приложения здесь: http://logging.apache.org/log4j/2.x/manual/extending.html#Appenders
Может быть удобно расширить
org.apache.logging.log4j.core.appender.AbstractAppender
, но это не требуется.Когда вы аннотируете свой пользовательский класс приложения с помощью
@Plugin(name="MyCustomAppender", ....
, имя плагина становится именем элемента конфигурации, поэтому конфигурация с ваш пользовательский аппендер будет выглядеть следующим образом:Обратите внимание, что атрибут<Configuration packages="com.yourcompany.yourcustomappenderpackage"> <Appenders> <MyCustomAppender name="ABC" otherAttribute="..."> ... </Appenders> <Loggers><Root><AppenderRef ref="ABC" /></Root></Loggers> </Configuration>
packages
в конфигурации представляет собой разделенный запятыми список всех пакетов с пользовательскими плагинами log4j2. Log4j2 будет искать эти пакеты в classpath для классов с аннотациями @Plugin.Вот пример пользовательского приложения, которое печатает на консоль:
package com.yourcompany.yourcustomappenderpackage; import java.io.Serializable; import java.util.concurrent.locks.*; import org.apache.logging.log4j.core.*; import org.apache.logging.log4j.core.config.plugins.*; import org.apache.logging.log4j.core.layout.PatternLayout; // note: class name need not match the @Plugin name. @Plugin(name="MyCustomAppender", category="Core", elementType="appender", printObject=true) public final class MyCustomAppenderImpl extends AbstractAppender { private final ReadWriteLock rwLock = new ReentrantReadWriteLock(); private final Lock readLock = rwLock.readLock(); protected MyCustomAppenderImpl(String name, Filter filter, Layout<? extends Serializable> layout, final boolean ignoreExceptions) { super(name, filter, layout, ignoreExceptions); } // The append method is where the appender does the work. // Given a log event, you are free to do with it what you want. // This example demonstrates: // 1. Concurrency: this method may be called by multiple threads concurrently // 2. How to use layouts // 3. Error handling @Override public void append(LogEvent event) { readLock.lock(); try { final byte[] bytes = getLayout().toByteArray(event); System.out.write(bytes); } catch (Exception ex) { if (!ignoreExceptions()) { throw new AppenderLoggingException(ex); } } finally { readLock.unlock(); } } // Your custom appender needs to declare a factory method // annotated with `@PluginFactory`. Log4j will parse the configuration // and call this factory method to construct an appender instance with // the configured attributes. @PluginFactory public static MyCustomAppenderImpl createAppender( @PluginAttribute("name") String name, @PluginElement("Layout") Layout<? extends Serializable> layout, @PluginElement("Filter") final Filter filter, @PluginAttribute("otherAttribute") String otherAttribute) { if (name == null) { LOGGER.error("No name provided for MyCustomAppenderImpl"); return null; } if (layout == null) { layout = PatternLayout.createDefaultLayout(); } return new MyCustomAppenderImpl(name, filter, layout, true); } }
Подробнее о плагинах: http://logging.apache.org/log4j/2.x/manual/plugins.html
Если руководство не является достаточно, может быть полезно посмотреть исходный код для встроенных приложений в log4j-core.
Похоже, что приложения плагинов сканируются при запуске и не могут быть добавлены во время выполнения. Это правда?
Чтобы добавить новое приложение во время работы, вы можете использовать свойство monitorInterval для обновления конфигурации журнала, т. е. каждые 60 секунд:
<Configuration monitorInterval="60">