作者: "zyl910" 一、緣由 NLog是一個很好用的日誌類庫。利用它,可以很方便的將日誌輸出到 調試器、文件 等目標,還支持輸出到窗體界面中的RichTextBox等目標。 而且它還支持在運行時修改配置,例如可用於實現這樣的需求——在界面上做個下拉框,可動態調整RichTextBox的日誌級別 ...
作者: zyl910
一、緣由
NLog是一個很好用的日誌類庫。利用它,可以很方便的將日誌輸出到 調試器、文件 等目標,還支持輸出到窗體界面中的RichTextBox等目標。
而且它還支持在運行時修改配置,例如可用於實現這樣的需求——在界面上做個下拉框,可動態調整RichTextBox的日誌級別過濾。
二、輸出到RichTextBox
2.1 辦法
首先,項目中需要加入NLog的程式包。既用 NuGet 下載這些包——
- NLog
- NLog.Config
- NLog.Windows.Forms
隨後便可修改 NLog.config 文件,增加RichTextBox目標了。
這時有2點需註意——
- RichTextBox的target配置中,formName是“RichTextBox所在窗體的類名”,controlName是“該窗體中的RichTextBox控制項名”。區分大小寫,需要完全一致。
- 在NLog載入配置前,需要確保該RichTextBox已存在。
若以上2條中有任意一條不符時,NLog會自動彈出一個含RichTextBox的小視窗來顯示日誌,而不是你所指定的RichTextBox。
這2中,第1條是很容易實現的,就是第2條稍微麻煩一點。它的處理訣竅是,不要做靜態初始化,而是要等到窗體的Load事件時才初始化Logger對象,且保證該窗體是首個使用NLog的類。這是因為NLog是在首次被使用時,才載入配置文件的。
即不能這樣寫——
private static Logger logger = LogManager.GetCurrentClassLogger();
而是要這樣寫——
private static Logger logger = null;
private void MainForm_Load(object sender, EventArgs e) {
if (null == logger) {
logger = LogManager.GetCurrentClassLogger();
}
}
2.2 範例
假設窗體名(formName)為MainForm,RichTextBox控制項名為rtbLog。那麼 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">
<targets async="true">
<target xsi:type="Debugger" name="debugger" layout="${longdate} ${level:uppercase=true} [${threadname}] ${message} ${onexception:${exception:format=tostring} ${newline}}" />
<target xsi:type="File" name="f"
fileName="${basedir}/logs/${shortdate}.log"
layout="${longdate} ${level:uppercase=true} [${threadname}] ${message} ${onexception:${exception:format=tostring} ${newline}}"
encoding="utf-8" />
<target xsi:type="RichTextBox" name="richTextBox"
layout="${longdate} ${level:uppercase=true} [${threadname}] ${message} ${onexception:${exception:format=Message}}"
autoScroll="true"
maxLines="1000"
formName="MainForm"
controlName="rtbLog"
useDefaultRowColoringRules="false" />
</targets>
<rules>
<logger name="*" minlevel="Debug" writeTo="debugger" />
<logger name="*" minlevel="Info" writeTo="f" />
<logger name="*" minlevel="Info" writeTo="richTextBox" />
</rules>
</nlog>
上面的配置文件還演示了這些功能——
- 將日誌輸出到調試器(Debugger)。
- 將日誌輸出到文件(File)。且是log子目錄下每天一個文件(
fileName="${basedir}/logs/${shortdate}.log"
),編碼指明為utf-8(encoding="utf-8"
)避免gbk外字元亂碼。 - 採用不同的日誌字元串格式(layout)。RichTextBox只顯示異常消息(Message),而不顯示包含錯誤棧的異常詳情(tostring)。
- 目標都是非同步模式(
<targets async="true">
)。 - 支持自動重新載入配置(
autoReload="true"
)。
三、動態修改日誌級別
3.1 需求
首先,NLog支持自動重新載入配置的機制,可參考上面配置的 autoReload="true"
。即修改NLog.config的配置,會對運行中的程式也是生效的,這樣便無需重啟程式了。
但對於RichTextBox輸出的日誌來說,上述機制還不夠方便。最好是界面上提供一些直接調整日誌配置的功能。例如——RichTextBox最初的最小日誌級別為Info級,當想看詳細日誌時,可點界面的下拉框,便可將最小日誌級別改為Debug級。
3.2 辦法
NLog提供了動態修改配置的介面。
調用 LogManager.Configuration ,可得到 LoggingConfiguration 對象。它就是當前的配置數據。
然後可通過 LoggingConfiguration.LoggingRules,獲取日誌規則集合(即 <rules>
)。這樣便能就行修改對應的配置了。
最後別忘了調 LogManager.ReconfigExistingLoggers
,使修改的配置生效。
3.3 範例
可這樣實現下拉選擇RichTextBox日誌級別過濾的功能——在窗體放一個名為 cboLogLevelMin 的下拉框,配好屬性,然後處理它的 SelectedIndexChanged 事件。
private void cboLogLevelMin_SelectedIndexChanged(object sender, EventArgs e) {
if (null == cboLogLevelMin.SelectedItem) return;
String str = cboLogLevelMin.SelectedItem.ToString(); // 獲取日誌級別.
LogLevel lv = LogLevel.Info; // 若選擇的值無效, 則當作 Info級.
try {
lv = LogLevel.FromString(str);
} catch (Exception ex) {
if (null == logger) return;
logger.Debug(ex, "LogLevel.FromString fail!");
}
LoggingConfiguration lc = LogManager.Configuration; // 取得 NLog 配置.
LoggingRule lr = lc.LoggingRules.FirstOrDefault(
r => r.Targets.Any(
t => "richTextBox" == t.Name
)
); // 查找 RichTextBox 所用的 LoggingRule .
if (null != lr) {
lc.LoggingRules.Remove(lr); // 刪除舊的 LoggingRule .
}
lc.AddRule(lv, LogLevel.Fatal, "richTextBox"); // 新增 LoggingRule .
LogManager.ReconfigExistingLoggers(); // 使配置生效.
}
參考文獻
- NLog wiki《RichTextBoxTarget》 . https://github.com/NLog/NLog.Windows.Forms/wiki/RichTextBoxTarget
- tvsofa2008《將NLog target設置為RichTextBox的註意事項,NLog版本4.2.1》 . http://blog.csdn.net/tvsofa2008/article/details/50081397
- GavinJun《NLog類庫使用探索——詳解配置》 . https://www.cnblogs.com/fuchongjundream/p/3936431.html
- viviachen《如何在運行時修改NLog配置》 . http://blog.csdn.net/viviachen/article/details/19171681
(完)