您现在的位置是:网站首页 > 代码编程 > JAVA开发JAVA开发
【原】为什么说在log4j中Threshold拥有最高优先级
不忘初心 2020-09-18 围观() 评论() 点赞() 【JAVA开发】
简介:在很早的时候,我在博客上专门写过几篇关于log4j的文章,当时学习的时候,还特意标注了Threshold的优先级最高,没成想,看文章的学会了,写文章的人自己忘记了。。。最近这几天,我在优化博客的代码,调试的过程中,想将所有的sql日志打印出来,多么简单的事情,却没注意细节,将Threshold的日志级别配错了,导致sql打印不出来,竟然浪费了我几乎半天的时间来找问题。
在很早的时候,我在博客上专门写过几篇关于log4j的文章,当时写文章的时候,还特意标注了Threshold的优先级最高,没成想,看文章的学会了,写文章的人自己忘记了。。。
最近这几天,我在优化博客的代码,调试的过程中,想将所有的sql日志打印出来,多么简单的事情,却没注意细节,将Threshold的日志级别配错了,导致sql打印不出来,竟然浪费了我几乎半天的时间来找问题。
我的配置文件(log4j.properties)如下:
log4j.rootLogger=INFO,console
# framework
log4j.logger.org.springframework=ERROR
log4j.logger.org.apache.ibatis=ERROR
log4j.logger.org.mybatis.spring=ERROR
log4j.logger.com.mchange.v2=ERROR
# self
log4j.logger.com.wolffy=DEBUG
# sql
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
# 控制台(console)
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Threshold=INFO
log4j.appender.console.ImmediateFlush=true
log4j.appender.console.Target=System.out
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%5p] - %c - %m%n
大家觉着上述配置,能打印出来sql日志吗?
有人可能会想,你开篇都这么说了,肯定是打印不出来呀!!!
没错,这个配置确实打印不出来sql日志,大家可能会怀疑是否rootLogger在作祟,但就算是我将rootLogger直接设置为DEBUG级别都不行,后来我debug的时候发现也确实不是它,反而问题出在了Threshold上,在这里,多余的代码我就不放了,直接放点儿需要debug的关键代码,让大家明白问题出在哪里。
AppenderSkeleton.java
在它里面有一个doAppend()方法
/**
* This method performs threshold checks and invokes filters before
* delegating actual logging to the subclasses specific {@link
* AppenderSkeleton#append} method.
* */
public
synchronized
void doAppend(LoggingEvent event) {
if(closed) {
LogLog.error("Attempted to append to closed appender named ["+name+"].");
return;
}
if(!isAsSevereAsThreshold(event.getLevel())) {
return;
}
Filter f = this.headFilter;
FILTER_LOOP:
while(f != null) {
switch(f.decide(event)) {
case Filter.DENY: return;
case Filter.ACCEPT: break FILTER_LOOP;
case Filter.NEUTRAL: f = f.getNext();
}
}
this.append(event);
}
紧接着,看它的isAsSevereAsThreshold()方法,问题就在这一行,我发现每次打印的sql日志,走到这一行的时候,直接就return掉了。
/**
Check whether the message level is below the appender's
threshold. If there is no threshold set, then the return value is
always <code>true</code>.
*/
public
boolean isAsSevereAsThreshold(Priority priority) {
return ((threshold == null) || priority.isGreaterOrEqual(threshold));
}
跟到这里,看到这个threshold了,大概清楚问题是出在哪里了,既然上一步return了,说明这一步肯定是返回了false,这个threshold参数肯定是没有为null的,因为我在配置文件中写了INFO,那就只有后面的isGreaterOrEqual()方法了。
/**
Returns <code>true</code> if this level has a higher or equal
level than the level passed as argument, <code>false</code>
otherwise.
<p>You should think twice before overriding the default
implementation of <code>isGreaterOrEqual</code> method.
*/
public
boolean isGreaterOrEqual(Priority r) {
return level >= r.level;
}
在该方法中,对两个日志级别进行了比较,一个是logger配置的level,一个是appender的threshold,如果传进来的logger超过了threshold的级别,那么不管你怎么配置,logger的日志最终都会以threshold的级别来输出,就类似于木桶效应,它打印的日志级别永远取决于Threshold的配置。
Priority.java
package org.apache.log4j;
/**
<font color="#AA4444">Refrain from using this class directly, use
the {@link Level} class instead</font>.
@author Ceki Gülcü */
public class Priority {
transient int level;
transient String levelStr;
transient int syslogEquivalent;
public final static int OFF_INT = Integer.MAX_VALUE;
public final static int FATAL_INT = 50000;
public final static int ERROR_INT = 40000;
public final static int WARN_INT = 30000;
public final static int INFO_INT = 20000;
public final static int DEBUG_INT = 10000;
//public final static int FINE_INT = DEBUG_INT;
public final static int ALL_INT = Integer.MIN_VALUE;
// 多余代码省略掉...
}
so,说到底还是自己配置错了~
再次感慨,在平时的工作中,真的是要温故知新呀!!!
log4j.rootLogger=INFO,console
# framework
log4j.logger.org.springframework=ERROR
log4j.logger.org.apache.ibatis=ERROR
log4j.logger.org.mybatis.spring=ERROR
log4j.logger.com.mchange.v2=ERROR
# self
log4j.logger.com.wolffy=DEBUG
# sql
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
# 控制台(console)
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.ImmediateFlush=true
log4j.appender.console.Target=System.out
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} [%5p] - %c - %m%n
修改配置如上所示,就可以正确打印出sql日志了,总之呢,就是最细粒度由Threshold控制,其他的自己根据不同的包名配置响应的日志级别。
看完文章,有任何疑问,请加入群聊一起交流!!!
很赞哦! ()
相关文章
- log4j配置文件详解
- log4j使用之ConsoleAppender教程
- log4j使用之FileAppender教程
- log4j使用之RollingFileAppender教程
- log4j使用之DailyRollingFileAppender教程
- log4j使用之JDBCAppender教程
- log4j使用之SMTPAppender教程
- log4j使用之SocketAppender教程
- 使用SMTPAppender碰到的几个问题
- org.apache.tomcat.util.bcel.classfile.ClassFormatException: Invalid byte tag in constant pool: 19
标签云
猜你喜欢
- IntelliJ IDEA 2019.2已经可以利用补丁永久破解激活了
- IntelliJ IDEA 2019.3利用补丁永久破解激活教程
- IntelliJ IDEA高版本最灵活的永久破解激活方法(含插件激活,时长你说了算)
- Jetbrains全家桶基于ja-netfilter的最新破解激活详细图文教程
- IntelliJ IDEA 2022.1永久破解激活教程(亲测可用,持续更新)
- 分享几个正版 IntelliJ IDEA 激活码(破解码、注册码),亲测可用,持续更新
- ja-netfilter到底需不需要mymap,2021.3.2版本激活失效?
- 如何激活idea2022.1及以上版本中的插件(亲测可用)
- 【史上最全】IntelliJ IDEA最新2022.1版本安装和激活视频教学(含插件)
- IntelliJ IDEA 2022.2 版本最新2099年永久激活方法,亲测可用,也可以开启新UI了。
站点信息
- 网站程序:spring + freemarker
- 主题模板:《今夕何夕》
- 文章统计:篇文章
- 标签管理:标签云
- 微信公众号:扫描二维码,关注我们