前言

日志是每个程序的基本模块。本文是为了探究如何通过NLog方便及记录日志并通过Log4View工具收集日志统一查看。

为什么是NLog?

下载量NLog和Log4Net差不多,这两个日志模块是.Net平台使用最多的两大日志模块。

Log4Net上次更新已经是17年3月

NLog更新的比较频繁,开发者比较活跃,有问题的话修复更及时。

NLog是适用于各种.net平台(包括.net standard)的灵活而免费的日志记录平台。通过NLog, 可以轻松地写入多个目标。(数据库、文件、控制台), 并动态更改日志记录配置。

NLog支持结构化和传统日志记录。NLog的特点: 高性能、易于使用、易于扩展和灵活配置。

目的

本文为了探究NLog的使用方式,以及如何通过NLog将日志统一收集查看并管理。

配置

NLog可以通过配置方式轻松的记录不同等级,不同结构的日志。

通过Nuget获取NLog库包

Install-Package NLog -Version 4.5.11

下载完后会自动在程序下加入默认的NLog配置

<?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="Info"
internalLogFile="./logs/nlog-internal.log"> <!-- optional, add some variables
https://github.com/nlog/NLog/wiki/Configuration-file#variables
-->
<!--
See https://github.com/nlog/nlog/wiki/Configuration-file
for information on customizing logging rules and outputs.
-->
<targets> <!--
add your targets here
See https://github.com/nlog/NLog/wiki/Targets for possible targets.
See https://github.com/nlog/NLog/wiki/Layout-Renderers for the possible layout renderers.
--> <!--
Write events to a file with the date in the filename.
<target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log"
layout="${longdate} ${uppercase:${level}} ${message}" />
-->
</targets>
<rules>
<!-- add your logging rules here --> <!--
Write all events with minimal level of Debug (So Debug, Info, Warn, Error and Fatal, but not Trace) to "f"
<logger name="*" minlevel="Debug" writeTo="f" />
-->
</rules>
</nlog>

Nlog支持多种配置方式,具体其他配置方式看下《一个简单好用的日志框架NLog》,讲解的很详细。

基本配置

<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="Info"
internalLogFile="./logs/nlog-internal.log">

NLog 根节点以下几种配置需要注意

  • autoReload:配置修改是否自动加载。
  • throwExceptions:日志出现异常时是否需要抛出异常,若配置为true日志记录异常时由于没有捕获异常,会导致程序挂掉。
  • internalLogLevel:表示nlog日志的执行日志记录等级。
  • internalLogFile:表示nlog日志的执行日志记录的位置。通过./XXXX的方式可以配置到程序的相对目录。

日志等级

Nlog支持以下几种日志等级

Level FirstCharacter Ordinal
Trace T 0
Debug D 1
Info I 2
Warn W 3
Error E 4
Fatal F 5
Off O 6

在日志输入时可以通过${level}输入日志等级,或者通过${level:format=FirstCharacter}输出日志等级的简写。

若想查看所有参数输出可以到这里查看。

输出例子

Logger logger = NLog.LogManager.GetLogger("test");
logger.Trace("测试test");
logger.Info("测试test");
logger.Warn("测试test");
logger.Error("测试test");
logger.Fatal("测试test");

通过NLog.LogManager.GetLogger我们可以获取一个日志对象示例。传入的参数为日志实例名,我们可以在日志名中通过${logger}参数输出日志实例名。可以将不同的日志保存到不同的文件。

在代码中我们不支持Off等级的输出。通过NLog不需要我们认为对日志模块进行启动或关闭,在我们程序关闭后,它会自动关闭日志。相关的Nlog的日志可以在internalLogFile配置的路径中中查看到,同时在生产环境建议将internalLogLevelNLog自己的日志等级设置为Info,这样只会记录关键的日志信息。

我们输入到文件中,输入配置如下:

