Nlog日志使用

视频:https://www.bilibili.com/video/BV1bv4y1a79X

参照:https://www.cnblogs.com/sheng-jie/p/17169929.html
PPT文件:https://files.cnblogs.com/files/summerZoo/NLog.pptx?t=1693272385&download=true

基础介绍

NLog 是一个跨平台的 .Net 日志组件。
NLog 遵从 BSD license,即允许商业应用且完全开放源代码。NLog日志支持高度自定义模板配置,且预置了大量的开箱即用的模板及字段(nlog-project.org),无需修改代码即可快速配置期望的日志结构,相对于Serilog有更高的灵活性。

日志等级

  1. Trace - 最常见的记录信息,一般用于普通输出
  2. Debug - 同样是记录信息,不过出现的频率要比Trace少一些,一般用来调试程序
  3. Info - 信息类型的消息
  4. Warn - 警告信息,一般用于比较重要的场合
  5. Error - 错误信息
  6. Fatal - 致命异常信息。一般来讲,发生致命异常之后程序将无法继续执行。

优先级:Trace <Debug<Info <Warn<Error<Fatal

重要概念

Targets——定义日志目标/输出

Rules—定义日志路由规则

配置

配置相关概念

Targets——定义日志目标/输出

Rules—定义日志路由规则

NLog 单独的配置文件是一个以 nlog 为根节点的 XML 文件。Targets、Rules在所有 NLog 配置文件中都必须存在,

extensionsincludesvariables这些元素是可选的。

Targets

定义了一系列日志输出目标,每一个输出目标是一个 target 元素。对于每一个 target 元素,name 属性和 type 属性是必须要指定的:

  • name - target 的名字。路由规则根据该属性将日志信息路由到当前目标。
  • type - target 的类型。当使用了 xsi 命名空间时,该属性被命名为 xsi:type。目前 NLog 支持的输出目标列表:Targets

不同类型的 target 节点可以接受不同的属性。例如对于 File 目标,fileName 参数指定了日志文件的文件名;对于 Console 目标,error 参数指定日志信息是写到标准错误流还是标准输出流。NLog 内置了许多预定义类型,详见如何自定义输出目标

示例:

<targets>
    <target name="f1" xsi:type="File" fileName="file1.txt"/>
    <target name="f2" xsi:type="File" fileName="file2.txt"/>
    <target name="n1" xsi:type="Network" address="tcp://localhost:4001"/>
    <target name="ds" xsi:type="OutputDebugString"/>
</targets>

Rules

定义日志路由规则的集合,由一个或多个 logger 元素组成。每个 logger 元素记录了 logger 的名字、目标输出以及要处理的日志等级。NLog 从路由规则表的第一个 logger 开始处理,如果当前 logger 有效,则日志信息将被输出到指定的 target。如果某个 logger 被标记为 final ,那么其后的 logger 都会被忽略。

logger 包含下列属性:

  • name - logger的名字(可以使用通配符*)
  • minLevel - 最小日志等级
  • maxLevel - 最大日志等级
  • level - 单一的日志等级
  • levels - 以逗号分割的日志等级列表
  • writeTo - 以逗号分割的输出目标列表
  • final - 标记当前规则为最后一条规则,此后申明的rule不再生效
  • enabled - 使能当前规则

如果在一条规则中定义了多个日志等级相关的属性(level, levels, minLevelmaxLevel),按照优先级只生效当前优先级最高的属性。等级相关属性优先级如下,

  1. level
  2. levels
  3. minLevelmaxLevel
  4. 没有设置(所有等级的日志都会被记录)

以下是 rules 节点的 例子

<rules>
    <logger name="Name.Space.Class1" minlevel="Debug" writeTo="f1" />
    <logger name="Name.Space.Class1" levels="Debug,Error" writeTo="f1" />
    <logger name="Name.Space.*" writeTo="f3,f4" />
    <logger name="Name.Space.*" minlevel="Debug" maxlevel="Error" final="true" />
</rules>
  1. 命名空间 Name.Space 下类 Class1 中高于 Debug 级别的日志信息将被写入输出目标 f1
  2. 命名空间 Name.Space 下类 Class1 中级别为 DebugError 的日志信息将被写入 target:f1
  3. 命名空间 Name.Space 下所有类中的日志信息将被写入 target:f3, f4
  4. 命名空间 Name.Space 下所有类中级别在 DebugError 之间 (Debug,Info,WarnError) 的日志信息不被记录(因为没有指定属性 writeTo)。由于标记了属性 final,之后的 logger 都会被忽略。

配置方式

NLog 支持两种文件格式:

  1. 在标准的 *.exe.config 或 web.config/appsettings.json 中嵌入配置
  2. 在单独的文件中进行配置,单独配置文件便于在项目中切换配置或日志库

NLog 单独的文件配置文件是一个以 nlog 为根节点的 XML 文件

