理解ASP.NET Core – 日誌(Logging)
- 2021 年 11 月 9 日
- 筆記
- .NET, Asp.Net Core, Logging, 日誌
註:本文隸屬於《理解ASP.NET Core》系列文章,請查看置頂部落格或點擊此處查看全文目錄
快速上手
添加日誌提供程式
在文章主機(Host)中,講到Host.CreateDefaultBuilder
方法,默認通過調用ConfigureLogging
方法添加了Console
、Debug
、EventSource
和EventLog
(僅Windows)共四種日誌記錄提供程式(Logger Provider),然後在主機Build
過程中,通過AddLogging()
註冊了日誌相關的服務。
.ConfigureLogging((hostingContext, logging) =>
{
bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
if (isWindows)
{
logging.AddFilter<EventLogLoggerProvider>(level => level >= LogLevel.Warning);
}
// 添加 Logging 配置
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
// ConsoleLoggerProvider
logging.AddConsole();
// DebugLoggerProvider
logging.AddDebug();
// EventSourceLoggerProvider
logging.AddEventSourceLogger();
if (isWindows)
{
// 在Windows平台上,添加 EventLogLoggerProvider
logging.AddEventLog();
}
logging.Configure(options =>
{
options.ActivityTrackingOptions = ActivityTrackingOptions.SpanId
| ActivityTrackingOptions.TraceId
| ActivityTrackingOptions.ParentId;
});
})
public class HostBuilder : IHostBuilder
{
private void CreateServiceProvider()
{
var services = new ServiceCollection();
// ...
services.AddLogging();
// ...
}
}
如果不想使用默認添加的日誌提供程式,我們可以通過ClearProviders
清除所有已添加的日誌記錄提供程式,然後添加自己想要的,如Console
:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.ClearProviders()
.AddConsole();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
記錄日誌
日誌記錄提供程式均實現了介面ILoggerProvider
,該介面可以創建ILogger
實例。
通過注入服務ILogger<TCategoryName>
,就可以非常方便的進行日誌記錄了。
該服務需要指定日誌的類別,可以是任意字元串,但是我們約定使用所屬類的名稱,通過泛型體現。例如,在控制器ValuesController
中,日誌類別就是ValuesController
類的完全限定類型名。
public class ValuesController : ControllerBase
{
private readonly ILogger<ValuesController> _logger;
public ValuesController(ILogger<ValuesController> logger)
{
_logger = logger;
}
[HttpGet]
public string Get()
{
_logger.LogInformation("ValuesController.Get");
return "Ok";
}
}
當請求Get
方法後,你就可以在控制台中看到看到輸出的「ValuesController.Get」
如果你想要顯式指定日誌類別,則可以使用ILoggerFactory.CreateLogger
方法:
public class ValuesController : ControllerBase
{
private readonly ILogger _logger1;
public ValuesController(ILoggerFactory loggerFactory)
{
_logger1 = loggerFactory.CreateLogger("MyCategory");
}
}
配置日誌
默認模板中,日誌的配置如下(在appsettings.{Environment}.json文件中):
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
針對所有日誌記錄提供程式進行配置
LogLevel
,顧名思義,就是指要記錄的日誌的最低級別(即要記錄大於等於該級別的日誌),想必大家都不陌生。下方會詳細介紹日誌級別。
LogLevel
中的欄位,如上面示例中的「Default」、「Microsoft」等,表示日誌的類別,也就是咱們上面注入ILogger
時指定的泛型參數。可以為每種類別設置記錄的最小日誌級別,也就是這些類別所對應的值。
下面詳細解釋一下示例中的三種日誌類別。
Default
默認情況下,如果分類沒有進行特別配置(即沒有在LogLevel
中配置),則應用Default
的配置。
Microsoft
所有分類以Microsoft
開頭的日誌均應用Microsoft
的配置。例如,Microsoft.AspNetCore.Routing.EndpointMiddleware
類別的日誌就會應用該配置。
Microsoft.Hosting.Lifetime
所有分類以Microsoft.Hosting.Lifetime
開頭的日誌均應用Microsoft.Hosting.Lifetime
的配置。例如,分類Microsoft.Hosting.Lifetime
就會應用該配置,而不會應用Microsoft
,因為Microsoft.Hosting.Lifetime
比Microsoft
更具體。
OK,以上三種日誌類別就說這些了。
回到示例,你可能沒有注意到,這裡面沒有針對某個日誌記錄提供程式進行單獨配置(如:Console只記錄Error及以上級別日誌,而EventSource則需要記錄記錄所有級別日誌)。像這種,如果沒有針對特定的日誌記錄提供程式進行配置,則該配置將會應用到所有日誌記錄提供程式。
Windows
EventLog
除外。EventLog
必須顯式地進行配置,否則會使用其默認的LogLevel.Warning
。
針對指定的日誌記錄提供程式進行配置
接下來看一下如何針對指定的日誌記錄提供程式進行配置,先上示例:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
},
"Console": {
"LogLevel": {
"Default": "Error"
}
},
"Debug": {
"LogLevel": {
"Microsoft": "None"
}
},
"EventSource": {
"LogLevel": {
"Default": "Trace",
"Microsoft": "Trace",
"Microsoft.Hosting.Lifetime": "Trace"
}
}
}
}
就像appsettings.{Environment}.json
和appsettings.json
之間的關係一樣,Logging.{Provider}.LogLevel
中的配置將會覆蓋Logging.LogLevel
中的配置。
例如Logging.Console.LogLevel.Default
將會覆蓋Logging.LogLevel.Default
,Console
日誌記錄器將默認記錄Error
及其以上級別的日誌。
剛才提到了,Windows EventLog
比較特殊,它不會繼承Logging.LogLevel
的配置。EventLog
默認日誌級別為LogLevel.Warning
,如果想要修改,則必須顯式進行指定,如:
{
"Logging": {
"EventLog": {
"LogLevel": {
"Default": "Information"
}
}
}
}
配置的篩選原理
當創建ILogger<TCategoryName>
的對象實例時,ILoggerFactory
根據不同的日誌記錄提供程式,將會:
- 查找匹配該日誌記錄提供程式的配置。如果找不到,則使用通用配置。
- 然後匹配擁有最長前綴的配置類別。如果找不到,則使用
Default
配置。 - 如果匹配到了多條配置,則採用最後一條。
- 如果沒有匹配到任何配置,則使用
MinimumLevel
,這是個配置項,默認是LogLevel.Information
。
可以在
ConfigureLogging
擴展中使用SetMinimumLevel
方法設置MinimumLevel
。
Log Level
日誌級別指示了日誌的嚴重程度,一共分為7等,從輕到重為(最後的None
較為特殊):
日誌級別 | 值 | 描述 |
---|---|---|
Trace |
0 | 追蹤級別,包含最詳細的資訊。這些資訊可能包含敏感數據,默認情況下是禁用的,並且絕不能出現在生產環境中。 |
Debug |
1 | 調試級別,用於開發人員開發和調試。資訊量一般比較大,在生產環境中一定要慎用。 |
Information |
2 | 資訊級別,該級別平時使用較多。 |
Warning |
3 | 警告級別,一些意外的事件,但這些事件並不對導致程式出錯。 |
Error |
4 | 錯誤級別,一些無法處理的錯誤或異常,這些事件會導致當前操作或請求失敗,但不會導致整個應用出錯。 |
Critical |
5 | 致命錯誤級別,這些錯誤會導致整個應用出錯。例如記憶體不足等。 |
None |
6 | 指示不記錄任何日誌 |
日誌記錄提供程式
Console
日誌將輸出到控制台中。
Debug
日誌將通過System.Diagnostics.Debug
類進行輸出,可以通過VS輸出窗口查看。
在 Linux 上,可以在/var/log/message
或/var/log/syslog
下找到
EventSource
跨平台日誌記錄,在Windows上則使用 ETW
Windows EventLog
僅在Windows系統下生效,可通過「事件查看器」進行日誌查看。
默認情況下
LogName
為「Application」SourceName
為「NET Runtime」MachineName
為本地電腦的名稱。
這些欄位都可以通過EventLogSettings
進行修改:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.AddEventLog(settings =>
{
settings.LogName = "My App";
settings.SourceName = "My Log";
settings.MachineName = "My Computer";
})
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
日誌記錄過濾器
通過日誌記錄過濾器,允許你書寫複雜的邏輯,來控制是否要記錄日誌。
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging
// 針對所有 LoggerProvider 設置 Microsoft 最小日誌級別,建議通過配置文件進行配置
.AddFilter("Microsoft", LogLevel.Trace)
// 針對 ConsoleLoggerProvider 設置 Microsoft 最小日誌級別,建議通過配置文件進行配置
.AddFilter<ConsoleLoggerProvider>("Microsoft", LogLevel.Debug)
// 針對所有 LoggerProvider 進行過濾配置
.AddFilter((provider, category, logLevel) =>
{
// 由於下面單獨針對 ConsoleLoggerProvider 添加了過濾配置,所以 ConsoleLoggerProvider 不會進入該方法
if (provider == typeof(ConsoleLoggerProvider).FullName
&& category == typeof(ValuesController).FullName
&& logLevel <= LogLevel.Warning)
{
// false:不記錄日誌
return false;
}
// true:記錄日誌
return true;
})
// 針對 ConsoleLoggerProvider 進行過濾配置
.AddFilter<ConsoleLoggerProvider>((category, logLevel) =>
{
if (category == typeof(ValuesController).FullName
&& logLevel <= LogLevel.Warning)
{
// false:不記錄日誌
return false;
}
// true:記錄日誌
return true;
});
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
日誌消息模版
應用開發過程中,對於某一類的日誌,我們希望它們的消息格式保持一致,僅僅是某些參數發生變化。這就要用到日誌消息模板了。
舉個例子:
[HttpGet("{id}")]
public int Get(int id)
{
_logger.LogInformation("Get {Id}", id);
return id;
}
其中Get {Id}
就是一個日誌消息模板,{Id}
則是模板參數(注意,請在裡面書寫名稱,而不是數字,這樣更容易理解參數含義)。
不過,需要注意的是,{Id}
這個模板參數,僅僅是用於讓人容易理解其含義的,和後面的參數名沒有任何關係,模板值關心參數的順序。例如:
[HttpGet("{id}")]
public int Get(int id)
{
_logger.LogInformation("Get {Id} at {Time}", DateTime.Now, id);
return id;
}
假設傳入id = 1,它的輸出是:Get 11/02/2021 11:42:14 at 1
日誌消息模板是一項非常重要的功能,在眾多開源日誌中間件中,均有使用。
主機構建期間的日誌記錄
ASP.NET Core框架不直接支援在主機構建期間進行日誌記錄。但是可以通過獨立的日誌記錄提供程式進行日誌記錄,例如,使用第三方日誌記錄提供程式:Serilog
安裝Nuget包:Install-Package Serilog.AspNetCore
public static void Main(string[] args)
{
// 從appsettings.json和命令行參數中讀取配置
var config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddCommandLine(args)
.Build();
// 創建Logger
Log.Logger = new LoggerConfiguration()
.WriteTo.Console() // 輸出到控制台
.WriteTo.File(config["Logging:File:Path"]) // 輸出到指定文件
.CreateLogger();
try
{
CreateHostBuilder(args).Build().Run();
}
catch(Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly");
throw;
}
finally
{
Log.CloseAndFlush();
}
}
appsettings.json
{
"Logging": {
"File": {
"Path": "logs/host.log"
}
}
}
控制台日誌格式配置
控制台日誌記錄提供程式是我們開發過程中必不可少的,通過上面我們已經得知可以通過AddConsole()
進行添加。不過它的局限性比較大,日誌格式我們都無法進行自定義。
因此,在.NET 5中,對控制台日誌記錄提供程式進行了擴展,預置了三種日誌輸出格式:Json、Simple、Systemd。
實際上,之前也有枚舉
ConsoleLoggerFormat
提供了Simple和Systemd格式,不過不能進行自定義,已經棄用了。
這些 Formatter 均繼承自抽象類ConsoleFormatter
,該抽象類構造函數接收一個「名字」參數,要求其實現類必須擁有名字。你可以通過靜態類ConsoleFormatterNames
獲取到內置的三種格式的名字。
public abstract class ConsoleFormatter
{
protected ConsoleFormatter(string name)
{
Name = name ?? throw new ArgumentNullException(nameof(name));
}
public string Name { get; }
public abstract void Write<TState>(in LogEntry<TState> logEntry, IExternalScopeProvider scopeProvider, TextWriter textWriter);
}
public static class ConsoleFormatterNames
{
public const string Simple = "simple";
public const string Json = "json";
public const string Systemd = "systemd";
}
你可以在使用AddConsole()
時,配置ConsoleLoggerOptions
的FormatterName
屬性,以達到自定義格式的目的,其默認值為「simple」。不過,為了方便使用,.NET 框架已經把內置的三種格式幫我們封裝好了。
這些 Formatter 的選項類均繼承自選項類ConsoleFormatterOptions
,該選項類包含以下三個屬性:
public class ConsoleFormatterOptions
{
// 啟用作用域,默認 false
public bool IncludeScopes { get; set; }
// 設置時間戳的格式,顯示在日誌消息開頭
// 默認為 null,不展示時間戳
public string TimestampFormat { get; set; }
// 是否將時間戳時區設置為 UTC,默認是false,即本地時區
public bool UseUtcTimestamp { get; set; }
}
SimpleConsoleFormatter
通過擴展方法AddSimpleConsole()
可以添加支援Simple
格式的控制台日誌記錄提供程式,默認行為與AddConsole()
一致。
.ConfigureLogging(logging =>
{
logging.ClearProviders()
.AddSimpleConsole();
}
示例輸出:
info: Microsoft.Hosting.Lifetime[0]
Now listening on: //localhost:5000
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
Content root path: C:\Repos\WebApplication
另外,你可以通過SimpleConsoleFormatterOptions
進行一些自定義配置:
.ConfigureLogging(logging =>
{
logging.ClearProviders()
.AddSimpleConsole(options =>
{
// 一條日誌消息展示在同一行
options.SingleLine = true;
options.IncludeScopes = true;
options.TimestampFormat = "yyyy-MM-dd HH:mm:ss ";
options.UseUtcTimestamp = false;
});
}
示例輸出:
2021-11-02 15:53:33 info: Microsoft.Hosting.Lifetime[0] Now listening on: //localhost:5000
2021-11-02 15:53:33 info: Microsoft.Hosting.Lifetime[0] Application started. Press Ctrl+C to shut down.
2021-11-02 15:53:33 info: Microsoft.Hosting.Lifetime[0] Hosting environment: Development
2021-11-02 15:53:33 info: Microsoft.Hosting.Lifetime[0] Content root path: C:\Repos\WebApplication
SystemdConsoleFormatter
通過擴展方法AddSystemdConsole()
可以添加支援Systemd
格式的控制台日誌記錄提供程式。如果你熟悉Linux,那你對它也一定不陌生。
.ConfigureLogging(logging =>
{
logging.ClearProviders()
.AddSystemdConsole();
}
示例輸出:
<6>Microsoft.Hosting.Lifetime[0] Now listening on: //localhost:5000
<6>Microsoft.Hosting.Lifetime[0] Application started. Press Ctrl+C to shut down.
<6>Microsoft.Hosting.Lifetime[0] Hosting environment: Development
<6>Microsoft.Hosting.Lifetime[0] Content root path: C:\Repos\WebApplication
前面的<6>
表示日誌級別info,如果你有興趣了解Systemd,可以訪問阮一峰老師的Systemd 入門教程:命令篇
JsonConsoleFormatter
通過擴展方法AddJsonConsole()
可以添加支援Json
格式的控制台日誌記錄提供程式。
.ConfigureLogging(logging =>
{
logging.ClearProviders()
.AddJsonConsole(options =>
{
options.JsonWriterOptions = new JsonWriterOptions
{
// 啟用縮進,看起來更舒服
Indented = true
};
});
}
示例輸出:
{
"EventId": 0,
"LogLevel": "Information",
"Category": "Microsoft.Hosting.Lifetime",
"Message": "Now listening on: //localhost:5000",
"State": {
"Message": "Now listening on: //localhost:5000",
"address": "//localhost:5000",
"{OriginalFormat}": "Now listening on: {address}"
}
}
{
"EventId": 0,
"LogLevel": "Information",
"Category": "Microsoft.Hosting.Lifetime",
"Message": "Application started. Press Ctrl\u002BC to shut down.",
"State": {
"Message": "Application started. Press Ctrl\u002BC to shut down.",
"{OriginalFormat}": "Application started. Press Ctrl\u002BC to shut down."
}
}
{
"EventId": 0,
"LogLevel": "Information",
"Category": "Microsoft.Hosting.Lifetime",
"Message": "Hosting environment: Development",
"State": {
"Message": "Hosting environment: Development",
"envName": "Development",
"{OriginalFormat}": "Hosting environment: {envName}"
}
}
{
"EventId": 0,
"LogLevel": "Information",
"Category": "Microsoft.Hosting.Lifetime",
"Message": "Content root path: C:\\Repos\\WebApplication",
"State": {
"Message": "Content root path: C:\\Repos\\WebApplication",
"contentRoot": "C:\\Repos\\WebApplication",
"{OriginalFormat}": "Content root path: {contentRoot}"
}
}
如果你同時添加了多種格式的控制台記錄程式,那麼只有最後一個添加的生效。
以上介紹的是通過程式碼進行控制台日誌記錄提供程式的設置,不過我想大家應該更喜歡通過配置去設置日誌記錄提供程式。下面是一個簡單地配置示例:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
},
"Console": {
"FormatterName": "json",
"FormatterOptions": {
"SingleLine": true,
"IncludeScopes": true,
"TimestampFormat": "yyyy-MM-dd HH:mm:ss ",
"UseUtcTimestamp": false,
"JsonWriterOptions": {
"Indented": true
}
}
}
}
}
ILogger<TCategoryName>對象實例的創建
講到這裡,不知道你會不會對ILogger<TCategoryName>
對象實例的創建有疑惑:它到底是如何被new
出來的呢?
要解決這個問題,我們先從AddLogging()
擴展方法入手:
public static class LoggingServiceCollectionExtensions
{
public static IServiceCollection AddLogging(this IServiceCollection services)
{
return AddLogging(services, builder => { });
}
public static IServiceCollection AddLogging(this IServiceCollection services, Action<ILoggingBuilder> configure)
{
services.AddOptions();
// 註冊單例 ILoggerFactory
services.TryAdd(ServiceDescriptor.Singleton<ILoggerFactory, LoggerFactory>());
// 註冊單例 ILogger<>
services.TryAdd(ServiceDescriptor.Singleton(typeof(ILogger<>), typeof(Logger<>)));
// 批量註冊單例 IConfigureOptions<LoggerFilterOptions>
services.TryAddEnumerable(ServiceDescriptor.Singleton<IConfigureOptions<LoggerFilterOptions>>(
new DefaultLoggerLevelConfigureOptions(LogLevel.Information)));
configure(new LoggingBuilder(services));
return services;
}
}
你可能也猜到了,這個Logger<>
不會是LoggerFactory
創建的吧?要不然註冊個這玩意幹嘛呢?
別著急,咱們接著先查看ILogger<>
服務的實現類Logger<>
:
public interface ILogger
{
void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter);
// 檢查能否記錄該日誌等級的日誌
bool IsEnabled(LogLevel logLevel);
IDisposable BeginScope<TState>(TState state);
}
public interface ILogger<out TCategoryName> : ILogger
{
}
public class Logger<T> : ILogger<T>
{
// 介面實現內部均是使用該實例進行操作
private readonly ILogger _logger;
// 果不其然,注入了 ILoggerFactory 實例
public Logger(ILoggerFactory factory)
{
// 還記得嗎?上面提到顯式指定日誌類別時,也是這樣創建 ILogger 實例的
_logger = factory.CreateLogger(TypeNameHelper.GetTypeDisplayName(typeof(T), includeGenericParameters: false, nestedTypeDelimiter: '.'));
}
// ...
}
沒錯,你猜對了,那就來看看這個LoggerFactory
吧(只列舉核心程式碼):
public interface ILoggerFactory : IDisposable
{
ILogger CreateLogger(string categoryName);
void AddProvider(ILoggerProvider provider);
}
public class LoggerFactory : ILoggerFactory
{
// 用於單例化 Logger<>
private readonly Dictionary<string, Logger> _loggers = new Dictionary<string, Logger>(StringComparer.Ordinal);
// 存放 ILoggerProviderRegistrations
private readonly List<ProviderRegistration> _providerRegistrations = new List<ProviderRegistration>();
private readonly object _sync = new object();
public LoggerFactory(IEnumerable<ILoggerProvider> providers, IOptionsMonitor<LoggerFilterOptions> filterOption, IOptions<LoggerFactoryOptions> options = null)
{
// ...
// 註冊 ILoggerProviders
foreach (ILoggerProvider provider in providers)
{
AddProviderRegistration(provider, dispose: false);
}
// ...
}
public ILogger CreateLogger(string categoryName)
{
lock (_sync)
{
// 如果不存在,則 new
if (!_loggers.TryGetValue(categoryName, out Logger logger))
{
logger = new Logger
{
Loggers = CreateLoggers(categoryName),
};
(logger.MessageLoggers, logger.ScopeLoggers) = ApplyFilters(logger.Loggers);
// 單例化 Logger<>
_loggers[categoryName] = logger;
}
return logger;
}
}
private void AddProviderRegistration(ILoggerProvider provider, bool dispose)
{
_providerRegistrations.Add(new ProviderRegistration
{
Provider = provider,
ShouldDispose = dispose
});
// ...
}
private LoggerInformation[] CreateLoggers(string categoryName)
{
var loggers = new LoggerInformation[_providerRegistrations.Count];
// 循環遍歷所有 ILoggerProvider
for (int i = 0; i < _providerRegistrations.Count; i++)
{
loggers[i] = new LoggerInformation(_providerRegistrations[i].Provider, categoryName);
}
return loggers;
}
}
注意
- 若要在
Startup.Configure
方法中記錄日誌,直接在參數上注入ILogger<Startup>
即可。 - 不支援在
Startup.ConfigureServices
方法中使用ILogger
,因為此時DI容器還未配置完成。 - 沒有非同步的日誌記錄方法。日誌記錄動作執行應該很快,不值的犧牲性能使用非同步方法。如果日誌記錄動作比較耗時,如記錄到MSSQL中,那麼請不要直接寫入MSSQL。你應該考慮先將日誌寫入到快速存儲介質,如記憶體隊列,然後通過後台工作執行緒將其從記憶體轉儲到MSSQL中。
- 無法使用日誌記錄 API 在應用運行時更改日誌記錄配置。不過,一些配置提供程式(如文件配置提供程式)可重新載入配置,這可以立即更新日誌記錄配置。
小結
Host.CreateDefaultBuilder
方法中,默認添加了Console
、Debug
、EventSource
和EventLog
(僅Windows)共四種日誌記錄提供程式(Logger Provider)。- 通過注入服務
ILogger<TCategoryName>
,可以方便的進行日誌記錄。 - 可以通過程式碼或配置對日誌記錄提供程式進行設置,如
LogLevel
、FormatterName
等。 - 可以通過擴展方法
AddFilter
添加日誌記錄過濾器,允許你書寫複雜的邏輯,來控制是否要記錄日誌。 - 支援日誌消息模板。
- 對於控制台記錄日誌程式,.NET框架內置了
Simple
(默認)、Systemd
、Json
三種日誌輸出格式。 - .NET 6 預覽版中新增了一個稱為「編譯時日誌記錄源生成」的功能,該功能非常實用,有興趣的可以先去了解一下。
- 最後,給大家列舉一些常用的日誌開源中間件: