设为首页 收藏本站
查看: 700|回复: 0

[经验分享] Log4j日志输出详解

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2016-10-25 11:01:24 | 显示全部楼层 |阅读模式
                      log4j的初始化,Logger的实例为NOPLogger,所有Appender,委托给
rootLogger管理,今天我们来看一下,日志的打印输出。
日志输出源头为下一句


  • log.info("========test daily level info=========");  


我们来看一下,这一句都做了些什么?


  • public final class NOPLogger extends Logger  
  • public class Logger extends Category  


而NOPLogger,Logger,没有info方法,来看Category
//Category 下载


  • public class Category  
  •     implements AppenderAttachable  
  • {  
  •   AppenderAttachableImpl aai;  
  •   static   
  •     {  
  •         FQCN = (org.apache.log4j.Category.class).getName();  
  •     }  
  •     //输出日志  
  •     public void info(Object message)  
  •     {  
  •         //查看info日志,是否开启  
  •         if(repository.isDisabled(20000))  
  •             return;  
  •      //如果INFO,大于等于有效的日志级别,则输出日志  
  •         if(Level.INFO.isGreaterOrEqual(getEffectiveLevel()))  
  •             forcedLog(FQCN, Level.INFO, message, null);  
  •     }  
  •     //根据日志级别,输出日志  
  •     protected void forcedLog(String fqcn, Priority level, Object message, Throwable t)  
  •     {  
  •         //将LoggingEvent,委托给AppenderS处理,  
  •         callAppenders(new LoggingEvent(fqcn, this, level, message, t));  
  •     }  
  •     public void callAppenders(LoggingEvent event)  
  •     {  
  •         int writes;  
  •         Category c;  
  •         writes = 0;  
  •         c = this;  
  • _L3:  
  • label0:  
  •         {  
  •             if(c == null)  
  •                 break; /* Loop/switch isn't completed */  
  •             synchronized(c)  
  •             {  
  •                 if(c.aai != null)  
  •             //Appenders处理日志输出事件  
  •                     writes += c.aai.appendLoopOnAppenders(event);  
  •                 if(c.additive)  
  •                     break label0;  
  •             }  
  •             break; /* Loop/switch isn't completed */  
  •         }  
  •         category;  
  •         JVM INSTR monitorexit ;  
  •           goto _L1  
  •         exception;  
  •         throw exception;  
  • _L1:  
  •         c = c.parent;  
  •         if(true) goto _L3; else goto _L2  
  • _L2:  
  •         if(writes == 0)  
  •             repository.emitNoAppenderWarning(this);  
  •         return;  
  •     }  
  • }  


//AppenderAttachableImpl


  • public class AppenderAttachableImpl  
  •     implements AppenderAttachable  
  • {  
  • protected Vector appenderList;  
  • //遍历rootLooger的Appenders,每一个Appenders分别处理log输出事件  
  • public int appendLoopOnAppenders(LoggingEvent event)  
  •     {  
  •         int size = 0;  
  •         if(appenderList != null)  
  •         {  
  •             size = appenderList.size();  
  •             for(int i = 0; i < size; i++)  
  •             {  
  •                 Appender appender = (Appender)appenderList.elementAt(i);  
  •                 appender.doAppend(event);  
  •             }  

  •         }  
  •         return size;  
  •     }  
  • }  


