1. 程式人生 > >為什麼要log4j和slf4j代替System.out.println()輸出日誌

為什麼要log4j和slf4j代替System.out.println()輸出日誌

內容:

1.什麼是log4j

2.log4j的特點

3.為什麼要用Log4j來替代System.out.println

一、什麼是log4j

Log4j是Apache的一個開源專案,通過使用Log4j,我們可以控制日誌資訊輸送的目的地是控制檯、檔案、GUI元件,甚至是套介面伺服器、NT的事件記錄器、UNIX Syslog守護程序等;我們也可以控制每一條日誌的輸出格式;通過定義每一條日誌資訊的級別,我們能夠更加細緻地控制日誌的生成過程。

二、log4j的特點

三、為什麼要用Log4j來替代System.out.println

關於log4j 的五個問題及答案:

(1)什麼情況使用log4j、什麼情況下使用System.out.println?

System.out.println在開發中可以使用,部署專案後用日誌檔案。最好不要用System.out.println。

(2)log4j是否會影響效能?

是的,log4j會拖慢程序響應時間

(3)為什麼log4j日誌的最高階是error,但error卻是“雖然發生錯誤事件,但仍然不影響系統的繼續執行”?

日誌有7個等級:

A:off 最高等級,用於關閉所有日誌記錄。

B:fatal 指出每個嚴重的錯誤事件將會導致應用程式的退出。

C:error 指出雖然發生錯誤事件,但仍然不影響系統的繼續執行。

D:warm 表明會出現潛在的錯誤情形。

E:info 一般和在粗粒度級別上,強調應用程式的執行全程。

F:debug 一般用於細粒度級別上,對除錯應用程式非常有幫助。

G:all 最低等級,用於開啟所有日誌記錄。

而log4j建議使用四種:debug、info、warn、error

(4)log4j 的檔案儲存位置?

存放到專案目錄下:

${task5.root}/WEB-INF/logs/log.log

(5)log4j列印堆疊資訊?

log.info("xxx", e)

轉載原文:為什麼要用Log4j來替代System.out.println

看到log4j有好處也有缺點,我再來看看為什麼要使用slf4j結合log4j來使用

為什麼使用 SLF4J 而不是 Log4J 來做 Java 日誌

每個Java開發人員都知道日誌記錄對Java應用的重要性,尤其是對服務端應用,而且其中許多人都已經熟悉了各種記錄日誌的庫,比如java.util.logging,Apache的log4j,logback,然而如果你不知道SLF4J,java的簡單記錄日誌的設計的話 ,那麼到了學習並在你的專案中使用它的時候了。在這篇Java文件裡,我們將學習為什麼使用SLF4J比使用log4j或者java.util.logging更好。從我寫 Java開發人員的10個記錄日誌的技巧 算起已經過去了很長一段時間了。我不記得我所寫的有關日誌記錄的任何事情了。無論如何,讓我們迴歸到這個主題上來,與所有提到的這些日誌記錄庫相比,SLF4J與它們之間有一個主要的區別。SLF4J或者說是Java的簡單記錄日誌設計沒有真正地實現日誌記錄,相反它只是一個允許你使用任何處於後端的日誌記錄庫的 抽象層 。如果你正在編寫內部或者外部使用的API或者應用庫的話,那麼你真的不需要讓使用你所編寫的庫的客戶端還去選擇日誌庫。假設專案已經使用了log4j,而且你包含一個名為Apache Active MQ的庫,這個庫還依賴於另一個日誌記錄庫logback的話,那麼你還需要包含它們,然而,如果Apache Active MQ使用了SLF4J的話,你可以繼續使用你的日誌記錄庫,而不需要痛苦地新增和維護新的日誌記錄框架。簡短的說,SLF4J讓你的程式碼獨立於任何特定的日誌記錄API,這個好的想法尤其適合於公共的API開發人員。雖然日誌記錄庫的抽象理念不是新的,而且Apache的commons logging日誌記錄庫也是用了這個理念,不過現在SLF4J很快就會成為Java世界裡標準的日誌記錄庫。讓我們看一些使用 SLF4J而不使用log4j,logback或者java.util.logging的理由。

 

寧願使用SLF4J也不願使用Log4J,logback和java.util.Logging

