扩展Nlog Layout Renderer原理、Demo、 工具下载
2012-08-30 10:28
141 查看
我们可以通过修改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>
(本文完)
相关文章推荐
- 扩展Nlog Layout Renderer原理、Demo、 工具下载
- 扩展Nlog Layout Renderer原理、Demo、 工具下载
- iOS酷我音乐导出工具使用说明和原理介绍(提供下载链接及工程源码)
- 秋色园QBlog技术原理解析:博客一键安装工具技术实现[附源码下载]
- 秋色园QBlog技术原理解析:博客一键安装工具技术实现[附源码下载]
- 豆丁网文档免登陆免积分下载工具原理分析
- jQuery头像裁剪工具jcrop用法实例(附演示与demo源码下载)
- 百度文库免积分免费下载工具的原理与实现
- 微信web开发者工具、破解文件、开发文档和开发Demo下载
- win2008禁止P2P工具下载的原理及操作步骤
- 虚拟机下载 FBreader源码 demo资源 编译rk依赖的工具
- 微信web开发者工具、破解文件、开发文档和开发Demo下载
- 【原创】下载通用工具“DownLoadNode”系列——2、类设计与使用Demo
- android下载工具demo
- 微信小程序demo、开发工具下载地址
- 百度文库免积分免费下载工具的原理与实现
- 秋色园QBlog技术原理解析:博客一键安装工具技术实现[附源码下载]
- jQuery头像裁剪工具jcrop用法实例(附演示与demo源码下载)
- ARP攻击原理及解决方法(NBTSCAN扫描工具下载和nbtscan使用方法)
- Hxj.Data, Hxj.Data实体生成工具, Hxj,Data Demo, Hxj.Web, Hxj.Web.UI 下载