登入 .NET Core 與 ASP.NET CoreLogging in .NET Core and ASP.NET Core

作者:Tom DykstraSteve SmithBy Tom Dykstra and Steve Smith

.NET Core 支援記錄 API,此 API 能與各種內建和第三方記錄提供者搭配使用。.NET Core supports a logging API that works with a variety of built-in and third-party logging providers. 此文章說明如何搭配內建提供者使用 API。This article shows how to use the logging API with built-in providers.

本文中顯示的大部分程式碼範例都來自 ASP.NET Core 應用程式。Most of the code examples shown in this article are from ASP.NET Core apps. 這些程式碼片段的記錄特定部分,適用於任何使用一般主機的 .NET Core 應用程式。The logging-specific parts of these code snippets apply to any .NET Core app that uses the Generic host. 如需如何在非 Web 主控台應用程式中使用一般主機的資訊,請參閱託管服務For information about how to use the Generic Host in non-web console apps, see Hosted services.

不含一般主機的應用程式記錄程式碼,會因新增提供者建立記錄器的方式而有所不同。Logging code for apps without Generic Host differs in the way providers are added and loggers are created. 非主機程式碼範例顯示於本文的這些章節中。Non-host code examples are shown in those sections of the article.

檢視或下載範例程式碼 (英文) (如何下載)View or download sample code (how to download)

新增提供者Add providers

記錄提供者會顯示或儲存記錄。A logging provider displays or stores logs. 例如,主控台提供者會在主控台上顯示記錄,而 Azure Application Insights 提供者則會將記錄儲存在 Azure Application Insights 中。For example, the Console provider displays logs on the console, and the Azure Application Insights provider stores them in Azure Application Insights. 您可以透過新增多個提供者的方式來將記錄傳送到多個目的地。Logs can be sent to multiple destinations by adding multiple providers.

若要在使用一般主機的應用程式中新增提供者,請在 Program.cs 中呼叫提供者的 Add{provider name} 擴充方法:To add a provider in an app that uses Generic Host, call the provider's Add{provider name} extension method in Program.cs:

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureLogging(logging =>
        {
            logging.ClearProviders();
            logging.AddConsole();
        })
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });

在非主機主控台應用程式中,於建立 LoggerFactory 時呼叫提供者的 Add{provider name} 擴充方法:In a non-host console app, call the provider's Add{provider name} extension method while creating a LoggerFactory:

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");

LoggerFactoryAddConsole 需要 Microsoft.Extensions.Loggingusing 陳述式。LoggerFactory and AddConsole require a using statement for Microsoft.Extensions.Logging.

預設 ASP.NET Core 專案範本會呼叫 CreateDefaultBuilder 新增下列記錄提供者:The default ASP.NET Core project templates call CreateDefaultBuilder, which adds the following logging providers:

  • 主控台Console
  • 偵錯Debug
  • EventSourceEventSource
  • EventLog (僅當在 Windows 上執行時)EventLog (only when running on Windows)

您可以使用您想要的提供者來取代預設提供者。You can replace the default providers with your own choices. 呼叫 ClearProviders 並新增您要的提供者。Call ClearProviders, and add the providers you want.

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureLogging(logging =>
        {
            logging.ClearProviders();
            logging.AddConsole();
        })
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });

若要新增提供者,請在 Program.cs 中呼叫提供者的 Add{provider name} 擴充方法:To add a provider, call the provider's Add{provider name} extension method in Program.cs:

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) =>
        {
            // Requires `using Microsoft.Extensions.Logging;`
            logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
            logging.AddConsole();
            logging.AddDebug();
            logging.AddEventSourceLogger();
        })
        .UseStartup<Startup>()
        .Build();

    webHost.Run();
}

上述程式碼需要對 Microsoft.Extensions.LoggingMicrosoft.Extensions.Configuration 的參考。The preceding code requires references to Microsoft.Extensions.Logging and Microsoft.Extensions.Configuration.

預設專案範本會呼叫 CreateDefaultBuilder,該項目會新增下列記錄提供者:The default project template calls CreateDefaultBuilder, which adds the following logging providers:

  • 主控台Console
  • 偵錯Debug
  • EventSource (從 ASP.NET Core 2.2 開始)EventSource (starting in ASP.NET Core 2.2)
public static void Main(string[] args)
{
    CreateWebHostBuilder(args).Build().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>();

若您使用 CreateDefaultBuilder,您可以使用您想要的提供者來取代預設提供者。If you use CreateDefaultBuilder, you can replace the default providers with your own choices. 呼叫 ClearProviders 並新增您要的提供者。Call ClearProviders, and add the providers you want.

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();
        });

在此文章中深入了解內建記錄提供者第三方記錄提供者Learn more about built-in logging providers and third-party logging providers later in the article.

建立記錄Create logs

若要建立記錄,請使用 ILogger<TCategoryName> 物件。To create logs, use an ILogger<TCategoryName> object. 在 Web 應用程式或託管服務中,從相依性插入 (DI) 取得 ILoggerIn a web app or hosted service, get an ILogger from dependency injection (DI). 在非主機主控台應用程式中,使用 LoggerFactory 來建立 ILoggerIn non-host console apps, use the LoggerFactory to create an ILogger.

下列 ASP.NET Core 範例會建立以 TodoApiSample.Pages.AboutModel 作為類別的記錄器。The following ASP.NET Core example creates a logger with TodoApiSample.Pages.AboutModel as the category. 記錄「類別」 是與每個記錄關聯的字串。The log category is a string that is associated with each log. 由 DI 提供的 ILogger<T> 執行個體,會建立使用型別 T 作為類別的完整名稱記錄。The ILogger<T> instance provided by DI creates logs that have the fully qualified name of type T as the category.

public class AboutModel : PageModel
{
    private readonly ILogger _logger;

    public AboutModel(ILogger<AboutModel> logger)
    {
        _logger = logger;
    }

下列非主機主控台應用程式範例會建立以 LoggingConsoleApp.Program 作為類別的記錄器。The following non-host console app example creates a logger with LoggingConsoleApp.Program as the category.

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");
public class AboutModel : PageModel
{
    private readonly ILogger _logger;

    public AboutModel(ILogger<AboutModel> logger)
    {
        _logger = logger;
    }

在下列 ASP.NET Core 和主控台應用程式範例中,記錄器會用於以 Information 作為層級來建立記錄。In the following ASP.NET Core and console app examples, the logger is used to create logs with Information as the level. 記錄「層級」 指出已記錄事件的嚴重性。The Log level indicates the severity of the logged event.

public void OnGet()
{
    Message = $"About page visited at {DateTime.UtcNow.ToLongTimeString()}";
    _logger.LogInformation("Message displayed: {Message}", Message);
}
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");
public void OnGet()
{
    Message = $"About page visited at {DateTime.UtcNow.ToLongTimeString()}";
    _logger.LogInformation("Message displayed: {Message}", Message);
}

此文章稍後將詳細說明層級類別Levels and categories are explained in more detail later in this article.

在 Program 類別中建立記錄Create logs in the Program class

若要在 ASP.NET Core 應用程式的 Program 類別中寫入記錄,請在建立主機之後從 DI 取得 ILogger 執行個體:To write logs in the Program class of an ASP.NET Core app, get an ILogger instance from DI after building the host:

public static void Main(string[] args)
{
    var host = CreateHostBuilder(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.");

    IMyService myService = host.Services.GetRequiredService<IMyService>();
    myService.WriteLog("Logged from MyService.");

    host.Run();
}

在 Startup 類別中建立記錄Create logs in the Startup class

若要在 ASP.NET Core 應用程式的 Startup.Configure 方法中寫入記錄,請在方法簽章中包含 ILogger 參數:To write logs in the Startup.Configure method of an ASP.NET Core app, include an ILogger parameter in the method signature:

public void Configure(IApplicationBuilder app, IHostEnvironment env, ILogger<Startup> logger)
{
    if (env.IsDevelopment())
    {
        logger.LogInformation("In Development environment");
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
        endpoints.MapRazorPages();
    });
}

在以 Startup.ConfigureServices 方法完成 DI 容器設定之前,不支援寫入記錄檔:Writing logs before completion of the DI container setup in the Startup.ConfigureServices method is not supported:

  • 不支援將記錄器插入 Startup 建構函式。Logger injection into the Startup constructor is not supported.
  • 不支援將記錄器插入 Startup.ConfigureServices 方法簽章Logger injection into the Startup.ConfigureServices method signature is not supported

這項限制的原因是記錄相依於 DI 和組態,而後者相依於 DI。The reason for this restriction is that logging depends on DI and on configuration, which in turns depends on DI. ConfigureServices 完成後才會設定 DI 容器。The DI container isn't set up until ConfigureServices finishes.

記錄器的建構函式插入 Startup 適用於舊版 ASP.NET Core,因為會為 Web 主機建立個別的 DI 容器。Constructor injection of a logger into Startup works in earlier versions of ASP.NET Core because a separate DI container is created for the Web Host. 如需為何只為一般主機建立一個容器的資訊,請參閱重大變更公告For information about why only one container is created for the Generic Host, see the breaking change announcement.

如果您需要設定相依於 ILogger<T> 的服務,您仍然可以使用建構函式插入或提供 Factory 方法來執行此動作。If you need to configure a service that depends on ILogger<T>, you can still do that by using constructor injection or by providing a factory method. 只有在沒有其他選項時,才建議使用 Factory 方法。The factory method approach is recommended only if there is no other option. 例如,假設您需要使用 DI 的服務來填入屬性:For example, suppose you need to fill a property with a service from 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 };
    });

    services.AddSingleton<ITodoRepository, TodoRepository>();
}

前面的醒目提示程式碼是 Func,會在 DI 容器第一次需要建立 MyService 的執行個體時執行。The preceding highlighted code is a Func that runs the first time the DI container needs to construct an instance of MyService. 您可以用此方式存取任何已註冊的服務。You can access any of the registered services in this way.

在啟動中建立記錄Create logs in Startup

若要在 Startup 類別中寫入記錄,請在建構函式簽章中包括 ILogger 參數:To write logs in the Startup class, include an ILogger parameter in the constructor signature:

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 類別中建立記錄Create logs in the Program class

若要在 Program 類別中寫入記錄,請從 DI 取得 ILogger 執行個體:To write logs in the Program class, get an ILogger instance from DI:

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();
        });

無非同步記錄器方法No asynchronous logger methods

記錄速度應該很快,不值得花費非同步程式碼的效能成本來處理。Logging should be so fast that it isn't worth the performance cost of asynchronous code. 若您的記錄資料存放區很慢,請不要直接寫入其中。If your logging data store is slow, don't write to it directly. 請考慮一開始將記錄寫入到快速的存放區,稍後再將它們移到慢速存放區。Consider writing the log messages to a fast store initially, then move them to the slow store later. 例如,如果您要登入 SQL Server,您不希望在 Log 方法中直接執行,因為 Log 方法是同步的。For example, if you're logging to SQL Server, you don't want to do that directly in a Log method, since the Log methods are synchronous. 相反地,以同步方式將記錄訊息新增到記憶體內佇列,並讓背景工作角色提取出佇列的訊息,藉此執行推送資料到 SQL Server 的非同步工作。Instead, synchronously add log messages to an in-memory queue and have a background worker pull the messages out of the queue to do the asynchronous work of pushing data to SQL Server.

ConfigurationConfiguration

記錄提供者設定是由一或多個記錄提供者提供:Logging provider configuration is provided by one or more configuration providers:

  • 檔案格式 (INI、JSON 及 XML)。File formats (INI, JSON, and XML).
  • 命令列引數。Command-line arguments.
  • 環境變數。Environment variables.
  • 記憶體內部 .NET 物件。In-memory .NET objects.
  • 未加密的祕密管理員儲存體。The unencrypted Secret Manager storage.
  • 類似 Azure Key Vault的加密使用者存放區。An encrypted user store, such as Azure Key Vault.
  • 自訂提供者 (已安裝或已建立)。Custom providers (installed or created).

例如,記錄設定通常是由應用程式的 Logging 區段所提供的。For example, logging configuration is commonly provided by the Logging section of app settings files. 下列範例顯示一般 appsettings.Development.json 檔案的內容:The following example shows the contents of a typical appsettings.Development.json file:

{
  "Logging": {
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    },
    "Console":
    {
      "IncludeScopes": true
    }
  }
}

Logging 屬性可以有 LogLevel 與記錄提供者屬性 (會顯示主控台)。The Logging property can have LogLevel and log provider properties (Console is shown).

Logging 下的 LogLevel 屬性會指定要針對所選類記錄的最小層級The LogLevel property under Logging specifies the minimum level to log for selected categories. 在範例中,System 與d Microsoft 類別會在 Information 層級記錄,而所有其他記錄則會在 Debug 層級記錄。In the example, System and Microsoft categories log at Information level, and all others log at Debug level.

Logging 下的其他屬性可指定記錄提供者。Other properties under Logging specify logging providers. 範例使用主控台提供者。The example is for the Console provider. 若提供者支援記錄範圍IncludeScopes 會指出是否已啟用記錄範圍。If a provider supports log scopes, IncludeScopes indicates whether they're enabled. 提供者屬性 (例如範例中的 Console) 可能也會指定 LogLevel 屬性。A provider property (such as Console in the example) may also specify a LogLevel property. 提供者下的 LogLevel 會指定提供者的記錄層級。LogLevel under a provider specifies levels to log for that provider.

