.NET Core开发实战(第20课:结构化日志组件Serilog:记录对查询分析友好的日志)--学习笔记

20 | 结构化日志组件Serilog:记录对查询分析友好的日志

以前讲解的日志框架,记录的日志都是文本,并且是非结构化的,这样一串串文本实际上不利于咱们去作分析git

结构化的日志它的好处就显而易见,它可让咱们更易于去检索,更易于与现有的分析系统进行结合github

结构化日志的主要场景:web

一、实现日志告警json

二、实现上下文的关联:能够在日志系统里面对一段业务逻辑输出的日志进行分析微信

三、实现与追踪系统集成:在调用链的系统里面看到有问题的状况下,能够追踪到调用链过程当中间的全部的日志信息架构

源码连接:
https://github.com/witskeeper/geektime/tree/master/samples/LoggingSerilogDemoapp

这里建立的依然是一个默认的 ASP.NET Core 的工程框架

引用包:Serilog.AspNetCoredom

这个包实际上依赖了 Serilog 不少的内置的包ide

好比核心的 Serilog (2.8.0)

配置 Serilog.Settings.Configuration (3.1.0)

Console 的输出 Serilog.Sinks.Console (3.1.1)

Debug 的输出 Serilog.Sinks.Debug (1.0.1)

File 的输出 Serilog.Sinks.File (4.0.0)

咱们在 Program 这里提早读取一下配置,而后传递给 Serilog 的初始化过程,这里咱们把 Main 函数进行了稍微的改造,以让 Serilog 能够接替整个默认的日志记录框架

namespace LoggingSerilogDemo
{
public class Program
{
// 读取配置
public static IConfiguration Configuration { get; } = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true)
.AddEnvironmentVariables()
.Build();

public static int Main(string[] args)
{
// 将配置传递给 Serilog 的初始化过程
Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(Configuration)
.MinimumLevel.Debug()
.Enrich.FromLogContext()
.WriteTo.Console(new RenderedCompactJsonFormatter())
.WriteTo.File(formatter: new CompactJsonFormatter(), "logs\\myapp.txt", rollingInterval: RollingInterval.Day)
.CreateLogger();
try
{
Log.Information("Starting web host");
CreateHostBuilder(args).Build().Run();
return 0;
}
catch (Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly");
return 1;
}
finally
{
Log.CloseAndFlush();
}
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.UseSerilog(dispose: true);// dispose 设置为 true,它就会在退出时帮咱们释放咱们的日志对象
}
}

启动程序,输出以下:

{"@t":"2020-03-08T15:47:40.2569100Z","@m":"Starting web host","@i":"4872fd06"}
{"@t":"2020-03-08T15:47:44.1978171Z","@m":"Get 随机建立数据","@i":"6936e72c","SourceContext":"LoggingSerilogDemo.Controllers.WeatherForecastController","ActionId":"8d8ebb60-2211-4acb-bc91-a079be45a689","ActionName":"LoggingSerilogDemo.Controllers.WeatherForecastController.Get (LoggingSerilogDemo)","RequestId":"0HLU3F052RUUN:00000001","RequestPath":"/weatherforecast","SpanId":"|99917a4d-4ccf47636d09b066.","TraceId":"99917a4d-4ccf47636d09b066","ParentId":""}

能够看到每一行都是一个 json,也就是将日志输出为 json 格式,这就意味着能够在整个日志系统里面以 json 的格式去检索数据,好比 SourceContext 就是 Logger 的 name

它还记录了请求上下文,而且输出了 RequestId,SpanId,TraceId,ParentId

RequestId 与 SpanId 的做用就是与追踪系统能够结合

咱们记录的日志的方式其实是与以前是同样的,Controller 里面仍是注入了 ILogger,依然使用 ILogger 来记录日志

namespace LoggingSerilogDemo.Controllers
{
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

private readonly ILogger<WeatherForecastController> _logger;

public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}

[HttpGet]
public IEnumerable<WeatherForecast> Get()
{

_logger.LogInformation("Get 随机建立数据");
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray();

}
}
}

也就是说能够经过简单的配置和几行代码的设置就能够替换官方提供的日志框架,让咱们具有记录结构化日志的能力

