加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

log4j.xml中的几个使用心得和说明

(2014-09-03 13:38:53)
标签:

log4j

分类: 技术
        项目中使用的是log4j 1的日志工具,之前的配置是沿用上一个项目的,这次改了改,改成了自己预期的样子。

1. 希望不同的环境能够打印的日志级别不同
       很多时候希望在开发和测试环境能够打印debug级别的日志,这样方便开发人员观察程序的运行和查找错误的原因。但如果这些日志都在生产环境进行打印一方面会造成生产环境日志过多,一方面加大了系统的开销。例如处理一个EXCEL上传文件,可以在测试环境将每一行的处理都进行详细的打印,但在生产上这样做日志会过多。对每一行的处理都打印的目的是为了在测试阶段方便观察和查找错误。

可以通过maven的profile来实现
a. 在project的pom.xml文件中增加参数log.level进行配置
log4j.xml中的几个使用心得和说明
b. 在log4j.xml文件中可以如下引用
log4j.xml中的几个使用心得和说明

这样就可以在开发和测试环境使用debug级别,而在生产环境使用info级别。

2. 希望开发环境的所有日志都能打印在console上,但在生产上不要这样做
       日志都被打印在文件中,但开发时希望能够在console打印所有的日志信息,这样方便调试,当然生产环境就不需要打印在console上了

同样,我们通过maven的profile来实现
a. 在project的pom.xml文件中增加参数default.appender进行配置
log4j.xml中的几个使用心得和说明

b. 在log4j.xml文件中可以如下引用
log4j.xml中的几个使用心得和说明

我们可以在log4j.xml文件中增加这些appender:
在开发环境使用console appender
log4j.xml中的几个使用心得和说明

在生产环境使用null appender
log4j.xml中的几个使用心得和说明
使用"org.apache.log4j.varia.NullAppender"表示什么都不做,不会进行打印。

当然也可以配置将所有的日志都打印在一个公共的文件。

3. log4j.xml配置文件的一些说明
a. appender的说明
log4j.xml中的几个使用心得和说明
"append" : "true"表示应用启动时,在原有的日志上添加新的日志
"threshold" : 表示级别的阀值,只有"error"级别的日志才打印

b. logger的说明
log4j.xml中的几个使用心得和说明

"root":是所有logger的父类
"additivity": 是否继承父类, false表示不继承

root是所有logger的最顶层父类,同时,如果有"a.b.c"和"a.b",那么"a.b"就是"a.b.c"的父类得了。就像"com.myweb"就是"com.myweb.project"的父类,在这样的情况下,com.myweb.project的日志也会打印在com.myweb下,解决这个问题的方法就是不继承,如果不继承了,就不会出现这种情况了。

c. 给出的配置是所有的logger都不继承root,这样的话配置文件会比较繁琐,不像继承root这样简单,但是解决了一个问题就是除了找到对应的logger进行打印外,其他的信息可以设置打印他们的级别和文件。也许有更好的方法。

log4j.xml中的几个使用心得和说明
这样做的结果就是其他日志的打印都是INFO,需要的日志可以为DEBUG,这样在console上就可以减少很多实用的框架的DEBUG信息了,例如一些框架像mybatis和struts2的信息等。

4. 日志打印的格式
当前打印的格式为:%d [%-5p] [%c{15}] - %m%n
参数说明:

%d: 日期 当前的格式为:yyyy-MM-dd HH:mm:ss,SSS

%-5p: %p表示该日志的级别,例如:INFO, DEBUG, ERROR等,"-5"的意思是:若日志的级别长度小于5,则右边用空格填充。因为日志级别最大是5,所以这样做的目的是为了对齐,美观。

%c{15}: logger的命名空间,"15"表示层数,假设当前logger名字空间是"a.b.c",那么%c{2}的值就是:b.c

%m: 显示具体的信息

%n: 当前平台下的换行符

具体支持的参数可以参考[6]

5. 关于打印行号的问题
目前的日志格式并没有显示行号,希望的日志应该是这样的:
2014-09-01 18:09:42,011 [INFO ] 
com.myweb.project.webapp.controller.ClassA.methodB(ClassA.java:49) - 我是坑丁小慢
日志有具体的类,方法还有行号

如果你在打印时如下使用: logger.info("abc");
那么只要将日志格式改为:%d [%-5p] [%l] - %m%n
%c{15} 改为 %l 就可以了。

但如果使用的是对logger方法封装的公共方法的话就比较麻烦了,如果只是将日志格式改为:%l,那么打印的类和方法和行数是这个公共方法的行数了,例如:
log4j.xml中的几个使用心得和说明

那么打印的时候的行数是:
com.myweb.project.MyLoggerUtils.info(MyLoggerUtils.java:20)

这并不是我们想要的,简单的说就是打印的是调用logger.info()方法的类,所以会有这种情况。要解决这个情况,深入分析log4j的源码会发现log4j是将堆栈信息打印,然后找到第一个和logger的name匹配的类就作为了日志所在的类了。具体可以看下org.apache.log4j.spi. LocationInfo类的源码,关键就是:fqnOfCallingClass参数,知道具体的原因,我们可以尝试着解决这个问题 :

编写类MyLogger继承org.apache.log4j.Logger类

log4j.xml中的几个使用心得和说明

关键就是属性:FQCN,这里可以定义为MyLoggerUtils.class.getName()。这样在处理的时候会跳过MyLoggerUtils.class,会继续找上一层,如果你有多层(打印日志在父类中),那么FQCN应该设置为实际类的最接近的一层。

随后编写类MyLoggerFactory 实现org.apache.log4j.spi.LoggerFactory接口

log4j.xml中的几个使用心得和说明

在声明logger时,这样定义:
log4j.xml中的几个使用心得和说明
就可以了,logger的使用和普通的用法没有区别,这样打印出来的日志就和我们期望的是一样的了。

6. 还可以做的事
希望在下一个项目的时候讲log4j升级为log4j 2代,也就是logback,同时研究下slf4j,使用slf4j。

参考资料:

[1] http://blog.csdn.net/yycdaizi/article/details/8276265 (java日志组件介绍(common-logging,log4j,slf4j,logback ))

[2] http://blog.csdn.net/wangjian5748/article/details/23824 (Log4j的中文文档)

[3] http://blog.jobbole.com/37518/ (从Log4j迁移到LogBack的理由)

[4] http://www.importnew.com/7450.html (为什么要使用SLF4J而不是Log4J)

[5] http://www.cnblogs.com/kevin-yuan/archive/2012/11/23/2784610.html (Log4j使用详解(log4j.XML格式)——整理)

[6] http://unmi.cc/log4j-patternlayout-all-parameters/ (Log4j输出格式控制--log4j的PatternLayout参数含义[转])

[7] http://www.coderli.com/log4j-slf4j-logger-linenumber (log4j日志封装说明—slf4j对于log4j的日志封装-正确获取调用堆栈)

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有