单独文件配置

  1. 添加NLog.Web.AspNetCore的引用

  2. 创建一个 nlog.config 文件。

    autoReload——是否在配置文件被修改时自动重新加载的属性

    internalLogLevel—用于指定NLog内部日志记录的详细程度

    internalLogFile—指定NLog内部日志记录的输出位置

    extensions ——有些类似${shortdate}、layout表达式需要引入对应的包才能生效

    <?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"
          autoReload="true"
          internalLogLevel="Info"
          internalLogFile="c:\temp\internal-nlog-AspNetCore.txt">
    
      <!-- enable asp.net core layout renderers -->
      <extensions>
        <add assembly="NLog.Web.AspNetCore"/>
      </extensions>
    
      <!-- the targets to write to -->
      <targets>
        <!-- File Target for all log messages with basic details -->
        <target xsi:type="File" name="allfile" fileName="c:\temp\nlog-AspNetCore-all-${shortdate}.log"
                layout="${longdate}|${event-properties:item=EventId:whenEmpty=0}|${level:uppercase=true}|${logger}|${message} ${exception:format=tostring}" />
    
        <!-- File Target for own log messages with extra web details using some ASP.NET core renderers -->
        <target xsi:type="File" name="ownFile-web" fileName="c:\temp\nlog-AspNetCore-own-${shortdate}.log"
                layout="${longdate}|${event-properties:item=EventId:whenEmpty=0}|${level:uppercase=true}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}|${callsite}" />
    
        <!--Console Target for hosting lifetime messages to improve Docker / Visual Studio startup detection -->
        <target xsi:type="Console" name="lifetimeConsole" layout="${MicrosoftConsoleLayout}" />
      </targets>
    
      <!-- rules to map from logger name to target -->
      <rules>
        <!--All logs, including from Microsoft-->
        <logger name="*" minlevel="Trace" writeTo="allfile" />
    
        <!--Output hosting lifetime messages to console target for faster startup detection -->
        <logger name="Microsoft.Hosting.Lifetime" minlevel="Info" writeTo="lifetimeConsole, ownFile-web" final="true" />
    
        <!--Skip non-critical Microsoft logs and so log only own logs (BlackHole) -->
        <logger name="Microsoft.*" maxlevel="Info" final="true" />
        <logger name="System.Net.Http.*" maxlevel="Info" final="true" />
    
        <logger name="*" minlevel="Trace" writeTo="ownFile-web" />
      </rules>
    </nlog>
    
  3. 做对应的依赖注入

     var builder = WebApplication.CreateBuilder(args);
    
        // Add services to the container.
        builder.Services.AddControllersWithViews();
    
        // NLog: Setup NLog for Dependency injection
        builder.Logging.ClearProviders();
        builder.Host.UseNLog();
    
        var app = builder.Build();
        //其他注入
    

    .net core 3.1见Getting started with ASP.NET Core 3 · NLog/NLog Wiki (github.com)

在appsettings.json里配置

  1. 添加NLog.Web.AspNetCore的引用

  2. 在appsettings.json里配置,也是要配置对应的targets、rules等属性

    //Nlog配置
      "NLog": {
        "throwConfigExceptions": true,
        "extensions": [
          {
            "assembly": "NLog.Web.AspNetCore"
          }
        ],
        "targets": {
          "async": true,
          "logfile": {
            "type": "File",
            "fileName": "Log/nlog-${shortdate}.log",
            "layout": {
              "type": "JsonLayout",
              "attributes": [
                {
                  "name": "@timestamp",
                  "layout": "${date}"
                },
                {
                  "name": "app",
                  "layout": "${processname}"
                },
                {
                  "name": "env",
                  "layout": "${environment:ASPNETCORE_ENVIRONMENT}"
                },
                {
                  "name": "level",
                  "layout": "${level}"
                },
                {
                  "name": "logger",
                  "layout": "${logger}"
                },
                {
                  "name": "message",
                  "layout": "${message}"
                },
                {
                  "name": "exception",
                  "layout": "${exception:format=toString}"
                },
                {
                  "name": "aspnet-request-method",
                  "layout": "${aspnet-request-method}"
                },
                {
                  "name": "aspnet-request-url",
                  "layout": "${aspnet-request-url}"
                },
                {
                  "name": "aspnet-mvc-controller",
                  "layout": "${aspnet-mvc-controller}"
                },
                {
                  "name": "aspnet-mvc-action",
                  "layout": "${aspnet-mvc-action}"
                }
              ]
            }
          },
          "logconsole": {
            "type": "Console"
          }
        },
        "rules": [
          {
            "logger": "*",
            "minLevel": "Info",
            "writeTo": "logconsole"
          },
          {
            "logger": "*",
            "minLevel": "Debug",
            "writeTo": "logfile"
          }
        ]
      },
    
  3. 注入

    var builder = WebApplication.CreateBuilder(args);
        builder.Configuration
            .SetBasePath(builder.Environment.ContentRootPath)
            .AddJsonFile("appsettings.json", true, true)
            .AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", true, true)
            .AddEnvironmentVariables();
        //从appsetting里读取NLog的配置作为配置
        NLog.LogManager.Configuration = new NLogLoggingConfiguration(builder.Configuration.GetSection("NLog"));
    
        // NLog: Setup NLog for Dependency injection
        builder.Logging.ClearProviders();//清除当前定义的所有日志提供程序
        //.net core 5+版本,默认情况下,NLog会对ILoggerFactory添加一个过滤器,该过滤器会过滤掉一些不需要记录日志的消息,从而提高日志记录效率。但是,在某些情况下,我们可能需要记录这些被过滤掉的消息,因此可以将RemoveLoggerFactoryFilter属性设置为false,以禁用NLog的默认过滤器,达到兼容ILogger的目的
        builder.Host.UseNLog(new NLogAspNetCoreOptions() { RemoveLoggerFactoryFilter = false });var builder = WebApplication.CreateBuilder(args);
        NLog.LogManager.Configuration = new NLogLoggingConfiguration(builder.Configuration.GetSection("NLog"));//从appsetings的NLog配置中读取配置
    
        // NLog: Setup NLog for Dependency injection
        builder.Logging.ClearProviders();//清除当前定义的所有日志提供程序
        //.net core 5+版本,默认情况下,NLog会对ILoggerFactory添加一个过滤器,该过滤器会过滤掉一些不需要记录日志的消息,从而提高日志记录效率。但是,在某些情况下,我们可能需要记录这些被过滤掉的消息,因此可以将RemoveLoggerFactoryFilter属性设置为false,以禁用NLog的默认过滤器,达到兼容ILogger的目的
        builder.Host.UseNLog(new NLogAspNetCoreOptions() { RemoveLoggerFactoryFilter = false });
        //其他版本builder.Host.UseNLog()
    
