1.系統爲什麼要有日誌?
一個合格的系統不僅要運行高效、計算準確,同時又必須兼顧穩定性、可靠性。其次從開發角度看,又必須有可拓展性和可維護性。各方面都必須很完善,這樣的一個系統才能稱得上是一個合格完美的系統。
說到可維護性,不得不涉及到系統監控和Bug的快速定位。在開發階段還比較容易對系統進行監控,一般都會在本機上對系統的運行進行實時監控。而對於bug的定位,開發者也會熟練使用debug功能進行bug定位,更有甚者有的開發者憑着多年的開發經驗通過對系統的異常信息能直接分析出Bug產生的原因、位置以及解決方案。但是,系統畢竟是人開發的,我們無法保證一個嚴格測試通過的系統一旦投入生產,在運行中會不會出現一些意想不到的問題。而且有些問題生產存在,但在本機由於場景比較複雜等原因難以復現,我們又該如何快速、準確地對bug進行定位分析和解決呢?
我們多麼希望存在一個好的工具可以實時記錄系統的運行狀況,並快速查找關鍵詞進行定位與分析,在這種背景下日誌系統應運而生。我們可以通過日誌工具在系統設計、開發和實現的過程中注意有效Log的輸出,方便我們日後對系統監控和異常分析。
2.系統的那些系統的哪些運行信息需要進行日誌記錄?
- 功能模塊的啓動和結束(完整的系統由多個功能模塊組成,每個模塊負責不同的功能,因此需要對模塊的啓動和結束進行監控。是否在需要的時機正常加載該模塊?又是否在退出結束的時候正常完成結束操作,正常退出?)
- 用戶的登錄和退出(哪位用戶在什麼時間通過什麼IP登錄或退出了系統)
- 系統的關鍵性操作(數據庫鏈接信息、網絡通信的成功與失敗等)
- 系統運行期間的異常信息(NPE、OOM以及其他的超時、轉換異常等)
- 關鍵性方法的進入和退出(一些重要業務處理的方法,在進入和結束的時候需要有日誌信息進行輸出)
3.什麼格式的日誌有助於開發者進行明確的分析?
日誌信息要求必須精簡,過多的無用信息不但對系統分析起不到什麼作用,反而會增加系統的運行壓力、消耗系統的運行資源。這裏有個日誌模板,可供參考。
時間-[線程名][日誌等級]-日誌輸出位置(全類名,可以精確到方法名):日誌信息
2013-09-04 10:49:20.296-[Thread-initRedis21504][INFO]-com.shanghai.LoginController.initLogInfo:LingMing[User] is logining
日誌信息的內容可以根據不同的情況進行設計,但是前面的時間到日誌輸出位置必須要保證完整性,這樣纔有利於日誌的分析。
4.如何對不同的日誌信息進行等級劃分?
日誌等級通常分爲四種:DEBUG、INFO、WARN、ERROR
- DEBUG:系統調試信息,通常用於開發過程中對系統運行情況的監控,在實際運行環境中不進行輸出。
- INFO:系統運行的關鍵性信息,通常用於對系統運行情況的監控。
- WARN:告警信息,系統存在潛在的問題,有可能引起運行異常,但此時並未產生異常。
- ERROR:系統錯誤信息,需要進行及時處理和優化。
- FATAL:非常嚴重的錯誤,導致系統中止。
這裏列出來了各種等級的日誌信息,在開發過程中哪些信息需要設置爲哪種等級有賴於開發者的自己判斷,這裏只是給個建議。
5.日誌有哪些實現方式?
- 使用common-loggi ng和log4j
Apache爲了讓衆多的日誌工具有一個相同操作方式,實現了一個通用日誌工具包:commons-logging。而Log4j基本上是Java平臺上最好的日誌組件了。
使用ommons-logging的Log接口,並由commons-logging在運行時決定使用哪種日誌架構(如Log4j)。現在,Apache通用日誌工具commons-logging和Log4j已經成爲Java日誌的標準工具。
1)Maven/Jar包
需要使用commons-logging.jar和log4j.jar包。如果使用Maven,則需要在pom中添加:
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
2)目錄結構
注意要添加對應的屬性文件
common-logging.properties:用於指定具體的實現方案;log4j.properties:用於指定日誌輸出格式以及對應終端
3)配置common-logging.properties文件
只需要一行即可,放在classpath下,如果是Maven中就在src/resources下:
org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger
4)配置log4j.properties文件
放在classpath下,如果是Maven中就在src/resources下。具體意義看註釋。
### set log levels ###
log4j.rootLogger = debug , stdout , D , E
### 輸出到控制檯 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
## 輸出INFO級別以上的日誌
log4j.appender.stdout.Threshold = INFO
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = %d{ABSOLUTE} %5p %c{1}:%L - %m%n
### 輸出到日誌文件 ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = D:/logs/log.log
log4j.appender.D.Append = true
## 輸出DEBUG級別以上的日誌
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
### 保存異常信息到單獨文件 ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
## 異常日誌文件名
log4j.appender.E.File = D:/logs/error.log
log4j.appender.E.Append = true
## 只輸出ERROR級別以上的日誌!!!
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
5)測試
package com.zzkun;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Created by kun on 2016/5/13.
*/
public class LogTest {
private static Log logger = LogFactory.getLog(LogTest.class);
public static void main(String[] args) {
logger.trace("我是trace信息");
logger.debug("我是debug信息");
logger.info("我是info信息");
logger.warn("我是warn信息");
logger.error("我是error信息");
logger.fatal("我是fatal信息");
}
}