若已在 Logging.{providername}.LogLevel 中指定層級,它們會覆寫 Logging.LogLevel 中設定的所有項目。If levels are specified in Logging.{providername}.LogLevel, they override anything set in Logging.LogLevel.

如需有關如何實作設定提供者的詳細資訊,請參閱 ASP.NET Core 的設定For information on implementing configuration providers, see ASP.NET Core 的設定.

範例記錄輸出Sample logging output

使用上一節中顯示的範例程式碼時,當從命令列執行應用程式時,記錄會出現在主控台中。With the sample code shown in the preceding section, logs appear in the console when the app is run from the command line. 主控台輸出範例如下:Here's an example of console output:

info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/1.1 GET http://localhost:5000/api/todo/0
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 84.26180000000001ms 307
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
      Request starting HTTP/2 GET https://localhost:5001/api/todo/0
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
      Executing endpoint 'TodoApiSample.Controllers.TodoController.GetById (TodoApiSample)'
info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[3]
      Route matched with {action = "GetById", controller = "Todo", page = ""}. Executing controller action with signature Microsoft.AspNetCore.Mvc.IActionResult GetById(System.String) on controller TodoApiSample.Controllers.TodoController (TodoApiSample).
info: TodoApiSample.Controllers.TodoController[1002]
      Getting item 0
warn: TodoApiSample.Controllers.TodoController[4000]
      GetById(0) NOT FOUND
info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
      Executing HttpStatusCodeResult, setting HTTP status code 404
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 的範例應用程式建立 HTTP Get 要求所產生。The preceding logs were generated by making an HTTP Get request to the sample app at http://localhost:5000/api/todo/0.

以下是您在 Visual Studio 中執行相同應用程式時,出現在 [偵錯] 視窗中的相同記錄範例:Here's an example of the same logs as they appear in the Debug window when you run the sample app in Visual Studio:

Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request starting HTTP/2.0 GET https://localhost:44328/api/todo/0  
Microsoft.AspNetCore.Routing.EndpointMiddleware: Information: Executing endpoint 'TodoApiSample.Controllers.TodoController.GetById (TodoApiSample)'
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker: Information: Route matched with {action = "GetById", controller = "Todo", page = ""}. Executing controller action with signature Microsoft.AspNetCore.Mvc.IActionResult GetById(System.String) on controller TodoApiSample.Controllers.TodoController (TodoApiSample).
TodoApiSample.Controllers.TodoController: Information: Getting item 0
TodoApiSample.Controllers.TodoController: Warning: GetById(0) NOT FOUND
Microsoft.AspNetCore.Mvc.StatusCodeResult: Information: Executing HttpStatusCodeResult, setting HTTP status code 404
Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker: Information: Executed action TodoApiSample.Controllers.TodoController.GetById (TodoApiSample) in 34.167ms
Microsoft.AspNetCore.Routing.EndpointMiddleware: Information: Executed endpoint 'TodoApiSample.Controllers.TodoController.GetById (TodoApiSample)'
Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request finished in 98.41300000000001ms 404

這些透過上一節中所示 ILogger 呼叫所建立的記錄是以 "TodoApiSample" 為開頭。The logs that are created by the ILogger calls shown in the preceding section begin with "TodoApiSample". 開頭為 "Microsoft" 類別的記錄則是來自 ASP.NET Core 架構程式碼。The logs that begin with "Microsoft" categories are from ASP.NET Core framework code. ASP.NET Core 與應用程式程式碼會使用相同的記錄 API 與提供者。ASP.NET Core and application code are using the same logging API and providers.

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 呼叫所建立的記錄是以 "TodoApi" 為開頭。The logs that are created by the ILogger calls shown in the preceding section begin with "TodoApi". 開頭為 "Microsoft" 類別的記錄則是來自 ASP.NET Core 架構程式碼。The logs that begin with "Microsoft" categories are from ASP.NET Core framework code. ASP.NET Core 與應用程式程式碼會使用相同的記錄 API 與提供者。ASP.NET Core and application code are using the same logging API and providers.

本文的其餘部分將說明記錄的一些詳細資料和選項。The remainder of this article explains some details and options for logging.

NuGet 套件NuGet packages

ILoggerILoggerFactory 介面位於 Microsoft.Extensions.Logging.Abstractions 中,其預設實作則位於 Microsoft.Extensions.Logging 中。The ILogger and ILoggerFactory interfaces are in Microsoft.Extensions.Logging.Abstractions, and default implementations for them are in Microsoft.Extensions.Logging.

記錄類別Log category

建立 ILogger 物件時,會為它指定「類別」 。When an ILogger object is created, a category is specified for it. 該類別會包含在每個由該 ILogger 執行個體所產生的記錄訊息中。That category is included with each log message created by that instance of ILogger. 類別可以是任意字串,但慣例是使用類別名稱,例如 "TodoApi.Controllers.TodoController"。The category may be any string, but the convention is to use the class name, such as "TodoApi.Controllers.TodoController".

使用 ILogger<T> 來取得ILogger 執行個體,它使用 T 的完整類型名稱做為類別:Use ILogger<T> to get an ILogger instance that uses the fully qualified type name of T as the category:

public class TodoController : Controller
{
    private readonly ITodoRepository _todoRepository;
    private readonly ILogger _logger;

    public TodoController(ITodoRepository todoRepository,
        ILogger<TodoController> logger)
    {
        _todoRepository = todoRepository;
        _logger = logger;
    }
public class TodoController : Controller
{
    private readonly ITodoRepository _todoRepository;
    private readonly ILogger _logger;

    public TodoController(ITodoRepository todoRepository,
        ILogger<TodoController> logger)
    {
        _todoRepository = todoRepository;
        _logger = logger;
    }

若要明確指定類別,請呼叫 ILoggerFactory.CreateLoggerTo explicitly specify the category, call ILoggerFactory.CreateLogger:

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");
    }
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> 相當於使用 T的完整類型名稱來呼叫 CreateLoggerILogger<T> is equivalent to calling CreateLogger with the fully qualified type name of T.

記錄層級Log level

每個記錄都會指定 LogLevel 值。Every log specifies a LogLevel value. 記錄層級表示嚴重性或重要性。The log level indicates the severity or importance. 例如,您可以在方法不正常終止時寫入 Information 記錄,並在方法傳回 404 找不到 狀態碼時寫入 Warning 記錄。For example, you might write an Information log when a method ends normally and a Warning log when a method returns a 404 Not Found status code.

下列程式碼會建立 InformationWarning 記錄:The following code creates Information and Warning logs:

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);
}
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);
}

在上述程式碼中,第一個參數是記錄事件識別碼In the preceding code, the first parameter is the Log event ID. 第二個參數是訊息範本,其中的預留位置會置入其餘方法參數所提供的引數值。The second parameter is a message template with placeholders for argument values provided by the remaining method parameters. 此文章稍後的訊息範本小節將詳細說明方法參數。The method parameters are explained in the message template section later in this article.

