Для создания пользовательского приложения в log4j 1.x мы должны расширить класс AppenderSkeleton и реализовать его метод append .
Аналогично, как мы можем создать пользовательское приложение в log4j2, поскольку у нас нет класса AppenderSkelton для расширения, а все остальные приложения расширяют класс AppenderBase .
Переведено автоматически
Ответ 1
В log4j2 это работает совершенно иначе, чем в log4j-1.2.
Может быть удобно расширить org.apache.logging.log4j.core.appender.AbstractAppender, но это не обязательно.
Когда вы аннотируете свой пользовательский класс Appender с помощью @Plugin(name="MyCustomAppender", ...., имя плагина становится именем элемента конфигурации, поэтому конфигурация с вашим пользовательским приложением будет выглядеть следующим образом:
Обратите внимание, что packages атрибут в конфигурации представляет собой разделенный запятыми список всех пакетов с пользовательскими плагинами log4j2. Log4j2 выполнит поиск этих пакетов в classpath для классов, аннотированных с помощью @Plugin .
Вот пример пользовательского приложения, которое выводится на консоль:
// note: class name need not match the @Plugin name. @Plugin(name="MyCustomAppender", category="Core", elementType="appender", printObject=true) publicfinalclassMyCustomAppenderImplextendsAbstractAppender {
// 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 publicvoidappend(LogEvent event) { readLock.lock(); try { finalbyte[] bytes = getLayout().toByteArray(event); System.out.write(bytes); } catch (Exception ex) { if (!ignoreExceptions()) { thrownewAppenderLoggingException(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 publicstatic 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"); returnnull; } if (layout == null) { layout = PatternLayout.createDefaultLayout(); } returnnewMyCustomAppenderImpl(name, filter, layout, true); } }
Использование Mockito или аналогичной библиотеки для создания приложения с ArgumentCaptor не будет работать, если вы ожидаете несколько сообщений журнала, потому что MutableLogEvent повторно используется поверх нескольких сообщений журнала.
Наиболее общее решение, которое я нашел для log4j2, - это предоставить макет реализации, который записывает все сообщения. Для этого не требуются какие-либо дополнительные библиотеки, такие как Mockito или JMockit.
/** * For some reason mvn test will not work if this is @Before, but in eclipse it works! As a * result, we use @BeforeClass. */ @BeforeClass publicstaticvoidsetupClass() { mockedAppender = newMockedAppender(); logger = (Logger)LogManager.getLogger(ClassWithLoggingToTest.class); logger.addAppender(mockedAppender); logger.setLevel(Level.INFO); }
Похоже, что добавляемые плагины сканируются при запуске и не могут быть добавлены во время выполнения. Это правда?
чтобы добавить новое приложение во время работы, вы можете использовать свойство monitorInterval для обновления конфигурации журнала, т. е. каждые 60 секунд: