ASP.NET Core 沉思录 - Logging 的两种介入方法
ASP.NET Core 中依賴注入是一個(gè)很重要的環(huán)節(jié)。因?yàn)閹缀跛械膶?duì)象都是由它創(chuàng)建的(相關(guān)文章請(qǐng)參見《ASP.NET Core 沉思錄 - ServiceProvider 的二度出生》)。因此整個(gè)日志記錄的相關(guān)類型也被直接添加到了 IServiceCollection 中。今天我們將介紹各個(gè)接口/類型之間的關(guān)系,并找到介入日志記錄功能的兩個(gè)主要的入口。
ASP.NET Core 的日志功能結(jié)構(gòu)
為什么當(dāng)我們恰當(dāng)對(duì)日志進(jìn)行配置之后就可以記錄日志呢。那是因?yàn)?Framework 一定已經(jīng)將最關(guān)鍵的類型添加到了 IServiceCollection 中。在 ASP.NET Core 中,應(yīng)用程序的啟動(dòng)一定會(huì)創(chuàng)建 WebHost 而創(chuàng)建 WebHost 一般會(huì)用到 WebHostBuilder。在 WebHostBuilder 創(chuàng)建過程中就將一些核心的日志記錄相關(guān)類型添加到了 IServiceCollection 中。
前面我們介紹過,IServiceProvider 有兩次創(chuàng)建過程,一次是在調(diào)用 WebHostBuilder.Build 時(shí)創(chuàng)建的 Hosting 相關(guān)的 IServiceProvider,另一次是在 WebHost.StartXxx 方法時(shí)創(chuàng)建的應(yīng)用程序使用的 IServiceProvider。而日志相關(guān)類型第一次的 IServiceProvider 創(chuàng)建之前就已經(jīng)添加到 IServiceCollection 中了。
在本文寫作時(shí),第一次 IServiceCollection 實(shí)例的創(chuàng)建是在 WebHostBuilder.BuildCommonServices 方法中,大概的流程是:
創(chuàng)建 ServiceCollection
調(diào)用 AddLogging 擴(kuò)展方法
將 IOptions<>; 及其它形式、ILoggerFactory、ILogger<>、IConfigurator、IConfigureOptions 添加到 ServiceCollection 中。
如果在配置 IWebHostBuilder 過程中調(diào)用過 ConfigureLogging 則調(diào)用相關(guān)委托添加或替換相關(guān)日志記錄的類型。
代碼請(qǐng)參見:WebHostBuilder.cs (https://github.com/aspnet/AspNetCore/blob/master/src/Hosting/Hosting/src/WebHostBuilder.cs) 以及LoggingServiceCollectionExtensions.cs (https://github.com/aspnet/Extensions/blob/master/src/Logging/Logging/src/LoggingServiceCollectionExtensions.cs)。
因此,以上提到的類型就是日志功能的核心類型了。梳理一下這些類型的依賴關(guān)系就可以弄清 ASP.NET Core 的日志功能結(jié)構(gòu)了。
弄清一個(gè)結(jié)構(gòu)需要關(guān)注兩個(gè)部分的內(nèi)容,第一個(gè)部分是聲明上的依賴關(guān)系(靜態(tài)),另一個(gè)部分是調(diào)用上的依賴關(guān)系(動(dòng)態(tài))。因此我們也會(huì)采用這種方式進(jìn)行梳理。首先聲明上的依賴關(guān)系如下:
以上結(jié)構(gòu)在運(yùn)行時(shí)會(huì)創(chuàng)建三層 ILogger 實(shí)現(xiàn)
最外面的一層就是我們使用的 ILogger<> 實(shí)現(xiàn)。它是由 IServiceProvider 直接創(chuàng)建的。
第二層是 LoggerFactory 創(chuàng)建的 Logger,它是一個(gè)組合 Logger。
第三層是由 ILoggerProvider 實(shí)現(xiàn)創(chuàng)建的負(fù)責(zé)具體記錄日志的 ILogger 實(shí)現(xiàn)。這些 Logger 都會(huì)添加到第二層的組合 Logger 中。
而后,在日志記錄時(shí),正是按照這三層結(jié)構(gòu)進(jìn)行任務(wù)分發(fā)的。
介入日志功能的幾個(gè)入口
在了解上述結(jié)構(gòu)之后不難使用我們的具體實(shí)現(xiàn)替換默認(rèn)的 .NET 日志記錄結(jié)構(gòu)。首先在使用上 ASP.NET Core 上使用的日志記錄接口有兩種,第一種即 ILoggerFactory,進(jìn)而創(chuàng)建 ILogger。例如 這里。而另外一種則是直接使用 ILogger<>。因此我們的介入點(diǎn)有兩個(gè):
直接替換 ILoggerFactory 的實(shí)現(xiàn),這樣可以完全定義自己的 Logger -> Sink 結(jié)構(gòu)和過濾邏輯;但工作量較大。
實(shí)現(xiàn) ILoggerProvider,并將其添加到 IServiceCollection 中。這樣可以復(fù)用現(xiàn)有的日志邏輯。
很多第三方日志庫(kù)就是有選擇的采用了上述一種或者兩種方式。例如,以 Serilog 為例,它支持上述兩種接口:
首先、我們可以使用 webHostBuilder.UseSerilog(...) 的方式將其納入應(yīng)用程序中。而這種方式使用第一種介入方法。具體代碼請(qǐng)看:https://github.com/serilog/serilog-aspnetcore/blob/dev/src/Serilog.AspNetCore/SerilogWebHostBuilderExtensions.cs。
其次、我們可以使用 loggerBuilder.AddSerilog(...) 的方式將其納入應(yīng)用程序中。而這種方式使用第二種介入方法。具體代碼請(qǐng)看:https://github.com/serilog/serilog-extensions-logging/blob/dev/src/Serilog.Extensions.Logging/SerilogLoggingBuilderExtensions.cs。
總結(jié)
日志記錄有很多可以思考的地方,今天我們只關(guān)注 ASP.NET Core 中日志介入的入口。總結(jié)起來(lái)有兩個(gè)主要入口:
第一、直接替換 ILoggerFactory 實(shí)現(xiàn);
第二、實(shí)現(xiàn)具體的 ILoggerProvider 并將其添加到 IServiceCollection 中。
如果您覺得本文對(duì)您有幫助,也歡迎分享給其他的人。我們一起進(jìn)步。歡迎關(guān)注我的博客(https://clrdaily.com)和微信公眾號(hào):
總結(jié)
以上是生活随笔為你收集整理的ASP.NET Core 沉思录 - Logging 的两种介入方法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Wexflow:C#中的开源工作流引擎
- 下一篇: Docker最全教程之使用.NET Co