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; }
两种配置最终效果是等效的, 唯一区别是生效时间, 代码配置方式在执行到该处代码后生效
总结
建议少使用或者不实用这种过滤器, 当程序进行同步日志时,除全局过滤器外,其余过滤器效率均相同,但在异步日志时,使用该过滤器并不能提高效率
相关文章推荐
- Springboot log4j2过滤器appender级别
- Springboot log4j2过滤器
- SpringBoot配置log4j2的JdbcAppender日志写入数据库,可定义哪些日志写入
- 完美spring boot 使用log4j2按级别输出到不同文件
- spring boot 配置 log4j2
- springboot 中 log4j2的使用及配置讲解
- SpringBoot学习笔记(4):添加自定义的过滤器
- 52. spring boot日志升级篇—log4j多环境不同日志级别的控制【从零开始学Spring Boot】
- 十一、springboot 配置log4j2以及打包成zip文件
- Springboot默认日志logback切换为log4j2
- 总结一下springboot项目整合log4j2框架过程中遇到的问题
- spring boot 过滤器 接口请求耗时统计
- springboot 上传文件 中过滤器配置*.do后缀 无法上传的问题
- springboot 集成log4j2配置
- Spring Cloud Spring Boot mybatis分布式微服务云架构(三十九)对log4j进行多环境不同日志级别的控制
- springboot(2.2.4)配置druid的log4j2日志监控
- 详谈springboot过滤器和拦截器的实现及区别
- spring boot 2集成log4j2
- spring-boot-starter-zuul实现动态路由和过滤器功能
- springboot中定时器、过滤器、拦截器、servlet