2014-02-27 152 views
14

能否請你解釋一下寫這樣的代碼是否好主意?拋出異常與日誌記錄

try { 
     //my code here 
    } catch (Exception e) { 
     logger.error("Some error ", e); 
     throw new MyCustomException("Some error ", e); 
    } 

我是否應該離開只有記錄器或更好的選擇離開「扔」結構? 或者最好的想法是在同一時間使用它們?

我知道用「throw」我可以在調用堆棧的其他部分捕獲異常,但也許其他日誌記錄有一些隱藏的好處,它也很有用。

+0

似乎對我來說很好,只要MyCustomException是一個選中的異常。 –

+0

感謝您的回覆! 您非常瞭解如何編寫日誌記錄/異常處理。 – xrabbit

回答

4

我在某些情況下使用這兩種方法,記錄並拋出異常。特別是,它在API中非常有用。通過拋出異常,我們允許調用者處理它,並通過記錄來確定它的根本原因。

而且,如果調用者在同一個系統中,那麼如果我們在每個catch中添加日誌,就會有重複的日誌。

+1

我同意@Kugathasan Abimaran。我目前正在開發一個API,並且在出現問題時需要經常查看我的日誌文件。同時,我必須拋出一個異常來通知客戶端 – crazyGuy

1

我想你可能需要明智地使用這種模式。正如你所寫的那樣,對於每個異常,你都要記錄2個堆棧跟蹤,這可能會在你的日誌中填充過多的信息。

關於伐木與投擲,他們是兩個不同的擔憂。拋出異常會中斷你的執行,阻止任何進一步的工作,也許回滾數據庫提交等。日誌記錄將簡單地將信息轉儲到日誌文件(或其他地方)。它更適用於調試,並且通常更難以測試。

2

使用您建議的模式時,通常最終會在日誌中多次報告錯誤事件。另外,在閱讀日誌時,並不總是很簡單。

就我個人而言,我更喜歡只記錄一次錯誤事件,並在較高的調用級別執行此操作。所以我幾乎從不記錄&重新投擲。我通常會讓異常進入調用堆棧,直到它到達可以以某種方式處理它的上下文爲止,並且這是我登錄的地方。

如果正確包裝並重新引發異常,則應從單個日誌消息的堆棧跟蹤中完全清除上下文。

2

正確的答案是:「這取決於」

你想在一般的日誌,你趕上,因爲它們對應於出亂子例外。這就是爲什麼諸如聲納之類的代碼分析工具會在你不記錄它們時提出警告。

考慮以下幾點:解析文件。在解析文件時,你實際上試圖解析每一行。有時候一些行會變得格格不入,因此你不想停止解析文件。在這種情況下,您可能只想記錄錯誤的行並繼續閱讀文件。 但是,想象一下,在某些時候,您在閱讀時遇到I/O異常(例如某些其他程序在您訪問它時刪除了該文件)。

在這種情況下,您可能希望將您遇到的錯誤記錄到日誌中,並拋出一個新的異常來停止處理整個文件。

所以總之,你必須考慮什麼是最好的做法。但這兩種做法都不錯。

+1

+1,指出有些事情出錯了,其他的事情都非常錯誤,差異是關鍵。 – Rainbolt

6

通常,我認爲你應該記錄 rethrow。兩者都會導致每一層都會一次又一次地記錄異常,這使日誌難以閱讀。更糟糕的是,很難弄清楚實際上有多少錯誤 - 是七個錯誤,還是七層記錄了相同錯誤的應用程序?

這表示如果您禁止例外,您將其記錄下來並說出爲什麼您不認爲值得重新投票。

另一方面,如果你重新拋出異常,你知道它要麼被捕獲並被壓制(在這種情況下,捕手記錄異常以及爲什麼被壓制),否則它會冒泡從應用程序中移出並被應用程序容器捕獲,該容器將捕獲並記錄異常。每個異常在日誌中只出現一次並且只出現一次。