<target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log"
layout="${longdate} ${uppercase:${level}} ${message}" />
<logger name="*" minlevel="Debug" writeTo="f" />

目标

NLog通过target配置日志输入的目标。可以通过配置多个target将日志输入到多个目录,多个目标(文件,网络,数据库等)。

<targets async="true">
<target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log"
layout="${longdate} ${uppercase:${level}} ${message}" />
</targets>

通过将async设置为true可以异步保存日志,从而防止日志影响业务性能。

  1. xsi:type:输入类型,支持以下类型。

    • ColoredConsole : 使用可自定义的颜色将日志消息写入控制台。
    • Console - 将日志消息写入控制台。
    • Debug - 模拟目标-用于测试。
    • File - 将日志消息写入一个或多个文件。
    • Mail - 使用 smtp 协议或拾取文件夹通过电子邮件发送日志邮件。
    • Null - 丢弃日志消息。主要用于调试和基准测试。
  2. name:目标的名字,可以通过创建Rule规则限制目标的输出。

  3. fileName:文件名,日志保存文件时可以保存到该文件中。文件名支持参数化,通过各种参数更方便的输出日志。

  4. layout:表示输出的格式,若为最简单的内容输入,则直接通过参数设置输入格式即可。除了最简单的文本格式还支持以下四种类型的数据,通过xsi:type参数设置layout的格式,如xsi:type="JsonLayout"

    • CSV - A specialized layout that renders CSV-formatted events.
    • Compound - A layout containing one or more nested layouts.
    • JSON - A specialized layout that renders to JSON.
    • Log4JXml - A specialized layout that renders Log4j-compatible XML events.

下面列举两项常用的输入方式,文件输出和网络输出。

文件输出

通过文件输入将日志保存到一个或多个文件。可以通过配置动态进行日志的保存。

下面通过json 的格式保存日志信息。

<?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="Info" internalLogFile="./logs/nlog-internal.log">
<targets>
<target xsi:type="File" name="InfoFile"
fileName="${logDir}/InfoLogs/log.txt"
archiveFileName="${logDir}/InfoLogs/log.{#}.txt"
createDirs="true" keepFileOpen="true" autoFlush="false"
openFileFlushTimeout="10" openFileCacheTimeout="30" archiveAboveSize="10240"
archiveNumbering="Sequence" concurrentWrites="true" encoding="UTF-8">
<layout xsi:type="JsonLayout">
<attribute name="counter" layout="${counter}" />
<attribute name="time" layout="${longdate}" />
<attribute name="level" layout="${level:upperCase=true}"/>
<attribute name="message" layout="${message:format=message}" encode="false" />
</layout>
</target>
</targets>
<rules>
<logger name="*" minlevel="Info" writeTo="InfoFile" />
</rules>
</nlog>
  1. xsi:type:将文件类型设置为File,将日志保存到文件中。
  2. fileName:将日志文件保存到"${logDir}/InfoLogs/log.txt"

    可以通过参数在文件名中加入参数设置

  3. archiveFileName:为了防止日志文件保存的太大,我们将日志文件拆分保存。通过archiveFileName参数设置保存格式,具体格式可以到这里查看。
  4. createDirs:若设置的日志文件夹不存在,则自动创建文件夹。
  5. keepFileOpen:为了提高文件写入性能,避免每次写入文件都开关文件,将keepFileOpen设置为true,我们通过openFileCacheTimeout参数定时关闭文件。
  6. autoFlush:为了提高日志写入性能,不必每次写入日志都直接写入到硬盘上,将autoFlush设置为false,我们通过openFileFlushTimeout参数定时写入文件。
  7. openFileCacheTimeout:将keepFileOpen参数设置为false,则设置定时关闭日志。防止日志一直开着占用着。
  8. openFileFlushTimeout:将autoFlush参数设置为false,则设置定时将日志从缓存写入到硬盘时间。
  9. archiveAboveSize:为了防止一个文件日志太大,我们需要根据指定大小将日志拆文件保存。archiveAboveSize参数的单位是字节。通过设置为10240=10KB,每个日志大小达到10KB就会自动拆分文件,拆分后的文件名规则通过archiveFileName设置,拆分文件名的规则通过archiveNumbering设置,具体规则可以查看这里
  10. concurrentWrites:支持多个并发一起写文件,提高文件写入性能。
  11. encoding: Nlog默认保存的编码格式为Encoding.Default,中文保存到日志中会出现乱码,将其设置为utf-8,就可以正常保存了。

