一、log4j2异步使用
在高并发场景下,日志的输出是一件非常耗时的操作。当日志输出的工作由主线程负责完成时,会拖慢主线程的执行速度,从而影响系统的响应速度。为了解决这个问题,我们可以使用Log4j2的异步日志支持。
在Log4j2中,异步日志的实现依赖于以下两个组件:AsyncLogger和AsyncAppender。AsyncLogger是Log4j2中的一个专门用于异步日志输出的Logger,而AsyncAppender允许我们将日志记录器日志事件发送到另一个线程执行。
使用AsyncLogger时,我们只需要在Logger的配置中配置上async="true"即可,如下所示:
<Configuration status="warn" name="AsyncTest">
<Appenders>
<Async name="Async" bufferSize="1024">
<AppenderRef ref="Console" />
</Async>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Async" />
</Root>
</Loggers>
</Configuration>
在上面的配置中,我们创建了一个名为Async的AsyncAppender,它的缓冲区大小为1024。然后,我们将指定日志输出到该Appender。最后,我们创建了一个名为Root的Logger,它的级别是info,并将日志事件附加到AsyncAppender。
二、log4j2添加自定义参数方式
- 自定义Layout实现添加自定义参数
添加自定义参数最常见的方式是继承Log4j2的PatternLayout类,并覆盖其format方法。PatternLayout是一种高度可定制化的Layout,使用相对简单的模式进行格式化输出。在覆盖format方法时,我们可以通过配置属性或使用配置API来向模式添加自定义参数。
public class MyLayout extends PatternLayout {
private String myParameter = "defaultValue";
public MyLayout(final Configuration config, final String myParameter, final String pattern, final Charset charset, final boolean alwaysWriteExceptions, final boolean noConsoleNoAnsi,
final boolean header, final boolean footer) {
super(config, pattern, charset, alwaysWriteExceptions, noConsoleNoAnsi, header, footer);
this.myParameter = myParameter;
}
@Override
public String format(final LogEvent event) {
// 在日志消息中添加自定义参数
return super.format(event).replace("%mypar%", myParameter);
}
}
- 自定义LogEventFactory实现添加自定义参数
另一种添加自定义参数的方式是实现自己的LogEventFactory。在这种情况下,我们不使用Log4j2提供的默认LogEventFactory,而是创建自己的LogEventFactory。我们可以在此过程中添加自定义属性。在LogEvent被创建之前,我们可以将自定义属性添加到LogEvent对象中,并将新的LogEvent对象返回给Appender。
public class MyLogEventFactory implements LogEventFactory {
private final String myParameter;
public MyLogEventFactory(String myParameter) {
this.myParameter = myParameter;
}
@Override
public LogEvent createEvent(String loggerName, Marker marker, String fqcn, Level level, Message data, List<Property> properties, Throwable t) {
// 将自定义属性添加到LogEvent中
properties.add(Property.createProperty("myParameter", myParameter));
return new Log4jLogEvent(loggerName, marker, fqcn, level, data, properties, t);
}
}
示例1:
<Configuration>
<Appenders>
<Console name="Console">
<PatternLayout pattern="%d{ISO8601} [%t] %-5p %c{1} - %msg - %property{myProperty}%n"/>
</Console>
<CustomAppender name="CustomAppender" >
<MyLayout>
<MyParameter>myParameterValue</MyParameter>
<Pattern>%d{ISO8601} [%t] %-5p %c{1} - %msg - %mypar%n</Pattern>
</MyLayout>
</CustomAppender>
</Appenders>
<Loggers>
<Root level="trace">
<AppenderRef ref="Console"/>
<AppenderRef ref="CustomAppender"/>
</Root>
</Loggers>
</Configuration>
在这个例子中,我们创建了一个名为CustomAppender的新Appender。对于这个Appender,我们在堆栈跟踪和输出消息行中添加了自定义参数。在PatternLayout中,我们将%myParameter的值设置为我们自己的默认值。自定义参数的值可以通过自定义的Layout配置中的MyLayout属性进行修改。
示例2:
public class MyAsyncAppender extends AsyncAppender {
private final String myParameter;
public MyAsyncAppender(String name, String myParameter, AppenderRef[] appenderRefs, LoggerConfig loggerConfig, int bufferSize, boolean blocking, Configuration configuration) {
super(name, appenderRefs, loggerConfig, bufferSize, blocking, configuration);
this.myParameter = myParameter;
}
@Override
protected LogEvent createEvent(final byte[] data, final int offset, final int length, final long timestamp, final String threadName,
final Level level, final String loggerName, final Message message, final Throwable throwable, final Map<String, String> contextMap,
final ThreadContext.ContextStack contextStack, final String fqcn, final StackTraceElement location) {
// 将自定义参数添加到日志事件中
return new Log4jLogEvent(loggerName, null, fqcn, level, message, new ArrayList<>(0), throwable, ThreadContext.getImmutableContext(), contextStack, location, null, timestamp).toBuilder()
.putContextData("myParameter", myParameter)
.build();
}
}
在这个例子中,我们创建了一个名为MyAsyncAppender的新Appender。对于这个Appender,我们在日志消息中添加了自定义参数。我们重写了AsyncAppender的createEvent()方法,在其中创建LogEvent,并将自定义参数添加到上下文数据中。它们可以在格式化时使用。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:log4j2的异步使用及添加自定义参数方式 - Python技术站