zoukankan      html  css  js  c++  java
  • NLog日志框架使用探究

    前言

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

    为什么是NLog?

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

    Log4Net上次更新已经是17年3月
    640?wx_fmt=png

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

    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支持以下几种日志等级

    LevelFirstCharacterOrdinal
    TraceT0
    DebugD1
    InfoI2
    WarnW3
    ErrorE4
    FatalF5
    OffO6

    在日志输入时可以通过${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" />

    640?wx_fmt=png

    640?wx_fmt=png

    目标

    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 - 丢弃日志消息。主要用于调试和基准测试。

    name:目标的名字,可以通过创建Rule规则限制目标的输出。

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

    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>

    640?wx_fmt=png

    参数

    在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支持多种目标的文件输入,可以通过文件,数据库或网络等途径输入日志。

    打开后界面如图所示
    640?wx_fmt=png

    在File-Receiver添加一个接收者
    640?wx_fmt=png

    640?wx_fmt=png

    640?wx_fmt=png

    640?wx_fmt=png

    通过以上设置即可在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);}

    640?wx_fmt=png

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

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

    640?wx_fmt=png
    640?wx_fmt=gif

    结语

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

  • 相关阅读:
    771. Jewels and Stones
    706. Design HashMap
    811. Subdomain Visit Count
    733. Flood Fill
    117. Populating Next Right Pointers in Each Node II
    250. Count Univalue Subtrees
    94. Binary Tree Inorder Traversal
    116. Populating Next Right Pointers in Each Node
    285. Inorder Successor in BST
    292. Nim Game Java Solutin
  • 原文地址:https://www.cnblogs.com/hgmyz/p/12351511.html
Copyright © 2011-2022 走看看