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的現狀、將來以及環境搭建)--學習筆記
本文分享自微信公衆號 - DotNet NB(DotNetNB)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。