在方法名稱中包含層級的記錄方法 (例如 LogInformationLogWarning) 是 ILogger 的擴充方法Log methods that include the level in the method name (for example, LogInformation and LogWarning) are extension methods for ILogger. 這些方法會呼叫接受 Log 參數的 LogLevelThese methods call a Log method that takes a LogLevel parameter. 您可以直接呼叫 Log 方法,而不是呼叫其中一個擴充方法,但語法會更複雜。You can call the Log method directly rather than one of these extension methods, but the syntax is relatively complicated. 如需詳細資訊,請參閱 ILogger記錄器延伸模組原始程式碼For more information, see ILogger and the logger extensions source code.

ASP.NET Core 定義下列記錄層級,並從最低嚴重性排列到最高嚴重性。ASP.NET Core defines the following log levels, ordered here from lowest to highest severity.

  • 追蹤 = 0Trace = 0

    針對通常只對偵錯有價值的資訊。For information that's typically valuable only for debugging. 這些訊息可能包含敏感性應用程式資料,因此不應該在生產環境中啟用。These messages may contain sensitive application data and so shouldn't be enabled in a production environment. 預設為停用。 Disabled by default.

  • 偵錯 = 1Debug = 1

    針對可在開發與偵錯中使用的資訊。For information that may be useful in development and debugging. 範例:Entering method Configure with flag set to true. 只有在進行疑難排解時才在生產環境中啟用 Debug 層級記錄,因為此類記錄的數目非常多。Example: Entering method Configure with flag set to true. Enable Debug level logs in production only when troubleshooting, due to the high volume of logs.

  • 資訊 = 2Information = 2

    針對一般應用程式流程的追蹤。For tracking the general flow of the app. 這些記錄通常有一些長期值。These logs typically have some long-term value. 範例:Request received for path /api/todoExample: Request received for path /api/todo

  • 警告 = 3Warning = 3

    針對應用程式流程中發生的異常或意外事件。For abnormal or unexpected events in the app flow. 這些記錄可能包含不會造成應用程式停止,但可能需要進行調查的錯誤或其他狀況。These may include errors or other conditions that don't cause the app to stop but might need to be investigated. 已處理的例外狀況即為使用 Warning 記錄層級的常見位置。Handled exceptions are a common place to use the Warning log level. 範例:FileNotFoundException for file quotes.txt.Example: FileNotFoundException for file quotes.txt.

  • 錯誤 = 4Error = 4

    發生無法處理的錯誤和例外狀況。For errors and exceptions that cannot be handled. 這些訊息指出目前活動或作業 (例如目前的 HTTP 要求) 中發生失敗,這不是整個應用程式的失敗。These messages indicate a failure in the current activity or operation (such as the current HTTP request), not an app-wide failure. 範例記錄訊息:Cannot insert record due to duplicate key violation.Example log message: Cannot insert record due to duplicate key violation.

  • 重大 = 5Critical = 5

    發生需要立即注意的失敗。For failures that require immediate attention. 範例:資料遺失情況、磁碟空間不足。Examples: data loss scenarios, out of disk space.

使用此記錄層級來控制要寫入至特定儲存媒體或顯示視窗的記錄輸出量。Use the log level to control how much log output is written to a particular storage medium or display window. 例如:For example:

  • 在生產環境中,透過 Information 層級將 Trace 傳送到大量資料存放區。In production, send Trace through Information level to a volume data store. 透過 CriticalWarning 傳送到值資料存放區。Send Warning through Critical to a value data store.
  • 在開發期間,透過 CriticalWarning 傳送到主控台,並在進行疑難排解時透過 Information 新增 TraceDuring development, send Warning through Critical to the console, and add Trace through Information when troubleshooting.

本文稍後的記錄篩選一節將說明如何控制提供者所處理的記錄層級。The Log filtering section later in this article explains how to control which log levels a provider handles.

ASP.NET Core 會寫入架構事件的記錄。ASP.NET Core writes logs for framework events. 此文章稍早的記錄範例已排除 Information 層級以下的記錄,因此未建立 DebugTrace 層級的任何記錄。The log examples earlier in this article excluded logs below Information level, so no Debug or Trace level logs were created. 以下是透過執行設定為顯示 Debug 記錄之範例應用程式所產生的主控台記錄範例:Here's an example of console logs produced by running the sample app configured to show Debug logs:

info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[3]
      Route matched with {action = "GetById", controller = "Todo", page = ""}. Executing controller action with signature Microsoft.AspNetCore.Mvc.IActionResult GetById(System.String) on controller TodoApiSample.Controllers.TodoController (TodoApiSample).
dbug: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[1]
      Execution plan of authorization filters (in the following order): None
dbug: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[1]
      Execution plan of resource filters (in the following order): Microsoft.AspNetCore.Mvc.ViewFeatures.Filters.SaveTempDataFilter
dbug: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[1]
      Execution plan of action filters (in the following order): Microsoft.AspNetCore.Mvc.Filters.ControllerActionFilter (Order: -2147483648), Microsoft.AspNetCore.Mvc.ModelBinding.UnsupportedContentTypeFilter (Order: -3000)
dbug: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[1]
      Execution plan of exception filters (in the following order): None
dbug: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[1]
      Execution plan of result filters (in the following order): Microsoft.AspNetCore.Mvc.ViewFeatures.Filters.SaveTempDataFilter
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder[22]
      Attempting to bind parameter 'id' of type 'System.String' ...
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.SimpleTypeModelBinder[44]
      Attempting to bind parameter 'id' of type 'System.String' using the name 'id' in request data ...
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.Binders.SimpleTypeModelBinder[45]
      Done attempting to bind parameter 'id' of type 'System.String'.
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder[23]
      Done attempting to bind parameter 'id' of type 'System.String'.
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder[26]
      Attempting to validate the bound parameter 'id' of type 'System.String' ...
dbug: Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder[27]
      Done attempting to validate the bound parameter 'id' of type 'System.String'.
info: TodoApiSample.Controllers.TodoController[1002]
      Getting item 0
warn: TodoApiSample.Controllers.TodoController[4000]
      GetById(0) NOT FOUND
info: Microsoft.AspNetCore.Mvc.StatusCodeResult[1]
      Executing HttpStatusCodeResult, setting HTTP status code 404
info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2]
      Executed action TodoApiSample.Controllers.TodoController.GetById (TodoApiSample) in 32.690400000000004ms
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
      Executed endpoint 'TodoApiSample.Controllers.TodoController.GetById (TodoApiSample)'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      Request finished in 176.9103ms 404
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

記錄事件識別碼Log event ID

每個記錄都可以指定「事件識別碼」 。Each log can specify an event ID. 範例應用程式透過使用本機定義的 LoggingEvents 類別來執行此動作:The sample app does this by using a locally defined LoggingEvents class:

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);
}
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;
}
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);
}
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;
}