输出方式配置

NLog 支持多种输出方式,常用的有控制台、文件和数据库输出,

控制台输出:

    <targets>
        <target name="console" xsi:type="ColoredConsole" layout="${longdate} ${level:uppercase=true} ${message}" />
    </targets>

    <rules>
        <logger name="*" minlevel="Trace" writeTo="console" />
    </rules>

文件输出:

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

    <rules>
        <logger name="*" minlevel="Trace" writeTo="file" />

数据库输出

   <targets>
        <target name="database" xsi:type="Database" connectionString="Data Source=myserver;Initial Catalog=mydatabase;Integrated Security=True;"
                commandText="INSERT INTO Log (Date, Level, Message) VALUES (@Date, @Level, @Message)">
          <parameter name="@Date" layout="${longdate}" />
          <parameter name="@Level" layout="${level:uppercase=true}" />
          <parameter name="@Message" layout="${message}" />
        </target>
    </targets>

    <rules>
        <logger name="*" minlevel="Trace" writeTo="database" />
    </rules>

Layout

NLog最强大的资产之一是Layout是一种用于定义日志消息格式的机制。它允许你在日志消息中包含文本、变量和属性,并将它们合并为一个格式化的字符串。${``}

支持多种格式输出,通过type来配置

json—JsonLayout

xml—XmlLayout

还有大量常用化的标签来配置消息格式

  • ${message}:日志消息的文本
  • ${longdate}:日期和时间(格式为 yyyy-MM-dd HH:mm:ss)
  • ${level}:日志级别(例如,Info、Warn、Error)。
  • ${exception}:异常信息。
  • ${aspnet-request-url}:记录 HTTP 请求 URL
  • ${aspnet-user-identity}:记录 ASP.NET 用户身份
  • ${aspnet-request-method}:记录 HTTP 请求方法(例如,GET、POST)。
  • ${aspnet-request-controller}:记录 ASP.NET MVC 框架中控制器的名称。

轮转日志

NLog 支持日志轮转(也称为日志滚动),即在日志文件大小或日期达到指定条件时,将当前日志文件重命名为备份文件,并创建一个新的日志文件,以继续记录日志。

按文件大小轮转:

 <target name="file" xsi:type="File" fileName="${basedir}/logs/${shortdate}.log"
                layout="${longdate} ${level:uppercase=true} ${message}" 
                archiveAboveSize="1024" 
                archiveFileName="${basedir}/logs/archives/${shortdate}.{#}.log" 
                archiveNumbering="Sequence" 
                maxArchiveFiles="10" />
  • archiveAboveSize="1024":当日志文件大小超过 1024 字节时,触发轮转操作。
  • archiveFileName="${basedir}/logs/archives/${shortdate}.{#}.log":指定备份文件的名称模板,在此模板中,{#} 表示备份文件的序号。
  • archiveNumbering="Sequence":指定备份文件的命名方式为序列号方式。
  • maxArchiveFiles="10":指定最多保留 10 个备份文件。

按日期轮转

<target name="file" xsi:type="File" fileName="${basedir}/logs/${shortdate}.log"
                layout="${longdate} ${level:uppercase=true} ${message}" 
                archiveEvery="Day" 
                archiveFileName="${basedir}/logs/archives/{#}.log" 
                archiveNumbering="Date" 
                maxArchiveDays="7" />
  • archiveEvery="Day":指定按天轮转日志文件。
  • archiveFileName="${basedir}/logs/archives/{#}.log":指定备份文件的名称模板,在此模板中,{#} 表示备份文件的日期。
  • archiveNumbering="Date":指定备份文件的命名方式为日期方式。
  • maxArchiveDays="7":指定最多保留 7 天的备份文件