这里我们来看一下DailyRollingFileAppender
//DailyRollingFileAppender


  • public class DailyRollingFileAppender extends FileAppender  
  • {  
  •     static final int TOP_OF_TROUBLE = -1;  
  •     static final int TOP_OF_MINUTE = 0;  
  •     static final int TOP_OF_HOUR = 1;  
  •     static final int HALF_DAY = 2;  
  •     static final int TOP_OF_DAY = 3;  
  •     static final int TOP_OF_WEEK = 4;  
  •     static final int TOP_OF_MONTH = 5;  
  •     private String datePattern;  
  •     private String scheduledFilename;  
  •     private long nextCheck;  
  •     Date now;  
  •     SimpleDateFormat sdf;  
  •     RollingCalendar rc;  
  •     int checkPeriod;  
  •     static final TimeZone gmtTimeZone = TimeZone.getTimeZone("GMT");  
  •     public DailyRollingFileAppender(Layout layout, String filename, String datePattern)  
  •         throws IOException  
  •     {  
  •         super(layout, filename, true);  
  •         this.datePattern = "'.'yyyy-MM-dd";  
  •         nextCheck = System.currentTimeMillis() - 1L;  
  •         now = new Date();  
  •         rc = new RollingCalendar();  
  •         checkPeriod = -1;  
  •         this.datePattern = datePattern;  
  •     //构造是调用激活配置方法  
  •         activateOptions();  
  •     }  
  • }  


//AppenderSkeleton


  • public abstract class AppenderSkeleton  
  •     implements Appender, OptionHandler  
  • {  
  •    //处理日志事件  
  • public synchronized void doAppend(LoggingEvent event)  
  •     {  
  •         append(event);  
  •     }  
  •     //待子类拓展  
  •    protected abstract void append(LoggingEvent loggingevent);  
  • }  


//AppenderSkeleton


  • public class WriterAppender extends AppenderSkeleton  
  • {  
  •    //处理日志事件  
  •    public void append(LoggingEvent event)  
  •     {  
  •         if(!checkEntryConditions())  
  •         {  
  •             return;  
  •         } else  
  •         {  
  •             subAppend(event);  
  •             return;  
  •         }  
  •     }  
  •     protected void subAppend(LoggingEvent event)  
  •     {  
  •         qw.write(layout.format(event));  
  •         if(layout.ignoresThrowable())  
  •         {  
  •             String s[] = event.getThrowableStrRep();  
  •             if(s != null)  
  •             {  
  •                 int len = s.length;  
  •                 for(int i = 0; i < len; i++)  
  •                 {  
  •             //输出日志,关键是QuietWriter  
  •                     qw.write(s);  
  •                     qw.write(Layout.LINE_SEP);  
  •                 }  

  •             }  
  •         }  
  •         if(shouldFlush(event))  
  •             qw.flush();  
  •     }  
  •     protected boolean immediateFlush;  
  •     protected String encoding;  
  •     protected QuietWriter qw;  
  • }  


下面看一下QuietWriter是什么?如何来的?
看DailyRollingFileAppender的构造方法中,调用了一个方法激活配置activateOptions 下载


  • public DailyRollingFileAppender(Layout layout, String filename, String datePattern)  
  •         throws IOException  
  •     {  
  •         super(layout, filename, true);  
  •         this.datePattern = "'.'yyyy-MM-dd";  
  •         nextCheck = System.currentTimeMillis() - 1L;  
  •         now = new Date();  
  •         rc = new RollingCalendar();  
  •         checkPeriod = -1;  
  •         this.datePattern = datePattern;  
  •     //激活配置  
  •         activateOptions();  
  •     }  
  •      public void activateOptions()  
  •     {  
  •         super.activateOptions();  
  •         if(datePattern != null && fileName != null)  
  •         {  
  •             now.setTime(System.currentTimeMillis());  
  •             sdf = new SimpleDateFormat(datePattern);  
  •             int type = computeCheckPeriod();  
  •             printPeriodicity(type);  
  •             rc.setType(type);  
  •             File file = new File(fileName);  
  •             scheduledFilename = fileName + sdf.format(new Date(file.lastModified()));  
  •         } else  
  •         {  
  •             LogLog.error("Either File or DatePattern options are not set for appender [" + name + "].");  
  •         }  
  •     }  


