Serilog简单使用指南
Serilog是.net平台上的一个记录程序诊断信息的日志框架,主要工作内容是决定将日志内容以何种格式保存到外部存储介质中(可以是控制台、文件、数据库和第三方日志服务)。除此之外还有NLog和Log4Net等类似的日志框架。
Serilog的优点是在云服务厂商中有支持Serilog的插件可以直接使用,而且支持将日志信息直接输出到第三方的日志服务中(ELK、ES等);而且支持输出日志内容到多种外部存储介质中;支持记录结构化的数据(将对象以“属性名称:属性值”键值对的形式记录到日志中),支持配置消息输出模板等。
本文主要介绍Serilog的简单使用,如果想深入学习的话,建议去看看官方文档。
1、引入Serilog包;
根据想把日志内容输出到哪里引用对应的Serilog.Sink.XXX包;
如果想使用异步的写入日志可以引入Serilog.Sinks.Async包;
(有个Serilog.AspNetCore的包是专门用于ASP.NET Core应用的,但在此处我还是使用一般的包,反正它也同样适用 .NET CORE。)
2、在Program.cs文件中进行配置:
Serilog支持使用代码的方式进行配置;也支持通过配置文件(appsetting.json、web.config)的方式进行配置(需要安装额外的Nuget包 Serilog.Settings.Configuration),但是这种方式并不是所有Serilog的功能都支持,因为是简单使用,故此出只介绍使用代码进行配置。
(1)最简单的方式是使用全局静态类Log进行配置,只需配置一次就可以在应用全局使用同一个Logger来进行日志记录:
1 Log.Logger = new LoggerConfiguration() 2 .MinimumLevel.Debug() 3 .WriteTo.Console() 4 .WriteTo.File("logs/myapp.txt", rollingInterval: RollingInterval.Day) 5 .CreateLogger();
上面的代码使用LoggerConfiguration.CreateLogger()创建了一个静态的、全局可访问的logger;
①使用 MinimumLevel.Debug() 设置了最低日志级别,Tracer\Verbose<Debug<Information<Warning<Error<Fatal,低于该级别的日志内容将不会被记录;
②使用WriteTo.Console()设置日志内容输出到控制台中;
③使用WriteTo.File 设置日志内容输出到文件中,方法参数path可以设置日志文件所在的路径、
rollingInterval设置日志文件生成间隔(每天、每小时、每月生成一个日志文件,避免单个日志文件过大)、
rollOnFileSizeLimit设置每个日志文件的大小限制、
restrictedToMinimumLevel 单独设置该sink(接收器:控制台接收器、文件接收器等)的最低日志级别,注意级别必须比logger上MinimumLevel设置高、
outputTemplate 设置记录日志内容的输出模板,代表日志内容以何种格式输出到外部;默认为"{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}"。
(2)使用依赖注入的方式来进行配置,通过使用AddSerilog方法注入相关的服务,然后在需要记录日志的地方,通过ILogger<T>的方式注入使用;
1 //注册serilog 2 builder.Services.AddSerilog(cfg => 3 { 4 cfg.Enrich.With(new ThreadIdEnricher()); 5 cfg.MinimumLevel.Information() 6 .WriteTo.File("Logs/log.txt", rollingInterval: RollingInterval.Day, restrictedToMinimumLevel: LogEventLevel.Information) 7 .WriteTo.File("Logs/Errors/log.txt", rollingInterval: RollingInterval.Day, restrictedToMinimumLevel: LogEventLevel.Error); 8 });
产生的日志内容如下:
3、Serilog中包含有中间件,对每个http request都会进行更加智能的日志记录,它对.NET CORE内置的request日志记录操作进行了相应的优化,把多个日志事件合并到一起,减少了资源的占用。
1 var app = builder.Build(); 2 3 app.UseSerilogRequestLogging(); // <-- Add this line 4 5 // Other app configuration
4、官方更推荐使用消息模板的方式记录日志内容,类似 logger.Information("This is a message from {name}","ZhangSan");
Serilog的消息模板是对.NET 格式字符串标准的超集,所以任何string.format可以接受的字符串格式,都适用于消息模板。
在Serilog内部对每个模板进行解析和缓存(有大小上限设置),类似下面的写法将字符串变量当作字符串传入,会降低性能和浪费缓存;
1 // Don't: 2 Log.Information("The time is " + DateTime.Now);
与之相对应的是,在记录日志消息的时候我们应该使用模板属性包含变量的方式,如下:
1 // Do: 2 Log.Information("The time is {Now}", DateTime.Now);
尽量使用PascalCase命名方式来命名模板属性以保持与Serilog的生态一致;更多的消息模板的内容可以查看 https://messagetemplates.org/
之后就可以在需要记录日志的地方使用 Log.Logger.Information 之类的方式直接使用;
5、两阶段初始化;
如果在ASP.NET CORE应用启动期间发生了异常,Serilog是没办法记录异常信息的,
第一种解决方法是可以采用首先使用全局静态类Log进行简单配置,然后用try catch语句将program.cs文件的代码包裹起来,记录应用启动期间发生的异常信息,最后使用 builder.Services.AddSerilog() 注入服务和配置信息;
但缺点是ASP.NET CORE应用的服务,包括appsettiong.json配置文件和依赖注入在此期间都还不可用。
1 using Serilog; 2 3 Log.Logger = new LoggerConfiguration() 4 .WriteTo.Console() 5 .CreateLogger(); 6 7 try 8 { 9 Log.Information("Starting web application"); 10 11 var builder = WebApplication.CreateBuilder(args); 12 builder.Services.AddSerilog(configuration=>{...... }); // <-- Add this line 13 14 var app = builder.Build(); 15 app.MapGet("/", () => "Hello World!"); 16 17 app.Run(); 18 } 19 catch (Exception ex) 20 { 21 Log.Fatal(ex, "Application terminated unexpectedly"); 22 } 23 finally 24 { 25 Log.CloseAndFlush(); 26 }
第二个解决方案是两阶段初始化;
在应用启动的时候,创建一个bootstrap的logger来记录启动期间异常信息,一旦启动完成后它立马会被配置好的logger替代;
1 using Serilog; 2 using Serilog.Events; 3 4 Log.Logger = new LoggerConfiguration() 5 .MinimumLevel.Override("Microsoft", LogEventLevel.Information) 6 .Enrich.FromLogContext() 7 .WriteTo.Console() 8 .CreateBootstrapLogger(); // <-- Change this line!
之后可以在注入Serilog服务的时候设置完整的配置信息,
1 builder.Services.AddSerilog((service, cfg) => 2 { 3 //在此处对Serilog进行配置 4 5 //添加线程id 6 cfg.Enrich.With(new ThreadIdEnricher()); 7 8 //重载AspNetCore内部默认的最低日志级别 9 cfg.MinimumLevel.Override("Microsoft.AspNetCore.Hosting", LogEventLevel.Warning); 10 cfg.MinimumLevel.Override("Microsoft.AspNetCore.Mvc", LogEventLevel.Warning); 11 cfg.MinimumLevel.Override("Microsoft.AspNetCore.Routing", LogEventLevel.Warning); 12 13 cfg.MinimumLevel.Information() 14 .WriteTo.File("Logs/log-.txt", rollingInterval: RollingInterval.Day, restrictedToMinimumLevel: LogEventLevel.Information, outputTemplate: _outputTemplate) 15 .WriteTo.File("Logs/Errors/log-.txt", rollingInterval: RollingInterval.Day, restrictedToMinimumLevel: LogEventLevel.Error, outputTemplate: _outputTemplate); 16 });
注意,之后配置的logger会完全替代掉之前创建的bootstraplogger,如果你也想在控制台输出日志内容的话,必须重新添加.writeToConsole配置;
以上就是本人对于Serilog这个日志记录框架简单使用的一点不成熟的见解,其中有可能包含错误的地方,希望各位指正和包含。
引用文献:
https://github.com/serilog/serilog-aspnetcore#serilogaspnetcore---
https://github.com/serilog/serilog/wiki/Getting-Started