在Java編程中,良好的日志記錄是一項重要的實踐。無論是在調試代碼還是在生產環境中追蹤問題,準確的日志信息能夠提供有價值的上下文和跟蹤數據。然而,對于許多開發者來說,正確地記錄日志可能是個挑戰。
本文介紹一些簡單且實用的技巧,以幫助讀者在Java編程中改善日志記錄,使其更加高效和易于調試。
理想的日志格式應包含最基本的信息,例如當前時間戳(通常精確到毫秒)、日志級別、線程名稱等。可以像下面這樣配置logback日志:
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{HH:mm:ss.SSS} %-5level [%thread][%logger{0}] %m%n</pattern> </encoder></appender>
如果開發者的日志格式不記錄當前時間,那么甚至無法知道請求發生的時間。
常見的日志級別有五個,分別是error、warn、info、debug和trace。在日常開發中,開發者需要選擇適當的日志級別,不要直接打印info級別的日志。
對于較低的日志級別,如trace/debug級別,必須進行日志級別開關判斷。
User user = new User(666L, "demo");if (log.isDebugEnabled()) { log.debug("userId is: {}", user.getId());}
由于目前存在以下日志代碼:
logger.debug("Processing trade with id: " + id + " and symbol: " + symbol);
如果配置的日志級別是warn,上述日志將不會被打印,但仍會執行字符串拼接操作。如果符號是對象,還將執行toString()方法,這會浪費系統資源。盡管進行了上述操作,但最終日志并未打印出來,因此建議添加日志開關判斷。
開發人員不需要打印大量的日志,只需要打印能夠快速定位問題的有效日志。什么是有效和關鍵的日志呢?
就參數而言,通常是關鍵信息,比如userId等。
SLF4J是一個以門面模式(facade mode)工作的日志框架,有利于統一各個類的維護和日志處理方法,而且可以輕松替換底層的日志框架且不需要修改代碼。
import org.slf4j.Logger;import org.slf4j.LoggerFactory;private static final Logger logger = LoggerFactory.getLogger(Demo.class);
當遇到 if...else... 或 switch 等條件語句時,應盡量在分支的第一行打印日志,這樣在排查問題時,可以通過日志確定進入了哪個分支,代碼邏輯更清晰,也更容易排查問題。
if (user.isVip()) { log.info("User isVip, Id: {}", user.getUserId());} else { log.info("User not isVip, Id: {}", user.getUserId());}
以上代碼示例在每個分支的第一行使用日志打印。
錯誤的用法:
logger.info("Processing trade with id: " + id + " and symbol: " + symbol);
在上面的例子中,使用 + 運算符來拼接字符串會帶來一定的性能損失。
正確的用法:
logger.info("Processing trade with id: {} and symbol: {}", id, symbol);
在日志中使用花括號 {} 作為占位符,這比使用 + 運算符更加優雅和簡潔。與負面示例相比,占位符的使用只是一個替換操作,可以有效提高性能。
錯誤的用法:
try { ...} catch (Exception e) { e.printStackTrace();}
正確的用法:
try { ...} catch (Exception e) { log.error("error", e);}
使用e.printStackTrace()打印的堆棧日志與業務代碼日志交織在一起,通常不方便檢查異常日志。
e.printStackTrace()語句生成的字符串記錄了堆棧信息。如果信息過長,字符串常量池所在的內存塊沒有空間,也就是內存已滿,那么用戶的請求會被阻塞。
日志最終會輸出到文件或其他輸出流中,這涉及到IO性能。如果采用異步方式,可以顯著提高IO性能。
除非有特殊要求,建議使用異步方式輸出日志。以logback為例,配置異步非常簡單,只需使用AsyncAppender:
<appender name="FILE_ASYNC" class="ch.qos.logback.classic.AsyncAppender"> <appender-ref ref="ASYNC"/></appender>
以上配置使用AsyncAppender來實現異步輸出日志。
在聯機環境中禁用調試功能非常重要。
因為通常系統會有大量的調試日志,各種框架也會大量使用調試日志,在線調試可能會很快填滿磁盤,影響業務系統的正常運行。
本文鏈接:http://www.www897cc.com/showinfo-26-57889-0.html十個Java編程中記錄日志的小技巧
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com
上一篇: Golang流水線設計模式實踐
下一篇: 別被前端框架 PUA 了!