查看FileAppender


  • public class FileAppender extends WriterAppender  
  • {  
  • public void activateOptions()  
  •     {  
  •         if(fileName != null)  
  •         {  
  •             try  
  •             {  
  •                 setFile(fileName, fileAppend, bufferedIO, bufferSize);  
  •             }  
  •     }  
  •     public synchronized void setFile(String fileName, boolean append, boolean bufferedIO, int bufferSize)  
  •         throws IOException  
  •     {  
  •         LogLog.debug("setFile called: " + fileName + ", " + append);  
  •         if(bufferedIO)  
  •             setImmediateFlush(false);  
  •         reset();  
  •         FileOutputStream ostream = null;  
  •         try  
  •         {  
  •             ostream = new FileOutputStream(fileName, append);  
  •         }  
  •     //根据文件流,创建Writer  
  •         Writer fw = createWriter(ostream);  
  •         if(bufferedIO)  
  •             fw = new BufferedWriter(fw, bufferSize);  
  •     //设置QuietWriter的输出流  
  •         setQWForFiles(fw);  
  •         this.fileName = fileName;  
  •         fileAppend = append;  
  •         this.bufferedIO = bufferedIO;  
  •         this.bufferSize = bufferSize;  
  •         writeHeader();  
  •         LogLog.debug("setFile ended");  
  •     }  
  •     //设置QuietWriter的输出流  
  •     protected OutputStreamWriter createWriter(OutputStream os)  
  •     {  
  •         OutputStreamWriter retval = null;  
  •         String enc = getEncoding();  
  •         if(enc != null)  
  •             try  
  •             {  
  •                 retval = new OutputStreamWriter(os, enc);  
  •             }  
  •         if(retval == null)  
  •             retval = new OutputStreamWriter(os);  
  •         return retval;  
  •     }  
  •     //设置QuietWriter的输出流  
  •      protected void setQWForFiles(Writer writer)  
  •     {  
  •         qw = new QuietWriter(writer, errorHandler);  
  •     }  
  • }  


再看一下ConsoleAppender


  • //ConsoleAppender。  
  • ublic class ConsoleAppender extends WriterAppender  
  • {  
  •     private static class SystemOutStream extends OutputStream  
  •     {  

  •         public void close()  
  •         {  
  •         }  

  •         public void flush()  
  •         {  
  •             System.out.flush();  
  •         }  

  •         public void write(byte b[])  
  •             throws IOException  
  •         {  
  •             System.out.write(b);  
  •         }  

  •         public void write(byte b[], int off, int len)  
  •             throws IOException  
  •         {  
  •             System.out.write(b, off, len);  
  •         }  

  •         public void write(int b)  
  •             throws IOException  
  •         {  
  •             System.out.write(b);  
  •         }  

  •         public SystemOutStream()  
  •         {  
  •         }  
  •     }  
  •      public ConsoleAppender(Layout layout, String target)  
  •     {  
  •         this.target = "System.out";  
  •         follow = false;  
  •         setLayout(layout);  
  •         setTarget(target);  
  •         activateOptions();  
  •     }  
  •     public void activateOptions()  
  •     {  
  •         if(follow)  
  •         {  
  •             if(target.equals("System.err"))  
  •                 setWriter(createWriter(new SystemErrStream()));  
  •             else  
  •             //设置输出流  
  •                 setWriter(createWriter(new SystemOutStream()));  
  •         } else  
  •         if(target.equals("System.err"))  
  •             setWriter(createWriter(System.err));  
  •         else  
  •             setWriter(createWriter(System.out));  
  •         super.activateOptions();  
  •     }  
  • }  


总结:
从上面的分析我们可以看出,log日志的输出,是遍历rootLogger的Appender来处理日志输出事件,Appender,首先确定日志级别是否大于RootLogger的日志级别,大于,则处理日志,而日志的输出委托给QuietWriter,而QuietWriter来源于DailyRollingFileAppender,
ConsoleAppender。

                   


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-291025-1-1.html 上篇帖子: centos 7.0上RabbitMQ 3.5.6版本多实例启动操作讲解 下篇帖子: [Linux]CentOS Minimal版安装纪录
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表