我们可以在targets节点下增加多个target,用于输出多中目标。

当我们开启异步记录日志时,同时设置了保持文件打开,且设置了缓存时间,若在时间内超过了日志大小,并不会立即分文件,而是在文件关闭后才会进行分文件。

Json格式保存

<layout xsi:type="JsonLayout">
<attribute name="counter" layout="${counter}" />
<attribute name="time" layout="${longdate}" />
<attribute name="level" layout="${level:upperCase=true}"/>
<attribute name="message" layout="${message:format=message}" encode="false" />

在target中将layout的 xsi:type设置为JsonLayout保存为Json格式。

Json格式保存我们需要在layout节点下增加attribute来增加字段。上面增加了四个字段。

  • counter:行数,行数表示日志当前记录的行数。
  • time:时间,可以通过参数保存自己想要的时间格式。
  • level:日志等级,当前记录的日志等级。
  • message:信息,记录的信息,若需要记录中文,则需要设置`encode="false",否则json格式会自动将json的中文内容保存为unicode编码。

具体的其他Json参数可以看这里

多目标

<targets>
<target xsi:type="File" name="InfoFile" fileName="${logDir}/InfoLogs/log.txt" archiveFileName="${logDir}/InfoLogs/log.{#}.txt" createDirs="true" keepFileOpen="true" autoFlush="false"
openFileFlushTimeout="10" openFileCacheTimeout="30"
archiveAboveSize="10240" archiveNumbering="Sequence" concurrentWrites="true" encoding="UTF-8">
<layout xsi:type="JsonLayout">
<attribute name="counter" layout="${counter}" />
<attribute name="time" layout="${longdate}" />
<attribute name="level" layout="${level:upperCase=true}"/>
<attribute name="message" layout="${message:format=message}" encode="false" />
</layout>
</target>
<target xsi:type="File" name="ErrorFile" fileName="${logDir}/ErrorLogs/log.txt"
archiveFileName="${logDir}/ErrorLogs/log.{#}.txt" createDirs="true" keepFileOpen="true" autoFlush="false"
openFileFlushTimeout="10" openFileCacheTimeout="30"
archiveAboveSize="10240" archiveNumbering="Sequence"
concurrentWrites="true" encoding="UTF-8">
<layout xsi:type="JsonLayout">
<attribute name="time" layout="${longdate}" />
<attribute name="level" layout="${level:upperCase=true}"/>
<attribute name="message" layout="${message}" encode="false" />
<attribute name="exception">
<layout xsi:type="JsonLayout">
<attribute name="callsite" layout="${callsite}" />
<attribute name="callsite-linenumber" layout="${callsite-linenumber} " />
</layout>
</attribute>
</layout>
</target>
</targets> <rules>
<logger name="*" minlevel="Info" writeTo="InfoFile" />
<logger name="*" minlevel="Error" writeTo="ErrorFile" />
</rules>

我们可以在<targets>节点下增加多个target增加多个输出目标,我们通过设置2个目标,将info和error日志分开保存。其中很多参数是共用的,我们可以设置一个默认参数default-target-parameters,减少配置文件节点。

<default-target-parameters xsi:type="File"
createDirs="true"
keepFileOpen="true" autoFlush="false" openFileFlushTimeout="10" openFileCacheTimeout="30"
archiveAboveSize="10240" archiveNumbering="Sequence" concurrentWrites="true" encoding="UTF-8"/>

通过以上设置,这些设计的节点就被设置为默认值,简化后的配置文件如下。

<target>

    <default-target-parameters xsi:type="File" createDirs="true" keepFileOpen="true" autoFlush="false" openFileFlushTimeout="10" openFileCacheTimeout="30" archiveAboveSize="10240" archiveNumbering="Sequence" concurrentWrites="true" encoding="UTF-8"/>
<target xsi:type="File" name="InfoFile" fileName="${logDir}/InfoLogs/log.txt" archiveFileName="${logDir}/InfoLogs/log.{#}.txt">
<layout xsi:type="JsonLayout">
<attribute name="counter" layout="${counter}" />
<attribute name="time" layout="${longdate}" />
<attribute name="level" layout="${level:upperCase=true}"/>
<attribute name="message" layout="${message:format=message}" encode="false" />
</layout>
</target>
<target xsi:type="File" name="ErrorFile" fileName="${logDir}/ErrorLogs/log.txt" archiveFileName="${logDir}/ErrorLogs/log.{#}.txt">
<layout xsi:type="JsonLayout">
<attribute name="time" layout="${longdate}" />
<attribute name="level" layout="${level:upperCase=true}"/>
<attribute name="message" layout="${message}" encode="false" />
<attribute name="exception">
<layout xsi:type="JsonLayout">
<attribute name="callsite" layout="${callsite}" />
<attribute name="callsite-linenumber" layout="${callsite-linenumber} " />
</layout>
</attribute>
</layout>
</target>
</targets> <rules>
<logger name="*" minlevel="Info" writeTo="InfoFile" />
<logger name="*" minlevel="Error" writeTo="ErrorFile" />
</rules>

参数

在Nlog节点下加入variable节点可以创建自定义参数。

  <variable name="logDir" value="${basedir}/logs/${logger:shortName=true} /${shortdate}"/>
  • name:表示参数名。
  • value:表示参数值。

参数设置完后就可以通过${name}的方式获取参数值。

Nlog已定义的一些参数可以到查看

规则

通过target我们可以自定义输出方式。同时我们可以创建一系列规则约束输出的内容。

  <rules>
<logger name="*" minlevel="Debug" writeTo="f" />
</rules>

Nlog节点下添加rules节点,rules节点下可以配置多个logger节点,每个logger节点即为一条约束。

  • name:logger名称,若为*则表示适用于所有日志,若我们某个target专门用于logdemo.test类的日志输出,则那么可以设置为logdemo.test.*,表示当前约束只允许命名空间为logdemo.test开头的日志输出。
  • minlevel:表示当前约束的最小等级,只有等于或大于该值的日志等级才会被记录。
  • writeTo:表示当前规则约束哪个target

更多其他规则参数可以看这里

日志分发

通过以上设置,我们可以通过各种targets将日志存放到不同地方,通过rules指定保存不同等级的日志。日志本地文件存放主要是用于进行系统排查错误用的,有时候我们可能希望将日志合并存放或查看。NLog本身就支持通过Tcp或Udp将日志分发到其他地方。

我们在保存文件的同时只需要添加一条target,同时将其类型设置为Network,在通过设置rules对其进行必要约束就可以将日志分发到其他地方。由于我们前面设置了async参数异步保存日志,因此网络好坏并不会影响我们业务处理时效。

<?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="Info" internalLogFile="./logs/nlog-internal.log">
...
<targets async="true"> ...
</targets> <targets async="true">
<target xsi:type="Network" address="udp://127.0.0.1:878" name="network" newLine="false" maxMessageSize="65000" encoding="gbk" layout="${log4jxmlevent:includeCallSite=true:includeNLogData=true}"/>
</targets> <rules>
<logger name="*" minlevel="Info" writeTo="network" />
...
</rules>
</nlog>

为了和文件区分,我们我们新增了一个targets专门用于Network。

  • xsi:type:通过设置类型为Network表示通过网络传输日志。
  • address:设置地址格式为协议://ip:端口
  • maxMessageSize:表示最大传输消息大小,默认为65000。
  • newLine:表示日志消息末尾追加换行符。
  • encoding:表示日志传输的编码,默认为UTF-8,中文需要设置为GBK编码,否则在对端可能会出现乱码的情况。

具体完整参数可以看这里

通过以上设置,就可以将日志发送到指定地址了,通过Log4JXml格式发送到对端。

日志收集

我们通过Log4View收集日志进行查看。目前官网最新的是Log4View2版本,有30天的免费使用时间,30天自动变为社区版本,依然可以免费使用,但是想使用一些高级功能则需要付费使用。

Log4View支持Nlog和Log4Net,同时支持查找,过滤等功能。

从官网下载后需要进行安装,目前Log4View不支持中文。

Log4View2支持多种目标的文件输入,可以通过文件,数据库或网络等途径输入日志。

打开后界面如图所示

在File-Receiver添加一个接收者

通过以上设置即可在Log4View接收数据了。我们发送几条消息

Logger logger = NLog.LogManager.GetLogger("test");

logger.Trace("测试test");
logger.Info("测试test");
logger.Warn("测试test");
logger.Error("测试test");
logger.Fatal("测试test");
try
{
throw new Exception("错误test");
}
catch (Exception exception)
{
logger.Error(exception);
}

由于我们设置的日志等级为Info,因此Trace等级的日志不会传输过来。

在界面左下角可以添加过滤器,支持多种筛选模式。



结语

本文对Nlog的简单使用进行了探究,通过配置的方式将文件异步保存到本地和通过udp的方式发送到Log4View2进行更方便的查看,同时Nlog也支持通过代码的方式进行控制,但是使用配置修改相比代码更为灵活,因此本文对代码修改配置的方式不做探讨。


参考文档

  1. 框架学习与探究之日志组件--Log4Net与NLog
  2. NLog基本介绍
  3. 一个简单好用的日志框架NLog
  4. .Net日志库Nlog的详细配置与调用演示
  5. NLog tutorial
  6. Advanced NLog Configuration file
  7. Log4ViewHelp



微信扫一扫二维码关注订阅号杰哥技术分享

本文地址:https://www.cnblogs.com/Jack-Blog/p/10117218.html

作者博客:杰哥很忙

欢迎转载,请在明显位置给出出处及链接

NLog日志框架使用探究-1的更多相关文章

  1. NLog日志框架使用探究-2

    目录 前言 自定义参数 日志输出方式 文件 网络传输 数据库 科学使用 参考文档 前言 在一年前,我写过一篇关于NLog入门文章<NLog日志框架使用探究-1>,文章简单的介绍了Nlog的 ...

  2. 日志管理-NLog日志框架简写用法

    本文转载:http://www.blogjava.net/qiyadeng/archive/2013/02/27/395799.html 在.net中也有非常多的日志工具,今天介绍下NLog.NLog ...

  3. NLog日志框架简写用法

    本文转载:http://www.blogjava.net/qiyadeng/archive/2013/02/27/395799.html 在.net中也有非常多的日志工具,今天介绍下NLog.NLog ...

  4. Nlog 日志框架简单教程

    安装 Nuget获取 配置寻找 会自动寻找在应用程序目录下的NLog.config(大小写敏感) 如何配置config <?xml version="1.0" encodin ...

  5. .Net -- NLog日志框架配置与使用

    NLog是适用于各种.NET平台(包括.NET标准)的灵活,免费的日志记录平台,NLog可将日志写入多个目标,比如Database.File.Console.Mail.下面介绍下NLog的基本使用方法 ...

  6. 从零开始,搭建博客系统MVC5+EF6搭建框架(3),添加Nlog日志、缓存机制(MemoryCache、RedisCache)、创建控制器父类BaseController

    一.回顾系统进度以及本章概要 目前博客系统已经数据库创建.以及依赖注入Autofac集成,接下来就是日志和缓存集成,这里日志用的是Nlog,其实还有其他的日志框架如log4,这些博客园都有很多介绍,这 ...

  7. 【干货】利用MVC5+EF6搭建博客系统(三)添加Nlog日志、缓存机制(MemoryCache、RedisCache)、创建控制器父类BaseController

    PS:如果图片模糊,鼠标右击复制图片网址,然后在浏览器中打开即可. 一.回顾系统进度以及本章概要 目前博客系统已经数据库创建.以及依赖注入Autofac集成,接下来就是日志和缓存集成,这里日志用的是N ...

  8. .net core中的那些常用的日志框架(Serilog篇)

    前言 上文说到Nlog日志框架,感觉它功能已经很强大,今天给大家介绍一个很不错的日志框架Serilog,根据我的了解,感觉它最大的优势是,结构化日志,它输出的日志是Json的格式,如果你使用的是Mon ...

  9. 日志框架对比 NLog VS Log4net

    Log4net 先说Log4net,它是.net平台上一个老牌的日志框架,我接触的时间也不长(因为公司有自己的日志库),但是看着各开源库都在用这个于是前段时间也尝试去了解了一下. 首先让我认识到Log ...

随机推荐

  1. 顺序队列(C语言)

    #define Queue_MAX_SIZE 20 #define OK 1 #define ERROR 0 #include <stdio.h> #include <stdlib. ...

  2. 2019.02.28 bzoj4199: [Noi2015]品酒大会(sam+线段树)

    传送门 题意:给一个串,每个位置有一个权值,当S[s...s+len−1]=S[t...t+len−1]&&S[s...s+len]̸=S[t..t+len]S[s...s+len-1 ...

  3. 源码解读Linux的limits.conf文件

    目录 目录 1 1. 前言 1 2. PAM 2 3. pam_limits 2 4. limits.conf的由来 3 5. 模块入口函数 4 6. 解析limits.conf 6 7. 生效lim ...

  4. vue.js项目nginx部署

    开发环境搭建完成.二.编译部署1.项目路径下demo输入命令npm run build编译完成后会发现在demo文件夹下多出一个dist文件夹这里面就是编译好的文件了.2.网上下载nginx,下载地址 ...

  5. 18.数组(一)之认识java数组

    数组是一个简单的复合数据类型,它是一组有序数据的集合,它当中的每一个数据都具有相同的数据类型,我们通过数组名再加上一个不会越界的下标值来唯一确定数组中的元素. 还有就是,数组是一个特殊的对象. 不管在 ...

  6. 初识Twisted(一)

    pip install Twisted 安装Twisted库 from twisted.internet import reactor #开启事件循环 #不是简单的循环 #不会带来任何性能损失 rea ...

  7. ubuntu16.04安装最新版docker、docker-compose、docker-machine

    安装前说明: 本文将介绍在ubuntu16.04系统下安装和升级docker.docker-compose.docker-machine. docker:有两个版本:docker-ce(社区版)和do ...

  8. unicode 编解码记录

    unicode 万国码.世界上所有的符号都有对应的Unicode code point.一般是2个字节. 这个字节可以通过任意中方式编码为二进制,例如用来保存到文件.一般通过UTF-x(例如utf-8 ...

  9. 9.3 翻译系列:数据注解特性之Key【EF 6 Code-First 系列】

    原文链接:http://www.entityframeworktutorial.net/code-first/key-dataannotations-attribute-in-code-first.a ...

  10. spring框架学习笔记6:JDBC模板

    JDBC模板:Spring中对数据库的操作. 这一部分对熟悉DBUtils的QueryRunner的开发者来说,非常简单 这是以前我简单写的dbutils的知识: http://www.cnblogs ...