[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》 . 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
(完)
[C#] 将NLog输出到RichTextBox,并在运行时动态修改日志级别过滤的更多相关文章
- SLF4j 居然不是编译时绑定?日志又该如何正确的分文件输出?——原理与总结篇
各位新年快乐,过了个新年,休(hua)息(shui)了三周,不过我又回来更新了,经过前面四篇想必小伙伴已经了解日志的使用以及最佳实践了,这个系列的文章也差不多要结束了,今天我们来总结一下. 概览 这篇 ...
- (转)log4j日志级别设置成DEBUG时输出Html代码等问题:
log4j日志级别设置成DEBUG时输出Html代码等问题: 问题: log4j日志级别设置成DEBUG时会输出很多信息,包括一些Html代码 解决方案: log4j的控制是树形,所以在log4j.p ...
- Tomcat 修改日志输出配置 定期删除日志
tomcat的下的日志catalina.out 和 qc.log疯狂增长,以下是解决办法 我生产环境tomcat版本 Server version: Apache Tomcat/7.0.35 Serv ...
- NLog输出目标及类型
targets:输出目标节点 target:配置一个输出目标 Type输出类型: Console 输出到控制台 Debugger 输出到VS输出窗口 File 输出 ...
- 如何利用NLog输出结构化日志,并在Kibana优雅分析日志?
上文我们演示了使用NLog向ElasticSearch写日志的基本过程(输出的是普通文本日志),今天我们来看下如何向ES输出结构化日志.并利用Kibana中分析日志. NLog输出结构化日志 Elas ...
- 详解log4j2(下) - Async/MongoDB/Flume Appender 按日志级别区分文件输出
1. 按日志级别区分文件输出 有些人习惯按日志信息级别输出到不同名称的文件中,如info.log,error.log,warn.log等,在log4j2中可通过配置Filters来实现. 假定需求是把 ...
- 自定义实现InputFormat、OutputFormat、输出到多个文件目录中去、hadoop1.x api写单词计数的例子、运行时接收命令行参数,代码例子
一:自定义实现InputFormat *数据源来自于内存 *1.InputFormat是用于处理各种数据源的,下面是实现InputFormat,数据源是来自于内存. *1.1 在程序的job.setI ...
- C# 在RichTextBox中滚动鼠标时滚动的是父窗口的滚动条
1. RichTextBox u2 = new RichTextBox(); 2. 先记住日RichTextBox没有显示滚动条时的总宽度和显示宽度 u2.Width - u2.ClientSize. ...
- shell脚本实现分日志级别输出
shell脚本如何优雅的记录日志信息,下面让我们一步一步,让shell脚本的日志也变得高端起来,实现如下功能 ①设定日志级别,实现可以输出不同级别的日志信息,方便调试 ②日志格式类似为:[日志级别] ...
随机推荐
- ZooKeeper用途
ZooKeeper还可以用作其他用途,例如: 数据发布与订阅(配置中心) 负载均衡 命名服务(Naming Service) 分布式通知/协调 集群管理与Master选举 分布式锁 分布式队列 一些在 ...
- dp经典问题-最大连续子序列和 hdu1003
题目描述: 这道题我先后做过三遍,结果每一遍都没有做出来.今天再仔仔细细的研究了一下,才发现用动态规划更好理解. 关于求最大连续子序列和的博文转载如下:https://www.cnblogs.com/ ...
- Get与Post方法的区别
Http协议定义了很多与服务器交互的方法,最基本的有4种,分别是GET,POST,PUT,DELETE. 一个URL地址用于描述一个网络上的资源,而HTTP中的GET, POST, PUT, DELE ...
- 将ant Design本地化,可通过link以及script直接引入html中使用
一直想着能本地化antd的,不用npm以及dva那么复杂的配置环境来开发,并且本地化以后对以后链接flask的模板渲染机制也能很好的结合.下面是具体的实现方法: 1.将react的相关链接引入: &l ...
- Intellij IDEA实现SpringBoot项目多端口启动
前言 有时候使用springboot项目时遇到这样一种情况,用一个项目需要复制很多遍进行测试,除了端口号不同以外,没有任何不同.这时我们强大的Intellij IDEA就能替我们实现. 实现方法 第一 ...
- 2186 ACM 水题 int 向下取整
题目:http://acm.hdu.edu.cn/showproblem.php?pid=2186 扩展: #include <cstdio> 使用floor函数.floor(x)返回的是 ...
- Scrapy基础(十二)————异步导出Item数据到Mysql中
异步导出数据到Mysql中 上次说过从Item中同步写入数据库,因为网络的下载速度和数据库的I/O速度是不一样的所以有可能会发生下载快,但是写入数据库速度慢,造成线程的堵塞:关于堵塞和非堵塞,同步和异 ...
- 潭州课堂25班:Ph201805201 django框架 第七课 常用 字段类型及参数,关系表的实现,表关系对象add,create的方法 (课堂笔记)
写个类,创建表格 执行命令生成文件 提交,在数据库中创建 进入数据库查看 对数据进行修改操作 只有用到 save() 才能触发 updaer_time 的更改, 下边 update 方法不会修改 up ...
- Spring配置JDBCTemplate
案例:单测查询全部学生 项目结构: 1.导入部署jar包:spring-jdbc <!--spring-jdbc--> <dependency> <groupId> ...
- 快速排序 [Qsort]
在做USACO1.4 等差数列的时候,我发现如果用结构体+sort就会超时,用二维数组+qsort就能AC,所以为了不忘记Quick Sort,我还是把代码贴出来以备以后要看吧. void qsort ...