zoukankan      html  css  js  c++  java
  • [C#] 将NLog输出到RichTextBox,并在运行时动态修改日志级别过滤

    作者: zyl910

    一、缘由

    NLog是一个很好用的日志类库。利用它,可以很方便的将日志输出到 调试器、文件 等目标,还支持输出到窗体界面中的RichTextBox等目标。
    而且它还支持在运行时修改配置,例如可用于实现这样的需求——在界面上做个下拉框,可动态调整RichTextBox的日志级别过滤。

    二、输出到RichTextBox

    2.1 办法

    首先,项目中需要加入NLog的程序包。既用 NuGet 下载这些包——

    • NLog
    • NLog.Config
    • NLog.Windows.Forms

    随后便可修改 NLog.config 文件,增加RichTextBox目标了。
    这时有2点需注意——

    1. RichTextBox的target配置中,formName是“RichTextBox所在窗体的类名”,controlName是“该窗体中的RichTextBox控件名”。区分大小写,需要完全一致。
    2. 在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:	emp
    log-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();    // 使配置生效.
    }
    

    参考文献

    (完)

  • 相关阅读:
    hdu4331 Image Recognition 就暴力啊。。啊。。
    [置顶] ASP.Net中服务器控件的生命周期
    Windows下通过脚本快速修改IP地址
    java对象转json应clone,避免生成json串有问题
    Oracle表空间常用操作
    redhat5安装jdk6、eclipse和tomcat6
    Oracle 表的常见操作
    一道来自华为的C机试题目
    [置顶] 获取系统时间的方法--linux
    html5 命运之轮生产
  • 原文地址:https://www.cnblogs.com/zyl910/p/cs_nlog_richtextboxtarget_editrule.html
Copyright © 2011-2022 走看看