玩转log4j

Posted pdzbokey

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了玩转log4j相关的知识,希望对你有一定的参考价值。

我的目标是授人以渔,而不是授人以鱼,我相信你仔细看完这篇文章,玩转log4j不成问题

先来一个log4j最简单的例子

public class MyApp {
    static Logger logger = Logger.getLogger(MyApp.class.getName());

    public static void main(String[] args) {
        logger.info("Entering application.");
        Bar bar = new Bar();
        bar.doIt();
        logger.info("Exiting application.");
    }
}
public class Bar {
    static Logger logger = Logger.getLogger(Bar.class);

    public void doIt() {
        logger.debug("Did it again!");
    }
}

在类路径(src目录下)创建log4j的配置文件log4j.properties,里面的内容

log4j.rootLogger=DEBUG, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.SimpleLayout

运行一下,你会看到控制台有输出,这就是一个最简单的log4j配置的例子

 

来解释一下这3行配置

第一行:设置了根记录器,值的格式为: 日志级别, appender1, appender2...

log4j从低到高有这么几个日志级别 DEBUG < INFO < WARN < ERROR < FATAL. 配置成DEBUG就会把所有级别的日志都打印出来,反之配置成FATAL就只会打印FATAL级别的日志

appender1, appender2就是第二行配置的

 

第二行:表示输出到控制台,那除了ConsoleAppender就没有别的Appender了么,答案当然是有的,如图

技术分享图片

只要实现了Appender接口的都可以,所以可以看到第一行里面的A1是在第二行定义的一个ConsoleAppender

 

第三行:log4j.appender.stdout一直到这里都知道,这就是第二行的appender,那么后面为什么要接一个layout呢?

里面是不是有一个属性还是什么呢?我们打开搜索一下,如图

技术分享图片

可以看到里面有一个继承自AppenderSkeleton的layout属性,那么A1后面接的layout就是这个layout属性么?

从第三行看到赋了一个SimpleLayout给layout,看起来一切合理,但是我想说的是第三行里面的layout不是这个layout属性,而是继承自AppenderSkeleton里面的setLayout方法的layout,我曾经在配置spring的时候也思考过这样的问题,后来证明spring配置里面的属性配置是setXxx方法的Xxx,所以我99%的肯定这里的layout是setLayout的layout,要想验证也简单,自己把ConsoleAppender到AppenderSkeleton所经过的类(并不是直接继承)复制下来,然后把setLayout方法改一个名字,比如setLayout1,然后再用你自己的类配置,就知道这里的layout到底还是layout1了,也就是到底是属性还是setter方法里面的,我没有测试,如果有哪位同学测试得到了和我说的不一样的结果,欢迎告诉我。

ConsoleAppender的setLayout是继承自AppenderSkeleton的,而AppenderSkeleton是重写的Appender接口里面的setLayout方法,也就是所有的appender都需要配置layout

所有的appender都继承自AppenderSkeleton,来看一下这个类里面有哪些setter方法

技术分享图片

可以看到有一个setThreshold方法,这个是配置日志级别的,也就是说每个appender都可以配置自己的日志级别,而不必使用统一的日志级别

 

 基于我的这个结果,也就是说只要类里面有setter方法,都可以注入值,我们发现ConsoleAppender里面有一个setTarget(String value)

 所以这个target也是可以配置的,像这样

log4j.appender.A1.target=System.out 

填什么值还是要看一下api,从api可以看出,target有2个值,分别是System.out和System.err,默认是System.out
target表示输出的目标,System.err只输出错误信息,System.out输出所有信息

 

如果第三行配置成下面的

log4j.appender.A1.layout=org.apache.log4j.PatternLayout

表示可以自定义的灵活布局,里面有一个setConversionPattern方法,传入转换模式就可以得到自定义的输出布局,可以看到setConversionPattern这个方法是PatternLayout独有的,其他的layout没有的,这是因为其他的layout的布局是固定的

如第三行的SimpleLayout表示简单布局,仅打印日志级别和日志信息,如DEBUG - Hello world

而PatternLayout的布局是需要自己定义的,所以需要加上一行转换默认的配置,比如可以这样配置

log4j.appender.A1.Layout.conversionPattern=%d{ABSOLUTE} %-4p [%t] %c{5} - %m%n

