文章目錄
NLog 設定 Rule 僅包含部份 Logger
log 是系統正式上線後,少數可以用來協助 debug 的資訊,而 debug 的難易度與解決問題的速度也就跟著 log 的品質而有極大的差異。
今天想要紀錄最近專案遇到的一個需求:某些 log 內容很少使用加上資料量又大實際效用不高,但卻是追查 bug 的最後一道不可或缺的防線(像是 EntityFramework 實際產出的 SQL script),而其他 log 則紀錄了整個程式流程的相關資訊,所以打算將 db 的 script log 與其他程式執行資訊分開儲存,避免 db 的大量 log 形成雜訊而拖慢 debug 的速度,就來看看 nlog 可以如何設定吧
預設 nlog 設定
以下是 nlog.config 的設定範例
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
autoReload="true"
throwExceptions="false"
internalLogLevel="Off" internalLogFile="c:\temp\nlog-internal.log">
<variable name="myvar" value="myvalue"/>
<targets>
<target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log"
layout="${longdate} ${uppercase:${level}} ${message}" />
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="f" />
</rules>
</nlog>
target 設定說明
- 預設寫至
File
- target 名稱為
f
- 檔案路徑為
${basedir}/logs/${shortdate}.log
- log 格式為
${longdate} ${uppercase:${level}} ${message}
- 預設寫至
rule 設定說明
- 接受的 logger name 為
*
(全部) - log 會紀錄的 level 為
Debug
- log 寫入 name 為
f
的 target
- 接受的 logger name 為
如何僅包含指定 log
以需求來看很明確:在 rule 中正向表列 logger name
但就 nlog 的文件看來是不支援這個需求,所以得要透過其他方式來達到目的了
方法一:將排除的 log 指定
final = "true"
個別儲存所有 log
<logger name="db" minlevel="Debug" writeTo="db" /> <logger name="audit" minlevel="Debug" writeTo="audit" /> <logger name="normal" minlevel="Debug" writeTo="normal" />
將需要結合的 log 組合
<logger name="*" minlevel="Debug" writeTo="f" />
指定排除不需結合的 log:加上
final
<logger name="db" minlevel="Debug" writeTo="db" final="true"/>
測試程式
private static ILogger dblogger = LogManager.GetLogger("db"); private static ILogger auditlogger = LogManager.GetLogger("audit"); private static ILogger normallogger = LogManager.GetLogger("normal"); static void Main(string[] args) { dblogger.Debug("db"); auditlogger.Debug("audit"); normallogger.Debug("normal"); }
實際效果
個別 log 及 整合 log
db log 未寫至 all log 中
完整 nlog.config
<?xml version="1.0" encoding="utf-8" ?> <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd" autoReload="true" throwExceptions="false" internalLogLevel="Off" internalLogFile="c:\temp\nlog-internal.log"> <variable name="myvar" value="myvalue"/> <targets> <target xsi:type="File" name="db" fileName="${basedir}/logs/db/${shortdate}.log" layout="${longdate} ${uppercase:${level}} ${message}" /> <target xsi:type="File" name="audit" fileName="${basedir}/logs/audit/${shortdate}.log" layout="${longdate} ${uppercase:${level}} ${message}" /> <target xsi:type="File" name="normal" fileName="${basedir}/logs/normal/${shortdate}.log" layout="${longdate} ${uppercase:${level}} ${message}" /> <target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log" layout="${longdate} ${uppercase:${level}} ${message}" /> </targets> <rules> <logger name="db" minlevel="Debug" writeTo="db" final="true"/> <logger name="audit" minlevel="Debug" writeTo="audit" /> <logger name="normal" minlevel="Debug" writeTo="normal" /> <logger name="*" minlevel="Debug" writeTo="f" /> </rules> </nlog>
方法二:調整 logger 名稱
個別儲存所有 log
<logger name="db" minlevel="Debug" writeTo="db" /> <logger name="main.audit" minlevel="Debug" writeTo="audit" /> <logger name="main.normal" minlevel="Debug" writeTo="normal" />
透過 logger name 將需要結合的 log 組合
<logger name="main.*" minlevel="Debug" />
測試程式
private static ILogger dblogger = LogManager.GetLogger("db"); private static ILogger auditlogger = LogManager.GetLogger("main.audit"); private static ILogger normallogger = LogManager.GetLogger("main.normal"); static void Main(string[] args) { dblogger.Debug("db"); auditlogger.Debug("audit"); normallogger.Debug("normal"); }
實際效果
個別 log 及 整合 log
db log 未寫至 all log 中
完整 nlog.config
<?xml version="1.0" encoding="utf-8" ?> <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd" autoReload="true" throwExceptions="false" internalLogLevel="Off" internalLogFile="c:\temp\nlog-internal.log"> <variable name="myvar" value="myvalue"/> <targets> <target xsi:type="File" name="db" fileName="${basedir}/logs/db/${shortdate}.log" layout="${longdate} ${uppercase:${level}} ${message}" /> <target xsi:type="File" name="audit" fileName="${basedir}/logs/audit/${shortdate}.log" layout="${longdate} ${uppercase:${level}} ${message}" /> <target xsi:type="File" name="normal" fileName="${basedir}/logs/normal/${shortdate}.log" layout="${longdate} ${uppercase:${level}} ${message}" /> <target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log" layout="${longdate} ${uppercase:${level}} ${message}" /> </targets> <rules> <logger name="db" minlevel="Debug" writeTo="db" /> <logger name="main.audit" minlevel="Debug" writeTo="audit" /> <logger name="main.normal" minlevel="Debug" writeTo="normal" /> <logger name="main.*" minlevel="Debug" writeTo="f" /> </rules> </nlog>
心得
雖然 nlog 要達成正向表面 log 對象 的做法比較沒那麼直覺(或者只是沒查到正確的文件),但其他設定上相較其他 log library 還是方便不少
趁著專案剛好有相關需求紀錄一下現在的做法,也許過陣子或是新版就會有不同的設定方式可更簡易地符合需求了
參考資訊
文章作者 Yowko Tsai
上次更新 2021-11-02
授權合約
本部落格 (Yowko's Notes) 所有的文章內容(包含圖片),任何轉載行為,必須通知並獲本部落格作者 (Yowko Tsai) 的同意始得轉載,且轉載皆須註明出處與作者。
Yowko's Notes 由 Yowko Tsai 製作,以創用CC 姓名標示-非商業性-相同方式分享 3.0 台灣 授權條款 釋出。