NLog类库使用探索——详解配置
1 配置文件的位置(Configuration file locations)
通过在启动的时候对一些常用目录的扫描,NLog会尝试使用找到的配置信息进行自动的自我配置。
1.1 单独的*.exe客户端
单独的客户端,NLog将在以下目录搜索配置信息:
- 标准的程序配置文件(通常为 程序名.exe.config)
- 程序目录下的程序名.exe.nlog文件
- 程序目录下的NLog.config文件
- NLog.dll所在目录下的NLog.dll.nlog文件 (在Nlog没有导入GAC情况下)
1.2 ASP.NET程序
在ASP.NET项目中搜索的目录包括:
- 标准的web程序配置文件web.config
- 和web.config在同一目录下的web.nlog文件
- 程序目录下的NLog.config文件
- NLog.dll所在目录下的NLog.dll.nlog文件 (在Nlog没有导入GAC情况下)
- 如果定义了NLOG_GLOBAL_CONFIG_FILE环境变量,则该变量所指向的文件
1.2 硬件设备类库(.NET Compact Framework)
.NET Compact Framework不支持程序配置文件(*.exe.config)和环境变量,因此NLog将只会扫描这些地方:
- 程序目录下的NLog.config文件
- NLog.dll所在目录下的NLog.dll.nlog文件 (在Nlog没有导入GAC情况下)
1.4 小结
从上面来看,不管哪个我们把配置文件命名为NLog.config,放在应用程序的目录下,肯定都可以扫描到,哈哈。
2 配置文件的格式(Configuration file format)
2.1 NLog支持两种配置文件格式
- 配置信息嵌入在.NET应用程序标准的*.exe.config或者web.config文件里
- 保存在独立文件里
第一种就是我们熟悉的常规配置,使用configSections
<configuration>
<configSections>
<section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog"/>
</configSections>
<nlog>
</nlog>
</configuration>
如果是第二种,是一个单独的Xml文件的话,需要按如下配置:
<nlog xmlns=http://www.nlog-project.org/schemas/NLog.xsd
xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance >
</nlog>
需要说明的是,根节点是<nlong></nlong>,两个命名空间是可选的,但是为了智能感应,你还是把它写上吧。
2.1 子元素的配置
- <targets /> – defines log targets/outputs ,声明目标
- <rules /> – defines log routing rules ,声明规则
- <extensions /> – loads NLog extensions from the *.dll file 加载dll扩展(其实我不懂,没用过)
- <include /> – includes external configuration file 包含外部配置文件
- <variable /> – sets the value of a configuration variable 为配置变量赋值
需要说明的是前两个元素,也就是targets和rules是必需配置的,其余是可选的,应该用于更复杂的配置上,我个人没用过还。
3 输出目标(Targets )
第一篇文章已经介绍过,应该不用再解释,具体输出到那个目标的详细配置,参见文档:https://github.com/nlog/NLog/wiki/Targets
4 路由规则(Rules)
<rules />区域定义了日志的路由规则。每一个路由表项就是一个<logger />元素。<logger />有以下属性:
- name - 日志源/记录者的名字 (允许使用通配符*)
- minlevel - 该规则所匹配日志范围的最低级别
- maxlevel - 该规则所匹配日志范围的最高级别
- level - 该规则所匹配的单一日志级别
- levels - 该规则所匹配的一系列日志级别,由逗号分隔。
- writeTo - 规则匹配时日志应该被写入的一系列目标,由逗号分隔。
- final - 标记当前规则为最后一个规则。其后的规则即时匹配也不会被运行。
如:
- <logger name="Name.Space.Class1" minlevel="Debug" writeTo="f1" /> - 名字空间Name.Space下的Class1这个类的所有级别等于或者高于Debug的日志信息都写入到“f1”这个目标里。
- <logger name="Name.Space.Class1" levels="Debug,Error" writeTo="f1" /> -名字空间Name.Space下的Class1这个类的所有级别等于Debug或Error的日志信息都写入到“f1”这个目标里。
- <logger name="Name.Space.*" writeTo="f3,f4" /> -名字空间Name.Space下所有类的所有级别的日志信息都写入到“f3”和“f4”这两个目标里。
- <logger name="Name.Space.*" minlevel="Debug" maxlevel="Error" final="true" /> - 名字空间Name.Space下所有类的、级别在Debug和Error之间的(包括Debug,Info,Warn,Error) 日志信息都不会被记录(因为这条规则没有定义writeTo),同时其它后续规则也都会被忽略(因为这里设置了final="true")。
5 上下文布局信息(Layouts and layout renderers)
NLog最强大的功能之一就是使用布局(layouts)的能力。语法为:“${属性}”为标记所包围的文本所组成。这个标记也就是所谓的“布局生成器(layout renderers),我们可以用它来把一些上下文相关的信息插入到日志信息中。布局可以应用在许多地方,比如可以被用在控制输出到屏幕或写入文件信息的格式,也可以用在控制文件名。
假设我们希望每个输出到控制台的信息都包含一些这些信息:
- 当前的日期和时间
- 产生日志信息的类和方法的名字
- 日志等级
- 日志内容
利用Layout来实现很简单:,前面已经提到过:
<target name="c" xsi:type="Console" layout="${longdate} ${callsite} ${level} ${message}"/>
使用Layout控制输出的文件名:
<target name="f" xsi:type="File" fileName="${logger}.txt"/>
使用日期来区分日志文件。如果使用${shortdate}布局生成器:
<target name="f" xsi:type="File" fileName="${shortdate}.txt"/>
更多的布局生成器参考官方文档:
https://github.com/nlog/NLog/wiki/Layout%20Renderers
6 包含配置文件(Include files)
我们有这样的需求,不想让NLog.cofige文件太大,太多,读起来太累,我们可以把它分割下。如何分割成若干小的config呢?使用include简单完成。
<nlog>
...
<include file="${basedir}/${machinename}.config"/>
...
</nlog>
制定了要包含的config小文件位置就行。
7 变量(Variables)
配置文件中也可以定义变量,直接上例子,很明了:
<variable name="var" value="xxx" />
<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>
8 自动再配置(Automatic reconfiguration)
听起来确实挺不好理解的。但是确实也没什么。换句简单的话来说,当我们一旦启动程序,这时候NLog.config文件被读取后,知道程序再启动都不会再读取配置文件了。假如我们不想停掉程序,比如说服务器哪能说停就停哈。这就用上这个配置了,这个配置功能是,一旦你对配置文件修改,程序将会重新读取配置文件,也就是自动再配置。直接上代码:
<nlog autoReload="true">
...
</nlog>
9 日志排错(Troubleshooting logging)
程序没问题了,日志却出了问题。这个该怎么办,到底是哪里不正确了?假如日志本身除了bug该如何解决?这就需要日志排错。把日志的错误信息写入日志。
- <nlog throwExceptions="true" />
- <nlog internalLogFile="file.txt" />- 设置internalLogFile属性可以让NLog把内部的调试和异常信息都写入指定文件里。
- <nlog internalLogLevel="Trace|Debug|Info|Warn|Error|Fatal" /> - 决定内部日志的级别,级别越高,输出的日志信息越简洁。
- <nlog internalLogToConsole="false|true" /> - 是否把内部日志输出到标准控制台。
- <nlog internalLogToConsoleError="false|true" /> - 是否把内部日志输出到标准错误控制台 (stderr)。
设置throwExceptions属性为“true”可以让NLog不再阻挡这类异常,而是把它们抛给调用者。在部署是这样做可以帮我们快速定位问题。一旦应用程序已经正确配置了,我们建议把throwExceptions的值设为“false”,这样由于日志引发的问题不至于导致应用程序的崩溃。
10、异步处理(Asynchronous processing )
原理也不多说,直接上代码,使其具备异步处理能力。
<nlog>
<targets async="true">
<!-- all targets in this section will automatically be asynchronous -->
</targets>
</nlog>
11 缺省封装(Default wrappers)
我们希望用同一种封装来处理所有的目标,比如说增加缓冲和/或自动重试功能。
NLog为此提供了专门的语法:<default-wrapper />。你只要把这个元素放在<targets />区域里,然后所有的目标都会自动加载同一个封装目标。需要注意的是<default-wrapper />只对当前这个<targets />区域有效,而你可以使用多个<targets />区域,这样你就可以把目标分组并用不同的封装目标处理。
<nlog>
<targets>
<default-wrapper xsi:type="BufferingWrapper" bufferSize="100"/>
<target name="f1" xsi:type="File" fileName="f1.txt"/>
<target name="f2" xsi:type="File" fileName="f2.txt"/>
</targets>
<targets>
<default-wrapper xsi:type="AsyncWrapper">
<wrapper-target xsi:type="RetryingWrapper"/>
</default-wrapper>
<target name="n1" xsi:type="Network" address="tcp://localhost:4001"/>
<target name="n2" xsi:type="Network" address="tcp://localhost:4002"/>
<target name="n3" xsi:type="Network" address="tcp://localhost:4003"/>
</targets>
</nlog>
上面的例子里我们定义了两个缓冲文件目标和三个异步以及自动重试网络目标。
12 缺省目标参数(Default target parameters)
其实缺省就是把分散的统一在一个区域来定义,仅仅是个语法糖问题,缺省参数自然是把参数相同的抽象出来放到一个区域,统一定义罢了。下面代码是等价的。
<nlog>
<targets>
<target name="f1" xsi:type="File" fileName="f1.txt" keepFileOpen="false"/>
<target name="f2" xsi:type="File" fileName="f2.txt" keepFileOpen="false"/>
<target name="f3" xsi:type="File" fileName="f3.txt" keepFileOpen="false"/>
</targets>
</nlog>
<nlog>
<targets>
<default-target-parameters xsi:type="File" keepFileOpen="false"/>
<target name="f1" xsi:type="File" fileName="f1.txt"/>
<target name="f2" xsi:type="File" fileName="f2.txt"/>
<target name="f3" xsi:type="File" fileName="f3.txt"/>
</targets>
</nlog>