事件識別碼會將一組事件關聯。An event ID associates a set of events. 例如,與在頁面上顯示項目清單相關的所有記錄可能都是 1001。For example, all logs related to displaying a list of items on a page might be 1001.

記錄提供者可能將事件識別碼存放到識別碼欄位、記錄訊息中或完全不存放。The logging provider may store the event ID in an ID field, in the logging message, or not at all. 偵錯提供者不會顯示事件識別碼。The Debug provider doesn't show event IDs. 主控台提供者會在類別後面以括弧顯示事件識別碼:The console provider shows event IDs in brackets after the category:

info: TodoApi.Controllers.TodoController[1002]
      Getting item invalidid
warn: TodoApi.Controllers.TodoController[4000]
      GetById(invalidid) NOT FOUND

記錄訊息範本Log message template

每個記錄都會指定訊息範本。Each log specifies a message template. 訊息範本可以包含有關提供哪個引數的預留位置。The message template can contain placeholders for which arguments are provided. 使用名稱而非數字做為預留位置。Use names for the placeholders, not numbers.

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);
}
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);
}

預留位置的順序 (而不是其名稱) 會決定使用哪些參數來提供其值。The order of placeholders, not their names, determines which parameters are used to provide their values. 請注意,在下列程式碼中,參數名稱在訊息範本中未依順序出現:In the following code, notice that the parameter names are out of sequence in the message template:

string p1 = "parm1";
string p2 = "parm2";
_logger.LogInformation("Parameter values: {p2}, {p1}", p1, p2);

此程式碼會使用依順序的參數值建立記錄訊息:This code creates a log message with the parameter values in sequence:

Parameter values: parm1, parm2

記錄架構以這種方式運作,因此記錄提供者可以實作語意記錄 (亦稱為結構化記錄)The logging framework works this way so that logging providers can implement semantic logging, also known as structured logging. 引數本身會被傳遞到記錄系統,而不只是格式化的訊息範本。The arguments themselves are passed to the logging system, not just the formatted message template. 此資訊可讓記錄提供者將參數值儲存為欄位。This information enables logging providers to store the parameter values as fields. 例如,假設記錄器方法呼叫看起來像這樣:For example, suppose logger method calls look like this:

_logger.LogInformation("Getting item {ID} at {RequestTime}", id, DateTime.Now);

若您正在將記錄傳送到 Azure 表格儲存體,每個 Azure 資料表實體都可以有 IDRequestTime 屬性,以簡化記錄資料的查詢。If you're sending the logs to Azure Table Storage, each Azure Table entity can have ID and RequestTime properties, which simplifies queries on log data. 查詢可以尋找特定 RequestTime 範圍內的所有記錄,而不需要從文字訊息剖析時間。A query can find all logs within a particular RequestTime range without parsing the time out of the text message.

記錄例外狀況Logging exceptions

記錄器方法具有多載,可讓您傳入例外狀況,如下列範例所示:The logger methods have overloads that let you pass in an exception, as in the following example:

catch (Exception ex)
{
    _logger.LogWarning(LoggingEvents.GetItemNotFound, ex, "GetById({ID}) NOT FOUND", id);
    return NotFound();
}
return new ObjectResult(item);
catch (Exception ex)
{
    _logger.LogWarning(LoggingEvents.GetItemNotFound, ex, "GetById({ID}) NOT FOUND", id);
    return NotFound();
}
return new ObjectResult(item);

不同提供者處理例外狀況資訊的方式會不同。Different providers handle the exception information in different ways. 以下是來自上述程式碼中的偵錯提供者輸出範例。Here's an example of Debug provider output from the code shown above.

TodoApiSample.Controllers.TodoController: Warning: GetById(55) NOT FOUND

System.Exception: Item not found exception.
   at TodoApiSample.Controllers.TodoController.GetById(String id) in C:\TodoApiSample\Controllers\TodoController.cs:line 226

記錄篩選Log filtering

您可以指定特定提供者和類別的最低記錄層級,也可以指定所有提供者或所有類別的最低記錄層級。You can specify a minimum log level for a specific provider and category or for all providers or all categories. 最低層級以下的任何記錄都不會傳遞給該提供者,因此不會顯示或儲存。Any logs below the minimum level aren't passed to that provider, so they don't get displayed or stored.

若要隱藏所有記錄,請指定 LogLevel.None 作為最低記錄層級。To suppress all logs, specify LogLevel.None as the minimum log level. LogLevel.None 的整數值為 6,高於 LogLevel.Critical (5)。The integer value of LogLevel.None is 6, which is higher than LogLevel.Critical (5).

在組態中建立篩選規則Create filter rules in configuration

專案範本程式碼會呼叫 CreateDefaultBuilder 以設定主控台與偵錯提供者的記錄。The project template code calls CreateDefaultBuilder to set up logging for the Console and Debug providers. CreateDefaultBuilder 方法會設定記錄以尋找 Logging 區段中的組態,如本文先前所述The CreateDefaultBuilder method sets up logging to look for configuration in a Logging section, as explained earlier in this article.

組態資料會依提供者和類別指定最低記錄層級,如下列範例所示:The configuration data specifies minimum log levels by provider and category, as in the following example:

{
  "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"
    }
  }
}
{
  "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 會建立六個篩選規則:一個適用於偵錯提供者、四個適用於主控台提供者,一個適用於所有提供者。This JSON creates six filter rules: one for the Debug provider, four for the Console provider, and one for all providers. 建立 ILogger 物件時,會為每個提供者選取一個規則。A single rule is chosen for each provider when an ILogger object is created.

程式碼中的篩選規則Filter rules in code

下列範例說明如何在程式碼中註冊篩選規則:The following example shows how to register filter rules in code:

.ConfigureLogging(logging =>
    logging.AddFilter("System", LogLevel.Debug)
           .AddFilter<DebugLoggerProvider>("Microsoft", LogLevel.Trace))
WebHost.CreateDefaultBuilder(args)
    .UseStartup<Startup>()
    .ConfigureLogging(logging =>
        logging.AddFilter("System", LogLevel.Debug)
               .AddFilter<DebugLoggerProvider>("Microsoft", LogLevel.Trace));

第二個 AddFilter 會使用其類型名稱來指定偵錯提供者。The second AddFilter specifies the Debug provider by using its type name. 第一個 AddFilter 由於未指定提供者類型,因此適用於所有提供者。The first AddFilter applies to all providers because it doesn't specify a provider type.

如何套用篩選規則How filtering rules are applied

組態資料和上述範例中所示的 AddFilter 程式碼會建立下表中所示的規則。The configuration data and the AddFilter code shown in the preceding examples create the rules shown in the following table. 前六項來自組態範例,最後兩項來自程式碼範例。The first six come from the configuration example and the last two come from the code example.

numberNumber 提供者Provider 開頭如下的類別...Categories that begin with ... 最低記錄層級Minimum log level
11 偵錯Debug 所有類別All categories 資訊Information
22 主控台Console Microsoft.AspNetCore.Mvc.Razor.InternalMicrosoft.AspNetCore.Mvc.Razor.Internal 警告Warning
33 主控台Console Microsoft.AspNetCore.Mvc.Razor.RazorMicrosoft.AspNetCore.Mvc.Razor.Razor 偵錯Debug
44 主控台Console Microsoft.AspNetCore.Mvc.RazorMicrosoft.AspNetCore.Mvc.Razor 錯誤Error
55 主控台Console 所有類別All categories 資訊Information
66 所有提供者All providers 所有類別All categories 偵錯Debug
77 所有提供者All providers 系統System 偵錯Debug
88 偵錯Debug MicrosoftMicrosoft 追蹤Trace

建立 ILogger 物件時,ILoggerFactory 物件會針對每個提供者選取一個規則來套用到該記錄器。When an ILogger object is created, the ILoggerFactory object selects a single rule per provider to apply to that logger. ILogger 執行個體寫入的所有訊息都會根據選取的規則進行篩選。All messages written by an ILogger instance are filtered based on the selected rules. 系統會從可用的規則中,盡可能選取對每個提供者和類別配對最明確的規則。The most specific rule possible for each provider and category pair is selected from the available rules.

當建立指定類別的 ILogger 時,系統會針對每個提供者使用下列演算法:The following algorithm is used for each provider when an ILogger is created for a given category:

  • 選取所有符合提供者或其別名的規則。Select all rules that match the provider or its alias. 如果找不到符合的項目,請選取所有規則搭配空白提供者。If no match is found, select all rules with an empty provider.
  • 從上一個步驟的結果中,選取具有最長相符類別前置字元的規則。From the result of the preceding step, select rules with longest matching category prefix. 如果找不到符合的項目,請選取未指定類別的所有規則。If no match is found, select all rules that don't specify a category.
  • 如果選取多個規則,請使用最後一個。If multiple rules are selected, take the last one.
  • 如果未選取任何規則,請使用 MinimumLevelIf no rules are selected, use MinimumLevel.

使用上述規則清單時,假設您建立 "Microsoft.AspNetCore.Mvc.Razor.RazorViewEngine" 類別的 ILogger 物件:With the preceding list of rules, suppose you create an ILogger object for category "Microsoft.AspNetCore.Mvc.Razor.RazorViewEngine":

  • 針對偵錯提供者,規則 1、6 和 8 均適用。For the Debug provider, rules 1, 6, and 8 apply. 規則 8 最明確,因此會選取此規則。Rule 8 is most specific, so that's the one selected.
  • 針對主控台提供者,規則 3、4、5 和 6 均適用。For the Console provider, rules 3, 4, 5, and 6 apply. 規則 3 最明確。Rule 3 is most specific.

產生的 ILogger 執行個體會傳送 Trace 層級以上的記錄到偵錯提供者。The resulting ILogger instance sends logs of Trace level and above to the Debug provider. Debug 層級以上的記錄會傳送到主控台提供者。Logs of Debug level and above are sent to the Console provider.

提供者別名Provider aliases

每個提供者都會定義「別名」 ,可在設定中用來取代完整類型名稱。Each provider defines an alias that can be used in configuration in place of the fully qualified type name. 針對內建提供者,請使用下列別名:For the built-in providers, use the following aliases:

  • 主控台Console
  • 偵錯Debug
  • EventSourceEventSource
  • EventLogEventLog
  • TraceSourceTraceSource
  • AzureAppServicesFileAzureAppServicesFile
  • AzureAppServicesBlobAzureAppServicesBlob
  • ApplicationInsightsApplicationInsights

預設最低層級Default minimum level

只有組態或程式碼中沒有適用於指定提供者和類別的規則時,最低層級設定才會生效。There's a minimum level setting that takes effect only if no rules from configuration or code apply for a given provider and category. 下列範例示範如何設定最低層級:The following example shows how to set the minimum level:

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureLogging(logging => logging.SetMinimumLevel(LogLevel.Warning))
WebHost.CreateDefaultBuilder(args)
    .UseStartup<Startup>()
    .ConfigureLogging(logging => logging.SetMinimumLevel(LogLevel.Warning));

如果您未明確設定最低層級,預設值為 Information,這表示會略過 TraceDebug 記錄。If you don't explicitly set the minimum level, the default value is Information, which means that Trace and Debug logs are ignored.

篩選函式Filter functions

針對組態或程式碼未指派規則的所有提供者和類別,會叫用篩選函式。A filter function is invoked for all providers and categories that don't have rules assigned to them by configuration or code. 函式中的程式碼可以存取提供者類型、類別與記錄層級。Code in the function has access to the provider type, category, and log level. 例如:For example:

.ConfigureLogging(logBuilder =>
{
    logBuilder.AddFilter((provider, category, logLevel) =>
    {
        if (provider == "Microsoft.Extensions.Logging.Console.ConsoleLoggerProvider" &&
            category == "TodoApiSample.Controllers.TodoController")
        {
            return false;
        }
        return true;
    });
})
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;
        });
    });

系統類別與層級System categories and levels

以下是由 ASP.NET Core 與 Entity Framework Core 所使用的一些類別,以及有關它們可傳回哪些記錄的附註:Here are some categories used by ASP.NET Core and Entity Framework Core, with notes about what logs to expect from them:

分類Category 注意Notes
Microsoft.AspNetCoreMicrosoft.AspNetCore 一般 ASP.NET Core 診斷。General ASP.NET Core diagnostics.
Microsoft.AspNetCore.DataProtectionMicrosoft.AspNetCore.DataProtection 已考慮、發現及使用哪些金鑰。Which keys were considered, found, and used.
Microsoft.AspNetCore.HostFilteringMicrosoft.AspNetCore.HostFiltering 允許主機。Hosts allowed.
Microsoft.AspNetCore.HostingMicrosoft.AspNetCore.Hosting HTTP 要求花了多少時間完成,以及其開始時間。How long HTTP requests took to complete and what time they started. 載入了哪些裝載啟動組件。Which hosting startup assemblies were loaded.
Microsoft.AspNetCore.MvcMicrosoft.AspNetCore.Mvc MVC 與 Razor 診斷。MVC and Razor diagnostics. 模型繫結、篩選執行、檢視編譯、動作選取。Model binding, filter execution, view compilation, action selection.
Microsoft.AspNetCore.RoutingMicrosoft.AspNetCore.Routing 路由比對資訊。Route matching information.
Microsoft.AspNetCore.ServerMicrosoft.AspNetCore.Server 連線開始、停止與保持運作回應。Connection start, stop, and keep alive responses. HTTPS 憑證資訊。HTTPS certificate information.
Microsoft.AspNetCore.StaticFilesMicrosoft.AspNetCore.StaticFiles 提供的檔案。Files served.
Microsoft.EntityFrameworkCoreMicrosoft.EntityFrameworkCore 一般 Entity Framework Core 診斷。General Entity Framework Core diagnostics. 資料庫活動與設定、變更偵測、移轉。Database activity and configuration, change detection, migrations.

記錄範圍Log scopes

「範圍」 可用來將邏輯作業組成群組。A scope can group a set of logical operations. 此分組功能可用來將相同的資料附加到已建立為集合之一部分的每個記錄。This grouping can be used to attach the same data to each log that's created as part of a set. 例如,在處理邀交易時建立的每個記錄都可以包括該交易識別碼。For example, every log created as part of processing a transaction can include the transaction ID.

範圍是 BeginScope 方法所傳回的 IDisposable 類型,並會持續到被處置為止。A scope is an IDisposable type that's returned by the BeginScope method and lasts until it's disposed. 透過將記錄器呼叫封裝在 using 區塊中以使用範圍:Use a scope by wrapping logger calls in a using block:

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);
}
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);
}

下列程式碼會啟用主控台提供者的範圍:The following code enables scopes for the console provider:

Program.csProgram.cs:

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureLogging((hostingContext, logging) =>
        {
            logging.ClearProviders();
            logging.AddConsole(options => options.IncludeScopes = true);
            logging.AddDebug();
        })
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });
.ConfigureLogging((hostingContext, logging) =>
{
    logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
    logging.AddConsole(options => options.IncludeScopes = true);
    logging.AddDebug();
})

注意

您必須設定 IncludeScopes 主控台記錄器選項才能啟用範圍記錄。Configuring the IncludeScopes console logger option is required to enable scope-based logging.

如需有關設定的詳細資訊,請參閱設定一節。For information on configuration, see the Configuration section.

每個記錄訊息包含範圍資訊:Each log message includes the scoped information:

info: TodoApiSample.Controllers.TodoController[1002]
      => RequestId:0HKV9C49II9CK RequestPath:/api/todo/0 => TodoApiSample.Controllers.TodoController.GetById (TodoApi) => Message attached to logs created in the using block
      Getting item 0
warn: TodoApiSample.Controllers.TodoController[4000]
      => RequestId:0HKV9C49II9CK RequestPath:/api/todo/0 => TodoApiSample.Controllers.TodoController.GetById (TodoApi) => Message attached to logs created in the using block
      GetById(0) NOT FOUND

內建記錄提供者Built-in logging providers

ASP.NET Core 隨附下列提供者:ASP.NET Core ships the following providers:

如需 ASP.NET Core 模組的 StdOut 和偵錯記錄相關資訊,請參閱 疑難排解 Azure App Service 和 IIS 上的 ASP.NET CoreASP.NET Core 模組For information on stdout and debug logging with the ASP.NET Core Module, see 疑難排解 Azure App Service 和 IIS 上的 ASP.NET Core and ASP.NET Core 模組.

Console 提供者Console provider

Microsoft.Extensions.Logging.Console 提供者套件會將記錄輸出傳送至主控台。The Microsoft.Extensions.Logging.Console provider package sends log output to the console.

logging.AddConsole();

若要查看主控台記錄輸出,請在專案資料夾中開啟命令提示字元,然後執行下列命令:To see console logging output, open a command prompt in the project folder and run the following command:

dotnet run

Debug 提供者Debug provider

Microsoft.Extensions.Logging.Debug 提供者套件使用 System.Diagnostics.Debug 類別 (Debug.WriteLine 方法呼叫) 來寫入記錄輸出。The Microsoft.Extensions.Logging.Debug provider package writes log output by using the System.Diagnostics.Debug class (Debug.WriteLine method calls).

在 Linux 上,此提供者會將記錄寫入至 /var/log/messageOn Linux, this provider writes logs to /var/log/message.

logging.AddDebug();

EventSource 提供者EventSource provider

針對以 ASP.NET Core 1.1.0 或更新版本為目標的應用程式,Microsoft.Extensions.Logging.EventSource 提供者套件可以實作事件追蹤。For apps that target ASP.NET Core 1.1.0 or later, the Microsoft.Extensions.Logging.EventSource provider package can implement event tracing. 在 Windows 上,它會使用 ETWOn Windows, it uses ETW. 提供者可以跨平台,但目前沒有適用於 Linux 或 macOS 的事件收集和顯示工具。The provider is cross-platform, but there are no event collection and display tools yet for Linux or macOS.

logging.AddEventSourceLogger();

收集及檢視記錄的一個好方法是使用 PerfView 公用程式A good way to collect and view logs is to use the PerfView utility. 此外還有一些其他工具可檢視 ETW 記錄,但 PerfView 提供處理 ASP.NET Core 所發出 ETW 事件的最佳體驗。There are other tools for viewing ETW logs, but PerfView provides the best experience for working with the ETW events emitted by ASP.NET Core.

若要設定 PerfView 以收集此提供者所記錄的事件,請將字串 *Microsoft-Extensions-Logging 新增至 [其他提供者] 清單To configure PerfView for collecting events logged by this provider, add the string *Microsoft-Extensions-Logging to the Additional Providers list. (請勿遺漏字串開頭的星號)。(Don't miss the asterisk at the start of the string.)

PerfView 的其他提供者

Windows EventLog 提供者Windows EventLog provider

Microsoft.Extensions.Logging.EventLog 提供者套件會將記錄輸出傳送至 Windows 事件記錄檔。The Microsoft.Extensions.Logging.EventLog provider package sends log output to the Windows Event Log.

logging.AddEventLog();

AddEventLog 多載可讓您傳入 EventLogSettingsAddEventLog overloads let you pass in EventLogSettings.

TraceSource 提供者TraceSource provider

Microsoft.Extensions.Logging.TraceSource 提供者套件使用 TraceSource 程式庫與提供者。The Microsoft.Extensions.Logging.TraceSource provider package uses the TraceSource libraries and providers.

logging.AddTraceSource(sourceSwitchName);

AddTraceSource 多載可讓您傳入來源參數和追蹤接聽項。AddTraceSource overloads let you pass in a source switch and a trace listener.

若要使用此提供者,應用程式必須在 .NET Framework (而非 .NET Core) 上執行。To use this provider, an app has to run on the .NET Framework (rather than .NET Core). 該提供者可讓您將訊息路由傳送到種不同的接聽程式,例如範例應用程式中所使用的 TextWriterTraceListenerThe provider can route messages to a variety of listeners, such as the TextWriterTraceListener used in the sample app.

Azure App Service 提供者Azure App Service provider

Microsoft.Extensions.Logging.AzureAppServices 提供者套件會將記錄寫入至 Azure App Service 應用程式檔案系統中的文字檔,並寫入至 Azure 儲存體帳戶中的 Blob 儲存體The Microsoft.Extensions.Logging.AzureAppServices provider package writes logs to text files in an Azure App Service app's file system and to blob storage in an Azure Storage account.

logging.AddAzureWebAppDiagnostics();

該提供者套件並未包含在共用架構中。The provider package isn't included in the shared framework. 若要使用提供者,請將提供者套件新增至專案。To use the provider, add the provider package to the project.

Microsoft.AspNetCore.App 中繼套件未包含提供者套件。The provider package isn't included in the Microsoft.AspNetCore.App metapackage. 當以 .NET Framework 為目標或是參考 Microsoft.AspNetCore.App 中繼套件時,請將提供者套件新增至專案。When targeting .NET Framework or referencing the Microsoft.AspNetCore.App metapackage, add the provider package to the project.

如果要進行提供者設定,請使用 AzureFileLoggerOptionsAzureBlobLoggerOptions,如以下範例中所示:To configure provider settings, use AzureFileLoggerOptions and AzureBlobLoggerOptions, as shown in the following example:

public static void Main(string[] args)
{
    var host = CreateHostBuilder(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 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>();
        });

如果要進行提供者設定,請使用 AzureFileLoggerOptionsAzureBlobLoggerOptions,如以下範例中所示:To configure provider settings, use AzureFileLoggerOptions and AzureBlobLoggerOptions, as shown in the following example:

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>();

AddAzureWebAppDiagnostics 多載可讓您傳入 AzureAppServicesDiagnosticsSettingsAn AddAzureWebAppDiagnostics overload lets you pass in AzureAppServicesDiagnosticsSettings. 設定物件可覆寫預設設定,例如記錄輸出範本、Blob 名稱與檔案大小限制。The settings object can override default settings, such as the logging output template, blob name, and file size limit. (輸出範本是訊息範本,它除了會套用到 ILogger 方法呼叫所提供的記錄之外,還會套用到所有記錄。)(Output template is a message template that's applied to all logs in addition to what's provided with an ILogger method call.)

當您部署到 App Service 應用程式時,應用程式會遵循 Azure 入口網站 [App Service] 頁面中 App Service 記錄區段的設定。When you deploy to an App Service app, the application honors the settings in the App Service logs section of the App Service page of the Azure portal. 當下列設定更新時,變更會立即生效,而不需要重新啟動或重新部署應用程式。When the following settings are updated, the changes take effect immediately without requiring a restart or redeployment of the app.

  • 應用程式記錄 (檔案系統)Application Logging (Filesystem)
  • 應用程式記錄 (Blob)Application Logging (Blob)

記錄檔的預設位置為 D:\home\LogFiles\Application 資料夾,而預設檔案名稱為 diagnostics-yyyymmdd.txtThe default location for log files is in the D:\home\LogFiles\Application folder, and the default file name is diagnostics-yyyymmdd.txt. 預設檔案大小限制為 10 MB,而預設保留的檔案數目上限為 2。The default file size limit is 10 MB, and the default maximum number of files retained is 2. 預設 Blob 名稱為 {app-name}{timestamp}/yyyy/mm/dd/hh/{guid}-applicationLog.txtThe default blob name is {app-name}{timestamp}/yyyy/mm/dd/hh/{guid}-applicationLog.txt.

此提供者僅適用於專案在 Azure 環境中執行的情況。The provider only works when the project runs in the Azure environment. 若在本機執行專案,不會有任何作用,即它不會寫入本機檔案或 blob 的本機開發儲存體。It has no effect when the project is run locally—it doesn't write to local files or local development storage for blobs.

Azure 記錄資料流Azure log streaming

Azure 記錄串流可讓您即時檢視來自下列位置的記錄活動:Azure log streaming lets you view log activity in real time from:

  • 應用程式伺服器The app server
  • 網頁伺服器The web server
  • 失敗的要求追蹤Failed request tracing

若要設定 Azure 記錄資料流:To configure Azure log streaming:

  • 從您應用程式的入口網站頁面瀏覽到 [App Service 記錄] 。Navigate to the App Service logs page from your app's portal page.
  • 將 [應用程式記錄 (檔案系統)] 設定為 [開啟] 。Set Application Logging (Filesystem) to On.
  • 選擇記錄 [層級] 。Choose the log Level.

瀏覽到 [記錄資料流] 頁面以檢視應用程式訊息。Navigate to the Log Stream page to view app messages. 這些是應用程式透過 ILogger 介面產生的訊息。They're logged by the app through the ILogger interface.

Azure Application Insights 追蹤記錄Azure Application Insights trace logging

Microsoft.Extensions.Logging.ApplicationInsights (英文) 提供者套件會將記錄寫入至 Azure Application Insights。The Microsoft.Extensions.Logging.ApplicationInsights provider package writes logs to Azure Application Insights. Application Insights 是可監視 Web 應用程式的服務,並提供可用來查詢及分析遙測資料的工具。Application Insights is a service that monitors a web app and provides tools for querying and analyzing the telemetry data. 如果您使用此提供者,就可以使用 Application Insights 工具來查詢及分析記錄。If you use this provider, you can query and analyze your logs by using the Application Insights tools.

記錄提供者會以 Microsoft.ApplicationInsights.AspNetCore (英文) 的相依性形式隨附,這是針對 ASP.NET Core 提供所有可用遙測的套件。The logging provider is included as a dependency of Microsoft.ApplicationInsights.AspNetCore, which is the package that provides all available telemetry for ASP.NET Core. 如果您使用此套件,就不需安裝提供者套件。If you use this package, you don't have to install the provider package.

不要使用 Microsoft.ApplicationInsights.Web (英文) 套件—該套件適用於 ASP.NET 4.x。Don't use the Microsoft.ApplicationInsights.Web package—that's for ASP.NET 4.x.

如需詳細資訊,請參閱下列資源:For more information, see the following resources:

協力廠商記錄提供者Third-party logging providers

可搭配 ASP.NET Core 使用的協力廠商記錄架構:Third-party logging frameworks that work with ASP.NET Core:

某些協力廠商架構可以執行語意記錄 (也稱為結構化記錄) (英文)。Some third-party frameworks can perform semantic logging, also known as structured logging.

使用協力廠商架構類似於使用內建的提供者之一:Using a third-party framework is similar to using one of the built-in providers:

  1. 將 NuGet 套件新增至專案。Add a NuGet package to your project.
  2. 呼叫 ILoggerFactoryCall an ILoggerFactory.

如需詳細資訊,請參閱每個提供者的文件。For more information, see each provider's documentation. Microsoft 不支援第三方記錄提供者。Third-party logging providers aren't supported by Microsoft.

其他資源Additional resources