[C#] 将NLog输出到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》 . https://www.geek-share.com/detail/2659669224.html
- GavinJun《NLog类库使用探索——详解配置》 . https://www.geek-share.com/detail/2620014320.html
- viviachen《如何在运行时修改NLog配置》 . https://www.geek-share.com/detail/2603293161.html
(完)
- [C#] 将NLog输出到RichTextBox,并在运行时动态修改日志级别过滤
- 运行环境下动态修改日志级别
- Spring Boot 1.5.x新特性:动态修改日志级别
- 动态修改log4j的日志级别,不重启服务器
- Android程序调试–LogCat按照日志信息级别进行输出和过滤
- logback动态修改配置文件实现打印不同级别日志
- 修改glog源码解决不同级别日志混合输出的问题
- springboot1.5.6版本运行时动态切换日志级别
- springboot动态修改系统日志级别
- Logback动态修改日志级别
- Spring Boot教程(九)Spring Boot 1.5.x新特性:动态修改日志级别
- Log4j 分级别过滤输出日志文件
- 动态修改日志级别
- SpringBoot动态修改日志级别
- springboot【21】日志管理之1.5.x新特性:动态修改日志级别
- Android程序调试–LogCat按照日志信息级别进行输出和过滤
- Spring Cloud Spring Boot mybatis分布式微服务云架构(四十四)动态修改日志级别(1)
- SpringBoot系列十一:SpringBoot整合Restful架构(使用 RestTemplate 模版实现 Rest 服务调用、Swagger 集成、动态修改日志级别)
- 基于Spring框架开发的Web程序,如何动态修改日志级别
- web项目Log4j日志输出路径配置问题 问题描述:一个web项目想在一个tomcat下运行多个实例(通过修改war包名称的实现),然后每个实例都将日志输出到tomcat的logs目录下实例名命名的文