溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Log4j日志輸出詳解

發(fā)布時(shí)間:2020-10-07 00:12:26 來(lái)源:網(wǎng)絡(luò) 閱讀:763 作者:qq580c2fa257dbd 欄目:開發(fā)技術(shù)

log4j的初始化,Logger的實(shí)例為NOPLogger,所有Appender,委托給 
rootLogger管理,今天我們來(lái)看一下,日志的打印輸出。 
日志輸出源頭為下一句 

Java代碼  Log4j日志輸出詳解

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


我們來(lái)看一下,這一句都做了些什么? 

Java代碼  Log4j日志輸出詳解

  1. public final class NOPLogger extends Logger  

  2. public class Logger extends Category  


而NOPLogger,Logger,沒(méi)有info方法,來(lái)看Category 
//Category 下載

Java代碼  Log4j日志輸出詳解

  1. public class Category  

  2.     implements AppenderAttachable  

  3. {  

  4.   AppenderAttachableImpl aai;  

  5.   static   

  6.     {  

  7.         FQCN = (org.apache.log4j.Category.class).getName();  

  8.     }  

  9.     //輸出日志  

  10.     public void info(Object message)  

  11.     {  

  12.         //查看info日志,是否開啟  

  13.         if(repository.isDisabled(20000))  

  14.             return;  

  15.      //如果INFO,大于等于有效的日志級(jí)別,則輸出日志  

  16.         if(Level.INFO.isGreaterOrEqual(getEffectiveLevel()))  

  17.             forcedLog(FQCN, Level.INFO, message, null);  

  18.     }  

  19.     //根據(jù)日志級(jí)別,輸出日志  

  20.     protected void forcedLog(String fqcn, Priority level, Object message, Throwable t)  

  21.     {  

  22.         //將LoggingEvent,委托給AppenderS處理,  

  23.         callAppenders(new LoggingEvent(fqcn, this, level, message, t));  

  24.     }  

  25.     public void callAppenders(LoggingEvent event)  

  26.     {  

  27.         int writes;  

  28.         Category c;  

  29.         writes = 0;  

  30.         c = this;  

  31. _L3:  

  32. label0:  

  33.         {  

  34.             if(c == null)  

  35.                 break/* Loop/switch isn't completed */  

  36.             synchronized(c)  

  37.             {  

  38.                 if(c.aai != null)  

  39.             //Appenders處理日志輸出事件  

  40.                     writes += c.aai.appendLoopOnAppenders(event);  

  41.                 if(c.additive)  

  42.                     break label0;  

  43.             }  

  44.             break/* Loop/switch isn't completed */  

  45.         }  

  46.         category;  

  47.         JVM INSTR monitorexit ;  

  48.           goto _L1  

  49.         exception;  

  50.         throw exception;  

  51. _L1:  

  52.         c = c.parent;  

  53.         if(truegoto _L3; else goto _L2  

  54. _L2:  

  55.         if(writes == 0)  

  56.             repository.emitNoAppenderWarning(this);  

  57.         return;  

  58.     }  

  59. }  


//AppenderAttachableImpl 

Java代碼  下載

  1. public class AppenderAttachableImpl  

  2.     implements AppenderAttachable  

  3. {  

  4. protected Vector appenderList;  

  5.  //遍歷rootLooger的Appenders,每一個(gè)Appenders分別處理log輸出事件  

  6.  public int appendLoopOnAppenders(LoggingEvent event)  

  7.     {  

  8.         int size = 0;  

  9.         if(appenderList != null)  

  10.         {  

  11.             size = appenderList.size();  

  12.             for(int i = 0; i < size; i++)  

  13.             {  

  14.                 Appender appender = (Appender)appenderList.elementAt(i);  

  15.                 appender.doAppend(event);  

  16.             }  

  17.   

  18.         }  

  19.         return size;  

  20.     }  

  21. }  


這里我們來(lái)看一下DailyRollingFileAppender 
//DailyRollingFileAppender 

Java代碼  下載

  1. public class DailyRollingFileAppender extends FileAppender  

  2. {  

  3.     static final int TOP_OF_TROUBLE = -1;  

  4.     static final int TOP_OF_MINUTE = 0;  

  5.     static final int TOP_OF_HOUR = 1;  

  6.     static final int HALF_DAY = 2;  

  7.     static final int TOP_OF_DAY = 3;  

  8.     static final int TOP_OF_WEEK = 4;  

  9.     static final int TOP_OF_MONTH = 5;  

  10.     private String datePattern;  

  11.     private String scheduledFilename;  

  12.     private long nextCheck;  

  13.     Date now;  

  14.     SimpleDateFormat sdf;  

  15.     RollingCalendar rc;  

  16.     int checkPeriod;  

  17.     static final TimeZone gmtTimeZone = TimeZone.getTimeZone("GMT");  

  18.     public DailyRollingFileAppender(Layout layout, String filename, String datePattern)  

  19.         throws IOException  

  20.     {  

  21.         super(layout, filename, true);  

  22.         this.datePattern = "'.'yyyy-MM-dd";  

  23.         nextCheck = System.currentTimeMillis() - 1L;  

  24.         now = new Date();  

  25.         rc = new RollingCalendar();  

  26.         checkPeriod = -1;  

  27.         this.datePattern = datePattern;  

  28.     //構(gòu)造是調(diào)用激活配置方法  

  29.         activateOptions();  

  30.     }  

  31. }  


//AppenderSkeleton 

Java代碼  

  1. public abstract class AppenderSkeleton  

  2.     implements Appender, OptionHandler  

  3. {  

  4.    //處理日志事件  

  5. public synchronized void doAppend(LoggingEvent event)  

  6.     {  

  7.         append(event);  

  8.     }  

  9.     //待子類拓展  

  10.    protected abstract void append(LoggingEvent loggingevent);  

  11. }  


//AppenderSkeleton 

Java代碼  下載

  1. public class WriterAppender extends AppenderSkeleton  

  2. {  

  3.    //處理日志事件  

  4.    public void append(LoggingEvent event)  

  5.     {  

  6.         if(!checkEntryConditions())  

  7.         {  

  8.             return;  

  9.         } else  

  10.         {  

  11.             subAppend(event);  

  12.             return;  

  13.         }  

  14.     }  

  15.     protected void subAppend(LoggingEvent event)  

  16.     {  

  17.         qw.write(layout.format(event));  

  18.         if(layout.ignoresThrowable())  

  19.         {  

  20.             String s[] = event.getThrowableStrRep();  

  21.             if(s != null)  

  22.             {  

  23.                 int len = s.length;  

  24.                 for(int i = 0; i < len; i++)  

  25.                 {  

  26.             //輸出日志,關(guān)鍵是QuietWriter  

  27.                     qw.write(s[i]);  

  28.                     qw.write(Layout.LINE_SEP);  

  29.                 }  

  30.   

  31.             }  

  32.         }  

  33.         if(shouldFlush(event))  

  34.             qw.flush();  

  35.     }  

  36.     protected boolean immediateFlush;  

  37.     protected String encoding;  

  38.     protected QuietWriter qw;  

  39. }  


下面看一下QuietWriter是什么?如何來(lái)的? 
看DailyRollingFileAppender的構(gòu)造方法中,調(diào)用了一個(gè)方法激活配置activateOptions 下載

Java代碼  Log4j日志輸出詳解

  1. public DailyRollingFileAppender(Layout layout, String filename, String datePattern)  

  2.         throws IOException  

  3.     {  

  4.         super(layout, filename, true);  

  5.         this.datePattern = "'.'yyyy-MM-dd";  

  6.         nextCheck = System.currentTimeMillis() - 1L;  

  7.         now = new Date();  

  8.         rc = new RollingCalendar();  

  9.         checkPeriod = -1;  

  10.         this.datePattern = datePattern;  

  11.     //激活配置  

  12.         activateOptions();  

  13.     }  

  14.      public void activateOptions()  

  15.     {  

  16.         super.activateOptions();  

  17.         if(datePattern != null && fileName != null)  

  18.         {  

  19.             now.setTime(System.currentTimeMillis());  

  20.             sdf = new SimpleDateFormat(datePattern);  

  21.             int type = computeCheckPeriod();  

  22.             printPeriodicity(type);  

  23.             rc.setType(type);  

  24.             File file = new File(fileName);  

  25.             scheduledFilename = fileName + sdf.format(new Date(file.lastModified()));  

  26.         } else  

  27.         {  

  28.             LogLog.error("Either File or DatePattern options are not set for appender [" + name + "].");  

  29.         }  

  30.     }  


查看FileAppender 

Java代碼  Log4j日志輸出詳解

  1. public class FileAppender extends WriterAppender  

  2. {  

  3. public void activateOptions()  

  4.     {  

  5.         if(fileName != null)  

  6.         {  

  7.             try  

  8.             {  

  9.                 setFile(fileName, fileAppend, bufferedIO, bufferSize);  

  10.             }  

  11.     }  

  12.     public synchronized void setFile(String fileName, boolean append, boolean bufferedIO, int bufferSize)  

  13.         throws IOException  

  14.     {  

  15.         LogLog.debug("setFile called: " + fileName + ", " + append);  

  16.         if(bufferedIO)  

  17.             setImmediateFlush(false);  

  18.         reset();  

  19.         FileOutputStream ostream = null;  

  20.         try  

  21.         {  

  22.             ostream = new FileOutputStream(fileName, append);  

  23.         }  

  24.     //根據(jù)文件流,創(chuàng)建Writer  

  25.         Writer fw = createWriter(ostream);  

  26.         if(bufferedIO)  

  27.             fw = new BufferedWriter(fw, bufferSize);  

  28.     //設(shè)置QuietWriter的輸出流  

  29.         setQWForFiles(fw);  

  30.         this.fileName = fileName;  

  31.         fileAppend = append;  

  32.         this.bufferedIO = bufferedIO;  

  33.         this.bufferSize = bufferSize;  

  34.         writeHeader();  

  35.         LogLog.debug("setFile ended");  

  36.     }  

  37.     //設(shè)置QuietWriter的輸出流  

  38.     protected OutputStreamWriter createWriter(OutputStream os)  

  39.     {  

  40.         OutputStreamWriter retval = null;  

  41.         String enc = getEncoding();  

  42.         if(enc != null)  

  43.             try  

  44.             {  

  45.                 retval = new OutputStreamWriter(os, enc);  

  46.             }  

  47.         if(retval == null)  

  48.             retval = new OutputStreamWriter(os);  

  49.         return retval;  

  50.     }  

  51.     //設(shè)置QuietWriter的輸出流  

  52.      protected void setQWForFiles(Writer writer)  

  53.     {  

  54.         qw = new QuietWriter(writer, errorHandler);  

  55.     }  

  56. }  


再看一下ConsoleAppender 

Java代碼  下載

  1. //ConsoleAppender。  

  2. ublic class ConsoleAppender extends WriterAppender  

  3. {  

  4.     private static class SystemOutStream extends OutputStream  

  5.     {  

  6.   

  7.         public void close()  

  8.         {  

  9.         }  

  10.   

  11.         public void flush()  

  12.         {  

  13.             System.out.flush();  

  14.         }  

  15.   

  16.         public void write(byte b[])  

  17.             throws IOException  

  18.         {  

  19.             System.out.write(b);  

  20.         }  

  21.   

  22.         public void write(byte b[], int off, int len)  

  23.             throws IOException  

  24.         {  

  25.             System.out.write(b, off, len);  

  26.         }  

  27.   

  28.         public void write(int b)  

  29.             throws IOException  

  30.         {  

  31.             System.out.write(b);  

  32.         }  

  33.   

  34.         public SystemOutStream()  

  35.         {  

  36.         }  

  37.     }  

  38.      public ConsoleAppender(Layout layout, String target)  

  39.     {  

  40.         this.target = "System.out";  

  41.         follow = false;  

  42.         setLayout(layout);  

  43.         setTarget(target);  

  44.         activateOptions();  

  45.     }  

  46.     public void activateOptions()  

  47.     {  

  48.         if(follow)  

  49.         {  

  50.             if(target.equals("System.err"))  

  51.                 setWriter(createWriter(new SystemErrStream()));  

  52.             else  

  53.             //設(shè)置輸出流  

  54.                 setWriter(createWriter(new SystemOutStream()));  

  55.         } else  

  56.         if(target.equals("System.err"))  

  57.             setWriter(createWriter(System.err));  

  58.         else  

  59.             setWriter(createWriter(System.out));  

  60.         super.activateOptions();  

  61.     }  

  62. }  


總結(jié): 
從上面的分析我們可以看出,log日志的輸出,是遍歷rootLogger的Appender來(lái)處理日志輸出事件,Appender,首先確定日志級(jí)別是否大于RootLogger的日志級(jí)別,大于,則處理日志,而日志的輸出委托給QuietWriter,而QuietWriter來(lái)源于DailyRollingFileAppender, 
ConsoleAppender。


向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI