程序那些事:日誌記錄的做用和方法

程序中記錄日誌通常有兩個目的:Troubleshooting和顯示程序運行狀態。好的日誌記錄方式能夠提供咱們足夠多定位問題的依據。日誌記錄你們都會認爲簡單,但如何經過日誌能夠高效定位問題並非簡單的事情。這裏列舉下面三個方面的內容,輔以代碼示例,總結如何寫好日誌,但願對他人有所啓發和幫助: 程序員

  • 怎樣記日誌能夠方便Troubleshooting
  • 程序運行狀態能夠記哪些
  • 應該避免怎樣的日誌方式

怎樣記日誌能夠方便Troubleshooting?

1. 對外部的調用封裝 編程

程序中對外部系統與模塊的依賴調用先後都記下日誌,方便接口調試。出問題時也能夠很快理清是哪塊的問題 ide

1.  LOG.debug("Calling external system:" + parameters);  
2.  Object result = null;  
3.  try {  
4.      result = callRemoteSystem(params);  
5.      LOG.debug("Called successfully. result is " + result);  
6.  } catch (Exception e) {  
7.      LOG.warn("Failed at calling xxx system . exception : " + e);  
8.  }

2.狀態變化 debug

程序中重要的狀態信息的變化應該記錄下來,方便查問題時還原現場,推斷程序運行過程 設計

1.  boolean isRunning;  
2.    
3.  isRunning = true;  
4.  LOG.info("System is running");  
5.    
6.  //...  
7.    
8.  isRunning = false;  
9.  LOG.info("System was interrupted by " + Thread.currentThread().getName());

3.系統入口與出口: 調試

這個粒度能夠是重要方法級或模塊級。記錄它的輸入與輸出,方便定位 日誌

1.  void execute(Object input) {  
2.      LOG.debug("Invoke parames : " + input);  
3.      Object result = null;  
4.        
5.      //business logic
6.        
7.      LOG.debug("Method result : " + result);  
8.  }

4.業務異常: code

任何業務異常都應該記下來: server

1.  try {  
2.      //business logical  
3.  } catch (IOException e) {  
4.      LOG.warn("Description xxx" , e);  
5.  } catch (BusinessException e) {  
6.      LOG.warn("Let me know anything");  
7.  } catch (Exception e) {  
8.      LOG.error("Description xxx", e);  
9.  }  
10.

5.非預期執行: 接口

爲程序在「有可能」執行到的地方打印日誌。若是我想刪除一個文件,結果返回成功。但事實上,那個文件在你想刪除以前就不存在了。最終結果是一致的,但程序得讓咱們知道這種狀況,要查清爲何文件在刪除以前就已經不存在

1.  int myValue = xxxx;  
2.  int absResult = Math.abs(myValue);  
3.  if (absResult < 0) {  
4.      LOG.info("Original int " + myValue + "has nagetive abs " + absResult);  
5.  }

6.不多出現的else狀況:

else可能吞掉你的請求,或是賦予難以理解的最終結果

1.  Object result = null;  
2.  if (running) {  
3.     result = xxx;  
4.  } else {  
5.     result = yyy;  
6.     LOG.debug("System does not running, we change the final result");  
7.  }

程序運行狀態能夠記哪些?

程序在運行時就像一個機器人,咱們能夠從它的日誌看出它正在作什麼,是否是按預期的設計在作,因此這些正常的運行狀態是要有的。

1. 程序運行時間:

1.  long startTime = System.currentTime();  
2.    
3.  // business logical  
4.    
5.  LOG.info("execution cost : " + (System.currentTime() - startTime) + "ms"); 

2. 大批量數據的執行進度:

1.  LOG.debug("current progress: " + (currentPos * 100 / totalAmount) + "%");

3.關鍵變量及正在作哪些重要的事情:

執行關鍵的邏輯,作IO操做等等

1.  String getJVMPid() {  
2.     String pid = "";  
3.     // Obtains JVM process ID  
4.     LOG.info("JVM pid is " + pid);  
5.     return pid;  
6.  }  
7.    
8.  void invokeRemoteMethod(Object params) {  
9.      LOG.info("Calling remote method : " + params);  
10.     //Calling remote server  
11. }

應該避免怎樣的日誌方式?

1. 混淆信息的Log

日誌應該是清晰準確的: 當看到日誌的時候,你知道是由於鏈接池取不到鏈接致使的問題麼?

1.  Connection connection = ConnectionFactory.getConnection();  
2.  if (connection == null) {  
3.      LOG.warn("System initialized unsuccessfully");  
4.  }

2. 記錯位置

產品代碼中,使用console記錄日誌,致使沒有找到日誌。

1. } catch (ConfigurationException e) {
     2.    e.printStackTrace();
     3. }

3. 記錯級別

記錯級別經常發生,常見的如:混淆代碼錯誤和用戶錯誤,如登陸系統中,若是惡意登陸,那系統內部會出現太多WARN,從而讓管理員誤覺得是代碼錯誤。能夠反饋用戶以錯誤,可是不要記錄用戶錯誤的行爲,除非想達到控制的目的。

1.  LOG.warn("Failed to login by "+username+");

4. 遺漏信息

這裏可能包含兩種狀況:(1)用戶本身少寫了信息,致使毫無參考價值;(2)用戶調用log的方式致使丟失信息,以下例,沒有stack trace.

1.  } catch (Exception ex) {
     2.   log.error(ex);
     3.  }

總結:

日誌記錄在程序員平常編程實踐中必須面對的事情,本文針對這個話題談了下本身的體會,但願讀者能有所收益。多有不足,請多包涵。

相關文章
相關標籤/搜索