作者:聂勇 欢迎转载,请保留作者信息并说明文章来源!
前面介绍了Log4j的总体架构 和 Log4j的初始化, 这篇文章接着介绍Log4j如何输出日志。
Log4j输出日志 | Log4j write log
Log4j输出日志分为六个步骤:全局开关控制、日志等级过滤、封装日志信息、过滤器处理、日志信息格式化、输出至文件。下面分两个环节来介绍这六个步骤是如何实现的:
1、第一环节:预处理
当调用Log4j的方法(如:debug(String, Throwable)、info(String, Throwable))输出日志时,首先对日志信息进行预处理,其序列图如下。
说明:
- isDisabled(int level):根据全局日志等级threshold进行判断,如果日志等级低于threshold,不输出日志。
- isGreaterOrEquals(Priority r):根据当前logger配置的日志等级level进行判断,如果日志等级低于当前logger配置的日志等级,不输出日志。
- foredLog(String fqcn Priority level, Object message, Throwable t):将日志信息封装成LoggingEvent对象。
- callAppenders(LoggingEvent event):将LoggingEvent对象分发给所有的Appender。其实现代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| public void callAppenders(LoggingEvent event) { int writes = 0; for (Category c = this; c != null; c = c.parent) { synchronized (c) { if (c.aai != null) { writes += c.aai.appendLoopOnAppenders(event); } if (!c.additive) { break; } } } if (writes == 0) { repository.emitNoAppenderWarning(this); } } public int appendLoopOnAppenders(LoggingEvent event) { int size = 0; Appender appender; if (appenderList != null) { size = appenderList.size(); for (int i = 0; i < size; i++) { appender = (Appender) appenderList.elementAt(i); appender.doAppend(event); } } return size; }
|
2、第二环节:输出日志
输出日志前还有两道工序需要处理:Filter处理和日志信息格式化。其执行序列图如下。
相应的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| 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); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| protected void subAppend(LoggingEvent event) { this.qw.write(this.layout.format(event)); if (layout.ignoresThrowable()) { String[] s = event.getThrowableStrRep(); if (s != null) { int len = s.length; for (int i = 0; i < len; i++) { this.qw.write(s[i]); this.qw.write(Layout.LINE_SEP); } } } if (shouldFlush(event)) { this.qw.flush(); } }
|
说明:
- decide(LoggingEvent event):有三种返回值 DENY、ACCEPT、NEUTRAL,DENY表示丢弃当前日志信息,ACCEPT表示输出当前日志信息,NEUTRAL表示继续下一个Filter。Filter只能在XML配置文件中使用,Properties文件中不支持。
- format(LoggingEvent event):对日志进行格式化处理。
- write(String string):将日志信息输出至目的地(文件、数据库或网格)。
相关文章 | Index
1、Apache Log4j 架构
2、Apache Log4j 架构之初始化
3、Apache Log4j 架构之输出日志