这两天看了下 log4j 手册,记录一下
做过的项目中有不少需要记录运行日志的,其中相当一部分使用了 log4j ,因为简单方便并且 JCL 推荐,用到最多的就是其中的 ConsoleAppender 和 RollingFileAppender ,配置一下 Layout , File 等就可以了,在深入的就没有用过了 :->, 现在发现 log4j 还有很多貌似不错的功能 ~~
先来个简单的配置文件, Properties 格式的
#home path
HomePath = C : /temp/log
log4j.rootCategory= DEBUG,stdout
log4j.appender.stdout= org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout= org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = %-d{yyyy-MM-dd HH : mm:ss} [%F:%L] [%c]-[%p] %m%n
#oo
log4j.logger.com.xx= ALL,oo
log4j.logger.com.xx.Threshold= INFO
log4j.appender.oo= org.apache.log4j.RollingFileAppender
log4j.appender.oo.File= ${HomePath}/websms.log
log4j.appender.oo.MaxFileSize= 4000KB
log4j.appender.oo.MaxBackupIndex= 100
log4j.appender.oo.Append= true
log4j.appender.oo.layout = org.apache.log4j.PatternLayout
log4j.appender.oo.layout.ConversionPattern = %-d{yyyy-MM-dd HH : mm:ss} [%c]-[%p] %m%n
1. Logger 的层次
Log4j 中处于最顶端的是 root logger 了,其默认的 level (在 1.1 是 priority )是 debug ,及 >=debug 级别的信息都会被记录(其实就是 all )。上面的前半部分就是给 root logger(category) 设置的 debug 级别并添加了一个 appender 。其层次结构可以类比 java 的类层次结构, root logger 相当于 object 。上例中定义了 com.xx 这个 logger ,即出现如下结构
Root
|
[com]------ 该层在 log4j 中不存在,为了提高访问层次的速度
|
com.xx
log4j 中的很多东西都是依托与层次结构的,例如每一层的 level 和 appender ,如果 com.xx 层没有定义 level ,则会沿着层次往上找, com 当然不存在了,找到 root ,如果 root 肯定有 level 了,也就是 com.xx 的 level ;上面例子中 com.xx 设置了 level 等于 all ,就不必再往上找了。
另一个与层次关系比较密切的就是 appender ,上例中 root 添加了 stdout 输出到 console , com.xx 添加了 oo 输出到文件,由于层次中的 appender 默认是下面的拥有上面的 appender ,则对于 com.xx 这个 logger ,如果符合条件的 log 就要即输出到屏幕又输出到文件,并且级别是 INFO (上面由于定义了 Threshold 这个属性)。当然这种 appender 的继承性也可以打断,就是设置某个层次的 additivity=false ,则位于该层次下方的 logger 只能拥有本身定义的 appender 和直到定义了 additivity=false 的上层节点(包括该节点)的层次中的 appender 。另外定义的 Threshold 不能够继承,只能使用本层次所定义的,如果没有就是 null 了, Threshold 优于 level 。
2. Logger 中的 level
Log4j 中的 level 和 java log 中的 level 基本一致,从低到高依次是 all,debug, info, warn, error, fatal 。一般是调试信息用 debug 即可,提示信息用 info , warn 和 error 感觉有交集,分得不是很清楚, fatal 就是有严重的导致程序不能运行下去了。记录日志必然会占用系统资源,导致应用性能有所下降,因此日志应该根据需要适当记录,即使提高了记录的 level ,遇到 log.debug(“”); 同样需要访问 log ,查看其 level 是否允许 debug 等级的日志输出。
3. Log 过程
在程序中调用 log.info(“”) 后,如果 info 不低于该 log 的 level 和 threshold ,则该信息会封装成 LoggingEvent 对象传递给层次结构中允许的 appender , appender 在检查是否符合 filter ,如果有的话,没有被过滤掉的话就会就调用 log 的 layout 对信息进行格式化最后输出到 log 定义的目的地,中间出错就会到该 appender 定义的 errorhandler 那里(如果有)。如果 log.info(obj) ,则会检查有没有符合该 obj 或其父类的 renderer 对 log 信息进行格式化,相当于重新定义了该 obj 的 toString 方法。
4.log4j 中的 appender
Log4j 提供了 ConsoleAppender , RollingFileAppender , DailyRollingFileAppender , SocketAppender , JMSAppender , SMTPAppender 和 AsyncAppender 。
ConsoleAppender :输出到屏幕;
RollingFileAppender :输出到文件,以滚动的方式生成文件。当日志文件大小超过 MaxFileSize ,则已生成的文件 index 会顺序下移,如果文件数量超过了 MaxBackupIndex ,则最旧的以后 log 文件被丢弃了;
DailyRollingAppender :输出到文件,以日期作为文件名称的一部分,日期在文件名 .log 的后面,可以定义日期的格式,粒度可到分钟;
SocketAppender :把日志信息发到某 socket ,及日志文件可存放在不同服务器上,并通过 socket 传送日志。 Log4j 已经写好了一个 org.apache.log4j.net.SimpleSocketServer 可以接收 client 发送来的日志信息,测试了一下,还不错,该 server 可以设置接收日志的存放方式,配置文件与 log4j 一致。
JMSAppender :用 JMS 发送日志,相比 SocketAppender 就是把发送者和接受者松耦合,但是速度就慢了。
SMTPAppender :可以把日志以邮件方式发送,这个项目中还没有用到,如果设置高界别的错误直接发送给维护者,应该不错, J
AsyncAppender :异步发送,可以和其他 appender 一起用,维护一个队列,由同步变为异步了。
各个 appender 都有相应的参数信息 ~~
5. Layout
Layout 用的比较多的就是 log4j 自带的 PatternLayout 了,当然也可自己定制个,不过 PatternLayout 已经提供了和 c 中的 printf 类似的输出格式定义,基本可以满足大部分要求。
同 printf 一样,每个格式化输出都用 % 来表示,例如
%-d{yyyy-MM-dd HH:mm:ss} [%c]-[%p] %m%n
c | 输出 logger |
C | 输出调用该 logger 的 class 的全名 |
d | 输出 logging event 中的 date |
F | 输出调用 logger 的文件名,一般为 xx.java |
l | 输出调用着的位置信息,在 windows 上会输出类全名,文件和行号 |
L | 输出调用 log 的代码的行号 |
m | 输出 logging event 的信息 |
M | 输出调用 log 的方法名 |
n | 输出平台的分行符 |
p | 输出 log 的 level |
r | 输出从程序运行开始到 log 是已经耗去的时间 |
t | 输出生成 logging event 的线程的名称 |
x | 输出 NDC |
X | 输出 MDC |
% | 输出百分号 |
还可以定义信息的左右对齐和最小最大长度
%20.30c 表示最小 20 个字符,最大 30 个字符,使用默认的最对齐
%-20.30c 标示……,使用右对齐
6. 其他
还可以定义 filter 过滤特定的消息;
定义 renderer 格式化特定类的日志形式
MDC 和 NDC 就是定义输出 log 是开头的一些信息, MDC ( Mapped Diagnostic Context ),定义一些属性值,如果在 pattern 中有这些属性的输出就会查询该属性,输出到 pattern 的相应位置,调用方式是 %X{ 属性名 } ; NDC ( Nested Diagnostic Context ) , 采用是 statck 的方式,会把 push 到栈的内容全部输出。
扩展 log4j ,如果感兴趣 ~~
写的比较粗糙,如果需要了解其中的详细,可以看手册;如果理解错误,请多多指教~ J