Вопрос-ответ

How to Create a Custom Appender in log4j2?

Как создать пользовательское приложение в log4j2?

Как описано по этой ссылке : Как создать собственное приложение в log4j?

Для создания пользовательского приложения в log4j 1.x мы должны расширить класс AppenderSkeleton и реализовать его метод append .

Аналогично, как мы можем создать пользовательское приложение в log4j2, поскольку у нас нет класса AppenderSkelton для расширения, а все остальные приложения расширяют класс AppenderBase .

Переведено автоматически
Ответ 1

В log4j2 это работает совершенно иначе, чем в log4j-1.2.

В log4j2 для этого нужно создать плагин. В руководстве есть объяснение с примером пользовательского приложения здесь: http://logging.apache.org/log4j/2.x/manual/extending.html#Appenders

Может быть удобно расширить org.apache.logging.log4j.core.appender.AbstractAppender, но это не обязательно.

Когда вы аннотируете свой пользовательский класс Appender с помощью @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.

Ответ 2

Как вы указали, AppenderSkeleton больше недоступен, поэтому решения в Как создать мое собственное приложение в log4j? не будут работать.

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

Наиболее общее решение, которое я нашел для log4j2, - это предоставить макет реализации, который записывает все сообщения. Для этого не требуются какие-либо дополнительные библиотеки, такие как Mockito или JMockit.

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.Logger;
import org.apache.logging.log4j.core.appender.AbstractAppender;

private static MockedAppender mockedAppender;
private static Logger logger;

@Before
public void setup() {
mockedAppender.message.clear();
}

/**
* For some reason mvn test will not work if this is @Before, but in eclipse it works! As a
* result, we use @BeforeClass.
*/

@BeforeClass
public static void setupClass() {
mockedAppender = new MockedAppender();
logger = (Logger)LogManager.getLogger(ClassWithLoggingToTest.class);
logger.addAppender(mockedAppender);
logger.setLevel(Level.INFO);
}

@AfterClass
public static void teardown() {
logger.removeAppender(mockedAppender);
}

@Test
public void test() {
// do something that causes logs
for (String e : mockedAppender.message) {
// add asserts for the log messages
}
}

private static class MockedAppender extends AbstractAppender {

List<String> message = new ArrayList<>();

protected MockedAppender() {
super("MockedAppender", null, null);
}

@Override
public void append(LogEvent event) {
message.add(event.getMessage().getFormattedMessage());
}
}
Ответ 3

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


чтобы добавить новое приложение во время работы, вы можете использовать свойство monitorInterval для обновления конфигурации журнала, т. е. каждые 60 секунд:

    <Configuration monitorInterval="60">
java logging