.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、注册服务配置写入文件

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、随便找个控制器在构造函数注入后即可使用

  [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个路径,对应不同的日志类型

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、(推荐,不设也行)设置好模板

string template = "{NewLine}时间:{Timestamp:yyyy-MM-dd HH:mm:ss.fff}{NewLine}等级:{Level}{NewLine}来源:{SourceContext}{NewLine}具体消息:{Message}{NewLine}{Exception}";

  3、具体配置

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 文件

<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

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()
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)//排除Microsoft日志
.MinimumLevel.Debug()
.Enrich.WithThreadId()
.Enrich.FromLogContext()
.WriteTo.Console(outputTemplate: OUTPUT_TEMPLATE)
.WriteTo.File("logs/app.txt" , rollingInterval: RollingInterval.Day , outputTemplate: OUTPUT_TEMPLATE)
.CreateLogger();
try {
Log.Information("Starting web host");
var builder = WebApplication .CreateBuilder(args);
builder.Host.UseSerilog(Log.Logger, dispose: true); // Add services to the container
. builder.Services.AddControllers();
var app = builder.Build(); // Configure the HTTP request pipeline
. app.UseAuthorization();
app.UseSerilogRequestLogging();
app.MapControllers();
app.Run();
} catch (Exception ex)
{ Log.Fatal(ex, "Host terminated unexpectedly"); }
finally { Log.CloseAndFlush(); }

  

 

posted @ 2024-06-27 15:18  yinghualeihenmei  阅读(7)  评论(0编辑  收藏  举报