.Net Core日志记录之第三方框架Serilog
原文链接:https://www.jb51.net/article/251755.htm
https://blog.csdn.net/hiose89/article/details/125012881
这篇文章介绍了.Net Core日志记录之第三方框架Serilog
一、前言
对内置日志系统的整体实现进行了介绍之后,可以通过使用内置记录器来实现日志的输出路径。而在实际项目开发中,使用第三方日志框架(如: Log4Net、NLog、Loggr、Serilog、Sentry 等)来记录也是非常多的。首先一般基础的内置日志记录器在第三方日志框架中都有实现,然后第三方日志框架在功能上更加强大和丰富,能满足我们更多的项目分析和诊断的需求。
所以在这一篇中,我们将介绍第三方日志记录提供程序——Serilog
二、回顾
系统内置日志系列:
这个时候我们发现,其实在asp.net core中已经内置了日志系统,并提供了各种内置和第三方日志记录提供程序的日志记录接口,在进行应用开发中,可以进行统一配置,并且利用第三方日志框架相结合,更加有效的实现日志记录。所以在这个系列中,主要是对内置日志记录系统的学习,以及后续使用第三方日志框架集成我们需要的日志系统。
在新建项目成功之后,我们都会看到一个命名为appsettings.json配置,打开一看,短短的几行配置,
然后启动运行的时候,程序会在调试面板和控制台中分别输出显示来源如下:
在控制台中:
在调试面板中:
这里的日志配置,在系统中到底都起来什么作用?让我们来一探究竟吧!
三、开始
3.1 默认配置
我们查看源代码发现,在程序的入口点中发现,在初始化时候,通过CreateDefaultBuilder方法来实现日志记录的默认配置。
从Serilog的官方介绍中,我们可以发现 其框架是.net中的诊断日志库,可以在所有的.net平台上运行。支持结构化日志记录,对复杂、分布式、异步应用程序的支持非常出色。
Serilog是基于日志事件(log events),而不是日志消息(log message)。可以将日志事件格式化为控制台的可读文本或者将事件化为JSON格式。应用程序中的日志语句会创建LogEvent对象,而连接到管道的接收器(sinks)会知道如何记录它们。(接收器 包括各种终端、控制台、文本、SqlServer、ElasticSearch等等可用的列表)
为什么要使用Serilog?
Serilog比NLog 功能更为强大,能支持结构化的消息,不像NLog扁平和繁琐,配置也更加方便。支持代码配置、json、xml。但我觉得用代码配置就挺好,nlog就是XML配置太麻烦。
1、nuget 安装
Serilog.AspNetCore 会自动安装依赖项
2、(可选,异步写入)nuget 安装 Serilog.Sinks.Async
3、注册服务配置写入文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | builder.Services.AddLogging(bulid => { Log.Logger = new LoggerConfiguration() .MinimumLevel.Debug() .Enrich.FromLogContext() WriteTo.Async(config => config.File( "d://.log" , rollingInterval: RollingInterval.Day, fileSizeLimitBytes: 1024 * 1024 * 10, //单位字节 不配置时默認1GB retainedFileCountLimit: 10, //保留最近多少個文件 不配置时默認31個 rollOnFileSizeLimit: true , //超過文件大小時 自動創建新文件 shared: true ) )) .CreateLogger(); bulid.AddSerilog(); }); |
4、随便找个控制器在构造函数注入后即可使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | [HttpGet(Name = "GetWeatherForecast" )] public IEnumerable<WeatherForecast> Get() { while ( true ) { _logger.LogInformation( "ASDASDASDASDASDADSASDASDASDASDASDADSASDASDASDASDASDADSASDASDASDASDASDADS" ); } return Enumerable.Range(1, 5).Select(index => new WeatherForecast { Date = DateTime.Now.AddDays(index), TemperatureC = Random.Shared.Next(-20, 55), Summary = Summaries[Random.Shared.Next(Summaries.Length)] }) .ToArray(); } |
打开d盘找到即可看见日志文本
输出格式如下:
2022-05-28 00:12:35.949 +08:00 [INF] ASDASDASDASDASDADSASDASDASDASDASDADSASDASDASDASDASDADSASDASDAS
(推荐)更高级一些的详细配置,建议把log等级分开配置 推荐配置4种
1、设置好4个路径,对应不同的日志类型
1 2 3 4 | string infoPath = Directory.GetCurrentDirectory() + @"\logs\info\.log" ; ; string waringPath = Directory.GetCurrentDirectory() + @"\logs\waring\.log" ; string errorPath = Directory.GetCurrentDirectory() + @"\logs\error\.log" ; string fatalPath = Directory.GetCurrentDirectory() + @"\logs\fatal\.log" ; |
2、(推荐,不设也行)设置好模板
1 | string template = "{NewLine}时间:{Timestamp:yyyy-MM-dd HH:mm:ss.fff}{NewLine}等级:{Level}{NewLine}来源:{SourceContext}{NewLine}具体消息:{Message}{NewLine}{Exception}" ; |
3、具体配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | builder.Services.AddLogging(bulid => { Log.Logger = new LoggerConfiguration() .MinimumLevel.Information() .Enrich.FromLogContext() .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(lev => lev.Level == LogEventLevel.Information). WriteTo.Async(congfig => congfig.File( infoPath, rollingInterval: RollingInterval.Day, fileSizeLimitBytes: 1024 * 1024 * 10, //默認1GB retainedFileCountLimit: 10, //保留最近多少個文件 默認31個 rollOnFileSizeLimit: true , //超過文件大小時 自動創建新文件 shared: true , outputTemplate: template) )) //----------------------------------------------------------------------------------- .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(lev => lev.Level == LogEventLevel.Warning). WriteTo.Async(congfig => congfig.File( waringPath, rollingInterval: RollingInterval.Day, fileSizeLimitBytes: 1024 * 1024 * 10, retainedFileCountLimit: 10, rollOnFileSizeLimit: true , shared: true , outputTemplate: template) )) //----------------------------------------------------------------------------------- .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(lev => lev.Level == LogEventLevel.Error). WriteTo.Async(congfig => congfig.File( errorPath, rollingInterval: RollingInterval.Day, fileSizeLimitBytes: 1024 * 1024 * 10, retainedFileCountLimit: 10, rollOnFileSizeLimit: true , shared: true , outputTemplate: template) )) //----------------------------------------------------------------------------------- .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(lev => lev.Level == LogEventLevel.Fatal). WriteTo.Async(congfig => congfig.File( fatalPath, rollingInterval: RollingInterval.Day, fileSizeLimitBytes: 1024 * 1024 * 10, retainedFileCountLimit: 10, rollOnFileSizeLimit: true , shared: true , outputTemplate: template) )) //----------------------------------------------------------------------------------- .CreateLogger(); bulid.AddSerilog(); |
只做了基本配置,不够用的话,具体更多配置或更高级用法自行查询官网。
https://github.com/serilog
疑问
Serilog 在 ASP.NET Core 5 中用的好好的,原项目升级到6也没有问题,可是为什么新建ASP.NET Core 6.0项目,使用不了"UseSerilog()"呢?
解释
因为6使用了"new minimal hosting model",5上面"UseSerilog()"是扩展在"IHostBuilder"上面的,而6上使用的是"WebApplicationBuilder",所以"UseSerilog()"自然就无法使用了,但是"builder.Host"上是"IHostBuilder"类型,可以把"UseSerilog()"用在"builder.Host"上,不建议使用"builder.WebHost"哦。
正确示例
.csproj 文件
1 2 3 4 5 6 7 | <ItemGroup> <PackageReference Include= "Serilog" Version= "2.10.0" /> <PackageReference Include= "Serilog.AspNetCore" Version= "4.1.0" /> <PackageReference Include= "Serilog.Enrichers.Thread" Version= "3.1.0" /> <PackageReference Include= "Serilog.Sinks.Console" Version= "4.0.0" /> <PackageReference Include= "Serilog.Sinks.File" Version= "5.0.0" /> </ItemGroup> |
Program.cs
1 2 3 4 | using Serilog; const string OUTPUT_TEMPLATE = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} <{ThreadId}> [{Level:u3}] {Message:lj}{NewLine}{Exception}" ; Log.Logger = new LoggerConfiguration()<br>.MinimumLevel.Override( "Microsoft" , LogEventLevel.Information) //排除Microsoft日志.MinimumLevel.Debug()<br>.Enrich.WithThreadId()<br>.Enrich.FromLogContext() <br>.WriteTo.Console(outputTemplate: OUTPUT_TEMPLATE) <br>.WriteTo.File("logs/app.txt" , rollingInterval: RollingInterval.Day , outputTemplate: OUTPUT_TEMPLATE) <br>.CreateLogger(); <br>try {<br>Log.Information("Starting web host"); <br>var builder = WebApplication .CreateBuilder(args); <br>builder.Host.UseSerilog(Log.Logger, dispose: true); // Add services to the container<br>. builder.Services.AddControllers(); <br>var app = builder.Build(); // Configure the HTTP request pipeline<br>. app.UseAuthorization(); <br>app.UseSerilogRequestLogging(); <br>app.MapControllers(); <br>app.Run(); <br>} catch (Exception ex) <br>{ Log.Fatal(ex, "Host terminated unexpectedly"); } <br>finally { Log.CloseAndFlush(); } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2023-06-27 sql server DATEPART() 函数的使用(注意防止入坑)
2023-06-27 浅谈asp.net中的AsyncPostBackTrigger
2023-06-27 asp.net中Timer定时器在web中无刷新的使用
2023-06-27 UpdatePanel控件的使用(实现局部刷新,简单例子)