java 日志设计_Java日志设计实践(3) - 开发篇
1.選擇恰當的日志級別
2.輸出明確的提示文字和充分的現場信息
3.輸出內容一行搞定,不要換行
4.其他
1.選擇恰當的日志級別
選擇日志級別時需要遵循一些通用規范,不可隨意定義
log4j的日志級別,由低到高排列:all trace debug info warn error fatal off
其中,all off僅用以log4j配置文件中開啟或關閉所有日志,trace fatal一般也用不到
對于開發人員來說,只需要關注debug info warn error
debug
正常情況下不需要輸出,只有當出問題時才需要輸出的日志信息,由于生產環境無法單步調試,可以把debug級別的日志想象成你在生成環境中debug
info
可能要關注或者只有比較重要的信息才需要輸出,如:用戶登錄、退出、后臺job執行時長等
warn
存在一些潛在的危險時輸出的日志,比如:請求參數中包含攻擊注入腳本
error
如:請求數據庫時的SQL異常
當然,最好的方法還是參考優秀的開源代碼
2.輸出明確的提示文字和充分的現場信息
要點:
1)明確的提示文字,看到這段提示文本就可以知道發生了什么,不需要再去扒拉源碼
2)充分的現場信息,如:用戶信息、引發異常的參數值、異常棧信息等
舉例:
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.一條日志一行搞定
這個是為了方便跟蹤和分析日志,使用grep命令時不至于僅看到一條日志的部分內容
4.其他
4.1.盡量使用一套日志接口,強烈推薦slf4j
兩大理由:
1)使用{}占位符,避免字符串拼接
以剛才三個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)執行實際日志輸出前強制檢查log是否開啟
組合使用log4j+slf4j時,執行的warn方法實際是這樣的:
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()
這個就不多說了,日志中看到一句莫名其妙hello,world你會怎么想,怎么查????
4.3.不要使用e.printStackTrace()
這種打印只能輸出到catalina.out中,無法單獨制定輸出目的文件,還會導致日志輸出混亂
4.4.slf4j打印異常堆棧信息
兩個例子:
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)]
差異:前者輸出了異常棧信息,后者沒有
原因:后者用{}占位符打印異常對象e,導致異常棧信息沒有輸出
參考文檔
總結
以上是生活随笔為你收集整理的java 日志设计_Java日志设计实践(3) - 开发篇的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux 例行性工作,Linux例行性
- 下一篇: java $和$$的区别_Java #{