正如我前面所說,在你的程式碼中編寫日誌記錄語句使用SLF4J的主要動機是讓你的程式獨立於任何特定的日誌記錄庫,這些日誌記錄庫可能需要與你現在配置不同的配置,而且還會引入更多令人頭疼的維護問題。然而除了這個之外,SLF4J API還有一個讓你使用SLF4J而不是用長期感興趣的 Log4j 更讓人信服的功能,也就是佔位符功能,在程式碼中用{}來表示。佔位符功能與 String的format()方法中 的%s非常相似,因為它在執行時刻才提取所提供的真正的字串。這不僅縮減了程式碼中的許多字串連線,而且減少了建立String物件所需要的資源。即便在你生產環境日誌級別比如DEBUG和INFO級別的字串連線可能不需要的時候,仍然可以起到同樣的效果。由於 字串是不可更改的 ,而且它們是在字串池中建立的,這些字串使用了 堆記憶體 ,當應用在生產環境中執行在ERROR級別的時候,字串在大多數情況下就不是必須的,比如DEBUG語句裡的字串就不是必須的。通過使用SLF4J,你可以延遲字串的建立到執行時刻,這意味著只有在需要字串的時候才建立它。如果你已經使用了log4j,那麼你已經熟悉把除錯語句放入if()條件內的工作場景,而SLF4J佔位符功能比log4j更適合這種場景。

下面是你用Log4j時的做法,當然這並不好玩而且它增加了不必要的公式化的程式碼,減少了程式碼的可讀性。

if (logger.isDebugEnabled()) {
    logger.debug("Processing trade with id: " + id + " symbol: " + symbol);
}

而如果你使用SLF4J,你可以使用更簡潔的格式達到同樣的效果,如下:

logger.debug("Processing trade with id: {} and symbol : {} ", id, symbol);

在SLF4J中,我們不需要進行字串拼接,不會導致使用臨時字串帶來的消耗。相反,我們使用帶佔位符的模板訊息來記錄日誌資訊,並提供實際值作為引數。也許你會想,要是有多個引數該怎麼辦,你可以使用帶引數版的日誌方法,也可以通過Object陣列傳入。這確實是非常方便而且高效的記日誌的方法。記住,在為日誌資訊產生最終的字串之前,該方法會檢查是否開啟了特定的日誌級別,這不僅降低了記憶體佔用,而且預先減少了執行字串拼接所消耗的CPU時間。下面的SLF4J日誌方法的程式碼,來自於slf4j-log4j12-1.6.1.jar包裡的Log4j的介面卡類Log4jLoggerAdapter.

public void debug(String format, Object arg1, Object arg2) { if (logger.isDebugEnabled()) {
      FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
      logger.log(FQCN, Level.DEBUG, ft.getMessage(), ft.getThrowable());
    }
}

同樣值得了解是,日誌也會對應用程式的效能產生壓力,大家通常宣揚的是隻在生產環境中才強制記錄日誌。

 

如何使用SLF4J和Log4J來做日誌

除了上面所說的好處,我認為還有個警告需要說一下,為了使用SLF4J你不僅需要進入SLF4J API Jar包,比如slf4j-api-1.6.1.jar,還需要引入協同工作的JAR包,具體是什麼jar包則依賴於後端你使用了什麼日誌工具庫。假如你想使用SLF4J,Simple Logging Facade for Java,還想使用Lo4J,那麼你需要把下列jar包引入到你的classpath中,具體版本要視你使用的SLF4J和log4J版本而定, 比如:

slf4j-api-1.6.1.jar - JAR for SLF4J API
log4j-1.2.16.jar    - JAR for Log4J API
slf4j-log4j12-1.6.1.jar - Log4J Adapter for SLF4J

如果你正在使用Maven來管理你的專案依賴,你可以只引入SLF4J JAR,然後maven會引入它所依賴的其它JAR包。為了使用Log4J和SLF4J,你可以在你專案的pom.xml中新增下列依賴:

<dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.6.1</version>
</dependency>
<dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.6.1</version>
</dependency> 

順便說一下,如果你對使用帶引數版的日誌方法感興趣,那就需要引入SLF4J 1.7版本。

總結

總結這篇文章,我具有充分的理由的來選擇SLF4J而不是直接選用Log4j, commons logging, logback 或者 java.util.logging。

1)在你的開源庫或者私有庫中使用SLF4J,可以使它獨立於任何的日誌實現,這就意味著不需要管理多個庫和多個日誌檔案。你的客戶端將會體會到這一點。

2)SLF4J提供了佔位日誌記錄,通過移除對isDebugEnabled(), isInfoEnabled()等等的檢查提高了程式碼的可讀性。

3)通過使用日誌記錄方法,直到你使用到的時候,才會去構造日誌資訊(字串),這就同時提高了記憶體和CPU的使用率。

4)做一個側面的說明,越少的臨時字串,垃圾回收器就意味著越少的工作,這就意味著為你的應用程式提供更好的吞吐量和效能。

這些優勢都只是冰山一角,當你開始使用SL4J並閱讀它,你會學到更多的好處。我強烈建議,在java中任何新的程式碼開發,都應使用SLF4J而不是任何的日誌API,包括log4J。