扩展Nlog Layout Renderer原理、Demo、 工具下载

 

我们可以通过修改NLog配置文件来控制日志输出格式,但是有时候我们会有这样的需求:我要把UserID OrderID也记录下来,我们可以像使用${date}${message}一样写${UserID} ${OrderID}么?答案是可以的,只需要写一个扩展。我们讲分析实现原理,给出代码示例,演示一下怎么在程序中应用,并提供一个生成Layout Renderer扩展代码的小工具。

 

Layout Renderer扩展的原理

        作为一个有着良好扩展性的日志组件,我们要实现上述目标也是不必修改NLog源代码的。这很好的符合了面对对象的OCP原则。不过要分析原理还是要从源代码下手,打开“\Log4WF\NLog-1.0\src\NLog\LayoutRenderers”文件夹,这里你可以看到NLog默认的提供的输出标记的实现。

      打开一个ThreadID.cs的文件,我们看一下

 1 using  System;
 2 using  System.Text;
 3 using  System.Runtime.InteropServices;
 4
 5 using  NLog.Internal;
 6
 7 namespace  NLog.LayoutRenderers
 8 {
 9    /// <summary>
10    /// The identifier of the current thread.
11    /// </summary>

12    [LayoutRenderer("threadid")]
13    public class ThreadIDLayoutRenderer: LayoutRenderer
14    {
15        /// <summary>
16        /// Returns the estimated number of characters that are needed to
17        /// hold the rendered value for the specified logging event.
18        /// </summary>
19        /// <param name="logEvent">Logging event information.</param>
20        /// <returns>The number of characters.</returns>
21        /// <remarks>
22        /// If the exact number is not known or
23        /// expensive to calculate this function should return a rough estimate
24        /// that's big enough in most cases, but not too big, in order to conserve memory.
25        /// </remarks>

26        protected internal override int GetEstimatedBufferSize(LogEventInfo logEvent)
27        {
28            return 32;
29        }

30
31        /// <summary>
32        /// Renders the current thread identifier and appends it to the specified <see cref="StringBuilder" />.
33        /// </summary>
34        /// <param name="builder">The <see cref="StringBuilder"/> to append the rendered data to.</param>
35        /// <param name="logEvent">Logging event.</param>

36        protected internal override void Append(StringBuilder builder, LogEventInfo logEvent)
37        {
38            builder.Append(ApplyPadding(ThreadIDHelper.Instance.CurrentThreadID.ToString()));
39        }

40    }

41}

42

 这里重载了两个方法:GetEstimatedBufferSize设置缓冲区大小;Append将要记录的内容追加到日志中。

      这也给我们指明了方向,其实我们要做的是两件事情:

1.估计缓冲区大小,这个不难,有些真的是无法估计缓冲区大小的怎么办?打开Message.cs看一下,可以写 logEvent.Message.Length;

2.把要标记所代表的信息追加到日志流中,追加可以很简单的模仿上面的写法,可是到哪里取我们的记录的数据呢?或者说我们要把数据放在哪里可以方便的提取呢?

LogEventInfo这个类代表了要记录的事件信息,除了Message等熟悉之外里面有一个字典类型的Context,可以在这里记录额外的信息。当然了后面我们还要从这里提取出来追加到日志中。看例子,

 

 1 这样LayoutRenderer的扩展也就毫无悬念了,比如我们要写的Query的扩展就会是类似下面这个样子:
 2 using  System;
 3 using  System.Collections.Generic;
 4 using  System.Text;
 5 using  NLog;
 6
 7 namespace  MyTest.NlogLayoutRenderers 
 8 {
 9    [LayoutRenderer("Query")]//注意这里
10    public class QueryLayloutRenderer : LayoutRenderer
11    {
12        protected override int GetEstimatedBufferSize(LogEventInfo logEvent)
13        {
14            return logEvent.Message.Length;//注意这里
15        }

16        protected override void Append(StringBuilder builder, LogEventInfo logEvent)
17        {
18            builder.Append(logEvent.Context["Query"].ToString());//注意这里
19        }

20    }

21}

22
23

在程序中使用自定义扩展

    NLog如何使用这些自定义的标记呢?

NLog在很多场合做同一件事情都会给我们两个选择,可以用配置文件来做,同样也可以用代码来完成同等的操作。

同样这里也是又两种方式可供选择:

  • 如果只是一个简单的扩展,可以考虑使用代码加载: LayoutRendererFactory.AddLayoutRenderer("UserID", typeof(NLogTest.UserIDLayoutRenderer)); 

完成这样一个预备工作,就可以在后续的代码中使用自定义的UserID标记了。

  • 同样的我们可以把这些自定义的LayoutRenderer的扩展放在一个程序集里面,通过配置NLog的配置文件,可以让NLog在初始化的时候加载这些扩展。这样显然更灵活了。具体配置文件样例如下:
  • <nlog> 
     
    <extensions> 
       
    <add assembly="MyTest"/> 
     
    </extensions> 
     
    <targets> 
       
    <target name="console" type="Console" 
               
    layout="${Query} ${message}"/> 
     
    </targets> 
     
    <rules> 
       
    <logger name="*" minLevel="Info" appendTo="console"/> 
     
    </rules> 
    </nlog> 
    这里有一个细节,extensions配置节必须要写在其它配置节的前面,否则会出错。

 

明白了原理,代码用工具生成吧

程序员也许是最讨厌重复的人群,于是好多人实践重构以消除重复。

  写了一些LayoutRenderer的扩展之后,我们会发现代码绝大多数是相似的,变化的点只有变量名和缓冲区的长度。写一个模板,然后简单的字符串替换生成文件就可以了。没有什么技术含量,只是简化复制粘贴的过程。如果NLog的架构能把这件工作给简化了,那才是真正的简化。

工具包含这样两个东西:

 1 1 .代码模板,需要替换的字符串是@Name @Size
 2 using  System;
 3 using  System.Collections.Generic;
 4 using  System.Text;
 5 using  NLog;
 6
 7 namespace  MyTest.NlogLayoutRenderers
 8 {
 9    [LayoutRenderer("@Name")]
10    public class @NameLayloutRenderer : LayoutRenderer
11    {
12        protected override int GetEstimatedBufferSize(LogEventInfo logEvent)
13        {
14            return @Size;
15        }

16        protected override void Append(StringBuilder builder, LogEventInfo logEvent)
17        {
18            builder.Append(logEvent.Context["@Name"].ToString());
19        }

20    }

21}

22

2.字段列表,每一行包含字段名和字段长度,中间使用TAB隔开

User        50

Session        36

IP        15

Login        24

Online        32

LoginMethod        logEvent.Message.Length

LogoutMethod        logEvent.Message.Length

Library        32

使用的时候只要修改这两个文件就可以了,生成的文件在当前目录的Output文件夹中,文件编码UTF-8

 

下载地址:NLogTool.rar

 

参考文献: <http://www.nlog-project.org/howto_write_layout_renderer.html>

 

(本文完)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值