項目維護總結——日誌打印


日誌打印在開發中一般都是有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

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