如何在log4j2中创建自定义Appender?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在log4j2中创建自定义Appender?相关的知识,希望对你有一定的参考价值。
正如在这个链接中讨论的:qazxsw poi
为了在log4j 1.x中创建自定义appender,我们必须扩展AppenderSkeleton类并实现其append方法。
类似地,我们如何在log4j2中创建自定义appender,因为我们没有扩展AppenderSkelton类,所有其他appender扩展AppenderBase类。
这在log4j2中的工作方式与在log4j-1.2中的工作方式完全不同。
在log4j2中,您将为此创建一个插件。手册中有一个自定义appender示例的解释:How to create a own Appender in log4j?
扩展http://logging.apache.org/log4j/2.x/manual/extending.html#Appenders可能很方便,但这不是必需的。
当您使用org.apache.logging.log4j.core.appender.AbstractAppender
注释自定义Appender类时,插件名称将成为配置元素名称,因此使用自定义appender的配置将如下所示:
@Plugin(name="MyCustomAppender", ....
请注意,配置中的<Configuration packages="com.yourcompany.yourcustomappenderpackage">
<Appenders>
<MyCustomAppender name="ABC" otherAttribute="...">
...
</Appenders>
<Loggers><Root><AppenderRef ref="ABC" /></Root></Loggers>
</Configuration>
属性是包含自定义log4j2插件的所有包的逗号分隔列表。 Log4j2将在类路径中搜索这些包,注释用@Plugin注释的类。
这是一个打印到控制台的示例自定义appender:
packages
有关插件的更多详细信息: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);
}
}
如果手册不够,那么查看log4j-core中内置appender的源代码可能会很有用。
看起来插件appender在启动时被扫描,并且在运行时无法添加。真的吗?
在运行时添加新的appender可以使用monitorInterval属性来更新日志配置,即每60秒:
http://logging.apache.org/log4j/2.x/manual/plugins.html
对于需要输出到TextArea的人来说,这是一个有效的调整
使TextArea静态
<Configuration monitorInterval="60">
在Frame中添加静态方法
NetBeans Swing TextArea is not static, causes trouble
打电话给Appender的追加
public class MyFrame extends javax.swing.JFrame {
...
public static void outputToTextArea(String message) {
jTextArea.append(message);
}
正如您所指出的,AppenderSkeleton不再可用,因此@Override
public void append(LogEvent event) {
final byte[] bytes = getLayout().toByteArray(event);
MyFrame.outputToTextArea(new String(bytes));
}
中的解决方案将无效。
如果您期望多个日志消息,则使用Mockito或类似的库来创建带有ArgumentCaptor的Appender将无法工作,因为MutableLogEvent会在多个日志消息上重用。
我在log4j2中找到的最通用的解决方案是提供一个记录所有消息的模拟实现。它不需要任何其他库,如Mockito或JMockit。
How to create my own Appender in log4j?
以上是关于如何在log4j2中创建自定义Appender?的主要内容,如果未能解决你的问题,请参考以下文章