[.NET][C#]Log日誌功能(二)NLog使用及追蹤

這兩天客戶碰到了NLog使用上的問題,程式將Fatal等級的log設定了兩組輸出(File and Windows Event log),但File產出時好時壞,有時那一天應該有log產生但卻整天都沒檔案,來筆記今天白天追蹤NLog無法寫出log的方法。

NLog

NLog是.NET log世界中很受歡迎的Open Source之一,屬於BSD License,一直以來都很想在新專案裡帶上她出門,這次趁幫客戶解問題,來筆記。

NLog本人美照

圖片來源:https://github.com/NLog

 


Nlog安裝及組態

1.首先新增一個Console專案,並從Nuget分別安裝NLog及NLog.config兩個套件。

Nlog:是Library Project引用寫log時要安裝的,Nlog.config則是Hosting Project要處理config時要安裝的,因為我們這篇的範例只有一個Console專案所以兩個都裝!

2.確認安裝完畢後,接下來我們要先認識組態檔案中Targets(log目的地)Rules(Routing條件)

 

Targets(log目的地)

Target是設定log的目的地,像是flat file、console、window event log、database、msmq、mail等等。(詳細Target可以參考 https://github.com/nlog/NLog/wiki/Targets)

打開NLog.config,她的位置在:

邊我們設定三個Target並加入到上方<targets>元素內,前兩個是log file(type=File),最後一個是event log(Type=EventLog)

<target name="flatfile" xsi:type="File" fileName="C:\temp\log\${shortdate}\debug.log"
        layout="${date}| ${level} | ${message}"/>
<target name="fatalfile" xsi:type="File" fileName="C:\temp\log\${shortdate}\fatal.log"
        layout="${date}| ${level} | ${message}"/>
<target name="eventlog" xsi:type="EventLog" source="NLogLogger" log="Application"
        layout="${date}| ${level} | ${message}"/>

 

Rules(Routing條件)

Rules是設定那些等級的錯誤要寫到哪一個Target

邊我們設定三個條件並加入上方<rules>元素內。

1.Log等級為Trace、Debug、Info、Warn及Error時對應寫入logfile的target,注意屬性是levels。

2.Log等級為Fatal時,寫入fatalfile的target

3. Log等級為Fatal時,也寫入eventlog的target

<logger name="*" levels="Trace,Debug,Info,Warn,Error" writeTo="logfile" />
<logger name="*" level="Fatal" writeTo="fatalfile" />
<logger name="*" level="Fatal" writeTo="eventlog" />

 

設定完Targets與Rules後,用簡單的圖來看我們的Logger routing

這次出問題的就是紫爆等級的Fatal小妹。

 


主機環境設定

這次範例的輸出是檔案及Windows Event log,因此要分別確認log資料夾權限並新增Event Source

1.建立log資料夾,確認權限。

 雖然Nlog會自己建立資料夾,但怕權限上有問題,還是先幫他確認。

2.powershell執行,建立event source NlogLogger

new-eventlog -Source NLogLogger -LogName Application

 


NLog元件在C#程式中的引用方式

在console專案下的program.cs輸入程式碼

using NLog;
class Program
{
    private static Logger logger = LogManager.GetCurrentClassLogger();
    static void Main(string[] args)
    {
        logger.Trace("我是追蹤:Trace");
        logger.Debug("我是偵錯:Debug");
        logger.Info("我是資訊:Info");
        logger.Warn("我是警告:Warn");
        logger.Error("我是錯誤:error");
        logger.Fatal("我是致命錯誤:Fatal");
    }
}

 

如果要把Exception物件輸出,也可以放在第一個引數,第二個引數可以接其他訊息。

執行程式結果: 

Log file

debug.log內容

fatal.log內容

Windows Event log

Windows鍵 + R 輸入 eventvwr.msc 打開事件檢視器

Windows記錄 > 應用程式 > 來源=NLogLogger > 內容

在本機或是測試環境總是順順利利的!

 


追蹤Nlog問題

但有時候我們可能會在正式上版後遇到NLog無法寫出log file或是寫到Windows Event log失敗的問題,但NLog內部執行時若遇到錯誤,避免影響主程式執行,NLog預設會先略過!

好在NLog有troubleshooting的步驟可以參考,這邊我們先用檔案追蹤: 

在NLog.Config檔案中的element內設定以下

<nlog ... internalLogLevel="Error" internalLogFile="c:\temp\log\nlog-internal.log">
 ...
</nlog>

(也可以output to console)

接下來去收internal log就可以知道Log檔案寫入失敗的原因了!

這邊我們會刻意關閉資料夾權限並且設定錯誤的event source來測試,執行完Console程式後,打開nlog-internal.log

檔案內容:

  • 找不到來源,但無法搜尋部分或全部的事件紀錄檔。無法存取的紀錄檔:Security: 用powershell新增event source。
  • 存取被拒: 確認資料夾是否有權限寫入

 

最後如果連internal log也失效,還有另外一招throwExceptions="true",讓錯誤回拋到主程式處理。

<nlog throwExceptions="true">
   ...
</nlog>

 


小結:

 


參考:

Will 保哥 .Net, ASP.NET, 介紹好用工具NLog

Nlog官網

Nlog Tutorial

Nlog Targets

Nlog Internal Logging

Logging Troubleshooting

NLog 也丟到 Slack 吧

NLog - Advanced .NET Logging (2)