作者: 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
(完)