作者:Jarosław Kowalski <jaak@jkowalski.net>
翻译:Dflying Chen:http://dflying.cnblogs.com/
原文:http://www.nlog-project.org/tutorial.html
本文为《NLog文章系列》的第三篇,将继续描述演示用NLog书写日志的方法。本想今天就能搞定整个入门教程,无奈时间实在来不及了……只能再分一篇了……匆忙而为,言语多有不顺,还请各位见谅……
日志配置
下面我们来看一下NLog的配置原理。于其他工具不同,NLog将在程序启动时尝试进行自动配置,换句话说,NLog将自动在某些默认位置中搜索其配置文件。当NLog和标准的exe文件配合使用时,将自动按照顺序搜索下列路径,以得到配置文件:
- 应用程序的标准配置文件(通常为applicationname.exe.config)
- 应用程序所在目录中的applicationname.exe.nlog文件
- 应用程序所在目录中的NLog.config文件
- NLog.dll所在目录中的NLog.dll.nlog文件
- 环境变量NLOG_GLOBAL_CONFIG_FILE所指向的文件
对于ASP.NET应用程序,NLog将自动按照顺序搜索下列路径:
- Web应用程序的标准配置文件——web.config
- web.config所在目录中的web.nlog文件
- 应用程序所在目录中的NLog.config文件
- NLog.dll所在目录中的NLog.dll.nlog文件
- 环境变量NLOG_GLOBAL_CONFIG_FILE所指向的文件
.NET Compact Framework并不支持应用程序配置文件(*.exe.config)以及环境变量,因此NLog将自动按照顺序搜索下列路径:
- 应用程序所在目录中的applicationname.exe.nlog文件
- 应用程序所在目录中的NLog.config文件
- NLog.dll所在目录中的NLog.dll.nlog文件
配置文件形式
NLog支持两种形式的配置文件:
- 嵌入到*.exe.config或web.config等标准配置文件中
- 单独的配置文件
对于第一种形式,我们使用了标准化的configSection机制。这样配置文件将类似如下所示:
<configuration>
<configSections>
<section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog"/>
</configSections>
<nlog>
</nlog>
</configuration>
而对于第二种形式,XML配置文件将以<nlog />作为其根节点。XML的命名空间是可选的,但如果按照如下所示指定了命名空间,将会得到Visual Studio的智能感知支持。
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
</nlog>
若不指定XML命名空间,则NLog的配置文件对大小写不敏感。若指定了XML命名空间,则将变为对大小写敏感。智能感知将只能在指定了XML的命名空间时正常工作。
配置文件元素
在配置文件的<nlog />根元素中,我们可以指定如下的子元素。其中前两个是必须设定的,其余三个为可选设定。
- <targets /> - 定义日志的输出目标
- <rules /> - 定义对日志信息进行路由的规则
- <extensions /> - 定义从其他dll文件中加载的NLog扩展模块
- <include /> - 引入外部的配置文件
- <variable /> - 定义配置文件中用到的变量
输出目标(Target)
<targets />配置节用来定义日志信息的输出位置。每一个输出位置都用一个<target />元素表示。<target />元素有两个必须设置的属性:
- name - 输出目标的名称
- type - 输出目标的类型,例如“File”、“DataBase”、“Mail”等。若我们为配置文件指定了命名空间,则该属性名为xsi:type。
除了上述两个必须设置的属性之外,<target />元素还支持一些其他的属性,同样可以影响记录诊断信息的方式。我们可以为每一个输出目标设定不同的属性参数,这些属性均在NLog的主页上有详细描述,且Visual Studio也都为其提供了智能感知功能支持。
例如:“File”输出目标接受一个名为fileName的参数,用来指定输出文件的名称;而“Console”输出目标则接受一个名为error的参数,表示是否用标准错误输出(stderr)代替标准输出(stdout)。
NLog提供了很多与定义的输出目标,这些均在NLog的主页上有详细介绍。若你觉得不够用,并希望能够编写自定义的输出目标,那么也同样非常简单——15-20行代码就够了,请参考Nlog的文档(documentation)。
路由规则(Rule)
路由规则将定义在配置文件的<rules />节中。这部分内容就是一个简单的路由表,用来定义不同的日志源(Logger的名称)以及记录等级的日志信息将被发送至哪个输出目标中。路由规则将从列表中的第一项开始执行,如果符合当前的路由规则,则该条日志信息将被发送至指定的输出目标中,若路由表中任意一项都不满足,则该条日志信息将不会被处理。
路由表中的每一个条目都由一个<logger />元素定义,<logger />元素支持如下几个属性:
- name - 日志源(Logger的名称),可以使用*通配符
- minlevel - 匹配该规则需要的最低记录等级
- maxlevel - 匹配该规则需要的最高记录等级
- level - 匹配该规则需要的单一的记录等级
- levels - 匹配该规则需要的记录等级列表,记录等级之间用逗号隔开
- writeTo - 匹配该规则的日志信息将被发送至的输出目标列表,输出目标之间用逗号隔开
- final - 让该规则成为日志信息的最后一个匹配条目。满足该条规则的日志信息被处理之后,将不会再继续尝试匹配下面定义的路由规则。
一些例子:
来自于命名空间Name.Space下Class1的、记录等级等于或高于Debug的日志信息将被发送至输出目标f1。
<logger name="Name.Space.Class1" minlevel="Debug" writeTo="f1" />
来自于命名空间Name.Space下Class1的、记录等级等于为Debug或Error的日志信息将被发送至输出目标f1。
<logger name="Name.Space.Class1" levels="Debug,Error" writeTo="f1" />
来自于命名空间Name.Space下任意类的任意日志信息将被发送至输出目标f3和f4。
<logger name="Name.Space.*" writeTo="f3,f4" />
来自于命名空间Name.Space下任意类的、记录等级在Debug和Error之间(包括Debug、Info、Warn和Error)的日志信息将被忽略(没有writeTo属性),且也不会再被下面的路由规则处理(因为设置了final="true")。
<logger name="Name.Space.*" minlevel="Debug" maxlevel="Error" final="true" />
在前面的示例程序中,配置文件只包含了一个<target />元素和一个<logger />元素。随着对程序的需求不断扩充,添加新的输出目标以及路由规则也将一样非常简单。
上下文信息
NLog最具优势的特性之一就是它的布局(layout)概念。“${}”符号用来表示“布局呈现器(layout renderer)”,即随当前日志插入一段上下文信息。我们可以在很多地方使用布局,例如控制日志信息写入到屏幕以及文件中的格式,甚至还可以控制日志输出文件的名称。这个特性功能非常强大,接下来我们就来看看:
假设我们需要为输出到控制台的每一条信息添加如下附加信息:
- 当前的时间日期
- 发送该消息的类名和方法名
- 日志等级
- 日志内容
实现起来非常简单:
<target name="c" xsi:type="Console"
layout="${longdate} ${callsite} ${level} ${message}"/>
还可以让来自不同类的日志信息输出到不同的文件中:
<target name="f" xsi:type="File" fileName="${logger}.txt"/>
可以看到,上面我们在fileName属性中使用了${logger}布局呈现器。这样将让来自不同类的日志信息输出到以类名区分的不同文件中,即输出如下几个日志文件:
- Name.Space.Class1.txt
- Name.Space.Class2.txt
- Name.Space.Class3.txt
- Other.Name.Space.Class1.txt
- Other.Name.Space.Class2.txt
- Other.Name.Space.Class3.txt
- ...
一个非常常见的需求就是将每天的日志文件分开存放。使用${shortdate}布局呈现器,这个要求真是小菜一碟:
<target name="f" xsi:type="File" filename="${shortdate}.txt"/>
想要为每个员工生成不同的日志文件?${windows-identity}布局呈现器可以轻松搞定:
<target name="f" xsi:type="File" filename="${windows-identity:domain=false}.txt"/>
这样,NLog将根据每个员工的登陆信息将日志输出到单独的文件中:
- Administrator.txt
- MaryManager.txt
- EdwardEmployee.txt
- ...
当然还有更加复杂的情况。下面这个配置文件就为每个人每天生成一个单独的日志文件,并存放至用时间区分的目录中:
<target name="f" xsi:type="File"
filename="${shortdate}/${windows-identity:domain=false}.txt"/>
这条配置信息将生成类似如下的一些日志文件:
- 2006-01-01/Administrator.txt
- 2006-01-01/MaryManager.txt
- 2006-01-01/EdwardEmployee.txt
- 2006-01-02/Administrator.txt
- 2006-01-02/MaryManager.txt
- 2006-01-02/EdwardEmployee.txt
- ...
NLog提供了很多与定义的布局呈现器,在http://www.nlog-project.org/layoutrenderers.html 这个页面中有详细介绍。创建自己的布局呈现器也同样简单,依然是15-20行代码的事,请参考NLog的文档(documentation )。
包含文件
有时我们需要将NLog的配置文件分割成几个存放。NLog同样支持在某一配置文件中对其他的配置文件进行引用包含,然后在运行时一起处理。和NLog配置文件中其他部分一样,我们可以使用熟悉的${var}标记。这样就方便根据不同环境设置智能装载相应的配置文件,例如如下示例降加载基于计算机名的配置文件:
<nlog>
...
<include file="${basedir}/${machinename}.config"/>
...
</nlog>
使用变量则可以方便地处理复杂的表达式,或者以统一的方式引用多次重复出现的表达式。我们可以使用<variable name="var" value="xxx" />表达式定义一个变量,定义之后该变量即可在各种布局呈现器中使用——同样是${var}语法。例如下面的示例:
<nlog>
<variable name="logDirectory" value="${basedir}/logs/${shortdate}"/>
<targets>
<target name="file1" xsi:type="File" filename="${logDirectory}/file1.txt"/>
<target name="file2" xsi:type="File" filename="${logDirectory}/file2.txt"/>
</targets>
</nlog>