.NET Core 和 ASP.NET Core 中的記錄 (機器翻譯)
注意
這不是這篇文章的最新版本。 如需目前的版本,請參閱 本文的 .NET 9 版本。
警告
不再支援此版本的 ASP.NET Core。 如需詳細資訊,請參閱 .NET 和 .NET Core 支持原則。 如需目前的版本,請參閱 本文的 .NET 9 版本。
作者:Kirk Larkin、Juergen Gutsch 和 Rick Anderson
本文章描述在 .NET 中的記錄,因為其適用於 ASP.NET Core 應用程式。 如需在 .NET 中記錄的詳細資訊,請參閱在 .NET 中記錄。
如需 Blazor 記錄指引 (其會新增或取代此節點中的指引),請參閱 ASP.NET Core Blazor 記錄。
記錄提供者
記錄提供者會儲存記錄,但顯示記錄的 Console
提供者則除外。 例如,Azure Application Insights 提供者會將記錄儲存在 Azure Application Insights 中。 您可以啟用多個提供者。
預設 ASP.NET Core Web 應用程式範本會呼叫 WebApplication.CreateBuilder,以新增下列記錄提供者:
- 主控台
- 偵錯
- EventSource
- EventLog:僅限 Windows
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
上述程式碼會顯示使用 ASP.NET Core Web 應用程式範本建立的 Program.cs
檔案。 接下來的幾節會根據 ASP.NET Core Web 應用程式範本來提供範例。
下列程式碼會覆寫 WebApplication.CreateBuilder
所新增的記錄提供者預設集:
var builder = WebApplication.CreateBuilder(args);
builder.Logging.ClearProviders();
builder.Logging.AddConsole();
builder.Services.AddRazorPages();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
或者,上述記錄程式碼可以撰寫如下:
var builder = WebApplication.CreateBuilder();
builder.Host.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.AddConsole();
});
如需其他提供者,請參閱:
建立記錄
若要建立記錄,請使用ILogger<TCategoryName>相依性插入 (DI) 的物件。
下列範例將:
- 建立記錄器 (
ILogger<AboutModel>
),這個記錄器會使用類型AboutModel
完整名稱的記錄類別。 記錄「類別」是與每個記錄關聯的字串。 - 呼叫 LogInformation 以在 Information 層級記錄。 記錄「層級」 指出已記錄事件的嚴重性。
public class AboutModel : PageModel
{
private readonly ILogger _logger;
public AboutModel(ILogger<AboutModel> logger)
{
_logger = logger;
}
public void OnGet()
{
_logger.LogInformation("About page visited at {DT}",
DateTime.UtcNow.ToLongTimeString());
}
}
如需 Blazor 的相關資訊,請參閱ASP.NET CoreBlazor 記錄。
設定記錄
記錄組態通常是由 appsettings.{ENVIRONMENT}.json
檔案的 Logging
區段所提供,其中 {ENVIRONMENT}
預留位置是環境。 下列 appsettings.Development.json
檔案是由 ASP.NET Core Web 應用程式範本所產生:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
在上述 JSON 中:
- 指定
"Default"
和"Microsoft.AspNetCore"
類別。 "Microsoft.AspNetCore"
類別會套用至開頭為"Microsoft.AspNetCore"
的所有類別。 例如,此設定適用於"Microsoft.AspNetCore.Routing.EndpointMiddleware"
類別。- 記錄層級
Warning
和更高層級的"Microsoft.AspNetCore"
類別記錄。 - 未指定特定的記錄提供者,因此
LogLevel
適用於 Windows EventLog 以外的所有已啟用記錄提供者。
Logging
屬性可以有 LogLevel 與記錄提供者屬性。 LogLevel
會指定要針對所選類別記錄的最小層級。 在上述 JSON 中,會指定 Information
和 Warning
記錄層級。 LogLevel
表示記錄的嚴重性,範圍從 0 到 6:
Trace
= 0、Debug
= 1、Information
= 2、Warning
= 3、Error
= 4、Critical
= 5 和 None
= 6。
指定 LogLevel
時,會針對指定層級和更高層級的訊息啟用記錄。 在上述 JSON 中,Default
類別會以 Information
和更高層級記錄。 例如,會記錄 Information
、Warning
、Error
和 Critical
訊息。 如果未指定 LogLevel
,則記錄預設為 Information
層級。 如需詳細資訊,請參閱記錄層級。
提供者屬性可以指定 LogLevel
屬性。 LogLevel
在提供者下,會指定要針對該提供者記錄的層級,並覆寫非提供者記錄設定。 請考量下列 appsettings.json
檔案:
{
"Logging": {
"LogLevel": { // All providers, LogLevel applies to all the enabled providers.
"Default": "Error", // Default logging, Error and higher.
"Microsoft": "Warning" // All Microsoft* categories, Warning and higher.
},
"Debug": { // Debug provider.
"LogLevel": {
"Default": "Information", // Overrides preceding LogLevel:Default setting.
"Microsoft.Hosting": "Trace" // Debug:Microsoft.Hosting category.
}
},
"EventSource": { // EventSource provider
"LogLevel": {
"Default": "Warning" // All categories of EventSource provider.
}
}
}
}
Logging.{PROVIDER NAME}.LogLevel
中的設定會覆寫 Logging.LogLevel
中的設定,其中 {PROVIDER NAME}
預留位置是提供者名稱。 在上述 JSON 中,Debug
提供者的預設記錄層級會設定為 Information
:
Logging:Debug:LogLevel:Default:Information
上述設定會指定每個 Logging:Debug:
類別的 Information
記錄層級,但 Microsoft.Hosting
除外。 列出特定類別時,特定類別會覆寫預設類別。 在上述 JSON 中,Logging:Debug:LogLevel
類別 "Microsoft.Hosting"
和 "Default"
會覆寫 Logging:LogLevel
中的設定
您可以針對下列任一項目指定最小記錄層級:
- 特定提供者:例如
Logging:EventSource:LogLevel:Default:Information
- 特定類別:例如
Logging:LogLevel:Microsoft:Warning
- 所有提供者和所有類別:
Logging:LogLevel:Default:Warning
低於最低層級的任何記錄都不是:
- 傳遞至提供者。
- 已記錄或顯示。
若要隱藏所有記錄,請指定 LogLevel.None。 LogLevel.None
的值為 6,其高於 LogLevel.Critical
(5)。
若提供者支援記錄範圍,IncludeScopes
會指出是否已啟用記錄範圍。 如需詳細資訊,請參閱記錄範圍。
下列 appsettings.json
檔案包含預設啟用的所有提供者:
{
"Logging": {
"LogLevel": { // No provider, LogLevel applies to all the enabled providers.
"Default": "Error",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Warning"
},
"Debug": { // Debug provider.
"LogLevel": {
"Default": "Information" // Overrides preceding LogLevel:Default setting.
}
},
"Console": {
"IncludeScopes": true,
"LogLevel": {
"Microsoft.AspNetCore.Mvc.Razor.Internal": "Warning",
"Microsoft.AspNetCore.Mvc.Razor.Razor": "Debug",
"Microsoft.AspNetCore.Mvc.Razor": "Error",
"Default": "Information"
}
},
"EventSource": {
"LogLevel": {
"Microsoft": "Information"
}
},
"EventLog": {
"LogLevel": {
"Microsoft": "Information"
}
},
"AzureAppServicesFile": {
"IncludeScopes": true,
"LogLevel": {
"Default": "Warning"
}
},
"AzureAppServicesBlob": {
"IncludeScopes": true,
"LogLevel": {
"Microsoft": "Information"
}
},
"ApplicationInsights": {
"LogLevel": {
"Default": "Information"
}
}
}
}
在上述範例中:
- 類別和層級不是建議的值。 會提供此範例以顯示所有的預設提供者。
Logging.{PROVIDER NAME}.LogLevel
中的設定會覆寫Logging.LogLevel
中的設定,其中{PROVIDER NAME}
預留位置是提供者名稱。 例如,Debug.LogLevel.Default
中的層級會覆寫LogLevel.Default
中的層級。- 會使用每個預設提供者「別名」。 每個提供者都會定義「別名」,可在設定中用來取代完整類型名稱。 內建提供者別名如下:
Console
Debug
EventSource
EventLog
AzureAppServicesFile
AzureAppServicesBlob
ApplicationInsights
登入 Program.cs
下列範例會呼叫 Program.cs
中的 Builder.WebApplication.Logger,並記錄參考訊息:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.Logger.LogInformation("Adding Routes");
app.MapGet("/", () => "Hello World!");
app.Logger.LogInformation("Starting the app");
app.Run();
下列範例會在 Program.cs
中呼叫 AddConsole 並記錄 /Test
端點:
var builder = WebApplication.CreateBuilder(args);
builder.Logging.AddConsole();
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.MapGet("/Test", async (ILogger<Program> logger, HttpResponse response) =>
{
logger.LogInformation("Testing logging in Program.cs");
await response.WriteAsync("Testing");
});
app.Run();
下列範例會在 Program.cs
中呼叫 AddSimpleConsole、停用色彩輸出,並記錄 /Test
端點:
using Microsoft.Extensions.Logging.Console;
var builder = WebApplication.CreateBuilder(args);
builder.Logging.AddSimpleConsole(i => i.ColorBehavior = LoggerColorBehavior.Disabled);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.MapGet("/Test", async (ILogger<Program> logger, HttpResponse response) =>
{
logger.LogInformation("Testing logging in Program.cs");
await response.WriteAsync("Testing");
});
app.Run();
依命令列、環境變數和其他組態設定記錄層級
記錄層級可由任何設定提供者進行設定。
:
分隔符號不適用於所有平台上的環境變數階層式機碼。 例如,Bash 不支援 :
分隔符號。 雙底線, __
,為:
- 所有平台都支援。
- 自動替換為冒號,
:
。
下列 命令:
- 將環境索引鍵
Logging:LogLevel:Microsoft
設定為 Windows 上的Information
值。 - 使用搭配 ASP.NET Core Web 應用程式範本建立的應用程式時,請測試設定。 在使用
set
之後,必須在專案目錄中執行dotnet run
命令。
set Logging__LogLevel__Microsoft=Information
dotnet run
上述環境設定:
- 只會在從其所設定命令視窗啟動的程序中進行設定。
- 不會由使用 Visual Studio 啟動的瀏覽器讀取。
下列 setx 命令也會設定 Windows 上的環境索引鍵和值。 不同於 set
,setx
設定會予以保存。 /M
參數會在系統內容中設定變數。 如果未使用 /M
,則會設定使用者環境變數。
setx Logging__LogLevel__Microsoft Information /M
請考量下列 appsettings.json
檔案:
"Logging": {
"Console": {
"LogLevel": {
"Microsoft.Hosting.Lifetime": "Trace"
}
}
}
下列命令會在環境中設定上述組態:
setx Logging__Console__LogLevel__Microsoft.Hosting.Lifetime Trace /M
注意
在 macOS 和 Linux 中使用包含 .
(句號) 的名稱來設定環境變數時,請考慮 Stack Exchange 上關於 "Exporting a variable with a dot (.) in it" (匯出具有點 (.) 的變數) 的問題,以及其對應的公認答案 (英文)。
在 Azure App Service 上,選取 [設定] > [組態] 頁面上的 [新增應用程式設定]。 Azure App Service 應用程式設定為:
- 在處於 rest 及透過加密通道傳輸時加密。
- 公開為環境變數。
如需詳細資訊,請參閱 Azure App:使用 Azure 入口網站覆寫應用程式設定。
如需使用環境變數設定 ASP.NET Core 組態值的詳細資訊,請參閱環境變數。 如需使用其他組態來源 (包括命令列、Azure Key Vault、Azure 應用程式組態、其他檔案格式等等) 的相關資訊,請參閱 ASP.NET Core 的設定。
如何套用篩選規則
建立 ILogger<TCategoryName> 物件時,ILoggerFactory 物件會針對每個提供者選取一個規則來套用到該記錄器。 由 ILogger
執行個體寫入的所有訊息都會根據選取的規則進行篩選。 系統會從可用的規則中,選取對每個提供者和類別配對最明確的規則。
當建立指定類別的 ILogger
時,系統會針對每個提供者使用下列演算法:
- 選取所有符合提供者或其別名的規則。 如果找不到符合的項目,請選取所有規則搭配空白提供者。
- 從上一個步驟的結果中,選取具有最長相符類別前置字元的規則。 如果找不到符合的項目,請選取未指定類別的所有規則。
- 如果選取多個規則,請使用最後一個。
- 如果未選取任何規則,請使用
MinimumLevel
。
記錄 dotnet run 和 Visual Studio 的輸出
使用預設記錄提供者建立的記錄會顯示:
- 在 Visual Studio 中
- 在 [偵錯輸出] 視窗中 (偵錯時)。
- 在 [ASP.NET Core Web 伺服器] 視窗中。
- 在主控台視窗中 (使用
dotnet run
執行應用程式時)。
開頭為 "Microsoft" 類別的記錄來自 .NET。 .NET 與應用程式程式碼會使用相同的記錄 API 與提供者。
記錄類別
建立 ILogger
物件時,會指定「類別」。 該類別會包含在每個由該 ILogger
執行個體所產生的記錄訊息中。 類別字串為任意值,但慣例是使用完整類別名稱。 例如,在控制器中,名稱可能是 "TodoApi.Controllers.TodoController"
。 ASP.NET Core Web 應用程式會使用 ILogger<T>
來自動取得 ILogger
執行個體,該執行個體會使用 T
的完整類型名稱來做為類別:
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.");
}
}
如果需要進一步分類,慣例是藉由將子類別目錄附加至完整類別名稱,並使用 ILoggerFactory.CreateLogger
明確地指定類別目錄,以使用階層式名稱:
public class ContactModel : PageModel
{
private readonly ILogger _logger;
public ContactModel(ILoggerFactory logger)
{
_logger = logger.CreateLogger("TodoApi.Pages.ContactModel.MyCategory");
}
public void OnGet()
{
_logger.LogInformation("GET Pages.ContactModel called.");
}
在多個方法中使用時,以固定名稱呼叫 CreateLogger
可能會很有用,因此可依類別來組織事件。
ILogger<T>
相當於使用 T
的完整類型名稱來呼叫 CreateLogger
。
記錄等級
下表列出 LogLevel 值、便利的 Log{LogLevel}
擴充方法和建議的使用方式:
LogLevel | 值 | 方法 | 描述 |
---|---|---|---|
Trace | 0 | LogTrace | 包含最詳細的訊息。 這些訊息可能包含敏感性應用程式資料。 這些訊息預設會停用,且不應在生產環境中啟用。 |
Debug | 1 | LogDebug | 用於偵錯和開發。 由於大量,因此在生產環境中請謹慎使用。 |
Information | 2 | LogInformation | 追蹤一般應用程式流程。 可能具有長期值。 |
Warning | 3 | LogWarning | 針對異常或意外事件。 通常包含不會導致應用程式失敗的錯誤或狀況。 |
Error | 4 | LogError | 發生無法處理的錯誤和例外狀況。 這些訊息指出目前作業或要求中發生失敗,而不是整個應用程式的失敗。 |
Critical | 5 | LogCritical | 發生需要立即注意的失敗。 範例:資料遺失情況、磁碟空間不足。 |
None | 6 | 指定記錄類別不應寫入訊息。 |
在上表中,會從最低到最高嚴重性列出 LogLevel
。
Log 方法的第一個參數 (LogLevel) 表示記錄的嚴重性。 大部分開發人員會呼叫 Log{LOG LEVEL}
擴充方法 (其中 {LOG LEVEL}
預留位置是記錄層級),而不是呼叫 Log(LogLevel, ...)
。 例如,下列兩個記錄呼叫在功能上相等,並產生相同的記錄:
[HttpGet]
public IActionResult Test1(int id)
{
var routeInfo = ControllerContext.ToCtxString(id);
_logger.Log(LogLevel.Information, MyLogEvents.TestItem, routeInfo);
_logger.LogInformation(MyLogEvents.TestItem, routeInfo);
return ControllerContext.MyDisplayRouteInfo();
}
MyLogEvents.TestItem
為事件識別碼。 MyLogEvents
是範例應用程式的一部分,且會顯示在記錄事件識別碼區段中。
MyDisplayRouteInfo 和 ToCtxString 是由 Rick.Docs.Samples.RouteInfo NuGet 套件提供。 方法會顯示 Controller
和 Razor Page
路由資訊。
下列程式碼會建立 Information
與 Warning
記錄:
[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);
}
在上述程式碼中,第一個 Log{LOG LEVEL}
參數 (MyLogEvents.GetItem
) 是記錄事件識別碼。 第二個參數是訊息範本,其中的預留位置會置入其餘方法參數所提供的引數值。 此文件稍後的訊息範本小節將詳細說明方法參數。
呼叫適當的 Log{LOG LEVEL}
方法來控制要寫入至特定儲存媒體的記錄輸出量。 例如:
- 生產環境:
Trace
、Debug
或Information
層級的記錄會產生大量的詳細記錄訊息。 若要控制成本,且不超過資料儲存體限制,請將Trace
、Debug
或Information
層級訊息記錄為大量、低成本的資料存放區。 請考慮將Trace
、Debug
或Information
限制為特定類別。- 透過
Critical
層級的Warning
記錄應該會產生一些記錄訊息。- 成本和儲存體限制通常無所謂。
- 記錄數少可讓資料存放區選擇更具彈性。
- 開發中:
- 設定為
Warning
。 - 進行疑難排解時,新增
Trace
、Debug
或Information
訊息。 若要限制輸出,請僅針對調查中的類別設定Trace
、Debug
或Information
。
- 設定為
ASP.NET Core 會寫入架構事件的記錄。 例如,請考慮下列項目的記錄輸出:
- 使用 ASP.NET Core 範本建立的 Razor Pages 應用程式。
- 記錄設定為
Logging:Console:LogLevel:Microsoft:Information
。 - 瀏覽至 Privacy 頁面:
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
Request starting HTTP/2 GET https://localhost:5001/Privacy
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
Executing endpoint '/Privacy'
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[3]
Route matched with {page = "/Privacy"}. Executing page /Privacy
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[101]
Executing handler method DefaultRP.Pages.PrivacyModel.OnGet - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[102]
Executed handler method OnGet, returned result .
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[103]
Executing an implicit handler method - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[104]
Executed an implicit handler method, returned result Microsoft.AspNetCore.Mvc.RazorPages.PageResult.
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[4]
Executed page /Privacy in 74.5188ms
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
Executed endpoint '/Privacy'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
Request finished in 149.3023ms 200 text/html; charset=utf-8
下列 JSON 會設定 Logging:Console:LogLevel:Microsoft:Information
:
{
"Logging": { // Default, all providers.
"LogLevel": {
"Microsoft": "Warning"
},
"Console": { // Console provider.
"LogLevel": {
"Microsoft": "Information"
}
}
}
}
記錄事件識別碼
每個記錄都可以指定「事件識別碼」。 範例應用程式會使用 MyLogEvents
類別來定義事件識別碼:
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);
}
事件識別碼會將一組事件關聯。 例如,與在頁面上顯示項目清單相關的所有記錄可能都是 1001。
記錄提供者可能將事件識別碼存放到識別碼欄位、記錄訊息中或完全不存放。 偵錯提供者不會顯示事件識別碼。 主控台提供者會在類別後面以括弧顯示事件識別碼:
info: TodoApi.Controllers.TodoItemsController[1002]
Getting item 1
warn: TodoApi.Controllers.TodoItemsController[4000]
Get(1) NOT FOUND
有些記錄提供者會將事件識別碼儲存在欄位中,以允許篩選識別碼。
記錄訊息範本
每個記錄 API 都會使用訊息範本。 訊息範本可以包含有關提供哪個引數的預留位置。 使用名稱而非數字做為預留位置。
[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);
}
參數的順序 (而不是其預留位置名稱) 會決定哪些參數可用來在記錄訊息中提供預留位置值。 在下列程式碼中,參數名稱在訊息範本的預留位置中未依順序出現:
var apples = 1;
var pears = 2;
var bananas = 3;
_logger.LogInformation("Parameters: {Pears}, {Bananas}, {Apples}", apples, pears, bananas);
不過,參數會依序指派給預留位置:apples
、pears
、bananas
。 記錄訊息會反映「參數的順序」:
Parameters: 1, 2, 3
此方法可讓記錄提供者實作語意或結構化記錄。 引數本身會被傳遞到記錄系統,而不只是格式化的訊息範本。 這可讓記錄提供者將參數值儲存為欄位。 例如,請考量下列記錄器方法:
_logger.LogInformation("Getting item {Id} at {RequestTime}", id, DateTime.Now);
例如,登入 Azure 資料表儲存體時:
- 每個 Azure 資料表實體都可以有
ID
和RequestTime
屬性。 - 具有屬性的資料表可簡化針對記錄資料的查詢。 例如,查詢可以尋找特定
RequestTime
範圍內的所有記錄,而不必剖析文字訊息中的時間。
記錄例外狀況
記錄器方法具有多載可接受例外狀況參數:
[HttpGet("{id}")]
public IActionResult TestExp(int id)
{
var routeInfo = ControllerContext.ToCtxString(id);
_logger.LogInformation(MyLogEvents.TestItem, routeInfo);
try
{
if (id == 3)
{
throw new Exception("Test exception");
}
}
catch (Exception ex)
{
_logger.LogWarning(MyLogEvents.GetItemNotFound, ex, "TestExp({Id})", id);
return NotFound();
}
return ControllerContext.MyDisplayRouteInfo();
}
MyDisplayRouteInfo 和 ToCtxString 是由 Rick.Docs.Samples.RouteInfo NuGet 套件提供。 方法會顯示 Controller
和 Razor Page
路由資訊。
例外狀況記錄是提供者特定的。
預設記錄層級
如果未設定預設記錄層級,則預設記錄層級值為 Information
。
例如,請考量下列 Web 應用程式:
- 使用 ASP.NET Web 應用程式範本所建立。
appsettings.json
和appsettings.Development.json
已刪除或重新命名。
在上述設定中,瀏覽至 privacy 或 home 頁面會產生類別名稱中具有 Microsoft
的許多 Trace
、Debug
和 Information
訊息。
下列程式碼會在設定中未設定預設記錄層級時,設定預設記錄層級:
var builder = WebApplication.CreateBuilder();
builder.Logging.SetMinimumLevel(LogLevel.Warning);
一般而言,應該在組態而不是程式碼中指定記錄層級。
Filter 函式
針對組態或程式碼未指派規則的所有提供者和類別,會叫用篩選函式:
var builder = WebApplication.CreateBuilder();
builder.Logging.AddFilter((provider, category, logLevel) =>
{
if (provider.Contains("ConsoleLoggerProvider")
&& category.Contains("Controller")
&& logLevel >= LogLevel.Information)
{
return true;
}
else if (provider.Contains("ConsoleLoggerProvider")
&& category.Contains("Microsoft")
&& logLevel >= LogLevel.Information)
{
return true;
}
else
{
return false;
}
});
上述程式碼會在類別包含 Controller
或 Microsoft
且記錄層級為 Information
或更高層級時顯示主控台記錄。
一般而言,應該在組態而不是程式碼中指定記錄層級。
ASP.NET Core 類別
下表包含 ASP.NET Core 所使用的一些類別。
類別 | 備註 |
---|---|
Microsoft.AspNetCore |
一般 ASP.NET Core 診斷。 |
Microsoft.AspNetCore.DataProtection |
已考慮、發現及使用哪些金鑰。 |
Microsoft.AspNetCore.HostFiltering |
允許主機。 |
Microsoft.AspNetCore.Hosting |
HTTP 要求花了多少時間完成,以及其開始時間。 載入了哪些裝載啟動組件。 |
Microsoft.AspNetCore.Mvc |
MVC 和 Razor 診斷。 模型繫結、篩選執行、檢視編譯、動作選取。 |
Microsoft.AspNetCore.Routing |
路由比對資訊。 |
Microsoft.AspNetCore.Server |
連線開始、停止與保持運作回應。 HTTPS 憑證資訊。 |
Microsoft.AspNetCore.StaticFiles |
提供的檔案。 |
若要在主控台視窗中檢視更多類別,請將 appsettings.Development.json
設定為下列項目:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Trace",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
如需 Entity Framework 類別清單,請參閱 EF 訊息類別。
記錄範圍
「範圍」可用來將邏輯作業組成群組。 此分組功能可用來將相同的資料附加到已建立為集合之一部分的每個記錄。 例如,在處理邀交易時建立的每個記錄都可以包括該交易識別碼。
範圍:
- 這是 BeginScope 方法所傳回的 IDisposable 類型。
- 會持續到處置為止。
下列提供者支援範圍:
透過將記錄器呼叫封裝在 using
區塊中以使用範圍:
[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
TodoItem todoItem;
var transactionId = Guid.NewGuid().ToString();
using (_logger.BeginScope(new List<KeyValuePair<string, object>>
{
new KeyValuePair<string, object>("TransactionId", transactionId),
}))
{
_logger.LogInformation(MyLogEvents.GetItem, "Getting item {Id}", id);
todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
_logger.LogWarning(MyLogEvents.GetItemNotFound,
"Get({Id}) NOT FOUND", id);
return NotFound();
}
}
return ItemToDTO(todoItem);
}
內建記錄提供者
ASP.NET Core 包含下列記錄提供者做為共用架構的一部分:
下列記錄提供者是由 Microsoft 提供,但不是共用架構的一部分。 必須將其安裝做為額外的 NuGet。
ASP.NET Core 不包含記錄提供者,可用來將記錄寫入檔案。 若要從 ASP.NET Core 應用程式將記錄寫入檔案,請考慮使用協力廠商記錄提供者。
如需使用 ASP.NET Core 模組進行 stdout
和偵錯記錄的相關資訊,請參閱針對 Azure App Service 上的 ASP.NET Core 進行疑難排解,以及 ASP.NET Core Module (ANCM) for IIS。
主控台
Console
提供者會將輸出記錄到主控台。 如需在開發中檢視 Console
記錄的相關詳細資訊,請參閱記錄 dotnet run 和 Visual Studio 的輸出。
偵錯
Debug
提供者會使用 System.Diagnostics.Debug 類別來寫入記錄輸出。 呼叫 System.Diagnostics.Debug.WriteLine
寫入 Debug
提供者。
在 Linux 上,Debug
提供者記錄位置與散發相依,可能是下列其中一項:
/var/log/message
/var/log/syslog
事件來源
EventSource
提供者會寫入名稱為 Microsoft-Extensions-Logging
的跨平台事件來源。 在 Windows 上,提供者會使用 ETW。
dotnet-trace 工具
dotnet-trace
工具是一種跨平台 CLI 全域工具,可收集執行中程序的 .NET Core 追蹤。 此工具會使用 LoggingEventSource 收集 Microsoft.Extensions.Logging.EventSource 提供者資料。
如需安裝指示,請參閱 dotnet-trace
。
使用 dotnet-trace
工具從應用程式收集追蹤:
使用
dotnet run
命令執行應用程式。判斷 .NET Core 應用程式的程序識別碼 (PID):
dotnet-trace ps
尋找與應用程式元件名稱相同程序的 PID。
執行
dotnet-trace
命令。一般命令語法:
dotnet-trace collect -p {PID} --providers Microsoft-Extensions-Logging:{Keyword}:{Provider Level} :FilterSpecs=\" {Logger Category 1}:{Category Level 1}; {Logger Category 2}:{Category Level 2}; ... {Logger Category N}:{Category Level N}\"
使用 PowerShell 命令殼層時,以單引號括住
--providers
值 ('
):dotnet-trace collect -p {PID} --providers 'Microsoft-Extensions-Logging:{Keyword}:{Provider Level} :FilterSpecs=\" {Logger Category 1}:{Category Level 1}; {Logger Category 2}:{Category Level 2}; ... {Logger Category N}:{Category Level N}\"'
在非 Windows 平台上,新增
-f speedscope
選項,將輸出追蹤檔案的格式變更為speedscope
。下表會定義關鍵字:
關鍵字 描述 1 記錄有關 LoggingEventSource
的中繼事件。 不會記錄來自ILogger
的事件。2 呼叫 ILogger.Log()
時,開啟Message
。 以程式設計 (而非格式化) 的方式提供資訊。4 呼叫 ILogger.Log()
時,開啟FormatMessage
。 提供資訊的格式化字串版本。8 呼叫 ILogger.Log()
時,開啟MessageJson
。 提供引數的 JSON 表示法。下表列出提供者層級:
提供者層級 描述 0 LogAlways
1 Critical
2 Error
3 Warning
4 Informational
5 Verbose
類別層級的剖析可以是字串或數字:
類別具名值 數值 Trace
0 Debug
1 Information
2 Warning
3 Error
4 Critical
5 提供者層級和類別層級:
- 是反向順序。
- 字串常數不完全相同。
如果未指定
FilterSpecs
,則EventSourceLogger
實作會嘗試將提供者層級轉換成類別層級,並將其套用至所有類別。提供者層級 類別層級 Verbose
(5)Debug
(1)Informational
(4)Information
(2)Warning
(3)Warning
(3)Error
(2)Error
(4)Critical
(1)Critical
(5)如果已提供
FilterSpecs
,則清單中所包含的任何類別都會使用在該處編碼的類別層級,並會篩選掉所有其他類別。下列範例假設:
- 應用程式正在執行並呼叫
logger.LogDebug("12345")
。 - 已透過
set PID=12345
設定程序識別碼 (PID),其中12345
是實際的 PID。
請考慮下列命令:
dotnet-trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:5
上述命令會:
- 擷取偵錯訊息。
- 不會套用
FilterSpecs
。 - 指定層級 5,其可對應類別偵錯。
請考慮下列命令:
dotnet-trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:5:\"FilterSpecs=*:5\"
上述命令會:
- 不會擷取偵錯訊息,因為類別層級 5 是
Critical
。 - 可提供
FilterSpecs
。
下列命令會擷取偵錯訊息,因為類別層級 1 指定
Debug
。dotnet-trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:5:\"FilterSpecs=*:1\"
下列命令會擷取偵錯訊息,因為類別指定
Debug
。dotnet-trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:5:\"FilterSpecs=*:Debug\"
{Logger Category}
和{Category Level}
的FilterSpecs
代表其他記錄篩選條件。 以;
分號字元分隔FilterSpecs
項目。使用 Windows 命令殼層的範例:
dotnet-trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:2:FilterSpecs=\"Microsoft.AspNetCore.Hosting*:4\"
上述命令會啟動︰
- 事件來源記錄器,可針對錯誤 (
2
) 產生格式化字串 (4
)。 Informational
記錄層級 (4
) 的Microsoft.AspNetCore.Hosting
記錄。
按下 Enter 鍵或 Ctrl+C 以停止
dotnet-trace
工具。追蹤會以
trace.nettrace
名稱儲存在執行dotnet-trace
命令的資料夾中。使用 Perfview 開啟追蹤。 開啟
trace.nettrace
檔案並探索追蹤事件。
如果應用程式未使用 WebApplication.CreateBuilder 建置主機,請將事件來源提供者新增至應用程式的記錄設定。
如需詳細資訊,請參閱
- 效能分析公用程式的追蹤 (
dotnet-trace
) (.NET Core 文件) - 效能分析公用程式的追蹤 (
dotnet-trace
) (dotnet/diagnostics GitHub 存放庫文件) - LoggingEventSource
- EventLevel
- Perfview:對檢視事件來源追蹤相當有用。
Perfview
使用 PerfView 公用程式來收集和檢視記錄。 此外還有一些其他工具可檢視 ETW 記錄,但 PerfView 提供處理 ASP.NET Core 所發出 ETW 事件的最佳體驗。
若要設定 PerfView 以收集此提供者所記錄的事件,請將字串 *Microsoft-Extensions-Logging
新增至 [其他提供者] 清單 請勿遺漏字串開頭的 *
。
Windows EventLog
EventLog
提供者會將記錄輸出傳送至 Windows 事件記錄檔。 與其他提供者不同,EventLog
提供者不會繼承預設的非提供者設定。 如果未指定 EventLog
記錄設定,則預設為 LogLevel.Warning。
若要記錄低於 LogLevel.Warning 的事件,請明確設定記錄層級。 下列範例會將事件記錄檔預設記錄層級設定為 LogLevel.Information:
"Logging": {
"EventLog": {
"LogLevel": {
"Default": "Information"
}
}
}
AddEventLog 多載可以傳入 EventLogSettings。 如果 null
或未指定,則會使用下列預設設定:
LogName
:「應用程式」SourceName
:「.NET Runtime」MachineName
:使用本機電腦名稱。
下列程式碼會將 SourceName
從 ".NET Runtime"
的預設值變更為 MyLogs
:
var builder = WebApplication.CreateBuilder();
builder.Logging.AddEventLog(eventLogSettings =>
{
eventLogSettings.SourceName = "MyLogs";
});
Azure App Service
Microsoft.Extensions.Logging.AzureAppServices
提供者套件會將記錄寫入至 Azure App Service 應用程式檔案系統中的文字檔,並寫入至 Azure 儲存體帳戶中的 Blob 儲存體。
該提供者套件並未包含在共用架構中。 若要使用提供者,請將提供者套件新增至專案。
如果要進行提供者設定,請使用 AzureFileLoggerOptions 和 AzureBlobLoggerOptions,如以下範例中所示:
using Microsoft.Extensions.Logging.AzureAppServices;
var builder = WebApplication.CreateBuilder();
builder.Logging.AddAzureWebAppDiagnostics();
builder.Services.Configure<AzureFileLoggerOptions>(options =>
{
options.FileName = "azure-diagnostics-";
options.FileSizeLimit = 50 * 1024;
options.RetainedFileCountLimit = 5;
});
builder.Services.Configure<AzureBlobLoggerOptions>(options =>
{
options.BlobName = "log.txt";
});
當部署到 Azure App Service 時,應用程式會使用 Azure 入口網站 [App Service] 頁面中 App Service 記錄區段的設定。 當下列設定更新時,變更會立即生效,而不需要重新啟動或重新部署應用程式。
- 應用程式記錄 (檔案系統)
- 應用程式記錄 (Blob)
記錄檔的預設位置位於 D:\\home\\LogFiles\\Application
資料夾中,而預設檔案名稱為 diagnostics-yyyymmdd.txt
。 預設檔案大小限制為 10 MB,而預設保留的檔案數目上限為 2。 預設 Blob 名稱為 {app-name}{timestamp}/yyyy/mm/dd/hh/{guid}-applicationLog.txt
。
此提供者僅記錄專案在 Azure 環境中執行的情況。
Azure 記錄串流
Azure 記錄串流可支援即時檢視來自下列位置的記錄活動:
- 應用程式伺服器
- 網頁伺服器
- 失敗要求的追蹤
若要設定 Azure 記錄資料流:
- 從應用程式的入口網站頁面瀏覽到 [App Service 記錄]。
- 將 [應用程式記錄 (檔案系統)] 設定為 [開啟]。
- 選擇記錄 [層級]。 此設定僅適用於 Azure 記錄串流。
瀏覽到 [記錄資料流] 頁面以檢視記錄。 記錄的訊息會與 ILogger
介面一起記錄。
Azure Application Insights
Microsoft.Extensions.Logging.ApplicationInsights
提供者封裝會將記錄寫入 Azure Application Insights。 Application Insights 是可監視 Web 應用程式的服務,並提供可用來查詢及分析遙測資料的工具。 如果您使用此提供者,就可以使用 Application Insights 工具來查詢及分析記錄。
記錄提供者會以 Microsoft.ApplicationInsights.AspNetCore
的相依性形式隨附,這是針對 ASP.NET Core 提供所有可用遙測的套件。 如果您使用此套件,就不需安裝提供者套件。
Microsoft.ApplicationInsights.Web
套件適用於 ASP.NET 4.x,而不適用於 ASP.NET Core。
如需詳細資訊,請參閱以下資源:
- Application Insights 概觀
- 適用於 ASP.NET Core 應用程式的 Application Insights:如果您想要實作完整範圍的 Application Insights 遙測以及記錄,請從這裡開始。
- 適用於 .NET Core ILogger 記錄的 ApplicationInsightsLoggerProvider:如果您想要實作記錄提供者,而不需要 Application Insights 遙測的 rest 部分,請從這裡開始。
- Application Insights 記錄配接器
- 安裝、設定及初始化 Application Insights SDK 的互動式教學課程。
協力廠商記錄提供者
可搭配 ASP.NET Core 使用的協力廠商記錄架構:
- elmah.io (GitHub 存放庫)
- Gelf (GitHub 存放庫)
- JSNLog (GitHub 存放庫)
- KissLog.net (GitHub 存放庫)
- Log4Net (GitHub 存放庫)
- NLog (GitHub 存放庫)
- PLogger (GitHub 存放庫)
- Sentry (GitHub 存放庫)
- Serilog (GitHub 存放庫)
- Stackdriver (Github 存放庫)
某些協力廠商架構可以執行語意記錄 (也稱為結構化記錄) \(英文\)。
使用協力廠商架構類似於使用內建的提供者之一:
- 將 NuGet 套件新增至專案。
- 呼叫記錄架構所提供的
ILoggerFactory
擴充方法。
如需詳細資訊,請參閱每個提供者的文件。 Microsoft 不支援第三方記錄提供者。
無非同步記錄器方法
記錄速度應該很快,不值得花費非同步程式碼的效能成本來處理。 若記錄資料存放區很慢,請不要直接寫入其中。 請考慮一開始將記錄寫入到快速的存放區,稍後再將其移到慢速存放區。 例如,當記錄到 SQL Server 時,請勿在 Log
方法中直接執行,因為 Log
方法是同步的。 相反地,以同步方式將記錄訊息新增到記憶體內佇列,並讓背景工作角色提取出佇列的訊息,藉此執行推送資料到 SQL Server 的非同步工作。 如需詳細資訊,請參閱如何針對慢速資料存放區 (dotnet/AspNetCore.Docs #11801) 登入訊息佇列的指引。
變更執行中應用程式的記錄層級
記錄 API 不包含應用程式執行時變更記錄層級的案例。 不過,某些組態提供者能夠重新載入組態,這會立即對記錄組態生效。 例如,檔案組態提供者預設會重新載入記錄組態。 如果應用程式執行時在程式碼中變更組態,則應用程式可以呼叫 IConfigurationRoot.Reload 來更新應用程式的記錄組態。
ILogger 和 ILoggerFactory
ILogger<TCategoryName> 和 ILoggerFactory 介面及實作會包含在 .NET Core SDK 中。 其也可以在下列 NuGet 套件中使用:
- 介面位於
Microsoft.Extensions.Logging.Abstractions
中。 - 預設實作位於
Microsoft.Extensions.Logging
中。
在程式碼中套用記錄篩選規則
設定記錄篩選規則的慣用方法是使用組態。
下列範例說明如何在程式碼中註冊篩選規則:
using Microsoft.Extensions.Logging.Console;
using Microsoft.Extensions.Logging.Debug;
var builder = WebApplication.CreateBuilder();
builder.Logging.AddFilter("System", LogLevel.Debug);
builder.Logging.AddFilter<DebugLoggerProvider>("Microsoft", LogLevel.Information);
builder.Logging.AddFilter<ConsoleLoggerProvider>("Microsoft", LogLevel.Trace);
logging.AddFilter("System", LogLevel.Debug)
會指定 System
類別和記錄層級 Debug
。 篩選條件會套用至所有提供者,因為未設定特定提供者。
AddFilter<DebugLoggerProvider>("Microsoft", LogLevel.Information)
會指定:
Debug
記錄提供者。- 記錄層級
Information
和更新版本。 - 從
"Microsoft"
開始的所有類別。
使用 SpanId
、TraceId
、ParentId
、Baggage
和 Tags
自動記錄範圍。
記錄程式庫會隱含地使用 SpanId
、TraceId
、ParentId
、Baggage
和 Tags
來建立範圍物件。 此行為是透過 ActivityTrackingOptions 進行設定。
var builder = WebApplication.CreateBuilder(args);
builder.Logging.AddSimpleConsole(options =>
{
options.IncludeScopes = true;
});
builder.Logging.Configure(options =>
{
options.ActivityTrackingOptions = ActivityTrackingOptions.SpanId
| ActivityTrackingOptions.TraceId
| ActivityTrackingOptions.ParentId
| ActivityTrackingOptions.Baggage
| ActivityTrackingOptions.Tags;
});
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
如果已設定 traceparent
http 要求標頭,則記錄範圍中的 ParentId
會顯示來自輸入 traceparent
標頭的 W3C parent-id
,而記錄範圍中的 SpanId
會顯示下一個輸出步驟/範圍的更新 parent-id
。 如需詳細資訊,請參閱變動 traceparent 欄位。
建立自訂記錄器
若要建立自訂記錄器,請參閱在 .NET 中實作自訂記錄提供者。
其他資源
作者:Kirk Larkin、Juergen Gutsch 和 Rick Anderson
本主題描述在 .NET 中記錄,因為其適用於 ASP.NET Core 應用程式。 如需在 .NET 中記錄的詳細資訊,請參閱在 .NET 中記錄。 如需有關在 Blazor 應用程式中記錄的詳細資訊,請參閱 ASP.NET Core Blazor 記錄。
檢視或下載範例程式碼 (如何下載)。
記錄提供者
記錄提供者會儲存記錄,但顯示記錄的 Console
提供者則除外。 例如,Azure Application Insights 提供者會將記錄儲存在 Azure Application Insights 中。 您可以啟用多個提供者。
預設 ASP.NET Core Web 應用程式範本:
- 使用泛型主機。
- 呼叫 CreateDefaultBuilder,可新增下列記錄提供者:
- 主控台
- 偵錯
- EventSource
- EventLog:僅限 Windows
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
上述程式碼會顯示使用 ASP.NET Core Web 應用程式範本建立的 Program
類別。 接下來的幾節會根據使用泛型主機的 ASP.NET Core Web 應用程式範本來提供範例。 本文件稍後將討論非主機主控台應用程式。
若要覆寫 Host.CreateDefaultBuilder
所新增的記錄提供者預設集,請呼叫 ClearProviders
並新增必要的記錄提供者。 例如,下列程式碼:
- 呼叫 ClearProviders 以從建立器中移除所有 ILoggerProvider 執行個體。
- 新增主控台記錄提供者。
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.AddConsole();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
如需其他提供者,請參閱:
建立記錄
若要建立記錄,請使用ILogger<TCategoryName>相依性插入 (DI) 的物件。
下列範例將:
- 建立記錄器 (
ILogger<AboutModel>
),這個記錄器會使用類型AboutModel
完整名稱的記錄類別。 記錄「類別」是與每個記錄關聯的字串。 - 呼叫 LogInformation 以在
Information
層級記錄。 記錄「層級」 指出已記錄事件的嚴重性。
public class AboutModel : PageModel
{
private readonly ILogger _logger;
public AboutModel(ILogger<AboutModel> logger)
{
_logger = logger;
}
public string Message { get; set; }
public void OnGet()
{
Message = $"About page visited at {DateTime.UtcNow.ToLongTimeString()}";
_logger.LogInformation(Message);
}
}
如需 Blazor 的相關資訊,請參閱ASP.NET CoreBlazor 記錄。
在 Main 和 Startup 中建立記錄示範如何在 Main
和 Startup
中建立記錄。
設定記錄
記錄組態通常是由 appsettings.{Environment}.json
檔案的 Logging
區段所提供。 下列 appsettings.Development.json
檔案是由 ASP.NET Core Web 應用程式範本所產生:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
在上述 JSON 中:
- 指定
"Default"
、"Microsoft"
和"Microsoft.Hosting.Lifetime"
類別。 "Microsoft"
類別會套用至開頭為"Microsoft"
的所有類別。 例如,此設定適用於"Microsoft.AspNetCore.Routing.EndpointMiddleware"
類別。- 記錄層級
Warning
和更高層級的"Microsoft"
類別記錄。 "Microsoft.Hosting.Lifetime"
類別比"Microsoft"
類別更具體,因此"Microsoft.Hosting.Lifetime"
類別會記錄「資訊」記錄層級和更高層級。- 未指定特定的記錄提供者,因此
LogLevel
適用於 Windows EventLog 以外的所有已啟用記錄提供者。
Logging
屬性可以有 LogLevel 與記錄提供者屬性。 LogLevel
會指定要針對所選類別記錄的最小層級。 在上述 JSON 中,會指定 Information
和 Warning
記錄層級。 LogLevel
表示記錄的嚴重性,範圍從 0 到 6:
Trace
= 0、Debug
= 1、Information
= 2、Warning
= 3、Error
= 4、Critical
= 5 和 None
= 6。
指定 LogLevel
時,會針對指定層級和更高層級的訊息啟用記錄。 在上述 JSON 中,Default
類別會以 Information
和更高層級記錄。 例如,會記錄 Information
、Warning
、Error
和 Critical
訊息。 如果未指定 LogLevel
,則記錄預設為 Information
層級。 如需詳細資訊,請參閱記錄層級。
提供者屬性可以指定 LogLevel
屬性。 LogLevel
在提供者下,會指定要針對該提供者記錄的層級,並覆寫非提供者記錄設定。 請考量下列 appsettings.json
檔案:
{
"Logging": {
"LogLevel": { // All providers, LogLevel applies to all the enabled providers.
"Default": "Error", // Default logging, Error and higher.
"Microsoft": "Warning" // All Microsoft* categories, Warning and higher.
},
"Debug": { // Debug provider.
"LogLevel": {
"Default": "Information", // Overrides preceding LogLevel:Default setting.
"Microsoft.Hosting": "Trace" // Debug:Microsoft.Hosting category.
}
},
"EventSource": { // EventSource provider
"LogLevel": {
"Default": "Warning" // All categories of EventSource provider.
}
}
}
}
Logging.{providername}.LogLevel
中的設定會覆寫 Logging.LogLevel
中的設定。 在上述 JSON 中,Debug
提供者的預設記錄層級會設定為 Information
:
Logging:Debug:LogLevel:Default:Information
上述設定會指定每個 Logging:Debug:
類別的 Information
記錄層級,但 Microsoft.Hosting
除外。 列出特定類別時,特定類別會覆寫預設類別。 在上述 JSON 中,Logging:Debug:LogLevel
類別 "Microsoft.Hosting"
和 "Default"
會覆寫 Logging:LogLevel
中的設定
您可以針對下列任一項目指定最小記錄層級:
- 特定提供者:例如
Logging:EventSource:LogLevel:Default:Information
- 特定類別:例如
Logging:LogLevel:Microsoft:Warning
- 所有提供者和所有類別:
Logging:LogLevel:Default:Warning
低於最低層級的任何記錄都不是:
- 傳遞至提供者。
- 已記錄或顯示。
若要隱藏所有記錄,請指定 LogLevel.None。 LogLevel.None
的值為 6,其高於 LogLevel.Critical
(5)。
若提供者支援記錄範圍,IncludeScopes
會指出是否已啟用記錄範圍。 如需詳細資訊,請參閱記錄範圍
下列 appsettings.json
檔案包含預設啟用的所有提供者:
{
"Logging": {
"LogLevel": { // No provider, LogLevel applies to all the enabled providers.
"Default": "Error",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Warning"
},
"Debug": { // Debug provider.
"LogLevel": {
"Default": "Information" // Overrides preceding LogLevel:Default setting.
}
},
"Console": {
"IncludeScopes": true,
"LogLevel": {
"Microsoft.AspNetCore.Mvc.Razor.Internal": "Warning",
"Microsoft.AspNetCore.Mvc.Razor.Razor": "Debug",
"Microsoft.AspNetCore.Mvc.Razor": "Error",
"Default": "Information"
}
},
"EventSource": {
"LogLevel": {
"Microsoft": "Information"
}
},
"EventLog": {
"LogLevel": {
"Microsoft": "Information"
}
},
"AzureAppServicesFile": {
"IncludeScopes": true,
"LogLevel": {
"Default": "Warning"
}
},
"AzureAppServicesBlob": {
"IncludeScopes": true,
"LogLevel": {
"Microsoft": "Information"
}
},
"ApplicationInsights": {
"LogLevel": {
"Default": "Information"
}
}
}
}
在上述範例中:
- 類別和層級不是建議的值。 會提供此範例以顯示所有的預設提供者。
Logging.{providername}.LogLevel
中的設定會覆寫Logging.LogLevel
中的設定。 例如,Debug.LogLevel.Default
中的層級會覆寫LogLevel.Default
中的層級。- 會使用每個預設提供者「別名」。 每個提供者都會定義「別名」,可在設定中用來取代完整類型名稱。 內建提供者別名如下:
- 主控台
- 偵錯
- EventSource
- EventLog
- AzureAppServicesFile
- AzureAppServicesBlob
- ApplicationInsights
依命令列、環境變數和其他組態設定記錄層級
記錄層級可由任何設定提供者進行設定。
:
分隔符號不適用於所有平台上的環境變數階層式機碼。 例如,Bash 不支援 :
分隔符號。 雙底線, __
,為:
- 所有平台都支援。
- 自動替換為冒號,
:
。
下列 命令:
- 將環境索引鍵
Logging:LogLevel:Microsoft
設定為 Windows 上的Information
值。 - 使用搭配 ASP.NET Core Web 應用程式範本建立的應用程式時,請測試設定。 在使用
set
之後,必須在專案目錄中執行dotnet run
命令。
set Logging__LogLevel__Microsoft=Information
dotnet run
上述環境設定:
- 只會在從其所設定命令視窗啟動的程序中進行設定。
- 不會由使用 Visual Studio 啟動的瀏覽器讀取。
下列 setx 命令也會設定 Windows 上的環境索引鍵和值。 不同於 set
,setx
設定會予以保存。 /M
參數會在系統內容中設定變數。 如果未使用 /M
,則會設定使用者環境變數。
setx Logging__LogLevel__Microsoft Information /M
請考量下列 appsettings.json
檔案:
"Logging": {
"Console": {
"LogLevel": {
"Microsoft.Hosting.Lifetime": "Trace"
}
}
}
下列命令會在環境中設定上述組態:
setx Logging__Console__LogLevel__Microsoft.Hosting.Lifetime Trace /M
在 Azure App Service 上,選取 [設定] > [組態] 頁面上的 [新增應用程式設定]。 Azure App Service 應用程式設定為:
- 在處於 rest 及透過加密通道傳輸時加密。
- 公開為環境變數。
如需詳細資訊,請參閱 Azure App:使用 Azure 入口網站覆寫應用程式設定。
如需使用環境變數設定 ASP.NET Core 組態值的詳細資訊,請參閱環境變數。 如需使用其他組態來源 (包括命令列、Azure Key Vault、Azure 應用程式組態、其他檔案格式等等) 的相關資訊,請參閱 ASP.NET Core 的設定。
如何套用篩選規則
建立 ILogger<TCategoryName> 物件時,ILoggerFactory 物件會針對每個提供者選取一個規則來套用到該記錄器。 由 ILogger
執行個體寫入的所有訊息都會根據選取的規則進行篩選。 系統會從可用的規則中,選取對每個提供者和類別配對最明確的規則。
當建立指定類別的 ILogger
時,系統會針對每個提供者使用下列演算法:
- 選取所有符合提供者或其別名的規則。 如果找不到符合的項目,請選取所有規則搭配空白提供者。
- 從上一個步驟的結果中,選取具有最長相符類別前置字元的規則。 如果找不到符合的項目,請選取未指定類別的所有規則。
- 如果選取多個規則,請使用最後一個。
- 如果未選取任何規則,請使用
MinimumLevel
。
記錄 dotnet run 和 Visual Studio 的輸出
使用預設記錄提供者建立的記錄會顯示:
- 在 Visual Studio 中
- 在 [偵錯輸出] 視窗中 (偵錯時)。
- 在 [ASP.NET Core Web 伺服器] 視窗中。
- 在主控台視窗中 (使用
dotnet run
執行應用程式時)。
開頭為 "Microsoft" 類別的記錄則是來自 ASP.NET Core 架構程式碼。 ASP.NET Core 與應用程式程式碼會使用相同的記錄 API 與提供者。
記錄類別
建立 ILogger
物件時,會指定「類別」。 該類別會包含在每個由該 ILogger
執行個體所產生的記錄訊息中。 類別字串為任意值,但慣例是使用類別名稱。 例如,在控制器中,名稱可能是 "TodoApi.Controllers.TodoController"
。 ASP.NET Core Web 應用程式會使用 ILogger<T>
來自動取得 ILogger
執行個體,該執行個體會使用 T
的完整類型名稱來做為類別:
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.");
}
}
若要明確指定類別,請呼叫 ILoggerFactory.CreateLogger
:
public class ContactModel : PageModel
{
private readonly ILogger _logger;
public ContactModel(ILoggerFactory logger)
{
_logger = logger.CreateLogger("TodoApi.Pages.ContactModel.MyCategory");
}
public void OnGet()
{
_logger.LogInformation("GET Pages.ContactModel called.");
}
在多個方法中使用時,以固定名稱呼叫 CreateLogger
可能會很有用,因此可依類別來組織事件。
ILogger<T>
相當於使用 T
的完整類型名稱來呼叫 CreateLogger
。
記錄等級
下表列出 LogLevel 值、便利的 Log{LogLevel}
擴充方法和建議的使用方式:
LogLevel | 值 | 方法 | 描述 |
---|---|---|---|
追蹤 | 0 | LogTrace | 包含最詳細的訊息。 這些訊息可能包含敏感性應用程式資料。 這些訊息預設會停用,且不應在生產環境中啟用。 |
偵錯 | 1 | LogDebug | 用於偵錯和開發。 由於大量,因此在生產環境中請謹慎使用。 |
資訊 | 2 | LogInformation | 追蹤一般應用程式流程。 可能具有長期值。 |
警告 | 3 | LogWarning | 針對異常或意外事件。 通常包含不會導致應用程式失敗的錯誤或狀況。 |
錯誤 | 4 | LogError | 發生無法處理的錯誤和例外狀況。 這些訊息指出目前作業或要求中發生失敗,而不是整個應用程式的失敗。 |
重大 | 5 | LogCritical | 發生需要立即注意的失敗。 範例:資料遺失情況、磁碟空間不足。 |
None | 6 | 指定記錄類別不應寫入任何訊息。 |
在上表中,會從最低到最高嚴重性列出 LogLevel
。
Log 方法的第一個參數 (LogLevel) 表示記錄的嚴重性。 大部分開發人員會呼叫 Log{LogLevel} 擴充方法,而不是呼叫 Log(LogLevel, ...)
。 Log{LogLevel}
擴充方法會呼叫 Log 方法,並指定 LogLevel。 例如,下列兩個記錄呼叫在功能上相等,並產生相同的記錄:
[HttpGet]
public IActionResult Test1(int id)
{
var routeInfo = ControllerContext.ToCtxString(id);
_logger.Log(LogLevel.Information, MyLogEvents.TestItem, routeInfo);
_logger.LogInformation(MyLogEvents.TestItem, routeInfo);
return ControllerContext.MyDisplayRouteInfo();
}
MyLogEvents.TestItem
為事件識別碼。 MyLogEvents
是範例應用程式的一部分,且會顯示在記錄事件識別碼區段中。
MyDisplayRouteInfo 和 ToCtxString 是由 Rick.Docs.Samples.RouteInfo NuGet 套件提供。 方法會顯示 Controller
和 Razor Page
路由資訊。
下列程式碼會建立 Information
與 Warning
記錄:
[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);
}
在上述程式碼中,第一個 Log{LogLevel}
參數 (MyLogEvents.GetItem
) 是記錄事件識別碼。 第二個參數是訊息範本,其中的預留位置會置入其餘方法參數所提供的引數值。 此文件稍後的訊息範本小節將詳細說明方法參數。
呼叫適當的 Log{LogLevel}
方法來控制要寫入至特定儲存媒體的記錄輸出量。 例如:
- 生產環境:
Trace
或Information
層級的記錄會產生大量的詳細記錄訊息。 若要控制成本,且不超過資料儲存體限制,請將Trace
和Information
層級訊息記錄為大量、低成本的資料存放區。 請考慮將Trace
和Information
限制為特定類別。- 透過
Critical
層級的Warning
記錄應該會產生一些記錄訊息。- 成本和儲存體限制通常無所謂。
- 記錄數少可讓資料存放區選擇更具彈性。
- 開發中:
- 設定為
Warning
。 - 進行疑難排解時,新增
Trace
或Information
訊息。 若要限制輸出,請僅針對調查中的類別設定Trace
或Information
。
- 設定為
ASP.NET Core 會寫入架構事件的記錄。 例如,請考慮下列項目的記錄輸出:
- 使用 ASP.NET Core 範本建立的 Razor Pages 應用程式。
- 記錄設定為
Logging:Console:LogLevel:Microsoft:Information
- 瀏覽至 Privacy 頁面:
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
Request starting HTTP/2 GET https://localhost:5001/Privacy
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
Executing endpoint '/Privacy'
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[3]
Route matched with {page = "/Privacy"}. Executing page /Privacy
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[101]
Executing handler method DefaultRP.Pages.PrivacyModel.OnGet - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[102]
Executed handler method OnGet, returned result .
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[103]
Executing an implicit handler method - ModelState is Valid
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[104]
Executed an implicit handler method, returned result Microsoft.AspNetCore.Mvc.RazorPages.PageResult.
info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[4]
Executed page /Privacy in 74.5188ms
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
Executed endpoint '/Privacy'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
Request finished in 149.3023ms 200 text/html; charset=utf-8
下列 JSON 會設定 Logging:Console:LogLevel:Microsoft:Information
:
{
"Logging": { // Default, all providers.
"LogLevel": {
"Microsoft": "Warning"
},
"Console": { // Console provider.
"LogLevel": {
"Microsoft": "Information"
}
}
}
}
記錄事件識別碼
每個記錄都可以指定「事件識別碼」。 範例應用程式會使用 MyLogEvents
類別來定義事件識別碼:
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);
}
事件識別碼會將一組事件關聯。 例如,與在頁面上顯示項目清單相關的所有記錄可能都是 1001。
記錄提供者可能將事件識別碼存放到識別碼欄位、記錄訊息中或完全不存放。 偵錯提供者不會顯示事件識別碼。 主控台提供者會在類別後面以括弧顯示事件識別碼:
info: TodoApi.Controllers.TodoItemsController[1002]
Getting item 1
warn: TodoApi.Controllers.TodoItemsController[4000]
Get(1) NOT FOUND
有些記錄提供者會將事件識別碼儲存在欄位中,以允許篩選識別碼。
記錄訊息範本
每個記錄 API 都會使用訊息範本。 訊息範本可以包含有關提供哪個引數的預留位置。 使用名稱而非數字做為預留位置。
[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);
}
參數的順序 (而不是其預留位置名稱) 會決定哪些參數可用來在記錄訊息中提供預留位置值。 在下列程式碼中,參數名稱在訊息範本的預留位置中未依順序出現:
var apples = 1;
var pears = 2;
var bananas = 3;
_logger.LogInformation("Parameters: {pears}, {bananas}, {apples}", apples, pears, bananas);
不過,參數會依序指派給預留位置:apples
、pears
、bananas
。 記錄訊息會反映「參數的順序」:
Parameters: 1, 2, 3
此方法可讓記錄提供者實作語意或結構化記錄。 引數本身會被傳遞到記錄系統,而不只是格式化的訊息範本。 這可讓記錄提供者將參數值儲存為欄位。 例如,請考量下列記錄器方法:
_logger.LogInformation("Getting item {Id} at {RequestTime}", id, DateTime.Now);
例如,登入 Azure 資料表儲存體時:
- 每個 Azure 資料表實體都可以有
ID
和RequestTime
屬性。 - 具有屬性的資料表可簡化針對記錄資料的查詢。 例如,查詢可以尋找特定
RequestTime
範圍內的所有記錄,而不必剖析文字訊息中的時間。
記錄例外狀況
記錄器方法具有多載可接受例外狀況參數:
[HttpGet("{id}")]
public IActionResult TestExp(int id)
{
var routeInfo = ControllerContext.ToCtxString(id);
_logger.LogInformation(MyLogEvents.TestItem, routeInfo);
try
{
if (id == 3)
{
throw new Exception("Test exception");
}
}
catch (Exception ex)
{
_logger.LogWarning(MyLogEvents.GetItemNotFound, ex, "TestExp({Id})", id);
return NotFound();
}
return ControllerContext.MyDisplayRouteInfo();
}
MyDisplayRouteInfo 和 ToCtxString 是由 Rick.Docs.Samples.RouteInfo NuGet 套件提供。 方法會顯示 Controller
和 Razor Page
路由資訊。
例外狀況記錄是提供者特定的。
預設記錄層級
如果未設定預設記錄層級,則預設記錄層級值為 Information
。
例如,請考量下列 Web 應用程式:
- 使用 ASP.NET Web 應用程式範本所建立。
appsettings.json
和appsettings.Development.json
已刪除或重新命名。
在上述設定中,瀏覽至 privacy 或 home 頁面會產生類別名稱中具有 Microsoft
的許多 Trace
、Debug
和 Information
訊息。
下列程式碼會在設定中未設定預設記錄層級時,設定預設記錄層級:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging => logging.SetMinimumLevel(LogLevel.Warning))
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
一般而言,應該在組態而不是程式碼中指定記錄層級。
Filter 函式
針對組態或程式碼未指派規則的所有提供者和類別,會叫用篩選函式:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.AddFilter((provider, category, logLevel) =>
{
if (provider.Contains("ConsoleLoggerProvider")
&& category.Contains("Controller")
&& logLevel >= LogLevel.Information)
{
return true;
}
else if (provider.Contains("ConsoleLoggerProvider")
&& category.Contains("Microsoft")
&& logLevel >= LogLevel.Information)
{
return true;
}
else
{
return false;
}
});
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
上述程式碼會在類別包含 Controller
或 Microsoft
且記錄層級為 Information
或更高層級時顯示主控台記錄。
一般而言,應該在組態而不是程式碼中指定記錄層級。
ASP.NET Core 和 EF Core 類別
下表包含 ASP.NET Core 和 Entity Framework Core 所使用的一些類別,以及記錄的相關注意事項:
類別 | 備註 |
---|---|
Microsoft.AspNetCore | 一般 ASP.NET Core 診斷。 |
Microsoft.AspNetCore.DataProtection | 已考慮、發現及使用哪些金鑰。 |
Microsoft.AspNetCore.HostFiltering | 允許主機。 |
Microsoft.AspNetCore.Hosting | HTTP 要求花了多少時間完成,以及其開始時間。 載入了哪些裝載啟動組件。 |
Microsoft.AspNetCore.Mvc | MVC 和 Razor 診斷。 模型繫結、篩選執行、檢視編譯、動作選取。 |
Microsoft.AspNetCore.Routing | 路由比對資訊。 |
Microsoft.AspNetCore.Server | 連線開始、停止與保持運作回應。 HTTPS 憑證資訊。 |
Microsoft.AspNetCore.StaticFiles | 提供的檔案。 |
Microsoft.EntityFrameworkCore | 一般 Entity Framework Core 診斷。 資料庫活動與設定、變更偵測、移轉。 |
若要在主控台視窗中檢視更多類別,請將 appsettings.Development.json
設定為下列項目:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Trace",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
記錄範圍
「範圍」可用來將邏輯作業組成群組。 此分組功能可用來將相同的資料附加到已建立為集合之一部分的每個記錄。 例如,在處理邀交易時建立的每個記錄都可以包括該交易識別碼。
範圍:
- 這是 BeginScope 方法所傳回的 IDisposable 類型。
- 會持續到處置為止。
下列提供者支援範圍:
透過將記錄器呼叫封裝在 using
區塊中以使用範圍:
[HttpGet("{id}")]
public async Task<ActionResult<TodoItemDTO>> GetTodoItem(long id)
{
TodoItem todoItem;
var transactionId = Guid.NewGuid().ToString();
using (_logger.BeginScope(new List<KeyValuePair<string, object>>
{
new KeyValuePair<string, object>("TransactionId", transactionId),
}))
{
_logger.LogInformation(MyLogEvents.GetItem, "Getting item {Id}", id);
todoItem = await _context.TodoItems.FindAsync(id);
if (todoItem == null)
{
_logger.LogWarning(MyLogEvents.GetItemNotFound,
"Get({Id}) NOT FOUND", id);
return NotFound();
}
}
return ItemToDTO(todoItem);
}
內建記錄提供者
ASP.NET Core 包含下列記錄提供者做為共用架構的一部分:
下列記錄提供者是由 Microsoft 提供,但不是共用架構的一部分。 必須將其安裝做為額外的 NuGet。
ASP.NET Core 不包含記錄提供者,可用來將記錄寫入檔案。 若要從 ASP.NET Core 應用程式將記錄寫入檔案,請考慮使用協力廠商記錄提供者。
如需使用 ASP.NET Core 模組進行 stdout
和偵錯記錄的相關資訊,請參閱針對 Azure App Service 上的 ASP.NET Core 進行疑難排解,以及 ASP.NET Core Module (ANCM) for IIS。
主控台
Console
提供者會將輸出記錄到主控台。 如需在開發中檢視 Console
記錄的相關詳細資訊,請參閱記錄 dotnet run 和 Visual Studio 的輸出。
偵錯
Debug
提供者會使用 System.Diagnostics.Debug 類別來寫入記錄輸出。 呼叫 System.Diagnostics.Debug.WriteLine
寫入 Debug
提供者。
在 Linux 上,Debug
提供者記錄位置與散發相依,可能是下列其中一項:
- /var/log/message
- /var/log/syslog
事件來源
EventSource
提供者會寫入名稱為 Microsoft-Extensions-Logging
的跨平台事件來源。 在 Windows 上,提供者會使用 ETW。
dotnet 追蹤工具
dotnet-trace 工具是一種跨平台 CLI 全域工具,可收集執行中程序的 .NET Core 追蹤。 此工具會使用 LoggingEventSource 收集 Microsoft.Extensions.Logging.EventSource 提供者資料。
如需安裝指示,請參閱 dotnet-trace。
使用 dotnet 追蹤工具從應用程式收集追蹤:
使用
dotnet run
命令執行應用程式。判斷 .NET Core 應用程式的程序識別碼 (PID):
dotnet trace ps
尋找與應用程式元件名稱相同程序的 PID。
執行
dotnet trace
命令。一般命令語法:
dotnet trace collect -p {PID} --providers Microsoft-Extensions-Logging:{Keyword}:{Provider Level} :FilterSpecs=\" {Logger Category 1}:{Category Level 1}; {Logger Category 2}:{Category Level 2}; ... {Logger Category N}:{Category Level N}\"
使用 PowerShell 命令殼層時,以單引號括住
--providers
值 ('
):dotnet trace collect -p {PID} --providers 'Microsoft-Extensions-Logging:{Keyword}:{Provider Level} :FilterSpecs=\" {Logger Category 1}:{Category Level 1}; {Logger Category 2}:{Category Level 2}; ... {Logger Category N}:{Category Level N}\"'
在非 Windows 平台上,新增
-f speedscope
選項,將輸出追蹤檔案的格式變更為speedscope
。下表會定義關鍵字:
關鍵字 描述 1 記錄有關 LoggingEventSource
的中繼事件。 不會記錄來自ILogger
的事件。2 呼叫 ILogger.Log()
時,開啟Message
。 以程式設計 (而非格式化) 的方式提供資訊。4 呼叫 ILogger.Log()
時,開啟FormatMessage
。 提供資訊的格式化字串版本。8 呼叫 ILogger.Log()
時,開啟MessageJson
。 提供引數的 JSON 表示法。下表列出提供者層級:
提供者層級 描述 0 LogAlways
1 Critical
2 Error
3 Warning
4 Informational
5 Verbose
類別層級的剖析可以是字串或數字:
類別具名值 數值 Trace
0 Debug
1 Information
2 Warning
3 Error
4 Critical
5 提供者層級和類別層級:
- 是反向順序。
- 字串常數不完全相同。
如果未指定
FilterSpecs
,則EventSourceLogger
實作會嘗試將提供者層級轉換成類別層級,並將其套用至所有類別。提供者層級 類別層級 Verbose
(5)Debug
(1)Informational
(4)Information
(2)Warning
(3)Warning
(3)Error
(2)Error
(4)Critical
(1)Critical
(5)如果已提供
FilterSpecs
,則清單中所包含的任何類別都會使用在該處編碼的類別層級,並會篩選掉所有其他類別。下列範例假設:
- 應用程式正在執行並呼叫
logger.LogDebug("12345")
。 - 已透過
set PID=12345
設定程序識別碼 (PID),其中12345
是實際的 PID。
請考慮下列命令:
dotnet trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:5
上述命令會:
- 擷取偵錯訊息。
- 不會套用
FilterSpecs
。 - 指定層級 5,其可對應類別偵錯。
請考慮下列命令:
dotnet trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:5:\"FilterSpecs=*:5\"
上述命令會:
- 不會擷取偵錯訊息,因為類別層級 5 是
Critical
。 - 可提供
FilterSpecs
。
下列命令會擷取偵錯訊息,因為類別層級 1 指定
Debug
。dotnet trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:5:\"FilterSpecs=*:1\"
下列命令會擷取偵錯訊息,因為類別指定
Debug
。dotnet trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:5:\"FilterSpecs=*:Debug\"
{Logger Category}
和{Category Level}
的FilterSpecs
代表其他記錄篩選條件。 以;
分號字元分隔FilterSpecs
項目。使用 Windows 命令殼層的範例:
dotnet trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:2:FilterSpecs=\"Microsoft.AspNetCore.Hosting*:4\"
上述命令會啟動︰
- 事件來源記錄器,可針對錯誤 (
2
) 產生格式化字串 (4
)。 Informational
記錄層級 (4
) 的Microsoft.AspNetCore.Hosting
記錄。
按下 Enter 鍵或 Ctrl+C 以停止 dotnet 追蹤工具。
追蹤會以 trace.nettrace 名稱儲存在執行
dotnet trace
命令的資料夾中。使用 Perfview 開啟追蹤。 開啟 trace.nettrace 檔案並探索追蹤事件。
如果應用程式未使用 CreateDefaultBuilder
建置主機,請將事件來源提供者新增至應用程式的記錄設定。
如需詳細資訊,請參閱
- 效能分析公用程式的追蹤 (dotnet-trace) (.NET Core 文件)
- 效能分析公用程式的追蹤 (dotnet-trace) (dotnet/diagnostics GitHub 存放庫文件)
- LoggingEventSource 類別 (.NET API 瀏覽器)
- EventLevel
- LoggingEventSource 參考來源 (3.0):若要取得不同版本的參考來源,請將分支變更為
release/{Version}
,其中{Version}
是所需的 ASP.NET Core 版本。 - Perfview:對檢視事件來源追蹤相當有用。
Perfview
使用 PerfView 公用程式來收集和檢視記錄。 此外還有一些其他工具可檢視 ETW 記錄,但 PerfView 提供處理 ASP.NET Core 所發出 ETW 事件的最佳體驗。
若要設定 PerfView 以收集此提供者所記錄的事件,請將字串 *Microsoft-Extensions-Logging
新增至 [其他提供者] 清單 請勿遺漏字串開頭的 *
。
Windows EventLog
EventLog
提供者會將記錄輸出傳送至 Windows 事件記錄檔。 與其他提供者不同,EventLog
提供者不會繼承預設的非提供者設定。 如果未指定 EventLog
記錄設定,則預設為 LogLevel.Warning。
若要記錄低於 LogLevel.Warning 的事件,請明確設定記錄層級。 下列範例會將事件記錄檔預設記錄層級設定為 LogLevel.Information:
"Logging": {
"EventLog": {
"LogLevel": {
"Default": "Information"
}
}
}
AddEventLog 多載 可傳入 EventLogSettings。 如果 null
或未指定,則會使用下列預設設定:
LogName
:「應用程式」SourceName
:「.NET Runtime」MachineName
:使用本機電腦名稱。
下列程式碼會將 SourceName
從 ".NET Runtime"
的預設值變更為 MyLogs
:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.AddEventLog(eventLogSettings =>
{
eventLogSettings.SourceName = "MyLogs";
});
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
Azure App Service
Microsoft.Extensions.Logging.AzureAppServices 提供者套件會將記錄寫入至 Azure App Service 應用程式檔案系統中的文字檔,並寫入至 Azure 儲存體帳戶中的 Blob 儲存體。
該提供者套件並未包含在共用架構中。 若要使用提供者,請將提供者套件新增至專案。
如果要進行提供者設定,請使用 AzureFileLoggerOptions 和 AzureBlobLoggerOptions,如以下範例中所示:
public class Scopes
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging => logging.AddAzureWebAppDiagnostics())
.ConfigureServices(serviceCollection => serviceCollection
.Configure<AzureFileLoggerOptions>(options =>
{
options.FileName = "azure-diagnostics-";
options.FileSizeLimit = 50 * 1024;
options.RetainedFileCountLimit = 5;
})
.Configure<AzureBlobLoggerOptions>(options =>
{
options.BlobName = "log.txt";
}))
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
當部署到 Azure App Service 時,應用程式會使用 Azure 入口網站 [App Service] 頁面中 App Service 記錄區段的設定。 當下列設定更新時,變更會立即生效,而不需要重新啟動或重新部署應用程式。
- 應用程式記錄 (檔案系統)
- 應用程式記錄 (Blob)
記錄檔的預設位置為 D:\home\LogFiles\Application 資料夾,而預設檔案名稱為 diagnostics-yyyymmdd.txt。 預設檔案大小限制為 10 MB,而預設保留的檔案數目上限為 2。 預設 Blob 名稱為 {app-name}{timestamp}/yyyy/mm/dd/hh/{guid}-applicationLog.txt。
此提供者僅記錄專案在 Azure 環境中執行的情況。
Azure 記錄串流
Azure 記錄串流可支援即時檢視來自下列位置的記錄活動:
- 應用程式伺服器
- 網頁伺服器
- 失敗要求的追蹤
若要設定 Azure 記錄資料流:
- 從應用程式的入口網站頁面瀏覽到 [App Service 記錄]。
- 將 [應用程式記錄 (檔案系統)] 設定為 [開啟]。
- 選擇記錄 [層級]。 此設定僅適用於 Azure 記錄串流。
瀏覽到 [記錄資料流] 頁面以檢視記錄。 記錄的訊息會與 ILogger
介面一起記錄。
Azure Application Insights
Microsoft.Extensions.Logging.ApplicationInsights 提供者套件會將記錄寫入至 Azure Application Insights。 Application Insights 是可監視 Web 應用程式的服務,並提供可用來查詢及分析遙測資料的工具。 如果您使用此提供者,就可以使用 Application Insights 工具來查詢及分析記錄。
記錄提供者會以 Microsoft.ApplicationInsights.AspNetCore \(英文\) 的相依性形式隨附,這是針對 ASP.NET Core 提供所有可用遙測的套件。 如果您使用此套件,就不需安裝提供者套件。
Microsoft.ApplicationInsights.Web 套件適用於 ASP.NET 4.x,而不適用於 ASP.NET Core。
如需詳細資訊,請參閱以下資源:
- Application Insights 概觀
- 適用於 ASP.NET Core 應用程式的 Application Insights:如果您想要實作完整範圍的 Application Insights 遙測以及記錄,請從這裡開始。
- 適用於 .NET Core ILogger 記錄的 ApplicationInsightsLoggerProvider:如果您想要實作記錄提供者,而不需要 Application Insights 遙測的 rest 部分,請從這裡開始。
- Application Insights logging adapters (Application Insights 記錄配接器)。
- 安裝、設定及初始化 Application Insights SDK 的互動式教學課程。
協力廠商記錄提供者
可搭配 ASP.NET Core 使用的協力廠商記錄架構:
- elmah.io (GitHub 存放庫)
- Gelf (GitHub 存放庫)
- JSNLog (GitHub 存放庫)
- KissLog.net (GitHub 存放庫)
- Log4Net (GitHub 存放庫)
- NLog (GitHub 存放庫)
- PLogger (GitHub 存放庫)
- Sentry (GitHub 存放庫)
- Serilog (GitHub 存放庫)
- Stackdriver (Github 存放庫)
某些協力廠商架構可以執行語意記錄 (也稱為結構化記錄) \(英文\)。
使用協力廠商架構類似於使用內建的提供者之一:
- 將 NuGet 套件新增至專案。
- 呼叫記錄架構所提供的
ILoggerFactory
擴充方法。
如需詳細資訊,請參閱每個提供者的文件。 Microsoft 不支援第三方記錄提供者。
非主機主控台應用程式
如需如何在非 Web 主控台應用程式中使用一般主機的範例,請參閱背景工作範例應用程式 (在 ASP.NET Core 中使用託管服務的背景工作) 的 Program.cs
檔案。
不含一般主機的應用程式記錄程式碼,會因新增提供者和建立記錄器的方式而有所不同。
記錄提供者
在非主機主控台應用程式中,於建立 LoggerFactory
時呼叫提供者的 Add{provider name}
擴充方法:
class Program
{
static void Main(string[] args)
{
using var loggerFactory = LoggerFactory.Create(builder =>
{
builder
.AddFilter("Microsoft", LogLevel.Warning)
.AddFilter("System", LogLevel.Warning)
.AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
.AddConsole()
.AddEventLog();
});
ILogger logger = loggerFactory.CreateLogger<Program>();
logger.LogInformation("Example log message");
}
}
建立記錄
若要建立記錄,請使用 ILogger<TCategoryName> 物件。 使用 LoggerFactory
來建立 ILogger
。
下列範例會建立以 LoggingConsoleApp.Program
做為類別的記錄器。
class Program
{
static void Main(string[] args)
{
using var loggerFactory = LoggerFactory.Create(builder =>
{
builder
.AddFilter("Microsoft", LogLevel.Warning)
.AddFilter("System", LogLevel.Warning)
.AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
.AddConsole()
.AddEventLog();
});
ILogger logger = loggerFactory.CreateLogger<Program>();
logger.LogInformation("Example log message");
}
}
在下列範例中,記錄器會用於以 Information
做為層級來建立記錄。 記錄「層級」 指出已記錄事件的嚴重性。
class Program
{
static void Main(string[] args)
{
using var loggerFactory = LoggerFactory.Create(builder =>
{
builder
.AddFilter("Microsoft", LogLevel.Warning)
.AddFilter("System", LogLevel.Warning)
.AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
.AddConsole()
.AddEventLog();
});
ILogger logger = loggerFactory.CreateLogger<Program>();
logger.LogInformation("Example log message");
}
}
主機建構期間的記錄
不直接支援在主機建構期間進行記錄。 不過,可以使用個別的記錄器。 在下列範例中,會使用 Serilog 記錄器來記錄 CreateHostBuilder
。 AddSerilog
會使用 Log.Logger
中指定的靜態組態:
using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args)
{
var builtConfig = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddCommandLine(args)
.Build();
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.WriteTo.File(builtConfig["Logging:FilePath"])
.CreateLogger();
try
{
return Host.CreateDefaultBuilder(args)
.ConfigureServices((context, services) =>
{
services.AddRazorPages();
})
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddConfiguration(builtConfig);
})
.ConfigureLogging(logging =>
{
logging.AddSerilog();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
catch (Exception ex)
{
Log.Fatal(ex, "Host builder error");
throw;
}
finally
{
Log.CloseAndFlush();
}
}
}
設定相依於 ILogger 的服務
記錄器的建構函式插入 Startup
適用於舊版 ASP.NET Core,因為會為 Web 主機建立個別的 DI 容器。 如需為何只為一般主機建立一個容器的資訊,請參閱重大變更公告。
若要設定相依於 ILogger<T>
的服務,請使用建構函式插入或提供 Factory 方法。 只有在沒有其他選項時,才建議使用 Factory 方法。 例如,請考慮需要 ILogger<T>
DI 所提供執行個體的服務:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddRazorPages();
services.AddSingleton<IMyService>((container) =>
{
var logger = container.GetRequiredService<ILogger<MyService>>();
return new MyService() { Logger = logger };
});
}
前面的醒目提示程式碼是 Func<T,TResult>,會在 DI 容器第一次需要建立 MyService
的執行個體時執行。 您可以用此方式存取任何已註冊的服務。
在 Main 中建立記錄
下列程式碼會藉由在建置主機之後,從 DI 取得 Main
執行個體來登入 ILogger
:
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
var logger = host.Services.GetRequiredService<ILogger<Program>>();
logger.LogInformation("Host created.");
host.Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
在啟動中建立記錄
下列程式碼會將記錄寫入在 Startup.Configure
中:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env,
ILogger<Startup> logger)
{
if (env.IsDevelopment())
{
logger.LogInformation("In Development.");
app.UseDeveloperExceptionPage();
}
else
{
logger.LogInformation("Not Development.");
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapRazorPages();
});
}
在以 Startup.ConfigureServices
方法完成 DI 容器設定之前,不支援寫入記錄檔:
- 不支援將記錄器插入
Startup
建構函式。 - 不支援將記錄器插入
Startup.ConfigureServices
方法簽章
這項限制的原因是記錄相依於 DI 和組態,而後者相依於 DI。 在 ConfigureServices
完成後才會設定 DI 容器。
如需設定相依於 ILogger<T>
的服務,或為何將記錄器的建構函式插入在舊版中運作 Startup
的相關資訊,請參閱設定相依於 ILogger 的服務
無非同步記錄器方法
記錄速度應該很快,不值得花費非同步程式碼的效能成本來處理。 若記錄資料存放區很慢,請不要直接寫入其中。 請考慮一開始將記錄寫入到快速的存放區,稍後再將其移到慢速存放區。 例如,當記錄到 SQL Server 時,請勿在 Log
方法中直接執行,因為 Log
方法是同步的。 相反地,以同步方式將記錄訊息新增到記憶體內佇列,並讓背景工作角色提取出佇列的訊息,藉此執行推送資料到 SQL Server 的非同步工作。 如需詳細資訊,請參閱這個 GitHub 問題。
變更執行中應用程式的記錄層級
記錄 API 不包含應用程式執行時變更記錄層級的案例。 不過,某些組態提供者能夠重新載入組態,這會立即對記錄組態生效。 例如,檔案組態提供者預設會重新載入記錄組態。 如果應用程式執行時在程式碼中變更組態,則應用程式可以呼叫 IConfigurationRoot.Reload 來更新應用程式的記錄組態。
ILogger 和 ILoggerFactory
ILogger<TCategoryName> 和 ILoggerFactory 介面及實作會包含在 .NET Core SDK 中。 其也可以在下列 NuGet 套件中使用:
在程式碼中套用記錄篩選規則
設定記錄篩選規則的慣用方法是使用組態。
下列範例說明如何在程式碼中註冊篩選規則:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
logging.AddFilter("System", LogLevel.Debug)
.AddFilter<DebugLoggerProvider>("Microsoft", LogLevel.Information)
.AddFilter<ConsoleLoggerProvider>("Microsoft", LogLevel.Trace))
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
logging.AddFilter("System", LogLevel.Debug)
會指定 System
類別和記錄層級 Debug
。 篩選條件會套用至所有提供者,因為未設定特定提供者。
AddFilter<DebugLoggerProvider>("Microsoft", LogLevel.Information)
會指定:
Debug
記錄提供者。- 記錄層級
Information
和更新版本。 - 從
"Microsoft"
開始的所有類別。
使用 SpanId、TraceId 和 ParentId 自動記錄範圍
記錄程式庫會隱含地使用 SpanId
、TraceId
和 ParentId
來建立範圍物件。 此行為是透過 ActivityTrackingOptions 進行設定。
var loggerFactory = LoggerFactory.Create(logging =>
{
logging.Configure(options =>
{
options.ActivityTrackingOptions = ActivityTrackingOptions.SpanId
| ActivityTrackingOptions.TraceId
| ActivityTrackingOptions.ParentId;
}).AddSimpleConsole(options =>
{
options.IncludeScopes = true;
});
});
如果已設定 traceparent
http 要求標頭,則記錄範圍中的 ParentId
會顯示來自輸入 traceparent
標頭的 W3C parent-id
,而記錄範圍中的 SpanId
會顯示下一個輸出步驟/範圍的更新 parent-id
。 如需詳細資訊,請參閱變動 traceparent 欄位。
建立自訂記錄器
若要建立自訂記錄器,請參閱在 .NET 中實作自訂記錄提供者。
其他資源
- 高效能記錄
- 應該在 github.com/dotnet/runtime/ 存放庫中建立記錄錯誤。
- ASP.NET Core Blazor 記錄