日志記錄提供程序會(huì)顯示或存儲(chǔ)日志。 例如,控制臺(tái)提供程序在控制臺(tái)上顯示日志,Azure Application Insights 提供程序會(huì)將這些日志存儲(chǔ)在 Azure Application Insights 中。 可通過(guò)添加多個(gè)提供程序?qū)⑷罩景l(fā)送到多個(gè)目標(biāo)。
要添加提供程序,請(qǐng)?jiān)?Program.cs 中調(diào)用提供程序的 Add{provider name} 擴(kuò)展方法:
C#
public static void Main(string[] args)
{
var webHost = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureAppConfiguration((hostingContext, config) =>
{
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json",
optional: true, reloadOnChange: true);
config.AddEnvironmentVariables();
})
.ConfigureLogging((hostingContext, logging) =>
{
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddConsole();
logging.AddDebug();
logging.AddEventSourceLogger();
})
.UseStartup<Startup>()
.Build();
webHost.Run();
}
默認(rèn)項(xiàng)目模板調(diào)用 CreateDefaultBuilder,該操作將添加以下日志記錄提供程序:
C#
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
如果使用 CreateDefaultBuilder,則可自行選擇提供程序來(lái)替換默認(rèn)提供程序。 調(diào)用 ClearProviders,然后添加所需的提供程序。
C#
public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args).Build();
var todoRepository = host.Services.GetRequiredService<ITodoRepository>();
todoRepository.Add(new Core.Model.TodoItem() { Name = "Feed the dog" });
todoRepository.Add(new Core.Model.TodoItem() { Name = "Walk the dog" });
var logger = host.Services.GetRequiredService<ILogger<Program>>();
logger.LogInformation("Seeded the database.");
host.Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.AddConsole();
});
詳細(xì)了解內(nèi)置日志記錄提供程序,以及本文稍后部分介紹的第三方日志記錄提供程序。
從 DI 中獲取 ILogger<TCategoryName> 對(duì)象。
以下控制器示例會(huì)創(chuàng)建 Information 和 Warning 日志。 類(lèi)別為 TodoApiSample.Controllers.TodoController(示例應(yīng)用中 TodoController 的完全限定類(lèi)名):
C#
public class TodoController : Controller
{
private readonly ITodoRepository _todoRepository;
private readonly ILogger _logger;
public TodoController(ITodoRepository todoRepository,
ILogger<TodoController> logger)
{
_todoRepository = todoRepository;
_logger = logger;
}
C#
public IActionResult GetById(string id)
{
_logger.LogInformation(LoggingEvents.GetItem, "Getting item {ID}", id);
var item = _todoRepository.Find(id);
if (item == null)
{
_logger.LogWarning(LoggingEvents.GetItemNotFound, "GetById({ID}) NOT FOUND", id);
return NotFound();
}
return new ObjectResult(item);
}
以下 Razor 頁(yè)面示例會(huì)創(chuàng)建“級(jí)別”為 Information 且“類(lèi)別”為 TodoApiSample.Pages.AboutModel 的日志:
C#
public class AboutModel : PageModel
{
private readonly ILogger _logger;
public AboutModel(ILogger<AboutModel> logger)
{
_logger = logger;
}
C#
public void OnGet()
{
Message = $"About page visited at {DateTime.UtcNow.ToLongTimeString()}";
_logger.LogInformation("Message displayed: {Message}", Message);
}
日志“級(jí)別”代表所記錄事件的嚴(yán)重程度。 日志“類(lèi)別”是與每個(gè)日志關(guān)聯(lián)的字符串。 ILogger<T> 實(shí)例會(huì)創(chuàng)建“類(lèi)別”為類(lèi)型 T 的完全限定名稱的日志。 本文稍后部分將更詳細(xì)地介紹級(jí)別和類(lèi)別。
要將日志寫(xiě)入 Startup 類(lèi),構(gòu)造函數(shù)簽名需包含 ILogger 參數(shù):
C#
public class Startup
{
private readonly ILogger _logger;
public Startup(IConfiguration configuration, ILogger<Startup> logger)
{
Configuration = configuration;
_logger = logger;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
// Add our repository type
services.AddSingleton<ITodoRepository, TodoRepository>();
_logger.LogInformation("Added TodoRepository to services");
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
_logger.LogInformation("In Development environment");
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseMvc();
}
}
要將日志寫(xiě)入 Program 類(lèi),請(qǐng)從 DI 獲取 ILogger 實(shí)例:
C#
public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args).Build();
var todoRepository = host.Services.GetRequiredService<ITodoRepository>();
todoRepository.Add(new Core.Model.TodoItem() { Name = "Feed the dog" });
todoRepository.Add(new Core.Model.TodoItem() { Name = "Walk the dog" });
var logger = host.Services.GetRequiredService<ILogger<Program>>();
logger.LogInformation("Seeded the database.");
host.Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.AddConsole();
});
日志記錄應(yīng)該會(huì)很快,不值得犧牲性能來(lái)使用異步代碼。 如果你的日志數(shù)據(jù)存儲(chǔ)很慢,請(qǐng)不要直接寫(xiě)入它。 首先考慮將日志消息寫(xiě)入快速存儲(chǔ),售后再將其變?yōu)槁俅鎯?chǔ)。 例如,如果你要記錄到 SQL Server,你可能不想直接在 Log 方法中記錄,因?yàn)?nbsp;Log 方法是同步的。 相反,你會(huì)將日志消息同步添加到內(nèi)存中的隊(duì)列,并讓后臺(tái)輔助線程從隊(duì)列中拉出消息,以完成將數(shù)據(jù)推送到 SQL Server 的異步工作。
日志記錄提供程序配置由一個(gè)或多個(gè)配置提供程序提供:
例如,日志記錄配置通常由應(yīng)用設(shè)置文件的 Logging 部分提供。 以下示例顯示了典型 appsettings.Development.json 文件的內(nèi)容:
JSON
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
},
"Console":
{
"IncludeScopes": true
}
}
}
Logging 屬性可具有 LogLevel 和日志提供程序?qū)傩裕@示控制臺(tái))。
Logging 下的 LogLevel 屬性指定了用于記錄所選類(lèi)別的最低級(jí)別。 在本例中,System 和 Microsoft 類(lèi)別在 Information 級(jí)別記錄,其他均在 Debug 級(jí)別記錄。
Logging 下的其他屬性均指定了日志記錄提供程序。 本示例針對(duì)控制臺(tái)提供程序。 如果提供程序支持日志作用域,則 IncludeScopes 將指示是否啟用這些域。 提供程序?qū)傩裕ɡ绫纠?nbsp;Console)也可指定 LogLevel 屬性。 LogLevel 在提供程序下指定要為該提供程序記錄的級(jí)別。
如果在 Logging.{providername}.LogLevel 中指定了級(jí)別,則這些級(jí)別將重寫(xiě) Logging.LogLevel 中設(shè)置的所有內(nèi)容。
若要了解如何實(shí)現(xiàn)配置提供程序,請(qǐng)參閱 ASP.NET Core 中的配置。
使用上一部分中顯示的示例代碼從命令行運(yùn)行應(yīng)用時(shí),將在控制臺(tái)中看到日志。 以下是控制臺(tái)輸出示例:
console
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://localhost:5000/api/todo/0
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
Executing action method TodoApi.Controllers.TodoController.GetById (TodoApi) with arguments (0) - ModelState is Valid
info: TodoApi.Controllers.TodoController[1002]
Getting item 0
warn: TodoApi.Controllers.TodoController[4000]
GetById(0) NOT FOUND
info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
Executing HttpStatusCodeResult, setting HTTP status code 404
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
Executed action TodoApi.Controllers.TodoController.GetById (TodoApi) in 42.9286ms
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 148.889ms 404
通過(guò)向 http://localhost:5000/api/todo/0 處的示例應(yīng)用發(fā)出 HTTP Get 請(qǐng)求來(lái)生成前述日志。
在 Visual Studio 中運(yùn)行示例應(yīng)用時(shí),“調(diào)試”窗口中將顯示如下日志:
console
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:53104/api/todo/0
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executing action method TodoApi.Controllers.TodoController.GetById (TodoApi) with arguments (0) - ModelState is Valid
TodoApi.Controllers.TodoController:Information: Getting item 0
TodoApi.Controllers.TodoController:Warning: GetById(0) NOT FOUND
Microsoft.AspNetCore.Mvc.StatusCodeResult:Information: Executing HttpStatusCodeResult, setting HTTP status code 404
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action TodoApi.Controllers.TodoController.GetById (TodoApi) in 152.5657ms
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 316.3195ms 404
由上一部分所示的 ILogger 調(diào)用創(chuàng)建的日志是以“TodoApi.Controllers.TodoController”開(kāi)頭的。以“Microsoft”類(lèi)別開(kāi)頭的日志來(lái)自 ASP.NET Core 框架代碼。 ASP.NET Core 和應(yīng)用程序代碼使用相同的日志記錄 API 和提供程序。
本文余下部分將介紹有關(guān)日志記錄的某些詳細(xì)信息及選項(xiàng)。
ILogger 和 ILoggerFactory 接口位于 Microsoft.Extensions.Logging.Abstractions 中,其默認(rèn)實(shí)現(xiàn)位于 Microsoft.Extensions.Logging 中。
創(chuàng)建 ILogger 對(duì)象后,將為其指定“類(lèi)別”。 該類(lèi)別包含在由此 ILogger 實(shí)例創(chuàng)建的每條日志消息中。 類(lèi)別可以是任何字符串,但約定需使用類(lèi)名,例如“TodoApi.Controllers.TodoController”。
使用 ILogger<T> 獲取一個(gè) ILogger 實(shí)例,該實(shí)例使用 T 的完全限定類(lèi)型名稱作為類(lèi)別:
C#
public class TodoController : Controller
{
private readonly ITodoRepository _todoRepository;
private readonly ILogger _logger;
public TodoController(ITodoRepository todoRepository,
ILogger<TodoController> logger)
{
_todoRepository = todoRepository;
_logger = logger;
}
要顯式指定類(lèi)別,請(qǐng)調(diào)用 ILoggerFactory.CreateLogger:
C#
public class TodoController : Controller
{
private readonly ITodoRepository _todoRepository;
private readonly ILogger _logger;
public TodoController(ITodoRepository todoRepository,
ILoggerFactory logger)
{
_todoRepository = todoRepository;
_logger = logger.CreateLogger("TodoApiSample.Controllers.TodoController");
}
ILogger<T> 相當(dāng)于調(diào)用完全限定類(lèi)型名稱為 T 的 CreateLogger。
每個(gè)日志都指定了一個(gè) LogLevel 值。 日志級(jí)別指示嚴(yán)重性或重要程度。 例如,可在方法正常結(jié)束時(shí)寫(xiě)入 Information 日志,在方法返回“404 找不到”狀態(tài)代碼時(shí)寫(xiě)入 Warning 日志。
下面的代碼會(huì)創(chuàng)建 Information 和 Warning 日志:
C#
public IActionResult GetById(string id)
{
_logger.LogInformation(LoggingEvents.GetItem, "Getting item {ID}", id);
var item = _todoRepository.Find(id);
if (item == null)
{
_logger.LogWarning(LoggingEvents.GetItemNotFound, "GetById({ID}) NOT FOUND", id);
return NotFound();
}
return new ObjectResult(item);
}
在上述代碼中,第一個(gè)參數(shù)是日志事件 ID。 第二個(gè)參數(shù)是消息模板,其中的占位符用于填寫(xiě)剩余方法形參提供的實(shí)參值。 稍后將在本文的消息模板部分介紹方法參數(shù)。
在方法名稱中包含級(jí)別的日志方法(例如 LogInformation 和 LogWarning)是 ILogger 的擴(kuò)展方法。 這些方法會(huì)調(diào)用可接受 LogLevel 參數(shù)的 Log 方法。 可直接調(diào)用 Log 方法而不調(diào)用其中某個(gè)擴(kuò)展方法,但語(yǔ)法相對(duì)復(fù)雜。 有關(guān)詳細(xì)信息,請(qǐng)參閱 ILogger 和記錄器擴(kuò)展源代碼。
ASP.NET Core 定義了以下日志級(jí)別(按嚴(yán)重性從低到高排列)。
使用日志級(jí)別控制寫(xiě)入到特定存儲(chǔ)介質(zhì)或顯示窗口的日志輸出量。 例如:
本文稍后的日志篩選部分介紹如何控制提供程序處理的日志級(jí)別。
ASP.NET Core 為框架事件寫(xiě)入日志。 本文前面部分提供的日志示例排除了低于 Information 級(jí)別的日志,因此未創(chuàng)建 Debug 或 Trace 級(jí)別日志。 以下示例介紹了通過(guò)運(yùn)行配置為顯示 Debug 日志的示例應(yīng)用而生成的控制臺(tái)日志:
console
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://localhost:62555/api/todo/0
dbug: Microsoft.AspNetCore.Routing.Tree.TreeRouter[1]
Request successfully matched the route with name 'GetTodo' and template 'api/Todo/{id}'.
dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
Action 'TodoApi.Controllers.TodoController.Update (TodoApi)' with id '089d59b6-92ec-472d-b552-cc613dfd625d' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
dbug: Microsoft.AspNetCore.Mvc.Internal.ActionSelector[2]
Action 'TodoApi.Controllers.TodoController.Delete (TodoApi)' with id 'f3476abe-4bd9-4ad3-9261-3ead09607366' did not match the constraint 'Microsoft.AspNetCore.Mvc.Internal.HttpMethodActionConstraint'
dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
Executing action TodoApi.Controllers.TodoController.GetById (TodoApi)
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
Executing action method TodoApi.Controllers.TodoController.GetById (TodoApi) with arguments (0) - ModelState is Valid
info: TodoApi.Controllers.TodoController[1002]
Getting item 0
warn: TodoApi.Controllers.TodoController[4000]
GetById(0) NOT FOUND
dbug: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
Executed action method TodoApi.Controllers.TodoController.GetById (TodoApi), returned result Microsoft.AspNetCore.Mvc.NotFoundResult.
info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
Executing HttpStatusCodeResult, setting HTTP status code 404
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
Executed action TodoApi.Controllers.TodoController.GetById (TodoApi) in 0.8788ms
dbug: Microsoft.AspNetCore.Server.Kestrel[9]
Connection id "0HL6L7NEFF2QD" completed keep alive response.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 2.7286ms 404
每個(gè)日志都可指定一個(gè)事件 ID。 該示例應(yīng)用通過(guò)使用本地定義的 LoggingEvents 類(lèi)來(lái)執(zhí)行此操作:
C#
public IActionResult GetById(string id)
{
_logger.LogInformation(LoggingEvents.GetItem, "Getting item {ID}", id);
var item = _todoRepository.Find(id);
if (item == null)
{
_logger.LogWarning(LoggingEvents.GetItemNotFound, "GetById({ID}) NOT FOUND", id);
return NotFound();
}
return new ObjectResult(item);
}
C#
public class LoggingEvents
{
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 GetItemNotFound = 4000;
public const int UpdateItemNotFound = 4001;
}
事件 ID 與一組事件相關(guān)聯(lián)。 例如,與在頁(yè)面上顯示項(xiàng)列表相關(guān)的所有日志可能是 1001。
日志記錄提供程序可將事件 ID 存儲(chǔ)在 ID 字段中,存儲(chǔ)在日志記錄消息中,或者不進(jìn)行存儲(chǔ)。 調(diào)試提供程序不顯示事件 ID。 控制臺(tái)提供程序在類(lèi)別后的括號(hào)中顯示事件 ID:
console
info: TodoApi.Controllers.TodoController[1002]
Getting item invalidid
warn: TodoApi.Controllers.TodoController[4000]
GetById(invalidid) NOT FOUND
每個(gè)日志都會(huì)指定一個(gè)消息模板。 消息模板可包含要填寫(xiě)參數(shù)的占位符。 請(qǐng)?jiān)谡嘉环惺褂妹Q而不是數(shù)字。
C#
public IActionResult GetById(string id)
{
_logger.LogInformation(LoggingEvents.GetItem, "Getting item {ID}", id);
var item = _todoRepository.Find(id);
if (item == null)
{
_logger.LogWarning(LoggingEvents.GetItemNotFound, "GetById({ID}) NOT FOUND", id);
return NotFound();
}
return new ObjectResult(item);
}
占位符的順序(而非其名稱)決定了為其提供值的參數(shù)。 在以下代碼中,請(qǐng)注意消息模板中的參數(shù)名稱未按順序排列:
C#
string p1 = "parm1";
string p2 = "parm2";
_logger.LogInformation("Parameter values: {p2}, {p1}", p1, p2);
此代碼創(chuàng)建了一個(gè)參數(shù)值按順序排列的日志消息:
Parameter values: parm1, parm2
日志記錄框架按此方式工作,這樣日志記錄提供程序即可實(shí)現(xiàn)語(yǔ)義日志記錄,也稱為結(jié)構(gòu)化日志記錄。 參數(shù)本身會(huì)傳遞給日志記錄系統(tǒng),而不僅僅是格式化的消息模板。 通過(guò)此信息,日志記錄提供程序能夠?qū)?shù)值存儲(chǔ)為字段。 例如,假設(shè)記錄器方法調(diào)用如下所示:
C#
_logger.LogInformation("Getting item {ID} at {RequestTime}", id, DateTime.Now);
如果要將日志發(fā)送到 Azure 表存儲(chǔ),則每個(gè) Azure 表實(shí)體都可具有 ID 和 RequestTime 屬性,這簡(jiǎn)化了對(duì)日志數(shù)據(jù)的查詢。 無(wú)需分析文本消息的超時(shí),查詢即可找到特定 RequestTime 范圍內(nèi)的全部日志。
記錄器方法有可傳入異常的重載,如下方示例所示:
C#
catch (Exception ex)
{
_logger.LogWarning(LoggingEvents.GetItemNotFound, ex, "GetById({ID}) NOT FOUND", id);
return NotFound();
}
return new ObjectResult(item);
不同的提供程序處理異常信息的方式不同。 以下是上示代碼的調(diào)試提供程序輸出示例。
TodoApi.Controllers.TodoController:Warning: GetById(036dd898-fb01-47e8-9a65-f92eb73cf924) NOT FOUND
System.Exception: Item not found exception.
at TodoApi.Controllers.TodoController.GetById(String id) in C:\logging\sample\src\TodoApi\Controllers\TodoController.cs:line 226
可為特定或所有提供程序和類(lèi)別指定最低日志級(jí)別。 最低級(jí)別以下的日志不會(huì)傳遞給該提供程序,因此不會(huì)顯示或存儲(chǔ)它們。
要禁止顯示所有日志,可將 LogLevel.None 指定為最低日志級(jí)別。 LogLevel.None 的整數(shù)值為 6,它大于 LogLevel.Critical (5)。
項(xiàng)目模板代碼調(diào)用 CreateDefaultBuilder 來(lái)為控制臺(tái)和調(diào)試提供程序設(shè)置日志記錄。 CreateDefaultBuilder 方法還使用如下所示的代碼,設(shè)置日志記錄以查找 Logging 部分的配置:
C#
public static void Main(string[] args)
{
var webHost = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureAppConfiguration((hostingContext, config) =>
{
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json",
optional: true, reloadOnChange: true);
config.AddEnvironmentVariables();
})
.ConfigureLogging((hostingContext, logging) =>
{
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddConsole();
logging.AddDebug();
logging.AddEventSourceLogger();
})
.UseStartup<Startup>()
.Build();
webHost.Run();
}
配置數(shù)據(jù)按提供程序和類(lèi)別指定最低日志級(jí)別,如下方示例所示:
JSON
{
"Logging": {
"Debug": {
"LogLevel": {
"Default": "Information"
}
},
"Console": {
"IncludeScopes": false,
"LogLevel": {
"Microsoft.AspNetCore.Mvc.Razor.Internal": "Warning",
"Microsoft.AspNetCore.Mvc.Razor.Razor": "Debug",
"Microsoft.AspNetCore.Mvc.Razor": "Error",
"Default": "Information"
}
},
"LogLevel": {
"Default": "Debug"
}
}
}
此 JSON 將創(chuàng)建 6 條篩選規(guī)則:1 條用于調(diào)試提供程序, 4 條用于控制臺(tái)提供程序, 1 條用于所有提供程序。 創(chuàng)建 ILogger 對(duì)象時(shí),為每個(gè)提供程序選擇一個(gè)規(guī)則。
下面的示例演示了如何在代碼中注冊(cè)篩選規(guī)則:
C#
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging(logging =>
logging.AddFilter("System", LogLevel.Debug)
.AddFilter<DebugLoggerProvider>("Microsoft", LogLevel.Trace));
第二個(gè) AddFilter 使用類(lèi)型名稱來(lái)指定調(diào)試提供程序。 第一個(gè) AddFilter 應(yīng)用于全部提供程序,因?yàn)樗粗付ㄌ峁┏绦蝾?lèi)型。
先前示例中顯示的配置數(shù)據(jù)和 AddFilter 代碼會(huì)創(chuàng)建下表所示的規(guī)則。 前六條由配置示例創(chuàng)建,后兩條由代碼示例創(chuàng)建。
數(shù)字 | 提供程序 | 類(lèi)別的開(kāi)頭為... | 最低日志級(jí)別 |
---|---|---|---|
1 | 調(diào)試 | 全部類(lèi)別 | 信息 |
2 | 控制臺(tái) | Microsoft.AspNetCore.Mvc.Razor.Internal | 警告 |
3 | 控制臺(tái) | Microsoft.AspNetCore.Mvc.Razor.Razor | 調(diào)試 |
4 | 控制臺(tái) | Microsoft.AspNetCore.Mvc.Razor | Error |
5 | 控制臺(tái) | 全部類(lèi)別 | 信息 |
6 | 全部提供程序 | 全部類(lèi)別 | 調(diào)試 |
7 | 全部提供程序 | 系統(tǒng) | 調(diào)試 |
8 | 調(diào)試 | Microsoft | 跟蹤 |
創(chuàng)建 ILogger 對(duì)象時(shí),ILoggerFactory 對(duì)象將根據(jù)提供程序選擇一條規(guī)則,將其應(yīng)用于該記錄器。將按所選規(guī)則篩選 ILogger 實(shí)例寫(xiě)入的所有消息。 從可用規(guī)則中為每個(gè)提供程序和類(lèi)別對(duì)選擇最具體的規(guī)則。
在為給定的類(lèi)別創(chuàng)建 ILogger 時(shí),以下算法將用于每個(gè)提供程序:
假設(shè)你使用上述規(guī)則列表為類(lèi)別“Microsoft.AspNetCore.Mvc.Razor.RazorViewEngine”創(chuàng)建了 ILogger 對(duì)象:
生成的 ILogger 實(shí)例將 Trace 級(jí)別及更高級(jí)別的日志發(fā)送到調(diào)試提供程序。 Debug 級(jí)別及更高級(jí)別的日志會(huì)發(fā)送到控制臺(tái)提供程序。
每個(gè)提供程序都定義了一個(gè)別名;可在配置中使用該別名來(lái)代替完全限定的類(lèi)型名稱。 對(duì)于內(nèi)置提供程序,請(qǐng)使用以下別名:
僅當(dāng)配置或代碼中的規(guī)則對(duì)給定提供程序和類(lèi)別都不適用時(shí),最低級(jí)別設(shè)置才會(huì)生效。 下面的示例演示如何設(shè)置最低級(jí)別:
C#
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging(logging => logging.SetMinimumLevel(LogLevel.Warning));
如果沒(méi)有明確設(shè)置最低級(jí)別,則默認(rèn)值為 Information,它表示 Trace 和 Debug 日志將被忽略。
對(duì)配置或代碼沒(méi)有向其分配規(guī)則的所有提供程序和類(lèi)別調(diào)用篩選器函數(shù)。 函數(shù)中的代碼可訪問(wèn)提供程序類(lèi)型、類(lèi)別和日志級(jí)別。 例如:
C#
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging(logBuilder =>
{
logBuilder.AddFilter((provider, category, logLevel) =>
{
if (provider == "Microsoft.Extensions.Logging.Console.ConsoleLoggerProvider" &&
category == "TodoApiSample.Controllers.TodoController")
{
return false;
}
return true;
});
});
下面是 ASP.NET Core 和 Entity Framework Core 使用的一些類(lèi)別,備注中說(shuō)明了可從這些類(lèi)別獲取的具體日志:
類(lèi)別 | 說(shuō)明 |
---|---|
Microsoft.AspNetCore | 常規(guī) ASP.NET Core 診斷。 |
Microsoft.AspNetCore.DataProtection | 考慮、找到并使用了哪些密鑰。 |
Microsoft.AspNetCore.HostFiltering | 所允許的主機(jī)。 |
Microsoft.AspNetCore.Hosting | HTTP 請(qǐng)求完成的時(shí)間和啟動(dòng)時(shí)間。 加載了哪些承載啟動(dòng)程序集。 |
Microsoft.AspNetCore.Mvc | MVC 和 Razor 診斷。 模型綁定、篩選器執(zhí)行、視圖編譯和操作選擇。 |
Microsoft.AspNetCore.Routing | 路由匹配信息。 |
Microsoft.AspNetCore.Server | 連接啟動(dòng)、停止和保持活動(dòng)響應(yīng)。 HTTP 證書(shū)信息。 |
Microsoft.AspNetCore.StaticFiles | 提供的文件。 |
Microsoft.EntityFrameworkCore | 常規(guī) Entity Framework Core 診斷。 數(shù)據(jù)庫(kù)活動(dòng)和配置、更改檢測(cè)、遷移。 |
“作用域”可對(duì)一組邏輯操作分組。 此分組可用于將相同的數(shù)據(jù)附加到作為集合的一部分而創(chuàng)建的每個(gè)日志。 例如,在處理事務(wù)期間創(chuàng)建的每個(gè)日志都可包括事務(wù) ID。
范圍是由 BeginScope 方法返回的 IDisposable 類(lèi)型,持續(xù)至釋放為止。 要使用作用域,請(qǐng)?jiān)?nbsp;using 塊中包裝記錄器調(diào)用:
C#
public IActionResult GetById(string id)
{
TodoItem item;
using (_logger.BeginScope("Message attached to logs created in the using block"))
{
_logger.LogInformation(LoggingEvents.GetItem, "Getting item {ID}", id);
item = _todoRepository.Find(id);
if (item == null)
{
_logger.LogWarning(LoggingEvents.GetItemNotFound, "GetById({ID}) NOT FOUND", id);
return NotFound();
}
}
return new ObjectResult(item);
}
下列代碼為控制臺(tái)提供程序啟用作用域:
Program.cs:
C#
.ConfigureLogging((hostingContext, logging) =>
{
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddConsole(options => options.IncludeScopes = true);
logging.AddDebug();
})
備注
要啟用基于作用域的日志記錄,必須先配置 IncludeScopes 控制臺(tái)記錄器選項(xiàng)。
若要了解關(guān)配置,請(qǐng)參閱配置部分。
每條日志消息都包含作用域內(nèi)的信息:
info: TodoApi.Controllers.TodoController[1002]
=> RequestId:0HKV9C49II9CK RequestPath:/api/todo/0 => TodoApi.Controllers.TodoController.GetById (TodoApi) => Message attached to logs created in the using block
Getting item 0
warn: TodoApi.Controllers.TodoController[4000]
=> RequestId:0HKV9C49II9CK RequestPath:/api/todo/0 => TodoApi.Controllers.TodoController.GetById (TodoApi) => Message attached to logs created in the using block
GetById(0) NOT FOUND
ASP.NET Core 提供以下提供程序:
本文稍后將介紹 Azure 的日志記錄選項(xiàng)。
有關(guān) stdout 日志記錄的信息,請(qǐng)參閱 對(duì) IIS 上的 ASP.NET Core 進(jìn)行故障排除 和 對(duì) Azure 應(yīng)用服務(wù)上的 ASP.NET Core 進(jìn)行故障排除。
Microsoft.Extensions.Logging.Console 提供程序包向控制臺(tái)發(fā)送日志輸出。
C#
logging.AddConsole();
要查看控制臺(tái)日志記錄輸出,請(qǐng)?jiān)陧?xiàng)目文件夾中打開(kāi)命令提示符并運(yùn)行以下命令:
console
dotnet run
Microsoft.Extensions.Logging.Debug 提供程序包使用 System.Diagnostics.Debug 類(lèi)(Debug.WriteLine 方法調(diào)用)來(lái)寫(xiě)入日志輸出。
在 Linux 中,此提供程序?qū)⑷罩緦?xiě)入 /var/log/message。
C#
logging.AddDebug();
對(duì)于面向 ASP.NET Core 1.1.0 或更高版本的應(yīng)用,Microsoft.Extensions.Logging.EventSource 提供程序包可實(shí)現(xiàn)事件跟蹤。 在 Windows 中,它使用 ETW。 提供程序可跨平臺(tái)使用,但尚無(wú)支持 Linux 或 macOS 的事件集合和顯示工具。
C#
logging.AddEventSourceLogger();
可使用 PerfView 實(shí)用工具收集和查看日志。 雖然其他工具也可以查看 ETW 日志,但在處理由 ASP.NET 發(fā)出的 ETW 事件時(shí),使用 PerfView 能獲得最佳體驗(yàn)。
要將 PerfView 配置為收集此提供程序記錄的事件,請(qǐng)向 Additional Providers 列表添加字符串 *Microsoft-Extensions-Logging。 (請(qǐng)勿遺漏字符串起始處的星號(hào)。)
Microsoft.Extensions.Logging.EventLog 提供程序包向 Windows 事件日志發(fā)送日志輸出。
C#
logging.AddEventLog();
Microsoft.Extensions.Logging.TraceSource 提供程序包使用 TraceSource 庫(kù)和提供程序。
C#
logging.AddTraceSource(sourceSwitchName);
AddTraceSource 重載 允許傳入資源開(kāi)關(guān)和跟蹤偵聽(tīng)器。
要使用此提供程序,應(yīng)用必須在 .NET Framework(而非 .NET Core)上運(yùn)行。 提供程序可將消息路由到多個(gè)偵聽(tīng)器,例如示例應(yīng)用中使用的 TextWriterTraceListener。
要了解 Azure 中的日志記錄,請(qǐng)參閱下列部分:
Microsoft.Extensions.Logging.AzureAppServices 提供程序包將日志寫(xiě)入 Azure App Service 應(yīng)用的文件系統(tǒng),以及 Azure 存儲(chǔ)帳戶中的 blob 存儲(chǔ)。 面向 .NET Core 1.1 或更高版本的應(yīng)用可使用該提供程序包。
如果面向 .NET Core,請(qǐng)注意以下幾點(diǎn):
如果面向 .NET Framework 或引用 Microsoft.AspNetCore.App 元包,請(qǐng)向項(xiàng)目添加提供程序包。 調(diào)用 AddAzureWebAppDiagnostics:
C#
logging.AddAzureWebAppDiagnostics();
要配置提供程序設(shè)置,請(qǐng)使用 AzureFileLoggerOptions 和 AzureBlobLoggerOptions,如以下示例所示:
C#
public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args).Build();
var todoRepository = host.Services.GetRequiredService<ITodoRepository>();
todoRepository.Add(new Core.Model.TodoItem() { Name = "Feed the dog" });
todoRepository.Add(new Core.Model.TodoItem() { Name = "Walk the dog" });
var logger = host.Services.GetRequiredService<ILogger<Program>>();
logger.LogInformation("Seeded the database.");
host.Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.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";
}))
.UseStartup<Startup>();
在部署應(yīng)用服務(wù)應(yīng)用時(shí),應(yīng)用程序?qū)⒆裱?Azure 門(mén)戶中“應(yīng)用服務(wù)”頁(yè)面下的診斷日志部分的設(shè)置。 更新這些設(shè)置后,更改會(huì)立即生效,無(wú)需重新啟動(dòng)或重新部署應(yīng)用。
日志文件的默認(rèn)位置是 D:\home\LogFiles\Application 文件夾,默認(rèn)文件名為 diagnostics-yyyymmdd.txt。 默認(rèn)文件大小上限為 10 MB,默認(rèn)最大保留文件數(shù)為 2。 默認(rèn) blob 名為 {app-name}{timestamp}/yyyy/mm/dd/hh/{guid}-applicationLog.txt。
該提供程序僅當(dāng)項(xiàng)目在 Azure 環(huán)境中運(yùn)行時(shí)有效。 項(xiàng)目在本地運(yùn)行時(shí),該提供程序無(wú)效 — 它不會(huì)寫(xiě)入本地文件或 blob 的本地開(kāi)發(fā)存儲(chǔ)。
通過(guò) Azure 日志流式處理,可從以下位置實(shí)時(shí)查看日志活動(dòng):
要配置 Azure 日志流式處理,請(qǐng)執(zhí)行以下操作:
導(dǎo)航到“日志流式處理”頁(yè),查看應(yīng)用消息。 它們由應(yīng)用通過(guò) ILogger 接口記錄。
Application Insights SDK 可收集和報(bào)告 ASP.NET Core 日志記錄基礎(chǔ)結(jié)構(gòu)生成的日志。 有關(guān)更多信息,請(qǐng)參見(jiàn)以下資源:
適用于 ASP.NET Core 的第三方日志記錄框架:
某些第三方框架可以執(zhí)行語(yǔ)義日志記錄(又稱結(jié)構(gòu)化日志記錄)。
使用第三方框架類(lèi)似于使用以下內(nèi)置提供程序之一:
有關(guān)詳細(xì)信息,請(qǐng)參閱各提供程序的相關(guān)文檔。 Microsoft 不支持第三方日志記錄提供程序。
更多建議: