Slf4j + logback 打印日誌的最佳實踐

 

我們拋開業務邏輯,僅僅從日誌的角度來考慮日誌問題。集合最近對項目的日誌優化,總結以下幾點最佳實踐。

 

Slf4j + logback 打印日誌的最佳實踐
1,日誌級別使用不當
2,謹慎使用e.printStackTrace()
3,使用佔位符,而不是字符串拼接
4,儘量打印更少的日誌
5,儘量不要在for循環中log日誌

 

下面結合代碼,來具體講解。

 

1,日誌級別使用不當

 

Slf4j有四個級別的log level可供選擇,級別從上到下由低到高,優先級高的將被打印出來。

Debug:簡單來說,對程序調試有利的信息都可以debug輸出。

info:對用戶有用的信息,比如最常見的打印接口入參和返參。

warn:可能會導致錯誤的信息,比如某個對象可能爲null的場景判斷。

error:顧名思義,發生錯誤的地方,最常見的catch代碼塊中的日誌。

 

這裏以error日誌爲例,舉一個例子,在合適的場合打印合適的日誌,是我們日誌界的規範。

        // ---------------- 1,日誌級別使用不當 ----------------
        try{
            String str = null;
            str.length();
        } catch(Exception e) {
            // 這裏不推薦打印info日誌
            logger.info("注意,這裏不要打印info日誌,", e);
            // 正確的做法
            logger.error("注意,這裏不要打印error日誌,", e);
        }

 

 

2,謹慎使用e.printStackTrace()

 

e.printStackTrace()打印的是異常堆棧信息,會佔用內存空間。正確的姿勢是把日誌打印到文件中。

        // ---------------- 2,謹慎使用e.printStackTrace() ----------------
        try{
            String str = null;
            str.length();
        } catch(Exception e) {
            // 謹慎使用e.printStackTrace()
            e.printStackTrace();
        }

 

3,使用佔位符,而不是字符串拼接

 

Slf4j打印日誌使用了佔位符,避免了字符串拼接操作。字符串拼接最大的弊端,就是需要new新的字符串對象,增加了內存的開銷。

        // ---------------- 3,使用佔位符,而不是字符串拼接 ----------------
        String str = null;
        String str2 = "五千年文明史";
        try{
            str.length();
        } catch(Exception e) {
            // 不推薦的做法,尤其是拼接的 字符串較多時,對性能有影響
            logger.error("str:" + str + ", str2:" + str2, e);
            // 正確的做法
            logger.error("str:{}, str2:{}", str, str2, e);
        }

 

4,儘量打印更少的日誌

 

日誌打印,要堅持一個原則:儘量打印更少的日誌。

因爲磁盤空間也是有限的,如果磁盤空間不足,會直接導致應用程序的崩潰。

 

好的做法是:不要打印無用的日誌,不要重複打印日誌,儘量不要在for循環中打印日誌。

        // ---------------- 4,儘量打印更少的日誌 ----------------
        String str1 = null;
        String str2 = null;
        String str3 = null;
        try{
            // 錯誤的做法
            logger.info("str1:{}", str1);
            logger.info("str1:{}", str1);
            logger.info("str1:{}", str1);
            
            // 正確的做法
            logger.info("str1:{}, str2:{}, str3:{}", str1, str2, str3);
            str.length();
        } catch(Exception e) {
            logger.error("str:{}", str, e);
        }

 

5,儘量不要在for循環中log日誌

 

一般來說,for循環中的log日誌,都可以提到for循環外面來打印。因爲for循環的對象

是集合,而集合都可以轉化成對應的json字符串。

特殊情況,必須要在for循環中打印的,需要評估是否有必要,已經這個日誌的量級,看

是否太耗內存。

 

        // ---------------- 5,儘量不要在for循環中log日誌 ----------------
        try{

            List<String> list = new ArrayList<>();
            list.add("唐朝");
            list.add("宋朝");
            list.add("董仲舒");

            // 不推薦的做法
            for (String str : list) {
                logger.info("str:{}", str);
                // 業務邏輯代碼
            }

            // 推薦的做法
            logger.info("list to json:{}", JSON.toJSON(list).toString());
            for (String str : list) {

                // 業務邏輯代碼
            }

        } catch(Exception e) {
            logger.error("{} error", this.getClass().getSimpleName(), e);
        }

 

如果是其他集合,同理,也可以轉化成json字符串,這裏不再贅述。

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章