日志記錄提供程序會顯示或存儲日志。 例如,控制臺提供程序在控制臺上顯示日志,Azure Application Insights 提供程序會將這些日志存儲在 Azure Application Insights 中。 可通過添加多個提供程序?qū)⑷罩景l(fā)送到多個目標。
要添加提供程序,請在 Program.cs 中調(diào)用提供程序的 Add{provider name} 擴展方法:
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();
}
默認項目模板調(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,則可自行選擇提供程序來替換默認提供程序。 調(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();
});
詳細了解內(nèi)置日志記錄提供程序,以及本文稍后部分介紹的第三方日志記錄提供程序。
從 DI 中獲取 ILogger<TCategoryName> 對象。
以下控制器示例會創(chuàng)建 Information 和 Warning 日志。 類別為 TodoApiSample.Controllers.TodoController(示例應(yīng)用中 TodoController 的完全限定類名):
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 頁面示例會創(chuàng)建“級別”為 Information 且“類別”為 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);
}
日志“級別”代表所記錄事件的嚴重程度。 日志“類別”是與每個日志關(guān)聯(lián)的字符串。 ILogger<T> 實例會創(chuàng)建“類別”為類型 T 的完全限定名稱的日志。 本文稍后部分將更詳細地介紹級別和類別。
要將日志寫入 Startup 類,構(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();
}
}
要將日志寫入 Program 類,請從 DI 獲取 ILogger 實例:
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)該會很快,不值得犧牲性能來使用異步代碼。 如果你的日志數(shù)據(jù)存儲很慢,請不要直接寫入它。 首先考慮將日志消息寫入快速存儲,售后再將其變?yōu)槁俅鎯Α?nbsp;例如,如果你要記錄到 SQL Server,你可能不想直接在 Log 方法中記錄,因為 Log 方法是同步的。 相反,你會將日志消息同步添加到內(nèi)存中的隊列,并讓后臺輔助線程從隊列中拉出消息,以完成將數(shù)據(jù)推送到 SQL Server 的異步工作。
日志記錄提供程序配置由一個或多個配置提供程序提供:
例如,日志記錄配置通常由應(yīng)用設(shè)置文件的 Logging 部分提供。 以下示例顯示了典型 appsettings.Development.json 文件的內(nèi)容:
JSON
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
},
"Console":
{
"IncludeScopes": true
}
}
}
Logging 屬性可具有 LogLevel 和日志提供程序?qū)傩裕@示控制臺)。
Logging 下的 LogLevel 屬性指定了用于記錄所選類別的最低級別。 在本例中,System 和 Microsoft 類別在 Information 級別記錄,其他均在 Debug 級別記錄。
Logging 下的其他屬性均指定了日志記錄提供程序。 本示例針對控制臺提供程序。 如果提供程序支持日志作用域,則 IncludeScopes 將指示是否啟用這些域。 提供程序?qū)傩裕ɡ绫纠?nbsp;Console)也可指定 LogLevel 屬性。 LogLevel 在提供程序下指定要為該提供程序記錄的級別。
如果在 Logging.{providername}.LogLevel 中指定了級別,則這些級別將重寫 Logging.LogLevel 中設(shè)置的所有內(nèi)容。
若要了解如何實現(xiàn)配置提供程序,請參閱 ASP.NET Core 中的配置。
使用上一部分中顯示的示例代碼從命令行運行應(yīng)用時,將在控制臺中看到日志。 以下是控制臺輸出示例:
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
通過向 http://localhost:5000/api/todo/0 處的示例應(yīng)用發(fā)出 HTTP Get 請求來生成前述日志。
在 Visual Studio 中運行示例應(yīng)用時,“調(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”開頭的。以“Microsoft”類別開頭的日志來自 ASP.NET Core 框架代碼。 ASP.NET Core 和應(yīng)用程序代碼使用相同的日志記錄 API 和提供程序。
本文余下部分將介紹有關(guān)日志記錄的某些詳細信息及選項。
ILogger 和 ILoggerFactory 接口位于 Microsoft.Extensions.Logging.Abstractions 中,其默認實現(xiàn)位于 Microsoft.Extensions.Logging 中。
創(chuàng)建 ILogger 對象后,將為其指定“類別”。 該類別包含在由此 ILogger 實例創(chuàng)建的每條日志消息中。 類別可以是任何字符串,但約定需使用類名,例如“TodoApi.Controllers.TodoController”。
使用 ILogger<T> 獲取一個 ILogger 實例,該實例使用 T 的完全限定類型名稱作為類別:
C#
public class TodoController : Controller
{
private readonly ITodoRepository _todoRepository;
private readonly ILogger _logger;
public TodoController(ITodoRepository todoRepository,
ILogger<TodoController> logger)
{
_todoRepository = todoRepository;
_logger = logger;
}
要顯式指定類別,請調(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> 相當于調(diào)用完全限定類型名稱為 T 的 CreateLogger。
每個日志都指定了一個 LogLevel 值。 日志級別指示嚴重性或重要程度。 例如,可在方法正常結(jié)束時寫入 Information 日志,在方法返回“404 找不到”狀態(tài)代碼時寫入 Warning 日志。
下面的代碼會創(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);
}
在上述代碼中,第一個參數(shù)是日志事件 ID。 第二個參數(shù)是消息模板,其中的占位符用于填寫剩余方法形參提供的實參值。 稍后將在本文的消息模板部分介紹方法參數(shù)。
在方法名稱中包含級別的日志方法(例如 LogInformation 和 LogWarning)是 ILogger 的擴展方法。 這些方法會調(diào)用可接受 LogLevel 參數(shù)的 Log 方法。 可直接調(diào)用 Log 方法而不調(diào)用其中某個擴展方法,但語法相對復雜。 有關(guān)詳細信息,請參閱 ILogger 和記錄器擴展源代碼。
ASP.NET Core 定義了以下日志級別(按嚴重性從低到高排列)。
使用日志級別控制寫入到特定存儲介質(zhì)或顯示窗口的日志輸出量。 例如:
本文稍后的日志篩選部分介紹如何控制提供程序處理的日志級別。
ASP.NET Core 為框架事件寫入日志。 本文前面部分提供的日志示例排除了低于 Information 級別的日志,因此未創(chuàng)建 Debug 或 Trace 級別日志。 以下示例介紹了通過運行配置為顯示 Debug 日志的示例應(yīng)用而生成的控制臺日志:
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
每個日志都可指定一個事件 ID。 該示例應(yīng)用通過使用本地定義的 LoggingEvents 類來執(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)。 例如,與在頁面上顯示項列表相關(guān)的所有日志可能是 1001。
日志記錄提供程序可將事件 ID 存儲在 ID 字段中,存儲在日志記錄消息中,或者不進行存儲。 調(diào)試提供程序不顯示事件 ID。 控制臺提供程序在類別后的括號中顯示事件 ID:
console
info: TodoApi.Controllers.TodoController[1002]
Getting item invalidid
warn: TodoApi.Controllers.TodoController[4000]
GetById(invalidid) NOT FOUND
每個日志都會指定一個消息模板。 消息模板可包含要填寫參數(shù)的占位符。 請在占位符中使用名稱而不是數(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ù)。 在以下代碼中,請注意消息模板中的參數(shù)名稱未按順序排列:
C#
string p1 = "parm1";
string p2 = "parm2";
_logger.LogInformation("Parameter values: {p2}, {p1}", p1, p2);
此代碼創(chuàng)建了一個參數(shù)值按順序排列的日志消息:
Parameter values: parm1, parm2
日志記錄框架按此方式工作,這樣日志記錄提供程序即可實現(xiàn)語義日志記錄,也稱為結(jié)構(gòu)化日志記錄。 參數(shù)本身會傳遞給日志記錄系統(tǒng),而不僅僅是格式化的消息模板。 通過此信息,日志記錄提供程序能夠?qū)?shù)值存儲為字段。 例如,假設(shè)記錄器方法調(diào)用如下所示:
C#
_logger.LogInformation("Getting item {ID} at {RequestTime}", id, DateTime.Now);
如果要將日志發(fā)送到 Azure 表存儲,則每個 Azure 表實體都可具有 ID 和 RequestTime 屬性,這簡化了對日志數(shù)據(jù)的查詢。 無需分析文本消息的超時,查詢即可找到特定 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
可為特定或所有提供程序和類別指定最低日志級別。 最低級別以下的日志不會傳遞給該提供程序,因此不會顯示或存儲它們。
要禁止顯示所有日志,可將 LogLevel.None 指定為最低日志級別。 LogLevel.None 的整數(shù)值為 6,它大于 LogLevel.Critical (5)。
項目模板代碼調(diào)用 CreateDefaultBuilder 來為控制臺和調(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ù)按提供程序和類別指定最低日志級別,如下方示例所示:
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 條用于控制臺提供程序, 1 條用于所有提供程序。 創(chuàng)建 ILogger 對象時,為每個提供程序選擇一個規(guī)則。
下面的示例演示了如何在代碼中注冊篩選規(guī)則:
C#
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging(logging =>
logging.AddFilter("System", LogLevel.Debug)
.AddFilter<DebugLoggerProvider>("Microsoft", LogLevel.Trace));
第二個 AddFilter 使用類型名稱來指定調(diào)試提供程序。 第一個 AddFilter 應(yīng)用于全部提供程序,因為它未指定提供程序類型。
先前示例中顯示的配置數(shù)據(jù)和 AddFilter 代碼會創(chuàng)建下表所示的規(guī)則。 前六條由配置示例創(chuàng)建,后兩條由代碼示例創(chuàng)建。
數(shù)字 | 提供程序 | 類別的開頭為... | 最低日志級別 |
---|---|---|---|
1 | 調(diào)試 | 全部類別 | 信息 |
2 | 控制臺 | Microsoft.AspNetCore.Mvc.Razor.Internal | 警告 |
3 | 控制臺 | Microsoft.AspNetCore.Mvc.Razor.Razor | 調(diào)試 |
4 | 控制臺 | Microsoft.AspNetCore.Mvc.Razor | Error |
5 | 控制臺 | 全部類別 | 信息 |
6 | 全部提供程序 | 全部類別 | 調(diào)試 |
7 | 全部提供程序 | 系統(tǒng) | 調(diào)試 |
8 | 調(diào)試 | Microsoft | 跟蹤 |
創(chuàng)建 ILogger 對象時,ILoggerFactory 對象將根據(jù)提供程序選擇一條規(guī)則,將其應(yīng)用于該記錄器。將按所選規(guī)則篩選 ILogger 實例寫入的所有消息。 從可用規(guī)則中為每個提供程序和類別對選擇最具體的規(guī)則。
在為給定的類別創(chuàng)建 ILogger 時,以下算法將用于每個提供程序:
假設(shè)你使用上述規(guī)則列表為類別“Microsoft.AspNetCore.Mvc.Razor.RazorViewEngine”創(chuàng)建了 ILogger 對象:
生成的 ILogger 實例將 Trace 級別及更高級別的日志發(fā)送到調(diào)試提供程序。 Debug 級別及更高級別的日志會發(fā)送到控制臺提供程序。
每個提供程序都定義了一個別名;可在配置中使用該別名來代替完全限定的類型名稱。 對于內(nèi)置提供程序,請使用以下別名:
僅當配置或代碼中的規(guī)則對給定提供程序和類別都不適用時,最低級別設(shè)置才會生效。 下面的示例演示如何設(shè)置最低級別:
C#
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging(logging => logging.SetMinimumLevel(LogLevel.Warning));
如果沒有明確設(shè)置最低級別,則默認值為 Information,它表示 Trace 和 Debug 日志將被忽略。
對配置或代碼沒有向其分配規(guī)則的所有提供程序和類別調(diào)用篩選器函數(shù)。 函數(shù)中的代碼可訪問提供程序類型、類別和日志級別。 例如:
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 使用的一些類別,備注中說明了可從這些類別獲取的具體日志:
類別 | 說明 |
---|---|
Microsoft.AspNetCore | 常規(guī) ASP.NET Core 診斷。 |
Microsoft.AspNetCore.DataProtection | 考慮、找到并使用了哪些密鑰。 |
Microsoft.AspNetCore.HostFiltering | 所允許的主機。 |
Microsoft.AspNetCore.Hosting | HTTP 請求完成的時間和啟動時間。 加載了哪些承載啟動程序集。 |
Microsoft.AspNetCore.Mvc | MVC 和 Razor 診斷。 模型綁定、篩選器執(zhí)行、視圖編譯和操作選擇。 |
Microsoft.AspNetCore.Routing | 路由匹配信息。 |
Microsoft.AspNetCore.Server | 連接啟動、停止和保持活動響應(yīng)。 HTTP 證書信息。 |
Microsoft.AspNetCore.StaticFiles | 提供的文件。 |
Microsoft.EntityFrameworkCore | 常規(guī) Entity Framework Core 診斷。 數(shù)據(jù)庫活動和配置、更改檢測、遷移。 |
“作用域”可對一組邏輯操作分組。 此分組可用于將相同的數(shù)據(jù)附加到作為集合的一部分而創(chuàng)建的每個日志。 例如,在處理事務(wù)期間創(chuàng)建的每個日志都可包括事務(wù) ID。
范圍是由 BeginScope 方法返回的 IDisposable 類型,持續(xù)至釋放為止。 要使用作用域,請在 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);
}
下列代碼為控制臺提供程序啟用作用域:
Program.cs:
C#
.ConfigureLogging((hostingContext, logging) =>
{
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddConsole(options => options.IncludeScopes = true);
logging.AddDebug();
})
備注
要啟用基于作用域的日志記錄,必須先配置 IncludeScopes 控制臺記錄器選項。
若要了解關(guān)配置,請參閱配置部分。
每條日志消息都包含作用域內(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 的日志記錄選項。
有關(guān) stdout 日志記錄的信息,請參閱 對 IIS 上的 ASP.NET Core 進行故障排除 和 對 Azure 應(yīng)用服務(wù)上的 ASP.NET Core 進行故障排除。
Microsoft.Extensions.Logging.Console 提供程序包向控制臺發(fā)送日志輸出。
C#
logging.AddConsole();
要查看控制臺日志記錄輸出,請在項目文件夾中打開命令提示符并運行以下命令:
console
dotnet run
Microsoft.Extensions.Logging.Debug 提供程序包使用 System.Diagnostics.Debug 類(Debug.WriteLine 方法調(diào)用)來寫入日志輸出。
在 Linux 中,此提供程序?qū)⑷罩緦懭?/var/log/message。
C#
logging.AddDebug();
對于面向 ASP.NET Core 1.1.0 或更高版本的應(yīng)用,Microsoft.Extensions.Logging.EventSource 提供程序包可實現(xiàn)事件跟蹤。 在 Windows 中,它使用 ETW。 提供程序可跨平臺使用,但尚無支持 Linux 或 macOS 的事件集合和顯示工具。
C#
logging.AddEventSourceLogger();
可使用 PerfView 實用工具收集和查看日志。 雖然其他工具也可以查看 ETW 日志,但在處理由 ASP.NET 發(fā)出的 ETW 事件時,使用 PerfView 能獲得最佳體驗。
要將 PerfView 配置為收集此提供程序記錄的事件,請向 Additional Providers 列表添加字符串 *Microsoft-Extensions-Logging。 (請勿遺漏字符串起始處的星號。)
Microsoft.Extensions.Logging.EventLog 提供程序包向 Windows 事件日志發(fā)送日志輸出。
C#
logging.AddEventLog();
Microsoft.Extensions.Logging.TraceSource 提供程序包使用 TraceSource 庫和提供程序。
C#
logging.AddTraceSource(sourceSwitchName);
AddTraceSource 重載 允許傳入資源開關(guān)和跟蹤偵聽器。
要使用此提供程序,應(yīng)用必須在 .NET Framework(而非 .NET Core)上運行。 提供程序可將消息路由到多個偵聽器,例如示例應(yīng)用中使用的 TextWriterTraceListener。
要了解 Azure 中的日志記錄,請參閱下列部分:
Microsoft.Extensions.Logging.AzureAppServices 提供程序包將日志寫入 Azure App Service 應(yīng)用的文件系統(tǒng),以及 Azure 存儲帳戶中的 blob 存儲。 面向 .NET Core 1.1 或更高版本的應(yīng)用可使用該提供程序包。
如果面向 .NET Core,請注意以下幾點:
如果面向 .NET Framework 或引用 Microsoft.AspNetCore.App 元包,請向項目添加提供程序包。 調(diào)用 AddAzureWebAppDiagnostics:
C#
logging.AddAzureWebAppDiagnostics();
要配置提供程序設(shè)置,請使用 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)用時,應(yīng)用程序?qū)⒆裱?Azure 門戶中“應(yīng)用服務(wù)”頁面下的診斷日志部分的設(shè)置。 更新這些設(shè)置后,更改會立即生效,無需重新啟動或重新部署應(yīng)用。
日志文件的默認位置是 D:\home\LogFiles\Application 文件夾,默認文件名為 diagnostics-yyyymmdd.txt。 默認文件大小上限為 10 MB,默認最大保留文件數(shù)為 2。 默認 blob 名為 {app-name}{timestamp}/yyyy/mm/dd/hh/{guid}-applicationLog.txt。
該提供程序僅當項目在 Azure 環(huán)境中運行時有效。 項目在本地運行時,該提供程序無效 — 它不會寫入本地文件或 blob 的本地開發(fā)存儲。
通過 Azure 日志流式處理,可從以下位置實時查看日志活動:
要配置 Azure 日志流式處理,請執(zhí)行以下操作:
導航到“日志流式處理”頁,查看應(yīng)用消息。 它們由應(yīng)用通過 ILogger 接口記錄。
Application Insights SDK 可收集和報告 ASP.NET Core 日志記錄基礎(chǔ)結(jié)構(gòu)生成的日志。 有關(guān)更多信息,請參見以下資源:
適用于 ASP.NET Core 的第三方日志記錄框架:
某些第三方框架可以執(zhí)行語義日志記錄(又稱結(jié)構(gòu)化日志記錄)。
使用第三方框架類似于使用以下內(nèi)置提供程序之一:
有關(guān)詳細信息,請參閱各提供程序的相關(guān)文檔。 Microsoft 不支持第三方日志記錄提供程序。
更多建議: