Ilogger:包括實際執行記錄日志操作的方法。
IloggerProvider:用於創建 ILogger 對象。
IloggerFactory:通過 ILoggerProvider 對象創建 ILogger 對象。
ILogger接口
要記錄日志,需要使用 ILogger 接口
public interface ILogger
{
//開始邏輯操作范圍。
IDisposable BeginScope<TState>(TState state);
//檢查是否已啟用給定 logLevel。
bool IsEnabled(LogLevel logLevel);
//寫入日志項。
void Log<TState> (Microsoft.Extensions.Logging.LogLevel logLevel, Microsoft.Extensions.Logging.EventId eventId, TState state, Exception exception, Func<TState,Exception,string> formatter);
}
日志級別
Log 方法的第一個參數指明了這條信息的級別,日志級別即其重要程度。ASP.NET Core 日志系統定義了 6 個級別
LogLevel | “值” | 方法 | 描述 |
---|---|---|---|
Trace | 0 | LogTrace | 包含最詳細的消息。 這些消息可能包含敏感的應用數據。 這些消息默認情況下處於禁用狀態,並且不應在生產中啟用。 |
調試 | 1 | LogDebug | 用於調試和開發。 由於量大,請在生產中小心使用。 |
信息 | 2 | LogInformation | 跟蹤應用的常規流。 可能具有長期值。 |
警告 | 3 | LogWarning | 對於異常事件或意外事件。 通常包括不會導致應用失敗的錯誤或情況。 |
錯誤 | 4 | LogError | 表示無法處理的錯誤和異常。 這些消息表示當前操作或請求失敗,而不是整個應用失敗。 |
嚴重 | 5 | LogCritical | 需要立即關注的失敗。 例如數據丟失、磁盤空間不足。 |
無 | 6 | 指定日志記錄類別不應寫入任何消息。 |
除了指定日志級別以外,還需要指定 EventId、一個返回值類型為字符串的委托,該委托的意義在於根據指定的狀態以及異常返回要輸出的日志信息。從上面的代碼中可以看出,直接使用 Log 方法來記錄日志會非常麻煩。為此 ILogger 接口提供了若干個擴展方法,用來更方便地記錄指定級別的日志,它們包括 LogTrace、LogDebug、LogInformation、LogWarning、LogError 和 LogCritical,這幾個方法分別對應上面所提到的各個級別。因此,上面的代碼可以改寫為:
public class PrivacyModel : PageModel
{
private readonly ILogger<PrivacyModel> _logger;
public PrivacyModel(ILogger<PrivacyModel> logger)
{
_logger = logger;
}
public void OnGet()
{
_logger.LogInformation("GET Pages.PrivacyModel called.");
}
}
在Startup記錄日志
當 ASP.NET Core 應用程序運行時,日志組件會被添加到其依賴注入容器中,因此只要在合適的位置將 ILogger 對象注入進來,即可使用它來記錄日志。
public class Startup
{
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILogger<Startup> logger)
{
app.Run(async (context) =>
{
logger.LogInformation("這是一條測試日志");
await context.Response.WriteAsync("Hello, world");
});
}
}
在 Startup 類的 Configure 方法中,通過方法注入將
ILogger<Startup>
作為該方法的參數注入進來
ILogger 接口有一個派生接口 ILogger<out TCategoryName>
,其中泛型類型 TCategoryName
表示日志類別名稱,它可以是任何類型,通常情況下,它的值應為當前所在類,如上面的 Startup
類。當注入 ILogger
時,必須為其指定泛型類型。
日志事件 ID
在日志的輸出結果中,日志類別后有一個用中括號括起來的數字,該數字為事件標識符(Event Id) ,它的值是一個數字,默認值為 0。合理地使用這個數字能夠幫助開發者對日志進一步分類,比如,某種操作的 Id 是1000,另一類操作的 Id 是 1002。注意,Event Id 的顯示格式由 Provider定義,上述顯示形式是由 ConsoleProvider(即控制台日志提供程序)定義的;在其他 Provider 中則不然,例如,DebugProvider 不顯示 Event Id。要設置 Event Id,我們只要使用 LogInformation 方法的另一個重載形式即可。
每個日志都可指定一個事件 ID 。 示例應用使用 MyLogEvents
類來定義事件 ID:
public class MyLogEvents
{
public const int GenerateItems = 1000;
public const int ListItems = 1001;
public const int GetItem = 1002;
public const int InsertItem = 1003;
public const int UpdateItem = 1004;
public const int DeleteItem = 1005;
public const int TestItem = 3000;
public const int GetItemNotFound = 4000;
public const int UpdateItemNotFound = 4001;
}
[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
_logger.LogInformation(MyLogEvents.GetItem, "Getting item {Id}", id);
var todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
_logger.LogWarning(MyLogEvents.GetItemNotFound, "Get({Id}) NOT FOUND", id);
return NotFound();
}
return ItemToDTO(todoItem);
}
事件 ID 與一組事件相關聯。 例如,與在頁面上顯示項列表相關的所有日志可能是 1001。
日志記錄提供程序可將事件 ID 存儲在 ID 字段中,存儲在日志記錄消息中,或者不進行存儲。 調試提供程序不顯示事件 ID。 控制台提供程序在類別后的括號中顯示事件 ID:
info: TodoApi.Controllers.TodoItemsController[1002]
Getting item 1
warn: TodoApi.Controllers.TodoItemsController[4000]
Get(1) NOT FOUND
一些日志記錄提供程序將事件 ID 存儲在一個字段中,該字段允許對 ID 進行篩選。
內置日志記錄提供程序
public static IWebHostBuilder CreateDefaultBuilder(string[] args)
{
var builder = new WebHostBuilder();
…
builder.ConfigureLogging((hostingContext, logging) =>
{
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddConsole();
logging.AddDebug();
logging.AddEventSourceLogger();
})
…
}
CreateDefaultBuilder 方法默認添加了 3 個日志提供程序,如果不需要默認所添加的這些日志提供程序,可以調用 ILoggerProvider 接口的 ClearProviders 方法,然后再添加所需要的日志提供程序。
- 控制台
向控制台窗口輸出日志 - 調試
向開發環境(IDE)的調試窗口輸出日志,它會調用System.Diagnostics.Debug 類的 WriteLine 方法向外輸出。 - EventSource
向事件跟蹤器輸出日志。 - EventLog
向 Window Event Log 輸出日志,僅支持 Windows 操作系統。 - AzureAppServicesFile 和 AzureAppServicesBlob
僅在 Azure 中使用,當應用程序部署到 Azure Web服務中后, Azure App Service 日志提供程序自動會添加進來。 - ApplicationInsights
提供程序包將日志寫入 Azure Application Insights。 Application Insights 是一項服務,可監視 Web 應用並提供用於查詢和分析遙測數據的工具。 如果使用此提供程序,則可以使用 Application Insights 工具來查詢和分析日志。
與 ILoggingBuilder 一樣,ILoggerFactory 在添加 ASP.NET Core 內置的日志提供程序時,也可以使用 AddConsole 和 AddDebug 等擴展方法來添加日志提供程序。
第三方日志記錄提供程序
適用於 ASP.NET Core 的第三方日志記錄框架:
- elmah.io(GitHub 存儲庫)
- Gelf(GitHub 存儲庫)
- JSNLog(GitHub 存儲庫)
- KissLog.net(GitHub 存儲庫)
- Log4Net(GitHub 存儲庫)
- Loggr(GitHub 存儲庫)
- NLog(GitHub 存儲庫)
- PLogger(GitHub 存儲庫)
- Sentry(GitHub 存儲庫)
- Serilog(GitHub 存儲庫)
- Stackdriver(Github 存儲庫)
某些第三方框架可以執行語義日志記錄(又稱結構化日志記錄)。
使用第三方框架類似於使用以下內置提供程序之一:
- 將 NuGet 包添加到你的項目。
- 調用日志記錄框架提供的
ILoggerFactory
擴展方法。
有關詳細信息,請參閱各提供程序的相關文檔。 Microsoft 不支持第三方日志記錄提供程序。
ILoggerFactory
ILoggerFactory 接口用於創建 ILogger 類型的對象。
public interface ILoggerFactory : IDisposable
{
//將 ILoggerProvider 添加到日志記錄系統。
void AddProvider(ILoggerProvider provider);
//創建一個新的 ILogger 實例。該方法的參數 categoryName 為類日志的類別名稱,它主要用來為日志指定分類名稱
ILogger CreateLogger(string categoryName);
}
要顯式指定類別,請調用 ILoggerFactory.CreateLogger
:
public class ContactModel : PageModel
{
private readonly ILogger _logger;
public ContactModel(ILoggerFactory logger)
{
_logger = logger.CreateLogger("MyCategory");
}
public void OnGet()
{
_logger.LogInformation("GET Pages.ContactModel called.");
}
}
分組和過濾
分組
參考:日志作用域
對於一組邏輯上相關的操作,將其日志信息分為一組是很有意義的,這需要使用 Scope 來實現。ILogger
接口有一個方法即BeginScope<TState>(TState state)
用於創建 Scope,其中 TState
指明要創建 Scope
的標識符,它可以為任何類型的數據,一般情況下,使用字符串來指明。BeginScope<TState>
方法的返回值類型為 IDisposable
,因此可以使用 using 語句塊來創建 Scope,代碼如下所示。
using (logger.BeginScope("獲取數據"))
{
logger.LogInformation("准備獲取數據");
…
if (data == null)
{
logger.LogError("數據不存在");
}
}
要在 Scope 中輸出日志,除了需要創建 Scope 外,還要在ILoggerProvider 對象中啟用這一功能。在添加日志提供程序時可以指定該ILoggerProvider 的一些選項。
例如,對於 ControlProvider,只要設置ConsoleLoggerOptions 的 IncludeScopes 屬性為 true,即可為其啟用Scope 功能,它的默認值為 false。
1.下列代碼為控制台提供程序啟用作用域:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging((hostingContext, logging) =>
{
logging.ClearProviders();
//ConsoleLoggerOptions的 IncludeScopes = true
logging.AddConsole(options => options.IncludeScopes = true);
logging.AddDebug();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
2.【推薦】以下 JSON 為控制台提供程序啟用范圍:
{
"Logging": {
"Debug": {
"LogLevel": {
"Default": "Information"
}
},
"Console": {
"IncludeScopes": true, // Required to use Scopes.
"LogLevel": {
"Microsoft": "Warning",
"Default": "Information"
}
},
"LogLevel": {
"Default": "Debug"
}
}
}
輸出
info: LoggingTest.Startup[0]
=> 獲取數據
准備獲取數據
fail: LoggingTest.Startup[0]
=> 獲取數據
數據不存在
過濾
可以通過設置最低日志級別來進行日志過濾,當這樣設置后,所有低於指定日志級別的日志都不會被處理,也不會顯示。例如,如果設置最低日志級別為 LogLevel.Information,那么 Debug 和 Trace 級別的日志都不會顯示。
1.SetMinimumLevel
要設置最低日志級別,同樣需要在 ConfigureLogging 方法中進行配置,此時只要調用 ILoggingBuilder 接口的 SetMinimumLevel 方法即可。
Host.CreateDefaultBuilder(args)
.ConfigureLogging(builder =>
{
builder.ClearProviders();
builder.AddConsole(loggerOptions => loggerOptions.IncludeScopes = true);
builder.SetMinimumLevel(LogLevel.Information);
})
.UseStartup<Startup>();
LogLevel.None
除了之前提到的那些級別以外,還有一個值是 None,該值高於其他所有值。如果指定這個值為最低級別,那么所有的日志都不會輸出。
2.AddFilter
除了設置最低日志級別外,ILoggerBuilder 接口還提供了 AddFilter
方法,該方法包括多個重載,它能夠指定更復雜的條件,並只顯示滿足條件的日志。在以下方法中,將顯示 LoggeringTest.Startup 類別中,等於並高於Information 級別的日志。
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.AddConsole().AddFilter("LoggingTest.Startup", LogLevel.Information);
})
加載JSON的Logging配置
默認情況下,在 appsettings.json 文件中包含了對日志的配置信息,要將日志配置加載並應用到程序的日志系統中,可以調用AddConfiguration
方法
Host.CreateDefaultBuilder(args)
.ConfigureLogging((hostingContext, logging) =>
{
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
...
})
.UseStartup<Startup>();
在 appsettings.json
配置文件的「Logging」一節則默認包含了關於記錄日志的統一配置,如 LogLevel 配置項用於設置對指定類別的日志的最低輸出級別,凡是在該類別中低於指定級別的日志將不會被輸出。除了設置統一配置外,還可以為每一種日志提供程序提供具體的輸出配置,只要在「Logging」一節為其增加相應的配置即可,如下例添加了對 Console 類型日志提供程序的配置。
{
"Logging": {
"Console": {
"IncludeScopes": true,
"LogLevel": {
"Microsoft.AspNetCore.Mvc.Razor": "Error",
"Default": "Information"
}
},
"LogLevel": {
"Default": "Debug"
}
}
}