1. 程式人生 > >專案維護總結——日誌列印

專案維護總結——日誌列印

日誌列印在開發中一般都是有2個極端,首先是什麼都不列印,出了問題之後一看後臺啥也沒有,然後修改;修改的結果就是什麼地方都列印,一出錯誤,找日誌找半天,定位一個問題要1,2個小時,甚至是更多的,之前遇到過一個開發團隊,定位解決一個問題用了三天(並不是什麼特別特殊的業務)。之前也出現過幾次前臺出錯沒有日誌,測試環境無法重現,把日誌加上走個變更再操作再看日誌定位的事情。

開發久了,總會遇到“這個問題生產環境上能重現,但是沒有日誌,業務很複雜,不知道哪一步出錯了?”,又或者“這幾行程式碼的異常被捕獲了,但是異常一直沒有打印出來” 這個時候,怎麼辦? 還能怎麼辦,發個版本,就是把所有地方加上日誌,沒有任何新功能,然後在讓使用者重現一遍,拿下日誌來看,呵呵,,原來是這個問題!。


還有另外一種場景:現在很多系統都是分散式的,一個系統有好多節點,出了問題找日誌真是痛苦,一個一個機器翻,N分鐘後終於找到了,找到了後發現好多相似日誌,一個一個排查;日誌有了,發現邏輯很複雜,不知道走到那個分支,只能根據邏輯分析,不停的翻看程式碼,半天過去了,終於找到了原因。。。一個問題定位就過去了2個小時,變更時間過去了一半。。。

日誌要求基本

1、能找到那個機器

2、 能找到使用者做了什麼

開發日誌要求

1、分支語句的變數需要列印變數

// optype決定程式碼走向,需要列印日誌
logger.info("edit user, opType:" + opType);

if (opType == CREATE) {
  // 新增操作
} else if (opType == UPDATE) {
  // 修改操作
} else {
  // 錯誤的型別,丟擲異常
  throw new IllegalArgumentException("unknown optype:" + opType);
}

重要建議:養成把不合法引數丟擲異常的好習慣,拋異常的時候把對應的非法值丟擲來。

2、修改操作需要列印操作的物件

大部分問題都是修改導致的。資料修改必須有據可查。

3、大量資料操作的時候需要列印資料長度

建議前後列印日誌,而且要打印出資料長度,目的是為了知道 處理了多少資料用了多少時間 。如一個操作用了3秒鐘,效能是好還是壞? 如果處理了1條資料,那麼可能就是效能差,如果處理了10000條資料,那麼可能就是效能好。
logger.info("query docment start ...");

List<Document> docList = query(params);

logger.info("query docment done, size:" + docList.size())

4、使用log4j的MDC列印使用者名稱等額外資訊

有時候,業務量大的系統要找到某一個使用者的操作日誌定位問題非常痛苦,每一個日誌上加使用者名稱又低效也容易漏掉,所以我們要在更高層級上解決這些共性問題。

我們使用log4j的MDC功能達成這個目的。

在單點登入後,設定使用者資訊的時候,把使用者標誌放到MDC中。

private final static ThreadLocal<String> tlUser = new ThreadLocal<>();

public static final String KEY_USER = "user";

public static void setUser(String userid) {
  tlUser.set(userid);
  
  // 把使用者資訊放到log4j
  MDC.put(KEY_USER, userid);
}

然後修改log4j配置,pattern上增加 %X{user} ,位置隨意。

增加執行緒相關配置 [%t] ,完整引數詳見log4j變數

<layout class="org.apache.log4j.PatternLayout">
  <param name="ConversionPattern" value="[%t]%-d{MM-dd HH:mm:ss,SSS} %-5p: %X{user} - %c - %m%n" />/>
</layout>


參考文章:

https://zhuanlan.zhihu.com/p/28629319