在本系例文章的第八篇中,我们聊过官方的日志实现,即《.NET6之MiniAPI(八):日志》。但官方的日志功能更多是提供了一个实现基础,对于要求一个灵活,强大,方便的日志体系,官方的还是有差距的,那么本篇就介绍一下NLog,这款强大,灵活,方便的日志库,在MiniAPI中的使用。

直入主题,首先引入NeGut包

NLog.Web.AspNetCore

添加代码实现很简单

using NLog; using NLog.Web; //启动日志 var logger = NLog.LogManager.Setup().LoadConfigurationFromAppSettings().GetCurrentClassLogger(); logger.Debug("init main"); try { var builder = WebApplication.CreateBuilder(args); //配置日志 builder.Logging.ClearProviders(); builder.Logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace); builder.Host.UseNLog(); var app = builder.Build(); //使用日志 app.MapGet("/logtest", () => { app.Logger.LogTrace("LogTrace"); app.Logger.LogDebug("LogDebug"); app.Logger.LogWarning("LogWarning"); app.Logger.LogInformation("LogInformation"); app.Logger.LogError("LogError"); app.Logger.LogCritical(new Exception("eLogCritical"), "LogCritical"); return "logtest"; }); app.MapGet("/myvalue", MyService.GetMyValue); app.Run(); } catch (Exception exception) { //异常时处理日志 logger.Fatal(exception, "Stopped program because of exception"); } finally { NLog.LogManager.Shutdown(); } class MyService { public static string GetMyValue(ILogger<MyService> logger) { logger.LogInformation("TestService.GetMyValue"); return "MyValue"; } }

NLog的真正方便,在配置的丰富,通过配置灵活地实现不日志方式,不同信息项目的采集。NLog的配置以nlog.config文件名保存在项目根目录下,当然也可以通过修改启动日志的LoadConfigurationFramAppSettings来配置nlog.config路径。

配置主要通过targets节点和rules节点协助实现配置,targets主要是配置保存或显示日志的方式,是txt文件,还json文件,以及layout中日志的内容,具体target的属性,有很多,参见https://github.com/NLog/NLog/wiki/File-target。另外一个就是layout中,也就是将来的日志信息有那些元素,可参见https://nlog-project.org/config/?tab=layout-renderers。

rules主要是配置不同的功能模块,日志级别等信息,参见https://github.com/nlog/nlog/wiki/Configuration-File#rules。

下面的案例配置,实现了官方模板自带的allfile和ownFile-web两个txt格式的模板,和一个jsonfile的模板,同时还有一个彩色控制台模板(各个模板的属性,官方文档比较详细,这里就不展开了)

<?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"> <!-- 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="${basedir}\logs\nlog-AspNetCore-all-${shortdate}.log" layout="${longdate}|${event-properties:item=EventId_Id: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="${basedir}\logs\nlog-AspNetCore-own-${shortdate}.log" layout="${longdate}|${event-properties:item=EventId_Id:whenEmpty=0}|${level:uppercase=true}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-Request-url}|action: ${aspnet-mvc-action}|${callsite}" /> <!--json格式--> <target name="jsonfile" xsi:type="File" fileName="${basedir}\logs\${shortdate}.json"> <layout xsi:type="JsonLayout" includeAllProperties="true"> <attribute name="time" layout="${date:format=O}" /> <attribute name="message" layout="${message}" /> <attribute name="logger" layout="${logger}"/> <attribute name="level" layout="${level}"/> <attribute name='exception' layout='${exception}' /> <attribute name='request' encode='false' > <layout type='JsonLayout'> <attribute name="aspnet-request-ip" layout="${aspnet-request-ip}"/> <attribute name="aspnet-Request-Url" layout="${aspnet-Request-Url}"/> <attribute name="aspnet-Request-Host" layout="${aspnet-Request-Host}"/> <attribute name="aspnet-Request-Method" layout="${aspnet-Request-Method}"/> </layout> </attribute> </layout> </target> <!--Console Target for hosting lifetime messages to improve Docker / Visual Studio startup detection --> <target xsi:type="ColoredConsole" name="lifetimeConsole" layout="${MicrosoftConsoleLayout}" > <highlight-row condition="level == LogLevel.Error" backgroundColor="NoChange" foregroundColor="NoChange"/> <highlight-row condition="level == LogLevel.Fatal" backgroundColor="NoChange" foregroundColor="NoChange"/> <highlight-row condition="level == LogLevel.Warn" backgroundColor="NoChange" foregroundColor="NoChange"/> <highlight-word text="info" condition="level == LogLevel.Info" backgroundColor="NoChange" foregroundColor="Green" ignoreCase="true" regex="info" wholeWords="true" compileRegex="true"/> <highlight-word text="warn" condition="level == LogLevel.Warn" backgroundColor="NoChange" foregroundColor="Yellow" ignoreCase="true" regex="warn" wholeWords="true" compileRegex="true"/> <highlight-word text="fail" condition="level == LogLevel.Error" backgroundColor="NoChange" foregroundColor="Red" ignoreCase="true" regex="fail" wholeWords="true" compileRegex="true"/> <highlight-word text="crit" condition="level == LogLevel.Fatal" backgroundColor="NoChange" foregroundColor="DarkRed" ignoreCase="true" regex="crit" wholeWords="true" compileRegex="true"/> </target> </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="*" minlevel="Trace" writeTo="lifetimeConsole" /> <!--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" /> <!--json格式--> <logger name="*" minlevel="Trace" writeTo="jsonfile" /> <logger name="*" minlevel="Trace" writeTo="ownFile-web" /> </rules> </nlog>

这里的appsettings.jsons配置如下

{ "Logging": { "LogLevel": { "Default": "Trace", "Microsoft.AspNetCore": "Trace" } }, "AllowedHosts": "*" }

根据配置,看看具体的实现效果:

控制台结果

net开发笔记(.NET6之MiniAPI十九)(1)

2022-02-20.json结果

net开发笔记(.NET6之MiniAPI十九)(2)

nlog-AspNetCore-own-2022-02-20.log结果

net开发笔记(.NET6之MiniAPI十九)(3)

nlog-AspNetCore-all-2022-02-20.log结果

net开发笔记(.NET6之MiniAPI十九)(4)

,