[Log]使用NLog記錄Exception

NLog 是在.Net Framework 中最熱門的 Log 記錄工具之一,它不僅使用簡單,並且設定檔的設定項目也十分豐富。
基本上,它的Layout能滿足大多設定上的需求,但因為可設定項目太多,光是要輸出個可以方便抓蟲的完整 Exception 資訊,可能就要試了老半天,
所以本篇就針對Exception 的 Layout 用法加以介紹,方便大家設定。

NLog 是在.Net Framework 中最熱門的 Log 記錄工具之一,它不僅使用簡單,並且設定檔的設定項目也十分豐富。
基本上,它的Layout能滿足大多設定上的需求,但因為可設定項目太多,光是要輸出個可以方便抓蟲的完整 Exception 資訊,可能就要試了老半天,
所以本篇就針對Exception 的 Layout 用法加以介紹,方便大家設定。

 

NLog - Advanced .NET Logging

官網: http://nlog-project.org/

文章使用版本: NLog v2.0

下載方式: NuGet

 

Layout基本格式

Layout 的內容分純文字(plain text)與變數預留位置(variable placeholder),如 "Msg: ${message}",被 ${} 包住的文件就是 Layout 的變數,在產生一筆記錄時 ${variable} 會換成變數值,而不在 ${} 中的文字就是純文字啦。

Layout 的設定可以參考: http://nlog-project.org/wiki/Layout_renderers

 

而每一個變數可能會有選項,選項與變數或其他選項用 : (冒號)分隔,而選項與值使用 = (等號)連結,如 ${exception:format=Type}

exceptionstacktaceonexception的格式


image

image

 image

使用範例

以下範例皆使用此程式執行,僅換掉 Layout 部分

class Program
{
    private static Logger logger = LogManager.GetCurrentClassLogger();

    static void Main(string[] args)
    {
        try
        {
            throw new InvalidProgramException("發生錯誤啦", new ArgumentException("args沒有值"));
        }
        catch (Exception ex)
        {
            logger.ErrorException("執行失敗", ex);
        }
    }
}

 

1. layout="${message} - ${exception}"

輸出:

執行失敗 - 發生錯誤啦

個人使用心得: 不好,只知道有錯誤,卻不知道錯誤的明細。

 

2. layout="${message} - ${exception} - ${stacktrace}"

輸出:

執行失敗 - 發生錯誤啦 - Program.Main

個人使用心得: 不好,雖然知道那一個Main出錯了,但不知道那一行。

 

3. layout="${message} - ${exception} - ${stacktrace:format=Raw}"

輸出:

執行失敗 - 發生錯誤啦 - Main at offset 176 in file:line:column <filename unknown>:0:0

個人使用心得: XD,看不懂後面的東西是什麼。

 

4. layout="${message} - ${exception} - ${stacktrace:format=DetailedFlat}"

輸出:

執行失敗 - 發生錯誤啦 - [Void Main(System.String[])]

個人使用心得: XD,只有 Mathod 與 Paramaters 好像沒有幫助了。

個人心得:

${stacktrace} 對輸出 Exception 資訊的用途很小,不過對非 Exception 的記錄多少有幫助,例如是在哪一個 Method 中呼叫 logger.Info("我是訊息") 的,不過用來抓蟲資訊又嫌不足。

 

5.layout="${message} - ${exception:format=Type}"

輸出:

執行失敗 - System.InvalidProgramException

個人使用心得: XD,只有Type好像沒有什麼幫助。

 

6.layout="${message} - ${exception:format=StackTrace}"

輸出: 

執行失敗 -    於 NlogTest.Program.Main(String[] args) 於 Program.cs: 行 17

個人使用心得: 好像有一點幫助了,但沒有Exception的訊息阿。

 

7.layout="${message} - ${exception:format=ToString}"

輸出:

執行失敗 - System.InvalidProgramException: 發生錯誤啦 ---> System.ArgumentException: args沒有值    
--- 內部例外狀況堆疊追蹤的結尾 ---
    於 NlogTest.Program.Main(String[] args) 於 Program.cs: 行 17

個人使用心得: 搞了半天還是 Exception.ToString() 的資料才是最完整的,而且 InnerException 的資訊也有顯示出來。

 

8.layout="${message} ${onexception:inner=${newline} *****Error***** ${newline} ${exception:format=ToString}}"

輸出:

執行失敗
*****Error***** 
System.InvalidProgramException: 發生錯誤啦 ---> System.ArgumentException: args沒有值
 --- 內部例外狀況堆疊追蹤的結尾 ---
    於 NlogTest.Program.Main(String[] args) 於 Program.cs: 行 17

個人使用心得: 如果你懶得用2個 Layout 來顯示一般訊息與有 Exception 訊息,可以使用 ${onexception:inner=  layout } 當發生 Exception 時才輸出特定的 Layout。

而當編譯成 .dll 或 .exe 後為什麼 Exception 的 StackTrace 呢?
祕密就在 .pdb (符號檔)檔案中,這個檔案會記錄原始檔案資訊,如 IL 對應到原始檔案的那一行,Debugger 想要中斷點也必需要靠這個檔案。
所以程式在執行時沒有部署 .dll 或 .exe 的 .pdb 檔,當發生 Exception 時,StackTrace 就不會有檔案的資訊與行號。
當然不部署 .pdb 也是有好處的,.pdb 檔案記錄得東西很多,所以不會太小,執行時不載入 .pdb 檔,可以節省一些記憶體空間。