Serilog的在.NetCore的使用指南
Serilog是使用人数较多的一个日志框架,完美支持.NetCore的开发环境。
引入nuget包:Serilog.AspNetCore,该nuget包会根据项目的.net版本自动安装需要的其他nuget包,当然你也可以按照自己的需求进行单独安装,或者需要其它功能的时候安装其他需要的包。

对Serilog的配置可以在程序启动阶段使用FluentAPI的方式进行配置,也可以提前把配置信息写在配置文件中,在程序启动的时候直接加载配置,在这里推荐使用后者,这样在需要修改配置的时候只需要修改相应的配置文件的配置项即可,而无需重新编译和发布项目。
以下是在appSettings.json文件中的Serilog的配置信息,默认使用Serilog节点下配置。
1 { 2 "Serilog": { 3 "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ], 4 "MinimumLevel": { 5 "Default": "Information", 6 "Override": { 7 "Microsoft": "Information" 8 } 9 }, 10 "WriteTo": [ 11 { 12 "Name": "Console" 13 }, 14 { 15 "Name": "File", 16 "Args": { 17 "path": "App_Logs/log-.txt", 18 "restrictedToMinimumLevel": "Warning", 19 "rollingInterval": "Day", 20 "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}{NewLine} {Level:u3}]{NewLine} {SourceContext} - {Message:lj}{NewLine}{Exception}" 21 } 22 }, 23 { 24 "Name": "File", 25 "Args": { 26 "path": "App_Logs/Errors/log-.txt", 27 "restrictedToMinimumLevel": "Error", 28 "rollingInterval": "Day", 29 "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}{NewLine} {Level:u3}]{NewLine} {SourceContext} - {Message:lj}{NewLine}{Exception}" 30 } 31 } 32 ] 33 } 34 }
接着是在程序启动的时候,引入Serilog,
1、用于在程序启动阶段,Serilog还没有加载配置的时候,记录相应的日志信息输出到控制台中;
2、配置Serilog接管整个项目的日志,对比红框3的好处是接管的更加彻底,红框3只是把Serilog日志服务注册到DI容器中,替换.NET自带的ILogger,接管的是运行时的日志,推荐使用红框2的方式,因为它覆盖面更加全面。

最后就是在需要使用日志服务的地方,使用依赖注入的方式获取日志服务并进行日志记录。

一些注意点:
Serilog的过滤器Filter能更加灵活的控制如何记录日志,分Sink级别过滤器和全局过滤器,比如让一个日志文件只记录 Warning 级别,不包含Error/Fatal/Info级别的日志内容。最简单的实现方式是在配置文件中把相应的日志接收器Sink的最大 restrictedToMaximumLevel 和最小日志级别 restrictedToMinimumLevel 设置相同即可,无需安装额外的nuget包,如下:

1 // 仅记录 Warning(最小=最大) 2 "restrictedToMinimumLevel": "Warning", 3 "restrictedToMaximumLevel": "Warning" 4 5 // 记录 >= Error(Error + Fatal) 6 "restrictedToMinimumLevel": "Error" 7 8 //记录 <= Error 9 "restrictedToMaximumLevel": "Warning"
但当需求变得更加复杂的时候,这个就不能满足我们了,比如我只想记录指定命名空间或者类下面的日志内容,或者消息内容包含关键字等等,就需要安装额外的nuget包来实现了;
安装 Serilog.Filters.Expressions nuget包,然后修改配置文件,
1 "Filter": [ 2 { 3 "Name": "ByIncludingOnly", // 只保留满足条件的日志(最常用),ByExcluding 则是排除满足条件的日志 4 "Args": { 5 "expression": "过滤表达式" 6 } 7 } 8 ]
可以加在某个日志接收器Sink下面(WriteTo内部)只对该日志接收器Sink生效(Sink级别),也可以加在Serilog根节点处全局生效,常见的过滤表达式如下:
| 需求 | 表达式 |
|---|---|
| 只记录 Warning | @Level = 'Warning' |
| 只记录 Error/Fatal | @Level in ['Error', 'Fatal'] |
| 只记录某个命名空间 | StartsWith(SourceContext, 'API.Controllers') |
| 排除系统日志 | not StartsWith(SourceContext, 'Microsoft') |
| 消息包含关键词 | Contains(Message, '订单') |
| 组合条件 | @Level = 'Warning' and StartsWith(SourceContext, 'API.Services') |
关键术语解释
@Level:日志级别(Debug/Info/Warning/Error/Fatal)SourceContext:日志来源(命名空间 / 类名,如API.Controllers.BookController)Message:日志文本内容Exception:异常信息Properties:自定义属性
接下来介绍的是Serilog的Enricher(增强器),它能在日志中统一加入额外的内容,使日志内容更加丰富,比如在日志内容中加入线程ID、请求ID、请求客户端信息、当前环境等等,而不需要我们在每个日志记录的地方自己手动加入,方便我们更好的追踪和排查日志。
1 //原本的日志: 2 [INF] 查询书籍成功 3 4 //加了 Enricher 后: 5 [INF] [线程:1] [机器:DESKTOP-XXX] [环境:Development] [请求ID:abc123] 查询书籍成功
为了使用这些Enricher,需要安装额外的nuget包,并在配置文件的Serilog根节点中的Enricher节点中加入需要使用的Enricher:

线程ID(ThreadId)、线程名称(ThreadName)和环境有关的信息(MachineName、EnvironmentUserName、EnvironmentName) 需要安装 Serilog.Enrichers.Thread 和 Serilog.Enrichers.Environment nuget包;client IP、Correlation Id, HTTP request headers、user claims则需要安装 Serilog.Enrichers.ClientInfo nuget包。
最后,如果你添加了对应的Enricher但是却没有自动添加对应信息到日志中,可能是需要你手动把额外信息设置到Sink的outputTemplate中(即在对应日志接收器的输出模板中设置输出额外信息);

此外,Serilog 根节点下的 using 节点是 显式指定要加载的插件程序集,确保 Sink、Enricher、Filter 能被正确加载,虽然在 ASP.NET Core 中不写也能用,但写上更安全、更规范、更符合官方标准。
以上仅是本人在学习Serilog日志框架过程中的一些浅显见解,也许会有错漏的地方,希望与各位共勉

浙公网安备 33010602011771号