Java日誌組件 log5j 使用介紹

你們都很熟悉log4j啦,log5j在log4j的基礎上提供了幾個改進,應該說是簡單和實用的封裝。有趣的是log5j主頁對本身名字的解釋,由於要感謝JDK 1.5,因此才叫了這個名字,不知道是否是升級到JDK1.7之後叫log7j :)java

主頁是:http://code.google.com/p/log5j/ 你們能夠看看,如今的版本是2.1.2。異步

log5j有幾個封裝是很是實用的,解釋功能的同時咱們稍微看看代碼,有些頗有趣的地方:性能

1,不須要指定log所在的類名了ui


原來的用法:this

 

1     private static final Logger log = Logger.getLogger( FeedTask.class );

新用法:google

1     private static final Logger log = Logger.getLogger();

這個能夠避免複製的時候忘記改類名。線程

咱們看看代碼,Logger裏的:debug

 

1     public static Logger getLogger() {
2         return getLogger(getCallerClassName(), true);
3     }
4   
5     private static String getCallerClassName() {
6         //有趣
7         return new Exception().getStackTrace()[2].getClassName();
8     }

 取類名的時候用的是new了一個Exception,直接截取沒用反射,簡單直接。code

2,支持message的format
原來:
 orm

1     log.debug( "This thing broke: " + foo + " due to bar: " + bar + " on this thing: " + car );

如今:
 

1     log.debug( "This thing broke: %s due to bar: %s on this thing: %s", foo, bar, car );

這個也很方便,效率也提升了,默認用了java.util.Formatter。
咱們看看代碼:

LogEvent裏的:
 

1     public String message() {
2         if (_params == null || _params.length == ) {
3             return _formatMessage;
4         else {
5            //有趣
6             return __tlMessageFormatter.get().format(_formatMessage, _params);
7         }
8     }

 其中format那部分共了工廠模式,實現的地方是:

 

01     public class DefaultMessageFormatter implements MessageFormatter {
02         private final Formatter _formatter;
03   
04         public DefaultMessageFormatter(Locale locale) {   
05  
06             //定義一個formatter
07             _formatter = new Formatter(locale);
08       }
09    
10       public String format(String format, Object... args) {
11           StringBuilder sb = (StringBuilder) _formatter.out();
12           try {
13               //格式化message
14               _formatter.format(format, args);
15               return sb.toString();
16           finally {
17               sb.setLength();
18           }
19       }
20    }

3,新接口
能夠這樣用:

 

1     private static final Log log = LogFactory.getLog();
2     try {    
3         // do something    
4         log.d("Success! Parameters f=$.10f and i=%d", f, i);  
5     catch (Exception e) {    
6         log.e(e, "Failure! Parameters f=$.10f and i=%d", f, i);    
7         // note: exception passed first separate from parameters  
8     }

這個做者也說,仁者見仁,智者見智了。
Log實如今LogImpl裏,其實Logger這個類實如今AbstractLoggable,這裏有個問題,重複了。
咱們回到主線Logger的調用方式上來吧。

4,能夠顯式關閉Log。
這樣用:

1 // initialization phase  
2 com.spinn3r.log5j.LogManager.enableExplicitShutdown();    ...   
3 // in the very end of the shutdown routine  
4 com.spinn3r.log5j.LogManager.shutdown();

 這個是說若是能夠接受log message丟失,而且自己應用程序能夠控制自身的初始化和銷燬的話,能夠用。
這個和log5j的異步log方式有關。

5,性能
簡化的寫法,看代碼:
  Logger:
  
 

1     public void debug(java.lang.Object message) {
2         super.debug(String.valueOf(message));
3     }


 AbstractLoggable:
  
 

1     public void debug(String formatMessage, Object... params) {
2         if (_logger.isEnabled(LogLevel.DEBUG)) {
3              log(LogEvent.create(_logger, _logName, LogLevel.DEBUG,
4                     formatMessage, params));
5         }
6     }

可見,不須要用logger.isDebugEnabled()這樣的代碼了。

另外log5j是默認使用異步方式的。
主要實如今AsyncLogger裏:

 

01 private static final int MAX_QUEUE_SIZE = 100000;
02  
03 private static final AtomicLong __errorCounter = new AtomicLong();
04  
05 //存LogEvent的Queue
06  private final BlockingQueue<LogEvent> __logEventQueue =
07            new ArrayBlockingQueue<LogEvent>(MAX_QUEUE_SIZE);
08  
09 //寫Log的線程
10  private final WriterThread _writerThread;
11  
12 //加入Event
13  public void add(LogEvent event) {
14        if (!__logEventQueue.offer(event)) {
15            logFallback(event);
16        }
17    }

 這個是個生產者消費者模式,WriterThread是消費者。

相關文章
相關標籤/搜索