.net core 序列日志Serilog
Serilog 是一个用于 .NET 应用程序的诊断日志库。它易于设置,具有干净的 API,并且可以在所有最新的 .NET 平台上运行。尽管即使在最简单的应用程序中它也很有用,但 Serilog 对结构化日志记录的支持在检测复杂、分布式和异步应用程序和系统时大放异彩。
与 .NET 的许多其他库一样,Serilog 为文件、控制台和许多其他输出提供诊断日志记录。
var log = new LoggerConfiguration()
.WriteTo.Console()
.WriteTo.File("log.txt")
.CreateLogger();
log.Information("Hello, Serilog!");
与其他日志库不同,Serilog 是从头开始构建的,用于记录结构化事件数据。
var position = new { Latitude = 25, Longitude = 134 };
var elapsedMs = 34;
log.Information("Processed {@Position} in {Elapsed} ms", position, elapsedMs);
Serilog 使用消息模板,这是一种简单的 DSL,它使用命名参数和位置参数扩展 .NET 格式字符串。Serilog 不会立即将事件格式化为文本,而是捕获与每个命名参数关联的值。
上面的示例在日志事件中记录了两个属性Position
和。前面Elapsed
的操作符告诉 Serilog序列化传入的对象,而不是使用. Serilog 对结构化事件数据的深入而丰富的支持开辟了使用传统记录器时不可用的大量诊断可能性。@
Position
ToString()
例如,呈现为JSON 格式的这些属性会出现在时间戳、级别和消息旁边,例如:
{"Position": {"Latitude": 25, "Longitude": 134}, "Elapsed": 34}
能够记录结构化事件数据的后端使日志搜索和分析成为可能,而无需日志解析或正则表达式。
支持结构化数据并不意味着放弃文本:当 Serilog 将事件写入文件或控制台时,模板和属性会呈现为友好的人类可读文本,就像传统的日志库会产生一样:
09:14:22 [INF] Processed {"Latitude": 25, "Longitude": 134} in 34 ms.
特征
- 社区支持并积极开发
- 基于格式的日志 API,具有熟悉的级别,如
Debug
、Information
、Warning
、Error
等 - 可发现的 C# 配置语法和可选的XML或JSON配置支持
- 启用时高效,关闭日志记录级别时开销极低
- 一流的 .NET Core 支持,包括与 ASP.NET Core 的丰富集成
- 支持全面的接收器,包括文件、控制台、本地和基于云的日志服务器、数据库和消息队列
- 使用上下文信息对日志事件进行复杂的丰富,包括范围 (
LogContext
) 属性、线程和进程标识符以及特定于域的相关 ID,例如HttpRequestId
- 零共享状态
Logger
对象,具有可选的全局静态Log
类 LogEvent
格式不可知的日志管道,可以以纯文本、JSON、内存对象(包括Rx 管道)和其他格式发出事件
入门
Serilog 是从 NuGet 安装的。要查看日志事件,还需要安装一个或多个接收器,这里我们将使用漂亮打印控制台接收器和滚动文件集:
dotnet add package Serilog
dotnet add package Serilog.Sinks.Console
dotnet add package Serilog.Sinks.File
![](https://img2022.cnblogs.com/blog/2550804/202208/2550804-20220831141349611-1575639932.png)
设置 Serilog 的最简单方法是使用静态Log
类。ALoggerConfiguration
用于创建和分配默认记录器。
using Serilog;
public class Program
{
public static void Main()
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.WriteTo.Console()
.WriteTo.File("log.txt",
rollingInterval: RollingInterval.Day,
rollOnFileSizeLimit: true)
.CreateLogger();
Log.Information("Hello, Serilog!");
Log.CloseAndFlush();
}
}
如被动接受设备数据:
var deviceValue = $"dmv:{dmon.Uid},Value:{dmon.Value},Status:{dmon.Status},BoxNo:{dmon.BoxNo},Name:{dmon.Name},BoxId:{dmon.BoxId},GroupName:{dmon.GroupName},Timestamp:{dmon.Timestamp}";
Log.Information(deviceValue);
实践,从 NuGet 安装 Serilog
核心的包是 Serilog 和 Serilog.AspNetCore
建议安装 Serilog.AspNetCore,几乎包含了Serilog常用的所有包
异步写入 Serilog.Sinks.Async
写入MSSQL Serilog.Sinks.MSSqlServer
Install-Package Serilog.AspNetCore
Install-Package Serilog
Install-Package Serilog.Sinks.Async
Install-Package Serilog.Sinks.MSSqlServer
日志输出
输出到控制台
1 using Serilog;
2 using System;
3 using System.Collections.Generic;
4 using System.ComponentModel;
5 using System.IO;
6 using System.Linq;
7
8 namespace NetCoreConsoleApp
9 {
10 class Program
11 {
12 static void Main(string[] args)
13 {
14 Log.Logger = new LoggerConfiguration()
15 .WriteTo.Console() //输出到控制台
16 .CreateLogger();
17
18 Log.Information("log");
19
20 }
21
22
23 }
24 }
输出到本地日志文件
WriteTo.File详解(日志默认路径为当前程序路径)
path:默认路径是程序的bin目录+path参数,当然也可以写绝对路径,只需要写入参数就可以了
rollingInterval:创建文件的类别,可以是分钟,小时,天,月。 此参数可以让创建的log文件名默认 + 时间。例如:log20191219.log
outputTemplate:日志模板,可以自定义
retainedFileCountLimit:设置日志文件个数最大值,默认31,意思就是只保留最近的31个日志文件,等于null时永远保留文件
1 using Serilog;
2 using System;
3 using System.Collections.Generic;
4 using System.ComponentModel;
5 using System.IO;
6 using System.Linq;
7
8 namespace NetCoreConsoleApp
9 {
10 class Program
11 {
12 static void Main(string[] args)
13 {
14 /*
15 WriteTo.File详解
16 path:默认路径是程序的bin目录+path参数,当然也可以写绝对路径,只需要写入参数就可以了
17 rollingInterval:创建文件的类别,可以是分钟,小时,天,月。 此参数可以让创建的log文件名 + 时间。例如log20191219.log
18 outputTemplate:日志模板,可以自定义
19 retainedFileCountLimit:设置日志文件个数最大值,默认31,意思就是只保留最近的31个日志文件,等于null时永远保留文件
20 */
21
22
23 string SerilogOutputTemplate = "{NewLine}{NewLine}Date:{Timestamp:yyyy-MM-dd HH:mm:ss.fff}{NewLine}LogLevel:{Level}{NewLine}Message:{Message}{NewLine}{Exception}" + new string('-', 100);
24
25 Log.Logger = new LoggerConfiguration()
26 .MinimumLevel.Debug() // 所有Sink的最小记录级别
27 .WriteTo.Console() //输出到控制台
28 .WriteTo.File("00_Logs\\log.log", //$"{AppContext.BaseDirectory}00_Logs\log.log"
29 rollingInterval: RollingInterval.Day,
30 outputTemplate: SerilogOutputTemplate
31 //,retainedFileCountLimit: 31
32 )
33 .CreateLogger();
34 Log.Information("log");
35 }
36 }
37 }
输出到本地日志文件(异步)
需要Serilog.Sinks.Async包,github详解路径:https://github.com/serilog/serilog-sinks-async
1 using Serilog;
2
3 namespace NetCoreConsoleApp
4 {
5 class Program
6 {
7 static void Main(string[] args)
8 {
9 //github详解路径:https://github.com/serilog/serilog-sinks-async
10
11 Log.Logger = new LoggerConfiguration()
12 .WriteTo.Async(a => a.File("00_Logs\\log.log", rollingInterval: RollingInterval.Day))
13 .CreateLogger();
14 Log.Information("log");
15 Log.CloseAndFlush();
16 }
17 }
18 }
不同的日志级别输出到不同的文件夹下
using Serilog;
using Serilog.Events;
using System;
namespace NetCoreConsoleApp
{
class Program
{
static void Main(string[] args)
{
string LogFilePath(string LogEvent) => $@"{AppContext.BaseDirectory}00_Logs\{LogEvent}\log.log";
string SerilogOutputTemplate = "{NewLine}{NewLine}Date:{Timestamp:yyyy-MM-dd HH:mm:ss.fff}{NewLine}LogLevel:{Level}{NewLine}Message:{Message}{NewLine}{Exception}" + new string('-', 50);
Log.Logger = new LoggerConfiguration()
.Enrich.FromLogContext()
.WriteTo.Console()
.MinimumLevel.Debug() // 所有Sink的最小记录级别
.WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Debug).WriteTo.File(LogFilePath("Debug"), rollingInterval: RollingInterval.Day, outputTemplate: SerilogOutputTemplate))
.WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Information).WriteTo.File(LogFilePath("Information"), rollingInterval: RollingInterval.Day, outputTemplate: SerilogOutputTemplate))
.WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(p => p.Level == LogEventLevel.Warning).WriteTo.File(LogFilePath("Warning"), rollingInterval: RollingInterval.Day, outputTemplate: SerilogOutputTemplate