您的位置:首页 > 编程语言 > Java开发

springboot log4j2过滤器AppenderControl级别

2020-07-14 05:42 281 查看

springboot log4j2过滤器总介绍

为log4j2配置AppenderControl级别的过滤器

源码分析

以输出一条debug日志为例

log.debug("this is a debug log.");

程序将调用org.apache.logging.log4j.spi.AbstractLogger#debug(java.lang.String)方法, 该方法会顺序调用以下方法

@Override
public void debug(final String message, final Object... params) {
logIfEnabled(FQCN, Level.DEBUG, null, message, params);
}
@Override
public void logIfEnabled(final String fqcn, final Level level, final Marker marker, final String message,
final Object... params) {
if (isEnabled(level, marker, message, params)) {
logMessage(fqcn, level, marker, message, params);
}
}
//org.apache.logging.log4j.spi.AbstractLogger#logMessage(java.lang.String, org.apache.logging.log4j.Level, org.apache.logging.log4j.Marker, java.lang.String, java.lang.Object...)
protected void logMessage(final String fqcn, final Level level, final Marker marker, final String message,
final Object... params) {
final Message msg = messageFactory.newMessage(message, params);
logMessageSafely(fqcn, level, marker, msg, msg.getThrowable());
}
@PerformanceSensitive
// NOTE: This is a hot method. Current implementation compiles to 30 bytes of byte code.
// This is within the 35 byte MaxInlineSize threshold. Modify with care!
private void logMessageSafely(final String fqcn, final Level level, final Marker marker, final Message msg,
final Throwable throwable) {
try {
logMessageTrackRecursion(fqcn, level, marker, msg, throwable);
} finally {
// LOG4J2-1583 prevent scrambled logs when logging calls are nested (logging in toString())
ReusableMessageFactory.release(msg);
}
}
@PerformanceSensitive
// NOTE: This is a hot method. Current implementation compiles to 29 bytes of byte code.
// This is within the 35 byte MaxInlineSize threshold. Modify with care!
private void logMessageTrackRecursion(final String fqcn,
final Level level,
final Marker marker,
final Message msg,
final Throwable throwable) {
try {
incrementRecursionDepth(); // LOG4J2-1518, LOG4J2-2031
tryLogMessage(fqcn, level, marker, msg, throwable);
} finally {
decrementRecursionDepth();
}
}
@PerformanceSensitive
// NOTE: This is a hot method. Current implementation compiles to 26 bytes of byte code.
// This is within the 35 byte MaxInlineSize threshold. Modify with care!
private void tryLogMessage(final String fqcn,
final Level level,
final Marker marker,
final Message msg,
final Throwable throwable) {
try {
logMessage(fqcn, level, marker, msg, throwable);
} catch (final Exception e) {
// LOG4J2-1990 Log4j2 suppresses all exceptions that occur once application called the logger
handleLogMessageException(e, fqcn, msg);
}
}
@Override
public void logMessage(final String fqcn, final Level level, final Marker marker, final Message message,
final Throwable t) {
final Message msg = message == null ? new SimpleMessage(Strings.EMPTY) : message;
final ReliabilityStrategy strategy = privateConfig.loggerConfig.getReliabilityStrategy();
strategy.log(this, getName(), fqcn, marker, level, msg, t);
}
// org.apache.logging.log4j.core.config.AwaitCompletionReliabilityStrategy#log(org.apache.logging.log4j.util.Supplier<org.apache.logging.log4j.core.config.LoggerConfig>, java.lang.String, java.lang.String, org.apache.logging.log4j.Marker, org.apache.logging.log4j.Level, org.apache.logging.log4j.message.Message, java.lang.Throwable)
@Override
public void log(final Supplier<LoggerConfig> reconfigured, final String loggerName, final String fqcn,
final Marker marker, final Level level, final Message data, final Throwable t) {

final LoggerConfig config = getActiveLoggerConfig(reconfigured);
try {
config.log(loggerName, fqcn, marker, level, data, t);
} finally {
config.getReliabilityStrategy().afterLogEvent();
}
}
//org.apache.logging.log4j.core.config.LoggerConfig#log(java.lang.String, java.lang.String, org.apache.logging.log4j.Marker, org.apache.logging.log4j.Level, org.apache.logging.log4j.message.Message, java.lang.Throwable)
@PerformanceSensitive("allocation")
public void log(final String loggerName, final String fqcn, final Marker marker, final Level level,
final Message data, final Throwable t) {
List<Property> props = null;
if (!propertiesRequireLookup) {
props = properties;
} else {
if (properties != null) {
props = new ArrayList<>(properties.size());
final LogEvent event = Log4jLogEvent.newBuilder()
.setMessage(data)
.setMarker(marker)
.setLevel(level)
.setLoggerName(loggerName)
.setLoggerFqcn(fqcn)
.setThrown(t)
.build();
for (int i = 0; i < properties.size(); i++) {
final Property prop = properties.get(i);
final String value = prop.isValueNeedsLookup() // since LOG4J2-1575
? config.getStrSubstitutor().replace(event, prop.getValue()) //
: prop.getValue();
props.add(Property.createProperty(prop.getName(), value));
}
}
}
final LogEvent logEvent = logEventFactory.createEvent(loggerName, marker, fqcn, level, data, props, t);
try {
log(logEvent);
} finally {
// LOG4J2-1583 prevent scrambled logs when logging calls are nested (logging in toString())
ReusableLogEventFactory.release(logEvent);
}
}
public void log(final LogEvent event) {
if (!isFiltered(event)) {
processLogEvent(event);
}
}
private void processLogEvent(final LogEvent event) {
event.setIncludeLocation(isIncludeLocation());
callAppenders(event);
logParent(event);
}
@PerformanceSensitive("allocation")
protected void callAppenders(final LogEvent event) {
final AppenderControl[] controls = appenders.get();
//noinspection ForLoopReplaceableByForEach
for (int i = 0; i < controls.length; i++) {
controls[i].callAppender(event);
}
}
public void callAppender(final LogEvent event) {
if (shouldSkip(event)) {
return;
}
callAppenderPreventRecursion(event);
}
private boolean shouldSkip(final LogEvent event) {
return isFilteredByAppenderControl(event) || isFilteredByLevel(event) || isRecursiveCall();
}
//org.apache.logging.log4j.core.config.AppenderControl#isFilteredByAppenderControl
@PerformanceSensitive
private boolean isFilteredByAppenderControl(final LogEvent event) {
final Filter filter = getFilter();
return filter != null && Filter.Result.DENY == filter.filter(event);
}