这一行表示什么意思呢?我们来看一下,可以看一下官方的说明

http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html 

不懂的自行有道翻译,还是翻译的不错的,至少我是翻译的,哈哈哈。。。
我取一些讲一下,每个转换字符都要用%开头,而且是区分大小写的,不要弄错了
%c  类的全路径,可以加参数使用,如果类路径是a.b.c.Test,那么%c{2}得到的结果是c.Test,表示只保留后面的2项
%C 和%c的作用是一样的,而且性能较差,所以我不知道为什么还要弄这个出来
%d  格式化时间,可以这样用%d{HH:mm:ss,SSS} or %d{dd MMM yyyy HH:mm:ss,SSS},这样是最终调用了SimpleDateFormat,
       这样性能不好,所以应该这样用%d{ISO8601} or %d{ABSOLUTE} or %d{DATE},这3种出来的格式分别是
       %d{ISO8601}: 2018-03-26 17:18:38,207
       %d{ABSOLUTE}: 17:19:06,630
       %d{DATE}: 26 三月 2018 17:13:12,056
%F 发出日志请求的文件名, 不推荐使用
%l   位置信息,不推荐使用
%m 日志信息
%n  换行
%p  日志级别
%r   从布局构建到日志记录事件创建的毫秒数
%t   线程
%x   用于输出与生成日志事件的线程关联的NDC(嵌套诊断上下文)
%%  输出一个%

敲黑板,敲黑板。重要的来了
在%和转换字符之间还可以配置对齐方式、最小字符宽度和最大字符宽度
  默认右对齐,负号-表示左对齐
  数字指定最小字符宽度,如果小于最小字符宽度则依据对齐规则在左边或右边添加空格
 . 数字(点号接数字)表示最大字符宽度,如果大于最大字符宽度,则保留后面的最大字符宽度的字符

看几个例子
%20c        右对齐最小宽度20的类路径
%-20c       左对齐最小宽度20的类路径
%.30c       最大宽度为30的类路径,因为总是没有多余的空间,所以没有对齐方式,表现出来的对齐方式是左对齐
%20.30c   右对齐最小宽度为20,最大宽度为30的类路径
%-20.30c  左对齐最小宽度为20,最大宽度为30的类路径

现在知道上面例子中%-4p的意思了:左对齐最小宽度为4的日志级别

如果想让特定的包下的类或特定的类输出指定级别的日志,可以像这样配置
log4j.logger.com.foo=WARN
说明:log4j.logger.是固定的
com.foo是你要指定日志级别的包或类,这样com.foo包下的所有类(或com.foo类)的日志级别就是WARN,其他包或类不受影响

 

来看一下其他常用的Appener

DailyRollingFileAppender(日常翻滚文件Appender):以时间来翻滚的appender

就把里面的一个setDatePattern方法讲一下,其他的setter方法就不说了,可以直接配置的

DailyRollingFileAppender默认是每天创建一个新的日志文件,通过setDatePattern方法可以设置为每个月,每个星期,每个小时设置每分钟创建一个新的日志文件

技术分享图片

 

 RollingFileAppender(翻滚文件appender):以日志文件大小来翻滚

默认翻滚大小是10M,翻滚个数是1个,这都是可以通过里面里面的setter方法来设置的,就不再多说了

最后给一个2个appender的配置文件示例

log4j.rootLogger=DEBUG, A1, A2
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.SimpleLayout

log4j.appender.A2=org.apache.log4j.DailyRollingFileAppender
log4j.appender.A2.datePattern=‘.‘yyyy-MM-dd HH-mm
log4j.appender.A2.file=test.log
log4j.appender.A2.encoding=utf-8
#log4j.appender.A2.append=true
log4j.appender.A2.layout=org.apache.log4j.PatternLayout
log4j.appender.A2.layout.conversionPattern=%r [%t] %-5p (%.30c) [%x] - %m%n

 































以上是关于玩转log4j的主要内容,如果未能解决你的问题,请参考以下文章

从零开始玩转logback

玩转Bash变量

玩转Bash变量

一文玩转 Java 日志数据脱敏

程序源代码Log4J 日志分割

通过java代码给log4j指定appender