前言
最近老大讓我修改項目里所有和log有關的代碼,之前我也用過log4j、slf4j或者Logback等日志框架/接口,一直以為打印異常信息就是簡單地一句log.info()或者log.error()而已,沒想到原來一直都使用錯了,以至於有些錯誤信息沒能在log文件中打印出堆棧信息,最終難以定位bug,排查困難。
如何正確地打印異常的堆棧信息?
一般在catch到異常的時候,不要使用e.printStackTrace()來打印異常信息。我們使用日志框架來打印信息,一般來說,日志框架的log級別從低到高是:debug, info, warn, error, fatal。
對於異常,一般使用log.error()來打印堆棧信息。下邊的三個log語句都打印了異常,但是寫法卻不一樣,打印出來的效果也是不同的:
log.error("ERROR", "Error found: ", e);
log.error("ERROR", "Error found: " + e.getMessage());
log.error("ERROR", "Error found: " + e);
以下邊的代碼為例:
try {
System.out.println(1/0);
} catch (final Exception e) {
log.error("ERROR", "Error found: ", e);
log.error("ERROR", "Error found: " + e.getMessage());
log.error("ERROR", "Error found: " + e);
}
在log文件中可以發現輸出是這樣的:
2018-11-09 11:46:34,834 main ERROR com.lewis.test.TestLewis - Message: ERROR; Description: Error found:
java.lang.ArithmeticException: / by zero
at com.lewis.test.TestLewis.main(TestLewis.java:46)
2018-11-09 11:46:34,837 main ERROR com.lewis.test.TestLewis - Message: ERROR; Description: Error found: / by zero
2018-11-09 11:46:34,838 main ERROR com.lewis.test.TestLewis - Message: ERROR; Description: Error found: java.lang.ArithmeticException: / by zero
對於第一個log語句,可以看到堆棧信息被打印了出來。
對於第二個log語句,只是打印出了異常的具體信息,既沒有異常類名,也沒有堆棧信息。
對於第三個log語句,打印出了異常的類名和具體信息,但是沒有打印出來堆棧信息。
總結一下,就是我們應該使用第一種log語句的形式來將堆棧信息打印出來,方便日后定位bug,排除錯誤。