1.選擇恰當(dāng)?shù)娜罩炯?jí)別 2.輸出明確的提示文字和充分的現(xiàn)場(chǎng)信息 3.輸出內(nèi)容一行搞定,不要換行 4.其他
1.選擇恰當(dāng)?shù)娜罩炯?jí)別
選擇日志級(jí)別時(shí)需要遵循一些通用規(guī)范,不可隨意定義
log4j的日志級(jí)別,由低到高排列:all trace debug info warn error fatal off 其中,all off僅用以log4j配置文件中開啟或關(guān)閉所有日志,trace fatal一般也用不到 對(duì)于開發(fā)人員來說,只需要關(guān)注debug info warn error
debug 正常情況下不需要輸出,只有當(dāng)出問題時(shí)才需要輸出的日志信息,由于生產(chǎn)環(huán)境無法單步調(diào)試,可以把debug級(jí)別的日志想象成你在生成環(huán)境中debug info 可能要關(guān)注或者只有比較重要的信息才需要輸出,如:用戶登錄、退出、后臺(tái)job執(zhí)行時(shí)長等 warn 存在一些潛在的危險(xiǎn)時(shí)輸出的日志,比如:請(qǐng)求參數(shù)中包含攻擊注入腳本 error 如:請(qǐng)求數(shù)據(jù)庫時(shí)的SQL異常
當(dāng)然,最好的方法還是參考優(yōu)秀的開源代碼
2.輸出明確的提示文字和充分的現(xiàn)場(chǎng)信息要點(diǎn): 1)明確的提示文字,看到這段提示文本就可以知道發(fā)生了什么,不需要再去扒拉源碼 2)充分的現(xiàn)場(chǎng)信息,如:用戶信息、引發(fā)異常的參數(shù)值、異常棧信息等
舉例: LOG.warn("Unknown value for includeParams parameter to URL tag: " + includeParams); LOG.warn("Unable to put request parameters (" + extractQueryString() + ") into parameter map.", e); LOG.warn("Could not find token mapped to token name " + tokenName);
3.一條日志一行搞定
這個(gè)是為了方便跟蹤和分析日志,使用grep命令時(shí)不至于僅看到一條日志的部分內(nèi)容
4.其他
4.1.盡量使用一套日志接口,強(qiáng)烈推薦slf4j
兩大理由: 1)使用{}占位符,避免字符串拼接
以剛才三個(gè)log為例 LOG.warn("Unknown value for includeParams parameter to URL tag: " + includeParams); LOG.warn("Unable to put request parameters (" + extractQueryString() + ") into parameter map.", e); LOG.warn("Could not find token mapped to token name " + tokenName);
如果改用slf4j的話,寫法如下: log.warn("Unknown value for includeParams parameter to URL tag: {}", includeParams); log.warn("Unable to put request parameters ({}) into parameter map.", extractQueryString(), e); log.warn("Could not find token mapped to token name {}", tokenName);
2)執(zhí)行實(shí)際日志輸出前強(qiáng)制檢查log是否開啟
組合使用log4j+slf4j時(shí),執(zhí)行的warn方法實(shí)際是這樣的: public void warn(String format, Object arg) { if (logger.isEnabledFor(Level.WARN)) { FormattingTuple ft = MessageFormatter.format(format, arg); logger.log(FQCN, Level.WARN, ft.getMessage(), ft.getThrowable()); } }
4.2.不要使用System.out.PRintln()
這個(gè)就不多說了,日志中看到一句莫名其妙hello,world你會(huì)怎么想,怎么查????
4.3.不要使用e.printStackTrace()這種打印只能輸出到catalina.out中,無法單獨(dú)制定輸出目的文件,還會(huì)導(dǎo)致日志輸出混亂
4.4.slf4j打印異常堆棧信息兩個(gè)例子:
try { if (true) { throw new RuntimeException("i'm ok"); } } catch (Exception e) { log.error("Error. param:{}, param2:{}, param3:{}", param, param2, param3, e); }將打印: ERROR 2015-01-17 15:11:51,426 Error. param:0, param2:2, param3:false [cn.xxt.log.test.Slf4jTest.main(Slf4jTest.java:36)] java.lang.RuntimeException: i'm ok at cn.xxt.log.test.Slf4jTest.main(Slf4jTest.java:33) try { if (true) { throw new RuntimeException("i'm sorry"); } } catch (Exception e) { log.error("Error. param:{}, param2:{}, param3:{}, {}", param, param2, param3, e); }將打印: ERROR 2015-01-17 15:11:51,429 Error. param:0, param2:2, param3:false, java.lang.RuntimeException: i'm sorry [cn.xxt.log.test.Slf4jTest.main(Slf4jTest.java:44)]
差異:前者輸出了異常棧信息,后者沒有 原因:后者用{}占位符打印異常對(duì)象e,導(dǎo)致異常棧信息沒有輸出
參考文檔
為什么要使用SLF4J而不是Log4J http://www.importnew.com/7450.html
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注