NLog一直以來都是以好用上手聞名,使用上也很少遇到問題,直到最近開始使用較深一點的功能後,卻發生了沒寫入卻又沒有錯誤訊息可以追查的事件
首先就先介紹一下NLog的基本功能
最重要的東西就是NLog.Config這個檔案了,裡面主要有兩個比較重要的元素構成
- Target
- Rules
裡面可以選用NLog就內建的一些系統參數
你也可以選擇target輸出的是file, db, email.... 之類的,真的是太便利了
不外乎就是basedir:目前的執行路徑, counter 第幾行, logger 像是 namespace的東西,
如果要記中文類的,encoding 記得要設成utf-8,否則會有亂碼產生
<target name="file" xsi:type="File"
fileName="${basedir}/App_Data/Logs/${shortdate}/${logger}.txt"
layout="${counter} | ${longdate} | ${level:uppercase=true} | ${logger:shortName=true}
| ${message} ${newline}" encoding="utf-8"/>
你可以設定自定的規則,logger name 不設限的話,全部會寫到我們上面所定義的 file target
但要注意的是這邊設定的是只有Info level的資料
請參考目前的 level 有哪些,最低的是Trace, 最高的則是 Fatal
<logger name="*" level="Info" writeTo="file" />
甚至你可以這樣定義,所有在System.Web.Controllers的namespace都可以寫到你所指定的 target裡
<logger name="System.Web.Controllers.*" minlevel="Info" writeTo="Controllerfile" />
要特別注意的是,如果你這兩條rule都加的話,這兩個log可是都會寫到不同的兩個地方去,所以你的log可是會多一倍的資料
再來要注意的是,如果你的namespace 沒有吻合到任何一條rule, 就會發生記不到的情況了
另一個minlevel 若設為 Info,代表的只有這幾個log level 才會被記進去, 保守起見的話還是設成最低的Trace
Fatal
Error
Warn
Info
預設來說,NLog都是發生錯誤不會導出錯誤訊息, 在NLog中可以這樣設置
throwExceptions="true"
internalLogLevel="Trace" internalLogFile="c:\temp\nlog-internal.log">
當你發佈到正式環境時,但卻又沒有Log產生時,你可以設定這樣,如此一來就可以到指定的路徑查看錯誤的原因了
錯誤的來源可說是有極多可能,比如說權限設定,config是不是正確的XML 檔案
這些輸出的訊息都是有極大的幫助
若是在c:\temp\nlog-internal.log看到這類的錯誤訊息 Exception: System.UnauthorizedAccessException: Access to the path 'C:\www\xxx\App_Data\Logs\2018-05-17\' is denied.
請在Log資料夾加上 IIS AppPool/[your iis identity] 的權限至該 folder,並授予足夠的權限可以寫入資料
雖然有這些debug工具可以使用,然而還是遇到了一個奇異的情況
那就是logger並沒有完整的呈現出我所定義的namespace,而是出現了Lambda_method 這樣的奇怪字眼
若是rule是以logger來做設定的話,你會發現一件事,就是你的log怎樣都記不到
然而去設定internalLogFile的偵錯日誌也看不出問題在哪
最後找了一些資料才發現這種情況是IoC (如Ninject, Autofac這一類的IoC套件)所產生的,而debug模式deploy的程式非常正常
但release模式deploy的卻會有這樣的情況
所以解決方案會有兩種
1. 使用debug mode發佈測試跟正式環境,但就得注意一下debug模式底下web.config的設定發佈到正式環境會不會產生問題
2. 修改IoC套件注入的方式,可參考這樣的做法
參考資料
https://github.com/nlog/NLog/wiki/Layout-Renderers
https://github.com/NLog/NLog/wiki/Configuration-file#log-levels
https://github.com/NLog/NLog/issues/364
https://stackoverflow.com/a/4525456
https://support.appharbor.com/discussions/problems/804-nloglogmanagergetcurrentclasslogger