咱们刚才看到日志输出到 Console,同时输出到文件,能够看到 logs 目录已经产生了一个 myapp20200308.txt 文件

{"@t":"2020-03-08T15:47:40.2569100Z","@mt":"Starting web host"}
{"@t":"2020-03-08T15:47:44.1978171Z","@mt":"Get 随机建立数据","SourceContext":"LoggingSerilogDemo.Controllers.WeatherForecastController","ActionId":"8d8ebb60-2211-4acb-bc91-a079be45a689","ActionName":"LoggingSerilogDemo.Controllers.WeatherForecastController.Get (LoggingSerilogDemo)","RequestId":"0HLU3F052RUUN:00000001","RequestPath":"/weatherforecast","SpanId":"|99917a4d-4ccf47636d09b066.","TraceId":"99917a4d-4ccf47636d09b066","ParentId":""}

这个文件能够看到每一行是一条日志,每一条日志都是一个 json 对象,包括刚才咱们记录的 Get 随机建立数据,已经输出出来了

咱们能够调整日志级别,打开配置文件

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Error",
"System": "Information"
}
}
},
"AllowedHosts": "*"
}

Serilog 须要单独配置,它与以前的配置方式略有不一样,它须要配置最小的日志输出级别,默认是 Information

Override 是重载上面 Logging 定义的日志级别

设置 Microsoft 为 Error 以后会把 Microsoft 默认的日志输出级别过滤掉

也意味着整个的配置和输出的方式与以前是级别相似的,咱们能够把日志输出到 Console,也能够把日志输出到文件,固然实际上 Serilog 还提供了不少的这种输出的提供程序,还能够与 EFK,ELK 这种日志的套件进行集成,把日志输出到分析系统里面

相关文章

.NET Core开发实战(第19课:日志做用域:解决不一样请求之间的日志干扰)--学习笔记

.NET Core开发实战(第18课:日志框架:聊聊记日志的最佳姿式)--学习笔记(下)

.NET Core开发实战(第18课:日志框架:聊聊记日志的最佳姿式)--学习笔记(上)

.NET Core开发实战(第17课:为选项数据添加验证:避免错误配置的应用接收用户流量)--学习笔记

.NET Core开发实战(第16课:选项数据热更新:让服务感知配置的变化)--学习笔记

.NET Core开发实战(第15课:选项框架:服务组件集成配置的最佳实践)--学习笔记

.NET Core开发实战(第14课:自定义配置数据源:低成本实现定制化配置方案)--学习笔记

.NET Core开发实战(第13课:配置绑定:使用强类型对象承载配置数据)--学习笔记

.NET Core开发实战(第12课:配置变动监听)--学习笔记

.NET Core开发实战(第11课:文件配置提供程序)--学习笔记

.NET Core开发实战(第10课:环境变量配置提供程序)--学习笔记

.NET Core开发实战(第9课:命令行配置提供程序)--学习笔记

.NET Core开发实战(第8课:配置框架:让服务无缝适应各类环境)--学习笔记

.NET Core开发实战(第7课:用Autofac加强容器能力)--学习笔记(下)

.NET Core开发实战(第7课:用Autofac加强容器能力)--学习笔记(上)

.NET Core开发实战(第6课:做用域与对象释放行为)--学习笔记(下)

.NET Core开发实战(第6课:做用域与对象释放行为)--学习笔记(上)

.NET Core开发实战(第5课:依赖注入:良好架构的起点)--学习笔记(下)

.NET Core开发实战(第5课:依赖注入:良好架构的起点)--学习笔记(中)

.NET Core开发实战(第5课:依赖注入:良好架构的起点)--学习笔记(上)

.NET Core开发实战(第4课:Startup:掌握ASP.NET Core的启动过程)--学习笔记

.NET Core开发实战(第3课:.NET Core的现状、将来以及环境搭建)--学习笔记

.NET Core开发实战(第2课:内容综述)--学习笔记

.NET Core开发实战(第1课:课程介绍)--学习笔记


欢迎各位读者加入微信群一块儿学习交流,
在公众号后台回复“加群”便可~~


本文分享自微信公众号 - DotNet NB(DotNetNB)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。

相关文章
相关标签/搜索