AppenderController过滤器配置

配置文件进行配置

配置后启动程序即生效

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="debug">
<AppenderRef ref="Console">
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
</AppenderRef>
</Root>
</Loggers>
</Configuration>

在application.properties中添加

logging.config=classpath:log4j2.xml

代码配置方式

@Bean("log4j-configuration")
public Configuration configuration() {
final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
Configuration configuration = ctx.getConfiguration();

List<AppenderRef> appenderRefs = new ArrayList<>();
Appender appender = configuration.getRootLogger().getAppenders().get("Console");
Filter filter = ThresholdFilter.createFilter(Level.INFO, Filter.Result.ACCEPT, Filter.Result.DENY);
AppenderRef ref = AppenderRef.createAppenderRef(appender.getName(),
null, filter);
appenderRefs.add(ref);

appenderRefs.forEach(appenderRef -> configuration.getRootLogger().removeAppender(appenderRef.getRef()));
doAsyncAppender(configuration, appenderRefs);

configuration.getRootLogger().getAppenderRefs().addAll(appenderRefs);

return configuration;
}

两种配置最终效果是等效的, 唯一区别是生效时间, 代码配置方式在执行到该处代码后生效

总结

建议少使用或者不实用这种过滤器, 当程序进行同步日志时,除全局过滤器外,其余过滤器效率均相同,但在异步日志时,使用该过滤器并不能提高效率

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: