Nlog详解

article/2025/10/11 17:36:58

Nlog详解

零、文章目录

一、Nlog详解

1、概述

NLog是一个基于.NET平台编写的日志记录类库,我们可以使用NLog在应用程序中添加极为完善的跟踪调试代码。可以在任何一种.NET语言中输出带有上下文的(contextual information)调试诊断信息,根据喜好配置其表现样式之后发送到一个或多个输出目标(target)中。

官网地址:https://nlog-project.org/

文档地址:https://github.com/NLog/NLog/wiki

2、快速开始

(1)nuget引入程序集

NLog  版本基于5.0版,Net5

(2)代码实现

//创建一个配置文件对象
var config = new NLog.Config.LoggingConfiguration();
//创建日志写入目的地
var logfile = new NLog.Targets.FileTarget("logfile") { FileName = $"logs/{DateTime.Now.ToString("yyyy-MM-dd")}.txt" };
//添加日志路由规则
config.AddRule(LogLevel.Debug, LogLevel.Fatal, logfile);
//配置文件生效
LogManager.Configuration = config;
//创建日志记录对象方式1
Logger Logger = LogManager.GetCurrentClassLogger();
//创建日志记录对象方式2,手动命名
Logger Logger2 = LogManager.GetLogger("MyLogger");
//打出日志
Logger.Debug("我打出了Nlog日志!");

(3)运行结果

image-20220619151929015

3、支持文件配置

(1)nuget引入程序集

NLog
NLog.Config  配置文件

(2)配置文件路径

NLog 启动时会在某些标准路径查找配置文件,进行自动配置:

  • 对于 stand-alone *.exe 应用程序,以下路径会被查询:

    • 标准的应用程序配置文件(通常是applicationname.exe.config)
    • 应用程序目录下的applicationname.exe.nlog 文件
    • 应用程序目录下的 NLog.config 文件 (Name sensitive; using docker dotnet core)
    • NLog.dll 所在目录下的 NLog.dll.nlog 文件(only if NLog isn’t installed in the GAC)
  • 对于 http://ASP.NET 应用程序,以下文件会被查询:

    • 标准 web 应用程序文件 web.config
    • web.config 所在目录下的 web.nlog 文件
    • 应用程序目录下的 NLog.config 文件
    • NLog.dll 所在目录下的 NLog.dll.nlog 文件(only if NLog isn’t installed in the GAC)
  • 对于 .NET Compact Framework 项目,应用程序配置文件(*.exe.config)和环境变量均不能被识别。因此,NLog 仅在以下路径查询:

    • 应用程序目录下的 applicationname.exe.nlog 文件
    • 应用程序目录下的 NLog.config 文件
    • NLog.dll 所在目录下的 NLog.dll.nlog 文件(only if NLog isn’t installed in the GAC)
  • 对于 Xamarin Android 项目,assert 文件夹中的 NLog.config 文件会被自动加载。如果配置文件名有所不同,可以执行以下命令:

    • LogManager.Configuration = new XmlLoggingConfiguration(“assets/someothername.config");

(3)配置文件

引入NLog.Config之后,项目会自动添加一个NLog.Config配置文件,这个是默认的配置文件,这个文件不在项目文件夹下需要复制过来,配置文件右键属性一定要设置成始终复制

程序运行的时候,会自动加载NLog.Config作为Nlog的配置。

XML文件中有详细说明,rules配置路由规则, targets配置输出目标。

<?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="Off" internalLogFile="c:\temp\nlog-internal.log"><!-- optional, add some variableshttps://github.com/nlog/NLog/wiki/Configuration-file#variables--><variable name="myvar" value="myvalue"/><!--See https://github.com/nlog/nlog/wiki/Configuration-filefor information on customizing logging rules and outputs.--><targets><!--add your targets hereSee 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>

将注释去掉,最精简版本如下

<?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" ><targets><!--输出目标:name名称f,xsi:type输出类型文件, fileName输出到程序根目录logs文件夹中, 以日期作为生成log文件名称, layout生成内容的格式--><target name="f"xsi:type="File"fileName="${basedir}/logs/${shortdate}.log"layout="${longdate} ${uppercase:${level}} ${message}" /></targets><rules><!--日志路由规则:最低级别Debug,输出到target目标f--><logger name="*" minlevel="Debug" writeTo="f" /></rules>
</nlog>

(4)代码实现

//创建日志记录对象
Logger Logger = NLog.LogManager.GetCurrentClassLogger();
//打出日志
Logger.Debug("我打出了Nlog日志!");

(5)运行结果

image-20220619152433357

4、配置文件详解

(1)全局配置

<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="Off" internalLogFile="c:\temp\nlog-internal.log">

建议throwExceptions的值设为“false”,这样由于日志引发的问题不至于导致应用程序的崩溃。

autoReload 修改配置文件后是否允许自动加载无须重启程序
throwExceptions 内部日志系统抛出异常
internalLogLevel 可选Trace|Debug|Info|Warn|Error|Fatal决定内部日志的级别 Off 关闭
internalLogFile 把内部的调试和异常信息都写入指定文件里

(2)根元素

在配置文件的根元素中,我们可以指定如下的子元素。其中前两个是必须设定的,其余三个为可选设定。

  1. targets:定义日志的输出目标
  2. rules:定义对日志信息的路由规则
  3. extensions:定义从其他dll文件中加载的NLog扩展模块
  4. include:引入外部的配置文件
  5. variable:定义配置文件中用到的变量

(3)targets定义日志的输出目标

<targets><target name="f"xsi:type="File"fileName="${basedir}/logs/${shortdate}.log"layout="${longdate} ${uppercase:${level}} ${message}" maxArchiveFiles="5"archiveAboveSize="10240"archiveEvery="Day"/>
</targets>

Nlog允许用户配置单个文件大小, 放置在内容过长效率过慢,配置了大小之后, Nlog会自动创建一个新的文件副本,插入新的日志输出。

maxArchiveFiles:允许生成的副本文件最大数量

archiveAboveSize:允许单个文件得最大容量

archiveEvery:按天生成

name:输出目标的名称,用于rules中路由规则writeTo指定

fileName:包含完整的生成文件的路径和文件名

xsi:type:输出类型

Chainsaw
ColoredConsole 
Console
Database
Debug
Debugger
EventLog
File
LogReceiverService
Mail
Memory
MethodCall
Network
NLogViewer
Null
OutputDebugString
PerfCounter
Trace
WebService

layout:用来规定输出内容格式,语法“${属性}”,可以把上下文信息插入到日志中。

$ {cached} -  将缓存应用于另一个布局输出。
$ {db-null} - 为数据库渲染DbNull
$ {exception} - 通过调用Logger方法之一提供的异常信息
$ {level} - 日志级别(例如ERROR,DEBUG)或级别序数(数字)
$ {literal} - 字符串文字。(文本)-有用,以逃避括号
$ {logger} - 记录器名称。GetLogger,GetCurrentClassLogger等
$ {message} - (格式化的)日志消息。
$ {newline} - 换行文字。
$ {object-path} -  渲染对象的(嵌套)属性
$ {onexception} -  仅在为日志消息定义了异常时才输出内部布局。
$ {var} - 渲染变量
呼叫站点和堆栈跟踪-------------------------------------------------------------
$ {callsite} - 调用站点(类名,方法名和源信息)
$ {callsite-linenumber} - 呼叫站点源行号。
$ {stacktrace} - 渲染堆栈跟踪
条件------------------------------------------------------------------------
$ {when} -  仅在满足指定条件时输出内部布局。
$ {whenempty} -  当内部布局产生空结果时,输出替代布局。
上下文信息-------------------------------------------------------------------
$ {activityid} - 将System.Diagnostics跟踪关联ID记录到日志中。
$ {all-event-properties} - 记录所有事件上下文数据。
$ {event-context} -  记录事件属性数据-替换为$ {event-properties}
$ {event-properties} - 记录事件属性数据-重命名$ {event-context}
$ {gdc} - 全局诊断上下文项。包含每个应用程序实例值的字典结构。
$ {install-context} - 安装参数(传递给InstallNLogConfig)。
$ {mdc} - 映射诊断上下文-线程局部结构。
$ {mdlc} - 异步映射诊断上下文-线程局部结构。MDC的异步版本
$ {ndc} - 嵌套诊断上下文-线程局部结构。
$ {ndlc} - 异步嵌套诊断上下文-线程本地结构。
专柜-----------------------------------------------------------------------
$ {counter} - 一个计数器值(在每个布局渲染中增加)
$ {guid} - 全局唯一标识符(GUID)。
$ {sequenceid} - 日志序列号
日期和时间------------------------------------------------------------------
$ {date} - 当前日期和时间。
$ {longdate} - 日期和时间,采用可排序的长格式`yyyy-MM-dd HH:mm:ss.ffff`。
$ {qpc} - 高精度计时器,基于QueryPerformanceCounter返回的值。
$ {shortdate} - 短日期,格式为yyyy-MM-dd。
$ {ticks} - 当前日期和时间的“ Ticks”值。
$ {时间} - 在24小时,可排序的格式HH的时间:MM:ss.mmm。
编码和字符串转换--------------------------------------------------------------
$ {json-encode} -  使用JSON规则转义另一个布局的输出。
$ {left} -  文字的左半部分
$ {小写} -  将另一个布局输出的结果转换为小写。
$ {norawvalue} -  防止将另一个布局渲染器的输出视为原始值
$ {pad} -  将填充应用于另一个布局输出。
$ {replace} -  将另一个布局的输出中的字符串替换为另一个字符串。正则表达式可选
$ {replace-newlines} -  用另一个字符串替换换行符。
$ {right} -  文字的右侧
$ {rot13} -  使用ROT-13解码“加密”的文本。
$ {substring} -  文本的子字符串
$ {trim-whitespace} -  从另一个布局渲染器的结果修剪空白。
$ {uppercase} -  将另一个布局输出的结果转换为大写。
$ {url-encode} -  编码另一个布局输出的结果,以供URL使用。
$ {wrapline} -  以指定的行长包装另一个布局输出的结果。
$ {xml-encode} -  将另一个布局输出的结果转换为XML兼容的。
环境和配置文件----------------------------------------------------------------
$ {appsetting} -. config文件 NLog.Extended中的应用程序配置设置
$ {configsetting} - 来自appsettings.json或ASP.NET Core和.NET Core中其他配置的值 NLog.Extensions.Logging NLog.Extensions.Hosting NLog.Web.AspNetCore
$ {environment} - 环境变量。(例如PATH,OSVersion)
$ {environment-user} - 用户身份信息(用户名)。
$ {}注册表 - 从Windows注册表中的值。
文件和目录--------------------------------------------------------------------
$ {basedir} - 当前应用程序域的基本目录。
$ {currentdir} - 应用程序的当前工作目录。
$ {file-contents} - 呈现指定文件的内容。
$ {filesystem-normalize} -  通过将文件名替换为安全字符来过滤文件名中不允许的字符。
$ {} nlogdir - 其中NLog.dll所在的目录。
$ {specialfolder} - 系统专用文件夹路径(包括“我的文档”,“我的音乐”,“程序文件”,“桌面”等)。
$ {tempdir} - 临时目录。
身分识别----------------------------------------------------------------------
$ {identity} - 线程身份信息(名称和身份验证信息)。
$ {windows-identity} - 线程Windows身份信息(用户名)
$ {windows-identity} - 线程Windows身份信息(用户名) Nlog.WindowsIdentity
整合方式----------------------------------------------------------------------
$ {gelf} - 将日志转换为GELF格式 NLog.GelfLayout 外部
$ {log4jxmlevent} - 与log4j,Chainsaw和NLogViewer兼容的XML事件描述。
进程,线程和程序集--------------------------------------------------------------
$ {appdomain} - 当前的应用程序域。
$ {assembly-version} - 默认应用程序域中可执行文件的版本。
$ {gc} - 有关垃圾收集器的信息。
$ {hostname} - 运行该进程的计算机的主机名。
$ {local-ip} - 来自网络接口的本地IP地址。
$ {machinename} - 运行进程的计算机名。
$ {performancecounter} - 性能计数器。
$ {processid} - 当前进程的标识符。
$ {processinfo} - 有关正在运行的进程的信息。例如StartTime,PagedMemorySize
$ {processname} - 当前进程的名称。
$ {processtime} - 格式为HH:mm:ss.mmm的处理时间。
$ {threadid} - 当前线程的标识符。
$ {threadname} - 当前线程的名称。
Silverlight------------------------------------------------------------------------
$ {document-uri} - 承载当前Silverlight应用程序的HTML页面的URI。
$ {sl-appinfo} - 有关Silverlight应用程序的信息。
Web,ASP.NET和ASP.NET Core----------------------------------------------------------
$ {ASPNET-appbasepath} - ASP.NET应用程序的基本路径(内容根) NLog.Web NLog.Web.AspNetCore
$ {ASPNET应用} - ASP.NET应用程序变量。 网络日志
$ {ASPNET环境} - ASP.NET环境名称 NLog.Web.AspNetCore
$ {ASPNET项} - ASP.NET`HttpContext`项变量。 NLog.Web NLog.Web.AspNetCore
$ {ASPNET-MVC-行动} - ASP.NET MVC动作名称 NLog.Web NLog.Web.AspNetCore
$ {ASPNET-MVC控制器} - ASP.NET MVC控制器名称 NLog.Web NLog.Web.AspNetCore
$ {ASPNET请求} - ASP.NET请求变量。 NLog.Web NLog.Web.AspNetCore
$ {ASPNET-请求的contentType} - ASP.NET Content-Type头(实施例应用/ JSON) NLog.Web.AspNetCore
$ {ASPNET请求,饼干} - ASP.NET请求的cookie的内容。 NLog.Web NLog.Web.AspNetCore
$ {ASPNET请求形式} - ASP.NET请求表的内容。 NLog.Web NLog.Web.AspNetCore
$ {ASPNET请求报头} - ASP.NET部首键/值对。 NLog.Web NLog.Web.AspNetCore
$ {ASPNET请求主机} - ASP.NET请求主机。 NLog.Web NLog.Web.AspNetCore
$ {aspnet-request-ip} - 客户端IP。 NLog.Web NLog.Web.AspNetCore
$ {ASPNET请求-方法} - ASP.NET请求方法(GET,POST等)。 NLog.Web NLog.Web.AspNetCore
$ {ASPNET请求,贴体} - ASP.NET贴体/净荷 NLog.Web NLog.Web.AspNetCore
$ {ASPNET-请求的查询字符串} - ASP.NET请求的查询字符串。 NLog.Web NLog.Web.AspNetCore
$ {ASPNET,请求引荐} - ASP.NET请求引用。 NLog.Web NLog.Web.AspNetCore
$ {ASPNET请求的URL} - ASP.NET请求URL。 NLog.Web NLog.Web.AspNetCore
$ {ASPNET请求,用户代理} - ASP.NET请求用户代理。 NLog.Web NLog.Web.AspNetCore
$ {ASPNET-响应的StatusCode} - ASP.NET响应状态代码的内容。 NLog.Web NLog.Web.AspNetCore
$ {ASPNET会话} - ASP.NET Session变量。 NLog.Web NLog.Web.AspNetCore
$ {ASPNET-的SessionID} - ASP.NET会话ID的变量。 NLog.Web NLog.Web.AspNetCore
$ {ASPNET-traceidentifier} - ASP.NET跟踪标识 NLog.Web NLog.Web.AspNetCore
$ {ASPNET用户-的authType} - ASP.NET用户验证。 NLog.Web NLog.Web.AspNetCore
$ {ASPNET用户身份} - ASP.NET用户变量。 NLog.Web NLog.Web.AspNetCore
$ {ASPNET用户-isauthenticated} - ASP.NET用户身份验证? NLog.Web NLog.Web.AspNetCore
$ {ASPNET-webrootpath} - ASP.NET Web根目录路径(wwwroot文件) NLog.Web NLog.Web.AspNetCore
$ {iis-site-name} - IIS网站的名称。 NLog.Web NLog.Web.AspNetCore

(4)rules定义对日志信息的路由规则

路由顺序会对日志打印产生影响。路由匹配逻辑为顺序匹配。

日志可以分不同级别进行输出,日志规则rules里面可以控制输出的日志级别。不同级别的日志代表日志的重要程度,比如一些debug级别的日志在生产环境就会被控制不输出,以减少日志文件的大小。

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

name:记录者的名字。

minlevel :最低日志级别。

maxlevel:最高日志级别。

level:单一日志级别。

levels:一系列日志级别,由逗号分隔。

final:是否是最后的匹配路由,true表示匹配到这里就结束。

writeTo:规则匹配时日志应该被写入的一系列目标,由逗号分隔。就是tagets对应的name。

日志级别有如下,自上而下,等级递增。

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

日志过滤器:可以在路由当中, 为每个路由配置自定义得日志过滤器fliter,如下所示

<rules><logger name="*" writeTo="file"><filters><when condition="length('${message}') > 100" action="Ignore" /><when condition="equals('${logger}','MyApps.SomeClass')" action="Ignore" /><when condition="(level >= LogLevel.Debug and contains('${message}','PleaseDontLogThis'))" action="Ignore" /><when condition="not starts-with('${message}','PleaseLogThis')" action="Ignore" /></filters></logger>
</rules>

日志过滤器–条件语言

过滤器表达式以特殊的迷你语言编写。该语言包括:
关系运算符:==,!=,<,<=,>=和>
注意:一些预先定义的XML字符可能需要转义。例如,如果尝试使用’<'字符,则XML解析器会将其解释为开始标记,这会导致配置文件中的错误。而是<在这种情况下使用转义版本的<<(())。
布尔运算符:and,or,not
始终被视为布局的字符串文字- ${somerenderer}
布尔文字- true和false
数值文字-例如12345(整数文字)和12345.678(浮点文字)
日志级别文字- LogLevel.Trace,LogLevel.Debug,…LogLevel.Fatal
预定义的关键字来访问最常用的日志事件属性- level,message和logger
花括号-一起覆盖默认优先级和分组表达式
条件函数-执行string和object测试
单引号应与另一个单引号转义。

日志过滤器–条件函数

contains(s1,s2)确定第二个字符串是否是第一个的子字符串。返回:true当第二个字符串是第一个字符串的子字符串时,false否则返回。
ends-with(s1,s2)确定第二个字符串是否是第一个字符串的后缀。返回:true当第二个字符串是第一个字符串的前缀时,false否则返回。
equals(o1,o2)比较两个对象是否相等。返回:true当两个对象相等时,false否则返回。
length(s) 返回字符串的长度。
starts-with(s1,s2)确定第二个字符串是否是第一个字符串的前缀。返回:true当第二个字符串是第一个字符串的前缀时,false否则返回。
regex-matches(input, pattern, options)在NLog 4.5中引入。指示正则表达式是否pattern在指定的input字符串中找到匹配项。options是一个可选的逗号分隔的RegexOptions枚举值列表。返回:true当在输入字符串中找到匹配项时,false否则返回

5、输出到多种存储介质

(1)配置文件

<?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" ><targets><!--输出目标:name名称f,xsi:type输出类型文件, fileName输出到程序根目录logs文件夹中, 以日期作为生成log文件名称, layout生成内容的格式--><target name="f"xsi:type="File"fileName="D:/logs/Nlog/${shortdate}/nlog.log"layout="${longdate} ${uppercase:${level}} ${message}"archiveAboveSize="102400"/><!--输出到控制台--><target name="c"xsi:type="Console"layout="${longdate} ${uppercase:${level}} ${message}" /><!--输出到csv文件--><target name="e" xsi:type="File" fileName="D:/logs/Nlog/${shortdate}/nlog.csv"><layout xsi:type="CSVLayout"><column name="time" layout="${longdate}" /><column name="message" layout="${message}" /><column name="logger" layout="${logger}"/><column name="level" layout="${level}"/></layout></target></targets><rules><!--日志路由规则:最低级别Debug,输出到target目标f--><logger name="*" minlevel="Debug" writeTo="f,c,e" /></rules>
</nlog>

(2)代码实现

Logger Logger = NLog.LogManager.GetCurrentClassLogger();
for (int i = 0; i < 10_000; i++)
{Logger.Debug($"我打出了Nlog日志!--{i.ToString()}");
}

(3)运行结果

日志文件超过设定大小就会增加新文件,这样后面查看的时候就不会因为日志文件太大而无法打开。名称后面的数字是按照内容从早到晚进行从小到大增长的,没有数字的那个文件始终是最新的日志内容。

image-20220620145803220

6、输出到数据库

(1)nuget引入程序集

NLog
NLog.Config
NLog.Database   NLog5.0+必须单独添加数据库支持
MySql.Data      数据库驱动

(2)安装数据库,创建数据库和表

安装数据库

安装数据库可以使用docker容器化安装,简单易用,一行命令解决,docker相关知识可以参考docker详解。

docker run --name mysqlserver -v /data/mysql/conf:/etc/mysql/conf.d -v /data/mysql/logs:/logs -v /data/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d -i -p 3306:3306 mysql:latest --lower_case_table_names=1
参数说明
–name mysqlserver容器运行的名字
-v /data/mysql/conf:/etc/mysql/conf.d将宿主机/data/mysql/conf映射到容器/etc/mysql/conf.d
-v /data/mysql/logs:/logs将宿主机/data/mysql/logs映射到容器/logs
-v /data/mysql/data:/var/lib/mysql将宿主机/data/mysql/data映射到容器 /var/lib/mysql
-e MYSQL_ROOT_PASSWORD=123456数据库初始密码123456
-p 3306:3306将宿主机3306端口映射到容器的3306端口
–lower_case_table_names=1设置表名忽略大小写,只能首次修改,后续无法修改

创建数据库logmanager

创建表nlog

CREATE TABLE `nlog` (`Id` int(10) unsigned NOT NULL AUTO_INCREMENT,`Application` varchar(50) DEFAULT NULL,`Logged` datetime DEFAULT NULL,`Level` varchar(50) DEFAULT NULL,`Message` varchar(512) DEFAULT NULL,`Logger` varchar(250) DEFAULT NULL,`Callsite` varchar(512) DEFAULT NULL,`Exception` varchar(512) DEFAULT NULL,PRIMARY KEY (`Id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

(3)配置文件

<?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"throwExceptions="true"internalLogLevel="Off"><targets><!--输出到数据库--><target name="d" xsi:type="Database"dbProvider="MySql.Data.MySqlClient.MySqlConnection, MySql.Data"connectionString="server=服务器IP地址;Database=logmanager;user id=root;password=123456;SslMode=none"><commandText>insert into nlog (Application, Logged, Level, Message,Logger, CallSite, Exception) values (@Application, @Logged, @Level, @Message,@Logger, @Callsite, @Exception);</commandText><parameter name="@application" layout="MyNlog" /><parameter name="@logged" layout="${date}" /><parameter name="@level" layout="${level}" /><parameter name="@message" layout="${message}" /><parameter name="@logger" layout="${logger}" /><parameter name="@callSite" layout="${callsite:filename=true}" /><parameter name="@exception" layout="${exception:tostring}" /></target></targets><rules>		<logger name="*" minlevel="Debug" writeTo="d" /></rules>
</nlog>

(4)代码实现

//创建日志记录对象
Logger Logger = NLog.LogManager.GetCurrentClassLogger();
//打出日志
Logger.Debug("我打出了Nlog日志!");

(5)运行结果

image-20220621145850481

7、最佳实践

(1)NLog.Logger 应为类的静态变量

新建 NLog.Logger 对象消耗一定的开销,例如需要获取锁或者分配对象。因此推荐以下方式创建NLog.Logger

public class MyClass
{private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
}

(2)应由 NLog.Logger 格式化日志

尽量避免直接使用字符串进行格式化。例如,

var message = "Hello" + "Earch";
logger.Info(message);

推荐使用 NLog.Logger 对象进行格式化。例如,

logger.Info("Hello {0}", "Earth");

NLog.Logger 对象可以推迟执行格式化操作的时机,从而减少开销。

(3)应将异常对象传递给 NLog.Logger

避免将异常作为字符串格式化的参数,而是显示的将异常作为参数传递给函数。例如,

try
{
}
catch (Exception ex)
{logger.Error(ex, "Something bad happened");
}

(4)开启配置文件的有效性验证

默认情况下,NLog 屏蔽了自身的所有异常,因此 NLog 出错时不会使应用程序崩溃。对于大多数应用程序,建议在 nlog 元素增加 throwConfigExceptions="true" 属性开启初始化配置时的异常捕获功能,以验证配置文件的有效性。

<?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"throwConfigExceptions="true">
</nlog>

⚠️注意:还有一个名为 throwExceptions 的属性,不应在生产环境中使用。它是为了单元测试和本地调试设计的。

(5)别忘了 Flush 日志信息

默认情况下,NLog 在程序关闭时会自动 flush。 Windows 限定 .NET 应用程序在程序终止前一定时间内进行关闭操作(一般是 2 秒)。如果 NLog 的 target 依赖于网络传输(例如 Http, Mail, Tcp),那么建议手动执行 Flush/Shutdown 操作。
Mono/Linux 上运行的 .NET 应用程序在关闭前需要停止 Thread/Timer。如果未能完成这些操作,则会引发未处理异常、段错误以及其他难以预料的行为,同样建议手动执行 Flush/Shutdown 操作。

NLog.LogManager.Shutdown(); // Flush and close down internal threads and timers

8、集成到Asp.NetCore5框架

(1)Nuget引入程序集

NLog
NLog.Config
NLog.Web.AspNetCore  集成框架

(2)配置文件

放到文件夹CfgFile统一管理,配置文件右键属性始终复制

<?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="Off" internalLogFile="c:\temp\nlog-internal.log"><targets><target xsi:type="File" name="f" fileName="D:/logs/Nlog/${shortdate}/nlog.log"layout="${longdate} ${uppercase:${level}} ${message}" /></targets><rules><!--Skip Microsoft logs and so log only own logs--><!--以Microsoft打头的日志将进入此路由,由于此路由没有writeTo属性,所有会被忽略--><!--且此路由设置了final,所以此路由被匹配到了不会再继续往下匹配。未匹配到的会继续匹配下一个路由--><logger name="Microsoft.*" minlevel="Trace"  final="true" /><logger name="*" minlevel="Debug" writeTo="f" /></rules>
</nlog>

(3)Program添加对Nlog支持

public class Program
{public static void Main(string[] args){CreateHostBuilder(args).Build().Run();}public static IHostBuilder CreateHostBuilder(string[] args) =>Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder =>{webBuilder.UseStartup<Startup>();}).ConfigureLogging(logBuilder =>{logBuilder.ClearProviders();//删除所有其他的关于日志记录的配置logBuilder.SetMinimumLevel(LogLevel.Trace);//设置最低的log级别logBuilder.AddNLog("CfgFile/NLog.config");//支持nlog});
}

(4)添加控制器和页面,注入日志对象

public class FirstController : Controller
{private readonly ILogger<FirstController> _ILogger;private readonly ILoggerFactory _ILoggerFactory;public FirstController(ILogger<FirstController> logger, ILoggerFactory iLoggerFactory){this._ILogger = logger;_ILogger.LogInformation($"{this.GetType().FullName} 被构造。。。。LogInformation");_ILogger.LogError($"{this.GetType().FullName} 被构造。。。。LogError");_ILogger.LogDebug($"{this.GetType().FullName} 被构造。。。。LogDebug");_ILogger.LogTrace($"{this.GetType().FullName} 被构造。。。。LogTrace");_ILogger.LogCritical($"{this.GetType().FullName} 被构造。。。。LogCritical");this._ILoggerFactory = iLoggerFactory;ILogger<FirstController> _ILogger2 = _ILoggerFactory.CreateLogger<FirstController>();_ILogger2.LogInformation("这里是通过Factory得到的Logger写的日志");}public IActionResult Index(){_ILogger.LogInformation($"{this.GetType().FullName} Index被请求");return View();}
}

(5)请求页面,运行结果

image-20220621154208469

9、集成到Asp.NetCore6框架

(1)Nuget引入程序集

NLog
NLog.Config
NLog.Web.AspNetCore  集成框架

(2)配置文件

放到文件夹CfgFile统一管理,配置文件右键属性始终复制

<?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="Off" internalLogFile="c:\temp\nlog-internal.log"><targets><target xsi:type="File" name="f" fileName="D:/logs/Nlog/${shortdate}/nlog.log"layout="${longdate} ${uppercase:${level}} ${message}" /></targets><rules><!--Skip Microsoft logs and so log only own logs--><!--以Microsoft打头的日志将进入此路由,由于此路由没有writeTo属性,所有会被忽略--><!--且此路由设置了final,所以此路由被匹配到了不会再继续往下匹配。未匹配到的会继续匹配下一个路由--><logger name="Microsoft.*" minlevel="Trace"  final="true" /><logger name="*" minlevel="Debug" writeTo="f" /></rules>
</nlog>

(3)Program添加对Nlog支持

public class Program
{public static void Main(string[] args){var builder = WebApplication.CreateBuilder(args);// Add services to the container.builder.Services.AddControllersWithViews();//配置日志builder.Services.AddLogging(logBuilder =>{logBuilder.ClearProviders();//删除所有其他的关于日志记录的配置logBuilder.SetMinimumLevel(LogLevel.Trace);//设置最低的log级别logBuilder.AddNLog("CfgFile/NLog.config");//支持nlog});var app = builder.Build();// Configure the HTTP request pipeline.if (!app.Environment.IsDevelopment()){app.UseExceptionHandler("/Home/Error");// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.app.UseHsts();}app.UseHttpsRedirection();app.UseStaticFiles();app.UseRouting();app.UseAuthorization();app.MapControllerRoute(name: "default",pattern: "{controller=Home}/{action=Index}/{id?}");app.Run();}
}

(4)添加控制器和页面,注入日志对象

public class FirstController : Controller
{private readonly ILogger<FirstController> _ILogger;private readonly ILoggerFactory _ILoggerFactory;public FirstController(ILogger<FirstController> logger, ILoggerFactory iLoggerFactory){this._ILogger = logger;_ILogger.LogInformation($"{this.GetType().FullName} 被构造。。。。LogInformation");_ILogger.LogError($"{this.GetType().FullName} 被构造。。。。LogError");_ILogger.LogDebug($"{this.GetType().FullName} 被构造。。。。LogDebug");_ILogger.LogTrace($"{this.GetType().FullName} 被构造。。。。LogTrace");_ILogger.LogCritical($"{this.GetType().FullName} 被构造。。。。LogCritical");this._ILoggerFactory = iLoggerFactory;ILogger<FirstController> _ILogger2 = _ILoggerFactory.CreateLogger<FirstController>();_ILogger2.LogInformation("这里是通过Factory得到的Logger写的日志");}public IActionResult Index(){_ILogger.LogInformation($"{this.GetType().FullName} Index被请求");return View();}
}

(5)请求页面,运行结果

image-20220621154326725


http://chatgpt.dhexx.cn/article/QTG2eA5n.shtml

相关文章

iOS之深入解析NSLog的调试技巧

一、DEBUG 宏区分调试模式和发布模式进行特殊处理 ① 利用 Configuration 配置不同的编译环境 一个应用往往对应多个域名的情况&#xff0c;测试地址、生产地址、后台接口开发者的个人主机地址&#xff1a; 1.开发人员环境&#xff08;Other&#xff09;连接写服务人的电脑&…

TDD(测试驱动开发)死了吗?

01、前言 很早之前&#xff0c;曾在网络上见到过 TDD 这 3 个大写的英文字母&#xff0c;它是 Test Driven Development 这三个单词的缩写&#xff0c;也就是“测试驱动开发”的意思——听起来很不错的一种理念。 其理念主要是确保两件事&#xff1a; 确保所有的需求都能被照…

unitTest+Ddt数据驱动测试

我们设计测试用例时&#xff0c;会出现测试步骤一样&#xff0c;只是其中的测试数据有变化的情况&#xff0c;比如测试登录时的账号密码。这个时候&#xff0c;如果我们依然使用一条case一个方法的话&#xff0c;会出现大量的代码冗余&#xff0c;而且效率也会大大降低。此时&a…

测试驱动开发(TDD)的理论基础

在开始理论介绍之前&#xff0c;先思考一个问题&#xff1a;软件开发中最重要的是什么&#xff1f; 可能有的小伙伴就会说&#xff1a;良好的数据库设计&#xff0c;一个健壮可扩展的架构&#xff0c;规范的编码风格&#xff0c;设计文档等。没错这些在开发中都很重要&#xf…

什么时候应该编写单元测试?什么是TDD?

一、传统方法与TDD方法 1、有人认为软件编码完成后编写单元测试&#xff08;传统方法&#xff09;&#xff0c;流程如下&#xff1a; 缺点&#xff1a;编写完功能代码再写单元测试会导致单元测试“粒度”比较粗。对同样的功能代码&#xff0c;如果采用TDD方案&#xff0c;结果…

前端做自动化测试 —— 用TDD的思想做组件测试

Test-Driven Development(测试驱动开发,以下简述TDD)是一种设计方法论, 原理是在开发功能代码之前, 先编写单元测试用例代码, 通过测试来推动整个开发的进行. 本文详细描述了在创作 react-stillness-component, 组件的过程中, 是如何学习 TDD 的思想来完成功能开发以及测试的 一…

深度解读 - TDD(测试驱动开发)

本文结构&#xff1a; 什么是 TDD为什么要 TDD怎么 TDDFAQ学习路径延伸阅读 什么是 TDD TDD 有广义和狭义之分&#xff0c;常说的是狭义的 TDD&#xff0c;也就是 UTDD&#xff08;Unit Test Driven Development&#xff09;。广义的 TDD 是 ATDD&#xff08;Acceptance Tes…

【TDD】测试驱动开发

欢迎关注微信公众号“Python小灶&#xff0c;和我一起每天学习Python新知识”&#xff0c;还可添加博主Vx&#xff1a;yf03064131&#xff0c;方便一起交流学习。 或者B站搜索 有只小新 原视频地址链接&#xff1a;点击这里 代码地址&#xff1a;点击这里 本文为大致翻译以及…

测试驱动开发(TDD)的学习使用

测试驱动开发TDD 是一种不同于传统软件开发流程的新型开发方式 特点&#xff1a; 先编写测试代码 – 实现主要逻辑 再写功能代码 – 实现细节 通过测试来推动整个开发的进行。 有助于编写简洁可用和高质量的代码&#xff0c;并加速开发过程呢。 比如写一个Person类&#xff0c;…

从 TDD 到测试策略

“ 前端没法 TDD / 前端不容易做 TDD / 前端 TDD 收益不大 ” 这是进公司后无数人给我判的“死刑”。 事实上好像的确如此&#xff1f; 在这个崇尚敏捷的组织里&#xff0c;我们有毕业生的入职前培训&#xff0c;入职后培训&#xff0c;有 TwU&#xff0c;有无数定期不定期的…

使用ddt执行数据驱动测试

所谓数据驱动测试&#xff0c;简单的理解为数据的改变从而驱动自动化测试的执行&#xff0c;最终引起测试结果的改变。通过使用数据驱动测试的方法&#xff0c;可以在需要验证多组数据测试场景中&#xff0c;使用外部数据源实现对输入输出与期望值的参数化&#xff0c;避免在测…

先测试再开发?TDD测试驱动开发了解一下?

1、什么是TDD 我第一次接触TDD这个概念&#xff0c;是在<<代码整洁之道>>中&#xff0c;作者鲍勃大叔在书中&#xff0c;写了一些关于测试代码的代码规范&#xff0c;其实就提到了有关TDD三定律: - 定律一&#xff1a; 在编写不能通过的单元测试前&#xff0c;不…

测试驱动开发(TDD)前端篇

当你在写生产代码时&#xff0c;你处在高认知的状态&#xff08;obvious&#xff09;&#xff0c;你的研发流程和你的工程实践&#xff0c;有助于你一步一步的提升你的认知能力&#xff0c;把你的问题进行一个降解&#xff08;分解&#xff09;&#xff0c;只要你做到同样的事情…

TDD 开发测试

测试驱动开发(Test-Driven Development)。是敏捷开发中的一项核心实践和技术。 TDD是在开发功能代码之前&#xff0c;先编写单元测试用例代码&#xff0c;测试代码确定需要编写什么产品代码。 变红 ——> 变绿 ——> 重构 在进行 TDD 案例编写的时候&#xff0c;看一…

TDD测试驱动开发

TDD测试驱动开发 什么是测试驱动开发测试驱动开发该怎么做&#xff1f;需求一&#xff1a;输入一个非元音字符&#xff0c;并预期返回字符本身 (输入"h" 返回“h”)需求二&#xff1a;输入一个元音&#xff08;a,e,i,o,u&#xff09;&#xff0c;返回 mommy (输入&qu…

TDD测试驱动学习

gtest 和 gmock 安装 //如果不知道对应库名字可以执行这个命令查找对应库,如果没找到要去跟新对应的源sudo apt update sudo apt-cache search gtest sudo apt-cache search gmock 测试例子 #include <string> using std::string;// 定义 Soundex 类 class Soundex {pub…

TDD (test driver development)测试驱动开发

##为什么需要测试驱动/或者说需要单元测试 我们工作接触的软件项目&#xff0c;不是学生时代&#xff0c;玩一玩就不管了&#xff0c;工作的项目&#xff0c;需要长期维护&#xff0c;并且随着时间的推移需要增加新的需求&#xff0c;进行修改&#xff0c;优化。此时已经距离你…

tdd(测试驱动开发)的概述

最近的工作的项目&#xff0c;使用了tdd&#xff08;test-driven development测试驱动开发&#xff09;的开发模式。 这两几年大概听说了无数种xxx-dd, ddd, tdd, atdd, bdd, fdd, udd各种名词眼花缭乱&#xff0c;当然很多dd其实也有相互借鉴&#xff08;抄袭&#xff09;的部…

测试驱动开发(TDD)实践与技巧

文章目录 引言Google Mock测试用例结构断言经典式断言Hamcrest 断言 测试驱动开发&#xff1a;第一个示例开场白开始吧去掉不干净的代码增量性fixture 设置思索与测试驱动开发测试驱动与测试 测试驱动开发基础与单元测试单元测试的组织结构测试驱动开发周期&#xff1a;红-绿-重…

opencv配置相关的截图参考

opencv配置相关的截图参考&#xff0c;如下&#xff1a;