前言
我們在編寫代碼時,都知道在關(guān)鍵算法侧甫,邏輯性較強的地方添加注釋珊佣。一來提高了代碼的可維護性。二來讓代碼有了自可讀性披粟。如果我們把注釋理解為靜態(tài)的自可讀性咒锻。那么,程序在運行時僻爽,我們?nèi)绾尾拍苤莱绦虻膶嶋H運行路徑呢虫碉?這就是今天的主角--日志!
為什么要打日志?
有很多朋友胸梆,不太喜歡打日志敦捧。好幾百,甚至上千行的代碼碰镜。啪兢卵,啪,啪的全寫完绪颖!自信滿滿秽荤,一行日志也沒打。聯(lián)調(diào)柠横,測試窃款,上線都沒問題。系統(tǒng)運行一段時間后牍氛,莫名的出現(xiàn)問題晨继。那么,到底是哪個地方出現(xiàn)問題了搬俊?方法的入?yún)⑹鞘裁次裳铮肯到y(tǒng)走到哪一步了?一無所知唉擂。這下就只剩抓瞎了餐屎。從這里我們應(yīng)該可以看出,打日志是非常有必要的玩祟。我們梳理一下腹缩,打日志有諸多好處。
最直接的好處就是方便解決BUG了。
記錄請求的耗時時間藏鹊,特別是接入第三方供應(yīng)商時胜臊,調(diào)用遠程服務(wù)時,我們可以通過日志來記錄請求的耗時時間伙判。
對關(guān)鍵業(yè)務(wù),關(guān)鍵算法的入?yún)⒑诔溃约敖Y(jié)果打點并記錄下來宴抚。
最后: 記錄日志是給自己分析問題,解決bug用的甫煞。我們盡量記錄的盡可能簡潔菇曲,易懂以及清晰,理想情況下甚至能通過日志還原一次請求抚吠,一次調(diào)用的全過程常潮。
如何打日志?
上面我們說了為什么需要打日志。現(xiàn)在我們說說楷力,如何打日志喊式。以我們最常用slf4j這個日志組件來說,它對應(yīng)的日志級別有: trace, debug萧朝,info岔留,warn,error這五個日志級別检柬。其范圍依次為: error>warn>info>debug>trace献联。
我們在日常開發(fā)中:
在開發(fā)初期,我們可以在進入方法時用info模式的日志級別何址,記錄方法的入里逆,出參。在遠程方法調(diào)用前用爪,調(diào)用后原押,使用info級別。記錄遠程方法的耗時项钮。在try{}catch處班眯,使用error級別日志級別,記錄信息烁巫。以方便用來快速查找署隘,以及分析問題。
服務(wù)運行穩(wěn)定一段時間后亚隙,我們可以將必須記錄的參數(shù)磁餐,修改為warn級別。日志級別設(shè)置為warn。也就是說诊霹,只顯示warn和error級別中的日志羞延。(有很多公司,都以error級別的日志作為報警信息脾还,發(fā)送給對應(yīng)的應(yīng)用負責(zé)人伴箩。)
在生產(chǎn)環(huán)境中,禁止啟用debug級別的日志鄙漏。因為debug級別的日志會顯示很多沒必要的日志嗤谚。這樣很容易造成服務(wù)器資源浪費。嚴重時甚至造成服務(wù)器撐滿怔蚌。直接導(dǎo)致服務(wù)不可用巩步。
凡事都是物極必反。同樣的桦踊,日志也不是越多越好椅野,過多的打印日志,同樣的也會造成服務(wù)性能下降籍胯。甚至造成服務(wù)器壓力過大竟闪。直接影響服務(wù)的可用性。
我們可以通過如下形式來記錄日志:
以log4j+slf4j-api為例:
pom.xml依賴:
<dependency>
? <groupId>org.slf4j</groupId>
? <artifactId>slf4j-api</artifactId>
? <version>1.7.25</version>
</dependency>
<dependency>
? <groupId>org.slf4j</groupId>
? <artifactId>slf4j-log4j12</artifactId>
? <version>1.7.25</version>
? <scope>test</scope>
</dependency>
<dependency>
? <groupId>log4j</groupId>
? <artifactId>log4j</artifactId>
? <version>1.2.17</version>
</dependency>
以下打日志例子:
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LogTest {
? ? private static Logger logger = LoggerFactory.getLogger(LogTest.class);
? ? @Test
? public void testLog(){
? ? ? ? String name="andyqian";
? ? ? ? String blog = "www.andyqian.com";
? ? ? ? //就日志
? ? ? ? logger.debug("name: {} and blog : {} ", name, blog);
? ? }
}
我們通過占位符的形式芒炼,記錄日志瘫怜。不建議使用字符串拼接的形式來記錄日志。
常用Java日志框架
在Java中本刽,常見的日志框架有
JDK自帶的JDK Logger鲸湃。
Apche commons Logging。
Apache log4j子寓。
Slf4j ( Simple Logging Facade for Java)
Logback
Apache log4j 2 (這其實是Apache log4j的升級版本暗挑。在log4j的基礎(chǔ)上,性能有進一步的提高斜友。)
在日常的開發(fā)中炸裆,我們通常都是通過Slf4j+的實現(xiàn)。以上述案例中鲜屏,我們就說到了(slf4j+log4j的形式)烹看。在實際使用中,我們也可以通過slf4j+ logback日志的形式做為日志組合洛史。
ps:各個日志框架的性能不在本文討論之中惯殊。有興趣的朋友,可自行測試也殖。