diff --git a/aspnetcore/blazor/fundamentals/logging.md b/aspnetcore/blazor/fundamentals/logging.md index 5fba6522a7d2..1d312d4377f2 100644 --- a/aspnetcore/blazor/fundamentals/logging.md +++ b/aspnetcore/blazor/fundamentals/logging.md @@ -1,11 +1,11 @@ --- title: ASP.NET Core Blazor logging author: guardrex -description: Learn about Blazor app logging, including configuration and how to write log messages from Razor components. +description: Learn about Blazor app logging, particularly in client-side logging scenarios. monikerRange: '>= aspnetcore-3.1' ms.author: wpickett ms.custom: mvc -ms.date: 11/12/2024 +ms.date: 09/29/2025 uid: blazor/fundamentals/logging --- # ASP.NET Core Blazor logging @@ -17,7 +17,9 @@ uid: blazor/fundamentals/logging at the ends of lines to generate a bare return in block quote output. --> -This article explains Blazor app logging, including configuration and how to write log messages from Razor components. +This article provides information on logging in Blazor apps, particularly in client-side logging scenarios. + +For general ASP.NET Core logging guidance, including how to log from Razor components, see . ## Configuration @@ -38,101 +40,6 @@ When the app is configured in the project file to use implicit namespaces (`. -## Razor component logging - -:::moniker range="< aspnetcore-6.0" - -The `using` directive for is required to support [IntelliSense](/visualstudio/ide/using-intellisense) completions for APIs, such as and . - -:::moniker-end - -The following example: - -* [Injects](xref:blazor/fundamentals/dependency-injection) an (`ILogger`) object to create a logger. The log's *category* is the fully qualified name of the component's type, `Counter`. -* Calls to log at the level. - -`Counter1.razor`: - -:::moniker range=">= aspnetcore-9.0" - -:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/Counter1.razor"::: - -:::moniker-end - -:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" - -:::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/Counter1.razor"::: - -:::moniker-end - -:::moniker range=">= aspnetcore-7.0 < aspnetcore-8.0" - -:::code language="razor" source="~/../blazor-samples/7.0/BlazorSample_WebAssembly/Pages/logging/Counter1.razor"::: - -:::moniker-end - -:::moniker range=">= aspnetcore-6.0 < aspnetcore-7.0" - -:::code language="razor" source="~/../blazor-samples/6.0/BlazorSample_WebAssembly/Pages/logging/Counter1.razor"::: - -:::moniker-end - -:::moniker range=">= aspnetcore-5.0 < aspnetcore-6.0" - -:::code language="razor" source="~/../blazor-samples/5.0/BlazorSample_WebAssembly/Pages/logging/Counter1.razor"::: - -:::moniker-end - -:::moniker range="< aspnetcore-5.0" - -:::code language="razor" source="~/../blazor-samples/3.1/BlazorSample_WebAssembly/Pages/logging/Counter1.razor"::: - -:::moniker-end - -The following example demonstrates logging with an in components. - -`Counter2.razor`: - -:::moniker range=">= aspnetcore-9.0" - -:::code language="razor" source="~/../blazor-samples/9.0/BlazorSample_BlazorWebApp/Components/Pages/Counter2.razor"::: - -:::moniker-end - -:::moniker range=">= aspnetcore-8.0 < aspnetcore-9.0" - -:::code language="razor" source="~/../blazor-samples/8.0/BlazorSample_BlazorWebApp/Components/Pages/Counter2.razor"::: - -:::moniker-end - -:::moniker range=">= aspnetcore-7.0 < aspnetcore-8.0" - -:::code language="razor" source="~/../blazor-samples/7.0/BlazorSample_WebAssembly/Pages/logging/Counter2.razor"::: - -:::moniker-end - -:::moniker range=">= aspnetcore-6.0 < aspnetcore-7.0" - -:::code language="razor" source="~/../blazor-samples/6.0/BlazorSample_WebAssembly/Pages/logging/Counter2.razor"::: - -:::moniker-end - -:::moniker range=">= aspnetcore-5.0 < aspnetcore-6.0" - -:::code language="razor" source="~/../blazor-samples/5.0/BlazorSample_WebAssembly/Pages/logging/Counter2.razor"::: - -:::moniker-end - -:::moniker range="< aspnetcore-5.0" - -:::code language="razor" source="~/../blazor-samples/3.1/BlazorSample_WebAssembly/Pages/logging/Counter2.razor"::: - -:::moniker-end - -## Server-side logging - -For general ASP.NET Core logging guidance, see . - ## Client-side logging Not every feature of [ASP.NET Core logging](xref:fundamentals/logging/index) is supported client-side. For example, client-side components don't have access to the client's file system or network, so writing logs to the client's physical or network storage isn't possible. When using a third-party logging service designed to work with single-page apps (SPAs), follow the service's security guidance. Keep in mind that every piece of data, including keys or secrets stored client-side are ***insecure*** and can be easily discovered by malicious users. diff --git a/aspnetcore/fundamentals/logging/index.md b/aspnetcore/fundamentals/logging/index.md index 5cbe99e2a7bc..4956e375fca8 100644 --- a/aspnetcore/fundamentals/logging/index.md +++ b/aspnetcore/fundamentals/logging/index.md @@ -1,93 +1,370 @@ --- title: Logging in .NET and ASP.NET Core +ai-usage: ai-assisted author: tdykstra -description: Learn how to use the logging framework provided by the Microsoft.Extensions.Logging NuGet package. +description: Learn how to use the ASP.NET Core logging framework provided by the Microsoft.Extensions.Logging NuGet package. monikerRange: '>= aspnetcore-3.1' ms.author: tdykstra ms.custom: mvc -ms.date: 09/18/2024 +ms.date: 10/01/2025 uid: fundamentals/logging/index --- - # Logging in .NET and ASP.NET Core [!INCLUDE[](~/includes/not-latest-version.md)] +This article describes logging in ASP.NET Core apps. For general guidance on logging in .NET, see [Logging in C# and .NET](/dotnet/core/extensions/logging). For Blazor logging guidance, which adds to or supersedes this guidance, see . + +## Logging providers + +ASP.NET Core supports high performance, structured logging via the API to help you monitor app behavior and diagnose problems. Logs are written to different destinations by configuring *logging providers*. A set of logging providers are built into the framework, and there are many third-party providers available. Multiple providers can be enabled in an app. + +Most logging providers write log messages to a data storage system. For example, the Azure Application Insights logging provider stores logs in [Azure Application Insights](/azure/azure-monitor/app/app-insights-overview). One provider, the `Console` provider, only displays log messages. The `Console` provider is useful when running an app locally for monitoring and debugging in real time. + :::moniker range=">= aspnetcore-6.0" -By [Kirk Larkin](https://twitter.com/serpent5), [Juergen Gutsch](https://github.com/JuergenGutsch), and [Rick Anderson](https://twitter.com/RickAndMSFT) +Apps created from an ASP.NET Core web app project template call in the app's `Program` file, which adds the following default logging providers: -This article describes logging in .NET as it applies to ASP.NET Core apps. For detailed information on logging in .NET, see [Logging in .NET](/dotnet/core/extensions/logging). +* [`Console`](#console) +* [`Debug`](#debug) +* [`EventSource`](#eventsource) +* [Windows `EventLog`](#windows-eventlog) + +```csharp +var builder = WebApplication.CreateBuilder(args); +``` -For Blazor logging guidance, which adds to or supersedes the guidance in this node, see . +To override the default logging providers, call on and use logging provider extension methods to add logging providers. The following example only sets up the [`Console`](#console) logging provider: - +```csharp +var builder = WebApplication.CreateBuilder(args); -## Logging providers +builder.Logging.ClearProviders(); +builder.Logging.AddConsole(); +``` + +Alternatively, the preceding code can be written as follows with of : + +```csharp +var builder = WebApplication.CreateBuilder(args); + +builder.Host.ConfigureLogging(logging => +{ + logging.ClearProviders(); + logging.AddConsole(); +}); +``` + +:::moniker-end + +:::moniker range="< aspnetcore-6.0" + +Apps created from an ASP.NET Core web app project template call , which adds the following default logging providers: + +* [`Console`](#console) +* [`Debug`](#debug) +* [`EventSource`](#eventsource) +* [Windows `EventLog`](#windows-eventlog) + +```csharp +Host.CreateDefaultBuilder(args) +``` + +To override the default logging providers, call to remove all the instances from the and use logging provider extension methods to add logging providers. The following example only sets up the [`Console`](#console) logging provider: + +```csharp +public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureLogging(logging => + { + logging.ClearProviders(); + logging.AddConsole(); + }) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); +``` + +:::moniker-end + +Additional providers are covered in the [Built-in logging providers](#built-in-logging-providers) and [Third-party logging providers](#third-party-logging-providers) sections. + +## Logging output + +Logs created by the [default logging providers](#logging-providers) are displayed: + +* In Visual Studio + * In the **Debug** output window when debugging. + * In the **ASP.NET Core Web Server** window. +* In the command shell when the app is run with the [`dotnet run`](/dotnet/core/tools/dotnet-run) command. + +.NET in general and ASP.NET Core use the same logging API and providers. More information can be found in [Logging in C# and .NET](/dotnet/core/extensions/logging), which covers general logging scenarios for C# and .NET. This article focuses on ASP.NET Core app logging. + +## Create log messages + +To create log messages, use an object from [dependency injection (DI)](xref:fundamentals/dependency-injection). + +The following examples: + +* Create an that specifies a log *category* based on the fully qualified name of the type. The log category is a string that is associated with each log, which is useful for identifying, sorting, and filtering log messages. More information on [log categories](#log-category) is provided later in this article. +* Calls to log at the level. The log *level* indicates the severity of the logged event. More information on [log levels](#log-level) is provided later in this article. + +In the following counter page (`Counter` Razor component) in a Blazor app, an `ILogger` is injected with the [`@inject` directive](xref:mvc/views/razor#inject). The logger instance (`Logger`) is used to log information when the `IncrementCount` method is called. + +`Pages/Counter.razor`: + +```razor +@page "/counter" +@inject ILogger Logger + +

Counter

+ +

Current count: @currentCount

+ + + +@code { + private int currentCount = 0; + + private void IncrementCount() + { + Logger.LogInformation("Someone incremented the counter!"); + + currentCount++; + } +} +``` + +:::moniker range="< aspnetcore-6.0" + +> [!NOTE] +> In .NET 5 or earlier, an [`@using` directive](xref:mvc/views/razor#using) for is required to support [IntelliSense](/visualstudio/ide/using-intellisense) logging API completions in Razor components. + +:::moniker-end + +Log message: + +> :::no-loc text="BlazorSample.Components.Pages.Counter: Information: Someone incremented the counter!"::: + +The log category is `BlazorSample.Components.Pages.Counter`, and the log level (severity) is `Information`. The message is `Someone incremented the counter!`. + +In the following Razor Pages privacy page class file, an `ILogger` is injected into the class's constructor to log when the page is visited. Note in this example that the message is a *template* that takes the current UTC date and time (`DateTime.UtcNow`) and writes it into the log message. Log message templates are covered in the [Log message template](#log-message-template) section later in this article. + +`Pages/Privacy.cshtml.cs`: + +```csharp +public class PrivacyModel(ILogger logger) : PageModel +{ + public void OnGet() => logger.LogInformation("Privacy page visited at {DT}", + DateTime.UtcNow); +} +``` + +## Log message template + +The log message template can contain placeholders for provided arguments. Use names for the placeholders, not numbers. + +In the following examples, `{Id}` is an identifier placeholder for an item ID, and `id` is the identifier parameter. + +```csharp +Logger.LogInformation(LogEvent.GetItem, "Getting item {Id}", id); +``` + +```csharp +Logger.LogWarning(LogEvent.GetItemNotFound, "Get({Id}) NOT FOUND", id); +``` + +The *order of the parameters*, not their placeholder names, determines which parameters are used to provide placeholder values in log messages. In the following code, the parameter names are out of sequence in the placeholders of the message template: + +```csharp +var apples = 1; +var pears = 2; +var bananas = 3; + +Logger.LogInformation("{Pears}, {Bananas}, {Apples}", apples, pears, bananas); +``` + +However, the parameters are assigned to the placeholders in the order: `apples`, `pears`, `bananas`. The log message reflects the *order of the parameters*: + +```text +1, 2, 3 +``` + +This approach allows logging providers to implement [semantic or structured logging](https://github.com/NLog/NLog/wiki/How-to-use-structured-logging). The arguments themselves are passed to the logging system, not just the formatted message template. This enables logging providers to store the parameter values as fields. For example, consider the following logger method: + +```csharp +Logger.LogInformation("Getting item {Id} at {RequestTime}", id, DateTime.Now); +``` + +When logging to Azure Table Storage: + +* Each Azure Table entity can have `ID` and `RequestTime` properties. +* Tables with properties simplify queries on logged data. For example, a query can find all logs within a particular `RequestTime` range without having to parse the time out of the text message. + +## Log at app startup + +:::moniker range=">= aspnetcore-6.0" + +The following example calls in the `Program` file to log informational messages: + +```csharp +var builder = WebApplication.CreateBuilder(args); + +var app = builder.Build(); + +app.Logger.LogInformation("Adding Routes"); + +app.MapGet("/", () => "Hello World!"); + +app.Logger.LogInformation("Starting the app"); + +app.Run(); +``` -Logging providers store logs, except for the `Console` provider which displays logs. For example, the Azure Application Insights provider stores logs in [Azure Application Insights](/azure/azure-monitor/app/app-insights-overview). Multiple providers can be enabled. +The following example calls and logs at the `/Test` endpoint: -The default ASP.NET Core web app templates call , which adds the following logging providers: +```csharp +var builder = WebApplication.CreateBuilder(args); -* [Console](#console) -* [Debug](#debug) -* [EventSource](#event-source) -* [EventLog](#welog): Windows only +builder.Logging.AddConsole(); -[!code-csharp[](~/fundamentals/logging/index/samples/6.x/WebApp/Program.cs?name=snippet1&highlight=1)] +var app = builder.Build(); -The preceding code shows the `Program.cs` file created with the ASP.NET Core web app templates. The next several sections provide samples based on the ASP.NET Core web app templates. +app.MapGet("/", () => "Hello World!"); -The following code overrides the default set of logging providers added by `WebApplication.CreateBuilder`: +app.MapGet("/Test", async (ILogger logger, HttpResponse response) => +{ + logger.LogInformation("'Test' logging in the Program file"); + await response.WriteAsync("Testing"); +}); -[!code-csharp[](~/fundamentals/logging/index/samples/6.x/WebApp/Program.cs?name=snippet2&highlight=2-3)] +app.Run(); +``` -Alternatively, the preceding logging code can be written as follows: +The following example calls , disables color output with a [console formatter option](xref:Microsoft.Extensions.Logging.Console.SimpleConsoleFormatterOptions), and logs at the `/Test` endpoint: -[!code-csharp[](~/fundamentals/logging/index/samples/6.x/WebApp/Program.cs?name=snippet3)] +```csharp +using Microsoft.Extensions.Logging.Console; -For additional providers, see: +var builder = WebApplication.CreateBuilder(args); -* [Built-in logging providers](#bilp) -* [Third-party logging providers](#third-party-logging-providers). +builder.Logging.AddSimpleConsole( + option => option.ColorBehavior = LoggerColorBehavior.Disabled); -## Create logs +var app = builder.Build(); -To create logs, use an object from [dependency injection (DI)](xref:fundamentals/dependency-injection). +app.MapGet("/", () => "Hello World!"); -The following example: +app.MapGet("/Test", async (ILogger logger, HttpResponse response) => +{ + logger.LogInformation("'Test' logging in the Program file"); + await response.WriteAsync("Testing"); +}); -* Creates a logger, `ILogger`, which uses a log *category* of the fully qualified name of the type `AboutModel`. The log category is a string that is associated with each log. -* Calls to log at the level. The Log *level* indicates the severity of the logged event. +app.Run(); +``` + +:::moniker-end -[!code-csharp[](~/fundamentals/logging/index/samples/6.x/TodoApiDTO/Pages/About.cshtml.cs?name=snippet_CallLogMethods&highlight=5,12-13)] +:::moniker range="< aspnetcore-6.0" -[Levels](#log-level) and [categories](#log-category) are explained in more detail later in this document. +The following code logs in `Program.Main` by obtaining an instance from DI after building the host: + +```csharp +public static void Main(string[] args) +{ + var host = CreateHostBuilder(args).Build(); + + var logger = host.Services.GetRequiredService>(); + logger.LogInformation("Host created."); + + host.Run(); +} +``` -For information on Blazor, see . +The following example shows how to inject an into `Startup.Configure`: + +```csharp +public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILogger logger) +{ + logger.LogInformation("'Startup'.Configure' logging"); + + ... +} +``` + +Logger injection into the `Startup` constructor or into the `Startup.ConfigureServices` method isn't supported because logging depends on dependency injection (DI) and on configuration, which in turns depends on DI. The DI container isn't set up until `ConfigureServices` finishes executing. + +For information on configuring a service that depends on or why constructor injection of a logger into `Startup` worked in earlier versions, see the [Configure a service that depends on `ILogger`](#configure-a-service-that-depends-on-ilogger) section. + +:::moniker-end ## Configure logging +When an object is created, a *category* is specified. That category is included with each log message created by that instance of the logger. + +The log level determines the level of detail for log messages at a default level for the app as a whole and for specific app assemblies. The log level can be set by any of the [configuration providers](xref:fundamentals/configuration/index). + +### App settings + Logging configuration is commonly provided by the `Logging` section of `appsettings.{ENVIRONMENT}.json` files, where the `{ENVIRONMENT}` placeholder is the [environment](xref:fundamentals/environments). The following `appsettings.Development.json` file is generated by the ASP.NET Core web app templates: -[!code-json[](~/fundamentals/logging/index/samples/6.x/TodoApiDTO/appsettings.Development.json)] +```json +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} +``` In the preceding JSON: * The `"Default"` and `"Microsoft.AspNetCore"` categories are specified. * The `"Microsoft.AspNetCore"` category applies to all categories that start with `"Microsoft.AspNetCore"`. For example, this setting applies to the `"Microsoft.AspNetCore.Routing.EndpointMiddleware"` category. -* The `"Microsoft.AspNetCore"` category logs at log level `Warning` and higher. -* A specific log provider is not specified, so `LogLevel` applies to all the enabled logging providers except for the [Windows EventLog](#welog). +* The `"Microsoft.AspNetCore"` category logs at log level `Warning` and higher (more severe). +* A specific log provider isn't specified, so `LogLevel` applies to all the enabled logging providers except for the [Windows `EventLog`](#windows-eventlog). -The `Logging` property can have and log provider properties. The `LogLevel` specifies the minimum [level](#log-level) to log for selected categories. In the preceding JSON, `Information` and `Warning` log levels are specified. `LogLevel` indicates the severity of the log and ranges from 0 to 6: +The `Logging` property can have and log provider properties. The `LogLevel` specifies the minimum [level](#log-level) to log for selected categories. In the preceding JSON, `Information` and `Warning` log levels are specified. `LogLevel`s indicate the severity of the log, which are shown in the following table with their corresponding `enum` values. -`Trace` = 0, `Debug` = 1, `Information` = 2, `Warning` = 3, `Error` = 4, `Critical` = 5, and `None` = 6. +Log Level | Value +--- | :---: +`Trace` | 0 +`Debug` | 1 +`Information` | 2 +`Warning` | 3 +`Error` | 4 +`Critical` | 5 +`None` | 6 -When a `LogLevel` is specified, logging is enabled for messages at the specified level and higher. In the preceding JSON, the `Default` category is logged for `Information` and higher. For example, `Information`, `Warning`, `Error`, and `Critical` messages are logged. If no `LogLevel` is specified, logging defaults to the `Information` level. For more information, see [Log levels](#llvl). +When a `LogLevel` is specified, logging is enabled for messages at the specified level and higher (more severe). In the preceding JSON, the `Default` category is logged for `Information` and higher. For example, `Information`, `Warning`, `Error`, and `Critical` messages are logged. If no `LogLevel` is specified, logging defaults to the `Information` level. For more information, see [Log levels](#log-level). A provider property can specify a `LogLevel` property. `LogLevel` under a provider specifies levels to log for that provider, and overrides the non-provider log settings. Consider the following `appsettings.json` file: -[!code-json[](~/fundamentals/logging/index/samples/3.x/TodoApiDTO/appsettings.Prod2.json)] +```json +{ + "Logging": { + "LogLevel": { // All providers, LogLevel applies to all the enabled providers. + "Default": "Error", // Default logging, Error and higher. + "Microsoft": "Warning" // All Microsoft* categories, Warning and higher. + }, + "Debug": { // Debug provider. + "LogLevel": { + "Default": "Information", // Overrides preceding LogLevel:Default setting. + "Microsoft.Hosting": "Trace" // Debug:Microsoft.Hosting category. + } + }, + "EventSource": { // EventSource provider + "LogLevel": { + "Default": "Warning" // All categories of EventSource provider. + } + } + } +} +``` Settings in `Logging.{PROVIDER NAME}.LogLevel` override settings in `Logging.LogLevel`, where the `{PROVIDER NAME}` placeholder is the provider name. In the preceding JSON, the `Debug` provider's default log level is set to `Information`: @@ -97,8 +374,8 @@ The preceding setting specifies the `Information` log level for every `Logging:D The minimum log level can be specified for any of: -* Specific providers: For example, `Logging:EventSource:LogLevel:Default:Information` -* Specific categories: For example, `Logging:LogLevel:Microsoft:Warning` +* Specific providers example: `Logging:EventSource:LogLevel:Default:Information` +* Specific categories example: `Logging:LogLevel:Microsoft:Warning` * All providers and all categories: `Logging:LogLevel:Default:Warning` Any logs below the minimum level are ***not***: @@ -108,11 +385,62 @@ Any logs below the minimum level are ***not***: To suppress all logs, specify . `LogLevel.None` has a value of 6, which is higher than `LogLevel.Critical` (5). -If a provider supports [log scopes](#logscopes), `IncludeScopes` indicates whether they're enabled. For more information, see [log scopes](#logscopes). +If a provider supports [log scopes](#log-scopes), `IncludeScopes` indicates whether they're enabled. For more information, see [log scopes](#log-scopes). The following `appsettings.json` file contains all the providers enabled by default: -[!code-json[](~/fundamentals/logging/index/samples/3.x/TodoApiDTO/appsettings.Production.json)] +```json +{ + "Logging": { + "LogLevel": { // No provider, LogLevel applies to all the enabled providers. + "Default": "Error", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Warning" + }, + "Debug": { // Debug provider. + "LogLevel": { + "Default": "Information" // Overrides preceding LogLevel:Default setting. + } + }, + "Console": { + "IncludeScopes": true, + "LogLevel": { + "Microsoft.AspNetCore.Mvc.Razor.Internal": "Warning", + "Microsoft.AspNetCore.Mvc.Razor.Razor": "Debug", + "Microsoft.AspNetCore.Mvc.Razor": "Error", + "Default": "Information" + } + }, + "EventSource": { + "LogLevel": { + "Microsoft": "Information" + } + }, + "EventLog": { + "LogLevel": { + "Microsoft": "Information" + } + }, + "AzureAppServicesFile": { + "IncludeScopes": true, + "LogLevel": { + "Default": "Warning" + } + }, + "AzureAppServicesBlob": { + "IncludeScopes": true, + "LogLevel": { + "Microsoft": "Information" + } + }, + "ApplicationInsights": { + "LogLevel": { + "Default": "Information" + } + } + } +} +``` In the preceding sample: @@ -127,318 +455,353 @@ In the preceding sample: * `AzureAppServicesBlob` * `ApplicationInsights` -## Log in `Program.cs` - -The following example calls [Builder.WebApplication.Logger](xref:Microsoft.AspNetCore.Builder.WebApplication.Logger) in `Program.cs` and logs informational messages: - -[!code-csharp[](~/fundamentals/logging/index/samples/6.x/WebLog/Program.cs?name=snippet3)] - -The following example calls in `Program.cs` and logs the `/Test` endpoint: - -[!code-csharp[](~/fundamentals/logging/index/samples/6.x/WebLog/Program.cs?name=snippet1)] +### Command shell -The following example calls in `Program.cs`, disables color output, and logs the `/Test` endpoint: - -[!code-csharp[](~/fundamentals/logging/index/samples/6.x/WebLog/Program.cs?name=snippet2)] - -## Set log level by command line, environment variables, and other configuration - -Log level can be set by any of the [configuration providers](xref:fundamentals/configuration/index). +Environment variables for logging configuration can be set via a command shell. [!INCLUDE[](~/includes/environmentVarableColon.md)] -The following commands: - -* Set the environment key `Logging:LogLevel:Microsoft` to a value of `Information` on Windows. -* Test the settings when using an app created with the ASP.NET Core web application templates. The `dotnet run` command must be run in the project directory after using `set`. +Set an environment variable with the [`set`](/windows-server/administration/windows-commands/set) command on Windows for the current command shell. In the following example, the environment key `Logging:LogLevel:Microsoft` is set to a value of `Information`. You can test the setting with any app created from an ASP.NET Core web app project template. ```dotnetcli set Logging__LogLevel__Microsoft=Information -dotnet run ``` -The preceding environment setting: - -* Is only set in processes launched from the command window they were set in. -* Isn't read by browsers launched with Visual Studio. +Execute the [`dotnet run`](/dotnet/core/tools/dotnet-run) command in the project directory after executing the preceding `set` command: -The following [setx](/windows-server/administration/windows-commands/setx) command also sets the environment key and value on Windows. Unlike `set`, `setx` settings are persisted. The `/M` switch sets the variable in the system environment. If `/M` isn't used, a user environment variable is set. - -```console -setx Logging__LogLevel__Microsoft Information /M +```dotnetcli +dotnet run ``` -Consider the following `appsettings.json` file: +The preceding environment variable: -```json -"Logging": { - "Console": { - "LogLevel": { - "Microsoft.Hosting.Lifetime": "Trace" - } - } -} -``` +* Is only set for apps launched from the current command shell. +* Isn't read by browsers launched by Visual Studio or Visual Studio Code. -The following command sets the preceding configuration in the environment: +Use the [`setx`](/windows-server/administration/windows-commands/setx) to persist the environment variable across command shell instances. The `/M` switch sets the variable in the system environment. If `/M` isn't used, a user environment variable is set. ```console -setx Logging__Console__LogLevel__Microsoft.Hosting.Lifetime Trace /M +setx Logging__LogLevel__Microsoft Information /M ``` + + > [!NOTE] > When configuring environment variables with names that contain `.` (periods) in macOS and Linux, consider the "Exporting a variable with a dot (.) in it" question on **Stack Exchange** and its corresponding [accepted answer](https://unix.stackexchange.com/a/93533). -On [Azure App Service](https://azure.microsoft.com/services/app-service/), select **New application setting** on the **Settings > Configuration** page. Azure App Service application settings are: +### Configure Azure App Service -* Encrypted at rest and transmitted over an encrypted channel. -* Exposed as environment variables. +On [Azure App Service](https://azure.microsoft.com/services/app-service/), follow the guidance in [Configure an App Service app](/azure/app-service/configure-common?tabs=portal#configure-app-settings) to set logging environment variables. For more information, see [Azure Apps: Override app configuration using the Azure portal](xref:host-and-deploy/azure-apps/index#override-app-configuration-using-the-azure-portal). -For more information on setting ASP.NET Core configuration values using environment variables, see [environment variables](xref:fundamentals/configuration/index#environment-variables). For information on using other configuration sources, including the command line, Azure Key Vault, Azure App Configuration, other file formats, and more, see . - -## How filtering rules are applied +## Log category -When an object is created, the object selects a single rule per provider to apply to that logger. All messages written by an `ILogger` instance are filtered based on the selected rules. The most specific rule for each provider and category pair is selected from the available rules. +When an object is created, a *category* is specified. The category is included with each log message created by that instance of the logger. The category string is arbitrary, but the convention is to use the fully qualified class name. The ASP.NET Core web apps use [`ILogger`](xref:Microsoft.Extensions.Logging.ILogger) to create a logger instance that uses the fully qualified type name of `T` as the category. -The following algorithm is used for each provider when an `ILogger` is created for a given category: +Log messages with a category name that begins with "Microsoft" are from .NET. Typically, log messages that begin with the app's assembly name are from the app. Packages outside of .NET usually have a category based on an assembly name from the package. For a list of common log categories, see the [Common log categories](#common-log-categories) section. -* 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. -* If no rules are selected, use `MinimumLevel`. +In a Razor component of a Blazor app, where the type `T` is `Counter` for a counter page rendered by a `Counter` component (`Pages/Counter.razor`): - - -## Logging output from dotnet run and Visual Studio +```razor +@inject ILogger Logger +``` -Logs created with the [default logging providers](#lp) are displayed: +In a Razor Pages page class model, where the type `T` is `PrivacyModel` for a privacy page (`Pages/Privacy.cshtml.cs`): -* In Visual Studio - * In the Debug output window when debugging. - * In the ASP.NET Core Web Server window. -* In the console window when the app is run with `dotnet run`. +```csharp +public class PrivacyModel(ILogger logger) : PageModel +``` -Logs that begin with "Microsoft" categories are from .NET. .NET and application code use the same [logging API and providers](/dotnet/core/extensions/logging). +If further categorization is desired, the convention is to use a hierarchical name by appending a subcategory to the fully qualified class name using . This approach is useful for scoping log messages to component or class methods. - +The following `Counter` component logs from the `IncrementByOne` method with the `BlazorSample.Components.Pages.Counter.IncrementByOne` category and from the `IncrementByTen` method with the `BlazorSample.Components.Pages.Privacy.IncrementByTen` category. -## Log category +`Pages/Counter.razor`: -When an `ILogger` object is created, a *category* is specified. That category is included with each log message created by that instance of `ILogger`. The category string is arbitrary, but the convention is to use the fully qualified class name. For example, in a controller the name might be `"TodoApi.Controllers.TodoController"`. The ASP.NET Core web apps use `ILogger` to automatically get an `ILogger` instance that uses the fully qualified type name of `T` as the category: +```razor +@page "/counter" +@inject ILogger Logger -[!code-csharp[](~/fundamentals/logging/index/samples/3.x/TodoApiDTO/Pages/Privacy.cshtml.cs?name=snippet)] +

Counter

-If further categorization is desired, the convention is to use a hierarchical name by appending a subcategory to the fully qualified class name, and explicitly specify the category using `ILoggerFactory.CreateLogger`: +

Current count: @currentCount

-[!code-csharp[](~/fundamentals/logging/index/samples/3.x/TodoApiDTO/Pages/Contact.cshtml.cs?name=snippet)] + + -Calling `CreateLogger` with a fixed name can be useful when used in multiple methods so the events can be organized by category. +@code { + private int currentCount = 0; -`ILogger` is equivalent to calling `CreateLogger` with the fully qualified type name of `T`. + private void IncrementByOne() + { + var logger = Logger.CreateLogger($"{typeof(Counter)}.IncrementByOne"); - + Logger.LogInformation("Someone incremented the counter!"); -## Log level - -The following table lists the values, the convenience `Log{LogLevel}` extension method, and the suggested usage: + currentCount++; + } -| LogLevel | Value | Method | Description | -| -------- | ----- | ------ | ----------- | -| | 0 | | Contain the most detailed messages. These messages may contain sensitive app data. These messages are disabled by default and should ***not*** be enabled in production. | -| | 1 | | For debugging and development. Use with caution in production due to the high volume. | -| | 2 | | Tracks the general flow of the app. May have long-term value. | -| | 3 | | For abnormal or unexpected events. Typically includes errors or conditions that don't cause the app to fail. | -| | 4 | | For errors and exceptions that cannot be handled. These messages indicate a failure in the current operation or request, not an app-wide failure. | -| | 5 | | For failures that require immediate attention. Examples: data loss scenarios, out of disk space. | -| | 6 | | Specifies that a logging category shouldn't write messages. | + private void IncrementByTen() + { + var logger = Logger.CreateLogger($"{typeof(Counter)}.IncrementByTen"); -In the previous table, the `LogLevel` is listed from lowest to highest severity. + Logger.LogInformation("Someone incremented the counter!"); -The method's first parameter, , indicates the severity of the log. Rather than calling `Log(LogLevel, ...)`, most developers call the [`Log{LOG LEVEL}`](xref:Microsoft.Extensions.Logging.LoggerExtensions) extension methods, where the `{LOG LEVEL}` placeholder is the log level. For example, the following two logging calls are functionally equivalent and produce the same log: + currentCount += 10; + } +} +``` -[!code-csharp[](~/fundamentals/logging/index/samples/3.x/TodoApiDTO/Controllers/TestController.cs?name=snippet0&highlight=6-7)] +Log messages: -`MyLogEvents.TestItem` is the event ID. `MyLogEvents` is part of the sample app and is displayed in the [Log event ID](#leid) section. +> :::no-loc text="BlazorSample.Components.Pages.Counter.IncrementByOne: Information: Someone incremented the counter!"::: +> :::no-loc text="BlazorSample.Components.Pages.Counter.IncrementByTen: Information: Someone incremented the counter!"::: -[!INCLUDE[](~/includes/MyDisplayRouteInfoBoth.md)] +In a Razor Pages page class model that uses a custom category ("`CustomCategory`") for the entire page model: -The following code creates `Information` and `Warning` logs: + -[!code-csharp[](~/fundamentals/logging/index/samples/3.x/TodoApiDTO/Controllers/TodoItemsController.cs?name=snippet_CallLogMethods&highlight=4,10)] +```csharp +public class PrivacyModel : PageModel +{ + private readonly ILogger _logger; -In the preceding code, the first `Log{LOG LEVEL}` parameter,`MyLogEvents.GetItem`, is the [Log event ID](#leid). 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](#lmt) section later in this document. + public PrivacyModel(ILoggerFactory logger) + { + _logger = logger.CreateLogger($"{typeof(PrivacyModel)}.CustomCategory"); + } -Call the appropriate `Log{LOG LEVEL}` method to control how much log output is written to a particular storage medium. For example: + public void OnGet() => + _logger.LogInformation("Privacy page visited at {DT}"), DateTime.UtcNow); +} +``` -* In production: - * Logging at the `Trace`, `Debug`, or `Information` levels produces a high-volume of detailed log messages. To control costs and not exceed data storage limits, log `Trace`, `Debug`, or `Information` level messages to a high-volume, low-cost data store. Consider limiting `Trace`, `Debug`, or `Information` to specific categories. - * Logging at `Warning` through `Critical` levels should produce few log messages. - * Costs and storage limits usually aren't a concern. - * Few logs allow more flexibility in data store choices. -* In development: - * Set to `Warning`. - * Add `Trace`, `Debug`, or `Information` messages when troubleshooting. To limit output, set `Trace`, `Debug`, or `Information` only for the categories under investigation. +## Log event ID -ASP.NET Core writes logs for framework events. For example, consider the log output for: +Each log message can specify an *event ID*. The following example creates a set of custom event IDs for use by an app. Notice how the IDs are in the 1,000 range for create, read, update, and delete (CRUD) operations, 3,000 for test logging, and in the 4,000 range for not found scenarios: -* A Razor Pages app created with the ASP.NET Core templates. -* Logging set to `Logging:Console:LogLevel:Microsoft:Information`. -* Navigation to the Privacy page: +```csharp +public class LogEvent +{ + public const int GenerateItems = 1000; + public const int ListItems = 1001; + public const int GetItem = 1002; + public const int InsertItem = 1003; + public const int UpdateItem = 1004; + public const int DeleteItem = 1005; + + public const int TestItem = 3000; + + public const int GetItemNotFound = 4000; + public const int UpdateItemNotFound = 4001; +} +``` -```console -info: Microsoft.AspNetCore.Hosting.Diagnostics[1] - Request starting HTTP/2 GET https://localhost:5001/Privacy -info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0] - Executing endpoint '/Privacy' -info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[3] - Route matched with {page = "/Privacy"}. Executing page /Privacy -info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[101] - Executing handler method DefaultRP.Pages.PrivacyModel.OnGet - ModelState is Valid -info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[102] - Executed handler method OnGet, returned result . -info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[103] - Executing an implicit handler method - ModelState is Valid -info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[104] - Executed an implicit handler method, returned result Microsoft.AspNetCore.Mvc.RazorPages.PageResult. -info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[4] - Executed page /Privacy in 74.5188ms -info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1] - Executed endpoint '/Privacy' -info: Microsoft.AspNetCore.Hosting.Diagnostics[2] - Request finished in 149.3023ms 200 text/html; charset=utf-8 -``` - -The following JSON sets `Logging:Console:LogLevel:Microsoft:Information`: - -[!code-json[](~/fundamentals/logging/index/samples/3.x/TodoApiDTO/appsettings.MSFT.json)] - - +Used in Razor component code, where an `ILogger` instance (`Logger`) is injected: -## Log event ID +* The `LogEvent.GetItem` ID (`1002`) is used with the informational log message for retrieving an item by its identifier (`id`). +* The `LogEvent.GetItemNotFound` ID (`4000`) is used with the warning log message if the item isn't found. -Each log can specify an *event ID*. The sample app uses the `MyLogEvents` class to define event IDs: +```csharp +Logger.LogInformation(LogEvent.GetItem, "Getting item {Id}", id); - -[!code-csharp[](~/fundamentals/logging/index/samples/3.x/TodoApiDTO/Models/MyLogEvents.cs?name=snippet_LoggingEvents)] +var todoItem = await TodoItemService.FindAsync(id); -[!code-csharp[](~/fundamentals/logging/index/samples/3.x/TodoApiDTO/Controllers/TodoItemsController.cs?name=snippet_CallLogMethods&highlight=4,10)] +if (todoItem == null) +{ + Logger.LogWarning(LogEvent.GetItemNotFound, "Get({Id}) NOT FOUND", id); -An event ID associates a set of events. For example, all logs related to displaying a list of items on a page might be 1001. + return NotFound(); +} +``` -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: +The logging provider may store the event ID in an ID (allows filtering on the ID), in the log message, or not at all. The [`Debug` provider](#debug) doesn't show event IDs. The console provider shows event IDs in brackets after the category: ```console -info: TodoApi.Controllers.TodoItemsController[1002] +info: BlazorSample.Components.Pages.Items[1002] Getting item 1 -warn: TodoApi.Controllers.TodoItemsController[4000] +warn: BlazorSample.Components.Pages.Items[4000] Get(1) NOT FOUND ``` -Some logging providers store the event ID in a field, which allows for filtering on the ID. - - +## Log level -## Log message template - -Each log API uses a message template. The message template can contain placeholders for which arguments are provided. Use names for the placeholders, not numbers. +The following table describes the logging levels from lowest to highest severity, their corresponding `enum` values, and their convenience extension methods. -[!code-csharp[](~/fundamentals/logging/index/samples/3.x/TodoApiDTO/Controllers/TodoItemsController.cs?name=snippet_CallLogMethods&highlight=4,10)] +`LogLevel` | Value | Method | Description +--- | --- | --- | --- + | 0 | | Contain the most detailed messages. These messages may contain sensitive app data. These messages are disabled by default and should ***not*** be enabled in production. + | 1 | | For debugging and development. Use with caution in production due to the high volume of messages logged. + | 2 | | Tracks the general flow of the app. + | 3 | | For abnormal or unexpected events. Typically includes errors or conditions that don't cause the app to fail. + | 4 | | Typically used for unhandled errors and exceptions. These messages indicate a failure in the current operation or request, not an app-wide failure. + | 5 | | For failures that require immediate attention, such as data loss or out of disk space. + | 6 | — | Specifies that a logging category shouldn't write messages. -The *order of the parameters*, not their placeholder names, determines which parameters are used to provide placeholder values in log messages. In the following code, the parameter names are out of sequence in the placeholders of the message template: +The method's first parameter, , indicates the severity of the log. Rather than calling `Log(LogLevel, ...)`, most developers call methods. For example, the following two logging calls are functionally equivalent and produce the same based on an injected `ILogger` instance (`Logger`) in a Razor component: ```csharp -var apples = 1; -var pears = 2; -var bananas = 3; +Logger.Log(LogLevel.Information, LogEvent.TestItem, routeInfo); -_logger.LogInformation("Parameters: {Pears}, {Bananas}, {Apples}", apples, pears, bananas); +Logger.LogInformation(LogEvent.TestItem, routeInfo); ``` -However, the parameters are assigned to the placeholders in the order: `apples`, `pears`, `bananas`. The log message reflects the *order of the parameters*: +> [!NOTE] +> `LogEvent.TestItem` is a [log event ID](#log-event-id). -```text -Parameters: 1, 2, 3 -``` +Log at an appropriate level to control how much log output is written to a particular storage medium: -This approach allows logging providers to implement [semantic or structured logging](https://github.com/NLog/NLog/wiki/How-to-use-structured-logging). The arguments themselves are passed to the logging system, not just the formatted message template. This enables logging providers to store the parameter values as fields. For example, consider the following logger method: +* In production: + * Logging at the , , or levels produces a high-volume of detailed log messages. To control costs and not exceed data storage limits, log at these levels to a high-volume, low-cost data store. Consider limiting these levels to specific categories. + * Logging at through levels usually produces few log messages. + * Costs and storage limits usually aren't a concern. + * Few logs allow more flexibility in data store choices. +* In development: + * We recommend the level (`"Default": "Information"`) for default logging and the level for Microsoft ASP.NET Core assemblies (`"Microsoft.AspNetCore": "Warning"`). + * Add and , or messages when troubleshooting. To limit output, only set these logging levels for the categories under investigation. -```csharp -_logger.LogInformation("Getting item {Id} at {RequestTime}", id, DateTime.Now); -``` +## Change log levels in a running app -For example, when logging to Azure Table Storage: +The Logging API doesn't include support for changing log levels while an app is running. However, some configuration providers are capable of reloading configuration, which takes immediate effect on logging configuration. For example, the [File Configuration Provider](xref:fundamentals/configuration/index#file-configuration-provider), reloads logging configuration by default. If configuration is changed in code while an app is running, the app can call to update the app's logging configuration. -* Each Azure Table entity can have `ID` and `RequestTime` properties. -* Tables with properties simplify queries on logged data. For example, a query can find all logs within a particular `RequestTime` range without having to parse the time out of the text message. +## How filtering rules are applied + +When an object is created, the object selects a single rule per provider to apply to that logger. All messages written by an instance are filtered based on the selected rules. The most specific rule for each provider and category pair is selected from the available rules. + +The following algorithm is used for each provider when an 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. +* If no rules are selected, use `MinimumLevel`. + +## `ILogger` and `ILoggerFactory` + +The and interfaces and implementations are included in the .NET SDK. They are also available in the following NuGet packages: + +* The interfaces are in the [`Microsoft.Extensions.Logging.Abstractions` NuGet package](https://www.nuget.org/packages/Microsoft.Extensions.Logging.Abstractions). +* The default implementations are in the [`Microsoft.Extensions.Logging` NuGet package](https://www.nuget.org/packages/microsoft.extensions.logging). ## Log exceptions The logger methods have overloads that take an exception parameter: -[!code-csharp[](~/fundamentals/logging/index/samples/3.x/TodoApiDTO/Controllers/TestController.cs?name=snippet_Exp)] +```csharp +try +{ + ... + + throw new Exception("Test exception"); +} +catch (Exception ex) +{ + Logger.LogWarning(LogEvent.GetItemNotFound, ex, "Test exception at {DT}", + DateTime.UtcNow); +} +``` -[!INCLUDE[](~/includes/MyDisplayRouteInfoBoth.md)] + Exception logging is provider-specific. ### Default log level -If the default log level is not set, the default log level value is `Information`. +If the default log level isn't explicitly set, the default log level is . -For example, consider the following web app: +If the default log level isn't set in configuration, it can be set with . The following example sets the level as the default logging level: -* Created with the ASP.NET web app templates. -* `appsettings.json` and `appsettings.Development.json` deleted or renamed. - -With the preceding setup, navigating to the privacy or home page produces many `Trace`, `Debug`, and `Information` messages with `Microsoft` in the category name. - -The following code sets the default log level when the default log level is not set in configuration: +```csharp +var builder = WebApplication.CreateBuilder(); -[!code-csharp[](~/fundamentals/logging/index/samples/6.x/WebApp/Program.cs?name=snippet_MIN)] +builder.Logging.SetMinimumLevel(LogLevel.Warning); +``` -Generally, log levels should be specified in configuration and not code. +We recommend setting the minimum default log level in configuration, not in C# code. ### Filter function -A filter function is invoked for all providers and categories that don't have rules assigned to them by configuration or code: +A filter function is invoked for all providers and categories that don't have rules assigned to them by configuration or code. The following example displays console logs when the category contains `Page` or `Microsoft` and the log level is or higher: -[!code-csharp[](~/fundamentals/logging/index/samples/6.x/WebApp/Program.cs?name=snippet_FF)] +```csharp +var builder = WebApplication.CreateBuilder(); + +builder.Logging.AddFilter((provider, category, logLevel) => +{ + if (provider is not null && category is not null) + { + return provider.Contains("ConsoleLoggerProvider") + && (category.Contains("Page") || category.Contains("Microsoft")) + && logLevel >= LogLevel.Information; + } -The preceding code displays console logs when the category contains `Controller` or `Microsoft` and the log level is `Information` or higher. + return false; +}); +``` -Generally, log levels should be specified in configuration and not code. + + +We recommend specifying log levels in configuration and not in code with filter functions. ## ASP.NET Core categories -The following table contains some categories used by ASP.NET Core. +The following table contains some of the logging categories used by ASP.NET Core. | Category | Notes | | ------------------------------------- | ----- | | `Microsoft.AspNetCore` | General ASP.NET Core diagnostics. | -| `Microsoft.AspNetCore.DataProtection` | Which keys were considered, found, and used. | +| `Microsoft.AspNetCore.DataProtection` | Which data protection keys were considered, found, and used. | | `Microsoft.AspNetCore.HostFiltering` | Hosts allowed. | | `Microsoft.AspNetCore.Hosting` | How long HTTP requests took to complete and what time they started. Which hosting startup assemblies were loaded. | -| `Microsoft.AspNetCore.Mvc` | MVC and Razor diagnostics. Model binding, filter execution, view compilation, action selection. | +| `Microsoft.AspNetCore.Mvc` | MVC and Razor diagnostics. Model binding, filter execution, view compilation, and action selection. | | `Microsoft.AspNetCore.Routing` | Route matching information. | | `Microsoft.AspNetCore.Server` | Connection start, stop, and keep alive responses. HTTPS certificate information. | | `Microsoft.AspNetCore.StaticFiles` | Files served. | +To study more categories using the [`Console`](#console) logger, set `appsettings.Development.json` in a test app: -To view more categories in the console window, set **`appsettings.Development.json`** to the following: - -[!code-json[](~/fundamentals/logging/index/samples/3.x/MyMain/appsettings.Trace.json)] - - +```json +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Trace", + "Microsoft.Hosting.Lifetime": "Information" + } + } +} +``` -For a list of Entity Framework categories, see [EF Message categories](/ef/core/logging-events-diagnostics/simple-logging#message-categories). +> [!WARNING] +> Reset the logging configuration back to its prior levels in `appsettings.Development.json` after studying the [`Console`](#console) logger output. - +For a list of Entity Framework categories, see [Simple Logging: Message categories (EF Core documentation)](/ef/core/logging-events-diagnostics/simple-logging#message-categories). ## 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. +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. A scope: @@ -447,26 +810,48 @@ A scope: The following providers support scopes: -* `Console` +* [`Console`](#console) * [`AzureAppServicesFile` and `AzureAppServicesBlob`](xref:Microsoft.Extensions.Logging.AzureAppServices.BatchingLoggerOptions.IncludeScopes) Use a scope by wrapping logger calls in a `using` block: -[!code-csharp[](~/fundamentals/logging/index/samples/3.x/TodoApiDTO/Controllers/TestController.cs?name=snippet_Scopes)] +```csharp +public async Task GetTodoItem(long id) +{ + TodoItem todoItem; + var transactionId = Guid.NewGuid().ToString(); + + using (Logger.BeginScope(new List> + { + new KeyValuePair("TransactionId", transactionId), + })) + { + Logger.LogInformation(LogEvent.GetItem, "Getting item {Id}", id); + + todoItem = await TodoItemsService.FindAsync(id); + + if (todoItem == null) + { + Logger.LogWarning(LogEvent.GetItemNotFound, "Get({Id}) NOT FOUND", id); + + return NotFound(); + } + } - + return todoItem; +} +``` ## Built-in logging providers -ASP.NET Core includes the following logging providers as part of the shared framework: +ASP.NET Core includes the following logging providers: * [`Console`](#console) * [`Debug`](#debug) -* [`EventSource`](#event-source) -* [`EventLog`](#welog) +* [`EventSource`](#eventsource) +* [Windows `EventLog`](#windows-eventlog) -The following logging providers are shipped by Microsoft, but not as part of the -shared framework. They must be installed as additional nuget. +The following logging providers are provided by Microsoft, but not as part of the .NET shared framework. They must be installed as an additional NuGet package added to the app. * [`AzureAppServicesFile` and `AzureAppServicesBlob`](#azure-app-service) * [`ApplicationInsights`](#azure-application-insights) @@ -475,11 +860,11 @@ ASP.NET Core doesn't include a logging provider for writing logs to files. To wr For information on `stdout` and debug logging with the ASP.NET Core Module, see and . -### Console +### `Console` -The `Console` provider logs output to the console. For more information on viewing `Console` logs in development, see [Logging output from dotnet run and Visual Studio](#dnrvs). +The `Console` provider logs output to the console. For more information on viewing `Console` logs in development, see the [Logging output](#logging-output) section. -### Debug +### `Debug` The `Debug` provider writes log output by using the class. Calls to `System.Diagnostics.Debug.WriteLine` write to the `Debug` provider. @@ -488,11 +873,11 @@ On Linux, the `Debug` provider log location is distribution-dependent and may be * `/var/log/message` * `/var/log/syslog` -### Event Source +### `EventSource` The `EventSource` provider writes to a cross-platform event source with the name `Microsoft-Extensions-Logging`. On Windows, the provider uses [ETW](/windows/win32/etw/event-tracing-portal). -#### dotnet-trace tooling +#### `dotnet-trace` tooling The [`dotnet-trace`](/dotnet/core/diagnostics/dotnet-trace) tool is a cross-platform CLI global tool that enables the collection of .NET traces of a running process. The tool collects provider data using a . @@ -513,40 +898,46 @@ Use the `dotnet-trace` tooling to collect a trace from an app: General command syntax: + * `{PID}`: Process identifier + * `{KEYWORD}`: Keyword + * `{PROVIDER LEVEL}`: Provider level + * `{LOGGER CATEGORY ...}`: Logger category + * `{CATEGORY LEVEL ...}`: Category level + ```dotnetcli dotnet-trace collect -p {PID} - --providers Microsoft-Extensions-Logging:{Keyword}:{Provider Level} + --providers Microsoft-Extensions-Logging:{KEYWORD}:{PROVIDER LEVEL} :FilterSpecs=\" - {Logger Category 1}:{Category Level 1}; - {Logger Category 2}:{Category Level 2}; + {LOGGER CATEGORY 1}:{CATEGORY LEVEL 1}; + {LOGGER CATEGORY 2}:{CATEGORY LEVEL 2}; ... - {Logger Category N}:{Category Level N}\" + {LOGGER CATEGORY N}:{CATEGORY LEVEL N}\" ``` When using a PowerShell command shell, enclose the `--providers` value in single quotes (`'`): - ```dotnetcli + ```powershell dotnet-trace collect -p {PID} - --providers 'Microsoft-Extensions-Logging:{Keyword}:{Provider Level} + --providers 'Microsoft-Extensions-Logging:{KEYWORD}:{PROVIDER LEVEL} :FilterSpecs=\" - {Logger Category 1}:{Category Level 1}; - {Logger Category 2}:{Category Level 2}; + {LOGGER CATEGORY 1}:{CATEGORY LEVEL 1}; + {LOGGER CATEGORY 2}:{CATEGORY LEVEL 2}; ... - {Logger Category N}:{Category Level N}\"' + {LOGGER CATEGORY N}:{CATEGORY LEVEL N}\"' ``` On non-Windows platforms, add the `-f speedscope` option to change the format of the output trace file to `speedscope`. - The following table defines the Keyword: + The following table defines the keyword (`{KEYWORD}` placeholder). | Keyword | Description | | :-----: | ----------- | - | 1 | Log meta events about the `LoggingEventSource`. Doesn't log events from `ILogger`. | + | 1 | Log meta events about the `LoggingEventSource`. Doesn't log events from . | | 2 | Turns on the `Message` event when `ILogger.Log()` is called. Provides information in a programmatic (not formatted) way. | | 4 | Turns on the `FormatMessage` event when `ILogger.Log()` is called. Provides the formatted string version of the information. | | 8 | Turns on the `MessageJson` event when `ILogger.Log()` is called. Provides a JSON representation of the arguments. | - The following table lists the provider levels: + The following table defines the provider levels. | Provider Level | Description | | :------------: | --------------- | @@ -557,10 +948,10 @@ Use the `dotnet-trace` tooling to collect a trace from an app: | 4 | `Informational` | | 5 | `Verbose` | - The parsing for a category level can be either a string or a number: + The parsing for a category level can be either a string or a number, as indicated in the following table. | Category named value | Numeric value | - | :------------------: | ------------- | + | -------------------- | :-----------: | | `Trace` | 0 | | `Debug` | 1 | | `Information` | 2 | @@ -573,22 +964,22 @@ Use the `dotnet-trace` tooling to collect a trace from an app: * Are in reverse order. * The string constants aren't all identical. - If no `FilterSpecs` are specified then the `EventSourceLogger` implementation attempts to convert the provider level to a category level and applies it to all categories. + If no `FilterSpecs` are specified, the `EventSourceLogger` implementation attempts to convert the provider level to a category level and applies it to all categories. | Provider Level | Category Level | - | :----------------: | ---------------- | + | ------------------ | ---------------- | | `Verbose`(5) | `Debug`(1) | | `Informational`(4) | `Information`(2) | | `Warning`(3) | `Warning`(3) | | `Error`(2) | `Error`(4) | | `Critical`(1) | `Critical`(5) | - If `FilterSpecs` are provided, any category that is included in the list uses the category level encoded there, all other categories are filtered out. + If `FilterSpecs` are provided, any category that's included in the list uses the category level encoded there, all other categories are filtered out. The following examples assume: - * An app is running and calling `logger.LogDebug("12345")`. - * The process ID (PID) has been set via `set PID=12345`, where `12345` is the actual PID. + * An app is running and calling `Logger.LogDebug("12345")`. + * The process ID (PID) is set via `set PID=12345`, where `12345` is the actual PID. Consider the following command: @@ -600,7 +991,7 @@ Use the `dotnet-trace` tooling to collect a trace from an app: * Captures debug messages. * Doesn't apply a `FilterSpecs`. - * Specifies level 5 which maps category Debug. + * Specifies level 5 which maps category . Consider the following command: @@ -610,22 +1001,22 @@ Use the `dotnet-trace` tooling to collect a trace from an app: The preceding command: - * Doesn't capture debug messages because the category level 5 is `Critical`. + * Doesn't capture debug messages because the category level 5 is . * Provides a `FilterSpecs`. - The following command captures debug messages because category level 1 specifies `Debug`. + The following command captures debug messages because category level 1 specifies : ```dotnetcli dotnet-trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:5:\"FilterSpecs=*:1\" ``` - The following command captures debug messages because category specifies `Debug`. + The following command captures debug messages because category specifies : ```dotnetcli dotnet-trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:5:\"FilterSpecs=*:Debug\" ``` - `FilterSpecs` entries for `{Logger Category}` and `{Category Level}` represent additional log filtering conditions. Separate `FilterSpecs` entries with the `;` semicolon character. + `FilterSpecs` entries for the logger category and category level represent additional log filtering conditions. Separate `FilterSpecs` entries with the `;` semicolon character. Example using a Windows command shell: @@ -635,24 +1026,24 @@ Use the `dotnet-trace` tooling to collect a trace from an app: The preceding command activates: - * The Event Source logger to produce formatted strings (`4`) for errors (`2`). - * `Microsoft.AspNetCore.Hosting` logging at the `Informational` logging level (`4`). + * The [`EventSource` provider](#eventsource) to produce formatted strings (`4`) for errors (`2`). + * `Microsoft.AspNetCore.Hosting` logging at the logging level (`4`). -1. Stop the `dotnet-trace` tooling by pressing the Enter key or Ctrl+C. +1. Stop the `dotnet-trace` tooling by pressing the Enter key or Ctrl+C. The trace is saved with the name `trace.nettrace` in the folder where the `dotnet-trace` command is executed. 1. Open the trace with [Perfview](#perfview). Open the `trace.nettrace` file and explore the trace events. -If the app doesn't build the host with , add the Event Source provider to the app's logging configuration. +If the app doesn't build the host with , add the [`EventSource` provider](#eventsource) to the app's logging configuration. For more information, see: * [Trace for performance analysis utility (`dotnet-trace`)](/dotnet/core/diagnostics/dotnet-trace) (.NET documentation) -* [Trace for performance analysis utility (`dotnet-trace`)](https://github.com/dotnet/diagnostics/blob/main/documentation/dotnet-trace-instructions.md) (dotnet/diagnostics GitHub repository documentation) +* [Trace for performance analysis utility (`dotnet-trace`)](https://github.com/dotnet/diagnostics/blob/main/documentation/dotnet-trace-instructions.md) (`dotnet/diagnostics` GitHub repository documentation) * * -* [Perfview](#perfview): Useful for viewing Event Source traces. +* [Perfview](#perfview) for viewing `EventSource` traces #### Perfview @@ -660,11 +1051,9 @@ Use the [PerfView utility](https://github.com/Microsoft/perfview) to collect and 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 `*` at the start of the string. - - ### Windows EventLog -The `EventLog` provider sends log output to the Windows Event Log. Unlike the other providers, the `EventLog` provider does ***not*** inherit the default non-provider settings. If `EventLog` log settings aren't specified, they default to . +The Windows `EventLog` provider sends log output to the Windows Event Log. Unlike the other providers, the `EventLog` provider doesn't inherit the default non-provider settings. If `EventLog` log settings aren't specified, they default to . To log events lower than , explicitly set the log level. The following example sets the Event Log default log level to : @@ -680,32 +1069,97 @@ To log events lower than overloads can pass in . If `null` or not specified, the following default settings are used: -* `LogName`: "Application" -* `SourceName`: ".NET Runtime" +* `LogName`: "`Application`" +* `SourceName`: "`.NET Runtime`" * `MachineName`: The local machine name is used. -The following code changes the `SourceName` from the default value of `".NET Runtime"` to `MyLogs`: +The following code changes the `SourceName` from the default value of `".NET Runtime"` to "`CustomLogs`": -[!code-csharp[](~/fundamentals/logging/index/samples/6.x/WebApp/Program.cs?name=snippet_WEL)] +```csharp +var builder = WebApplication.CreateBuilder(); -### Azure App Service +builder.Logging.AddEventLog(eventLogSettings => +{ + eventLogSettings.SourceName = "CustomLogs"; +}); +``` -The [`Microsoft.Extensions.Logging.AzureAppServices`](https://www.nuget.org/packages/Microsoft.Extensions.Logging.AzureAppServices) provider package writes logs to text files in an Azure App Service app's file system and to [blob storage](/azure/storage/blobs/storage-quickstart-blobs-dotnet#what-is-blob-storage) in an Azure Storage account. +When the app calls the overload with , a new instance of is created with the provided settings. If there's already an instance registered, which is the case if the app doesn't call to remove all the instances, the new settings don't replace the existing ones. If you want to ensure that the are used, call before calling . + +#### Azure App Service + +The [`Microsoft.Extensions.Logging.AzureAppServices` provider NuGet package](https://www.nuget.org/packages/Microsoft.Extensions.Logging.AzureAppServices) writes logs to text files in an Azure App Service app's file system and to [blob storage](/azure/storage/blobs/storage-quickstart-blobs-dotnet#what-is-blob-storage) in an Azure Storage account. The provider only logs when the project runs in the Azure environment. The provider package isn't included in the shared framework. To use the provider, add the provider package to the project. To configure provider settings, use and , as shown in the following example: -[!code-csharp[](~/fundamentals/logging/index/samples/6.x/WebApp/Program.cs?name=snippet_AAS)] +:::moniker range=">= aspnetcore-6.0" + +```csharp +using Microsoft.Extensions.Logging.AzureAppServices; + +var builder = WebApplication.CreateBuilder(); + +builder.Logging.AddAzureWebAppDiagnostics(); + +builder.Services.Configure(options => +{ + options.FileName = "azure-diagnostics-"; + options.FileSizeLimit = 50 * 1024; + options.RetainedFileCountLimit = 5; +}); + +builder.Services.Configure(options => +{ + options.BlobName = "log.txt"; +}); +``` + +:::moniker-end + +:::moniker range="< aspnetcore-6.0" + +```csharp +public class Scopes +{ + public class Program + { + public static void Main(string[] args) + { + CreateHostBuilder(args).Build().Run(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureLogging(logging => logging.AddAzureWebAppDiagnostics()) + .ConfigureServices(serviceCollection => serviceCollection + .Configure(options => + { + options.FileName = "azure-diagnostics-"; + options.FileSizeLimit = 50 * 1024; + options.RetainedFileCountLimit = 5; + }) + .Configure(options => + { + options.BlobName = "log.txt"; + })) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); + } +} +``` + +:::moniker-end When deployed to Azure App Service, the app uses the settings in the [App Service logs](/azure/app-service/troubleshoot-diagnostic-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)** * **Application Logging (Blob)** -The default location for log files is in the `D:\\home\\LogFiles\\Application` folder, and the default file name is `diagnostics-yyyymmdd.txt`. The default file size limit is 10 MB, and the default maximum number of files retained is 2. The default blob name is `{app-name}{timestamp}/yyyy/mm/dd/hh/{guid}-applicationLog.txt`. - -This provider only logs when the project runs in the Azure environment. +The default location for log files is `D:\home\LogFiles\Application`. The default file size limit is 10 MB, and the default maximum number of files retained is two files. #### Azure log streaming @@ -721,15 +1175,16 @@ To configure Azure log streaming: * Set **Application Logging (Filesystem)** to **On**. * Choose the log **Level**. This setting only applies to Azure log streaming. -Navigate to the **Log Stream** page to view logs. The logged messages are logged with the `ILogger` interface. +Navigate to the **Log Stream** page to view logs. The logged messages are logged with the interface. ### Azure Application Insights -The [`Microsoft.Extensions.Logging.ApplicationInsights`](https://www.nuget.org/packages/Microsoft.Extensions.Logging.ApplicationInsights) provider package writes logs to [Azure Application Insights](/azure/azure-monitor/app/cloudservices). Application Insights is a service that monitors a web app and provides tools for querying and analyzing the telemetry data. If you use this provider, you can query and analyze your logs by using the Application Insights tools. +Application Insights is a service that monitors a web app and provides tools for querying and analyzing the telemetry data. If you use this provider, you can query and analyze your logs by using the Application Insights tools. -The logging provider is included as a dependency of [`Microsoft.ApplicationInsights.AspNetCore`](https://www.nuget.org/packages/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. +The [`Microsoft.Extensions.Logging.ApplicationInsights` provider NuGet package](https://www.nuget.org/packages/Microsoft.Extensions.Logging.ApplicationInsights) writes logs to [Azure Application Insights](/azure/azure-monitor/app/cloudservices). The logging provider is included as a dependency of the [`Microsoft.ApplicationInsights.AspNetCore` NuGet package](https://www.nuget.org/packages/Microsoft.ApplicationInsights.AspNetCore), which is the package that provides all available telemetry for ASP.NET Core. If you use the `Microsoft.ApplicationInsights.AspNetCore` NuGet package, you aren't required to install the `Microsoft.Extensions.Logging.ApplicationInsights` provider package. -The [`Microsoft.ApplicationInsights.Web`](https://www.nuget.org/packages/Microsoft.ApplicationInsights.Web) package is for ASP.NET 4.x, not ASP.NET Core. +> [!NOTE] +> The [`Microsoft.ApplicationInsights.Web` NuGet package](https://www.nuget.org/packages/Microsoft.ApplicationInsights.Web) is for ASP.NET 4.x, not ASP.NET Core, and shouldn't be used in an ASP.NET Core app. For more information, see the following resources: @@ -743,89 +1198,357 @@ For more information, see the following resources: Third-party logging frameworks that work with ASP.NET Core: -* [elmah.io](https://elmah.io/) ([GitHub repo](https://github.com/elmahio/Elmah.Io.Extensions.Logging)) -* [Gelf](https://go2docs.graylog.org/5-0/getting_in_log_data/gelf.html) ([GitHub repo](https://github.com/mattwcole/gelf-extensions-logging)) -* [JSNLog](https://jsnlog.com/) ([GitHub repo](https://github.com/mperdeck/jsnlog)) -* [KissLog.net](https://kisslog.net/) ([GitHub repo](https://github.com/catalingavan/KissLog-net)) -* [Log4Net](https://logging.apache.org/log4net/) ([GitHub repo](https://github.com/huorswords/Microsoft.Extensions.Logging.Log4Net.AspNetCore)) -* [NLog](https://nlog-project.org/) ([GitHub repo](https://github.com/NLog/NLog.Extensions.Logging)) -* [PLogger](https://www.nuget.org/packages/InvertedSoftware.PLogger.Core/) ([GitHub repo](https://github.com/invertedsoftware/InvertedSoftware.PLogger.Core)) -* [Sentry](https://sentry.io/welcome/) ([GitHub repo](https://github.com/getsentry/sentry-dotnet)) -* [Serilog](https://serilog.net/) ([GitHub repo](https://github.com/serilog/serilog-aspnetcore)) -* [Stackdriver](https://cloud.google.com/dotnet/docs/stackdriver#logging) ([Github repo](https://github.com/googleapis/google-cloud-dotnet)) +* [elmah.io](https://elmah.io/) ([GitHub repository](https://github.com/elmahio/Elmah.Io.Extensions.Logging)) +* [Gelf](https://go2docs.graylog.org/5-0/getting_in_log_data/gelf.html) ([GitHub repository](https://github.com/mattwcole/gelf-extensions-logging)) +* [JSNLog](https://jsnlog.com/) ([GitHub repository](https://github.com/mperdeck/jsnlog)) +* [KissLog.net](https://kisslog.net/) ([GitHub repository](https://github.com/catalingavan/KissLog-net)) +* [Log4Net](https://logging.apache.org/log4net/) ([GitHub repository](https://github.com/huorswords/Microsoft.Extensions.Logging.Log4Net.AspNetCore)) +* [NLog](https://nlog-project.org/) ([GitHub repository](https://github.com/NLog/NLog.Extensions.Logging)) +* [PLogger](https://www.nuget.org/packages/InvertedSoftware.PLogger.Core/) ([GitHub repository](https://github.com/invertedsoftware/InvertedSoftware.PLogger.Core)) +* [Sentry](https://sentry.io/welcome/) ([GitHub repository](https://github.com/getsentry/sentry-dotnet)) +* [Serilog](https://serilog.net/) ([GitHub repository](https://github.com/serilog/serilog-aspnetcore)) +* [Stackdriver](https://cloud.google.com/dotnet/docs/stackdriver#logging) ([GitHub repository](https://github.com/googleapis/google-cloud-dotnet)) Some third-party frameworks can perform [semantic logging, also known as structured logging](https://softwareengineering.stackexchange.com/questions/312197/benefits-of-structured-logging-vs-basic-logging). Using a third-party framework is similar to using one of the built-in providers: -1. Add a NuGet package to your project. -1. Call an `ILoggerFactory` extension method provided by the logging framework. +1. Add the provider's NuGet package to the project. +1. Call an extension method provided by the logging framework. -For more information, see each provider's documentation. Third-party logging providers aren't supported by Microsoft. +For more information, see the provider's documentation. Third-party logging providers aren't owned, maintained, or supported by Microsoft. -### No asynchronous logger methods +## Non-host console app logging -Logging should be so fast that it isn't worth the performance cost of asynchronous code. If a logging data store is slow, don't write to it directly. Consider writing the log messages to a fast store initially, then moving them to the slow store later. For example, when logging to SQL Server, don't do so directly in a `Log` method, since the `Log` methods are synchronous. 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. For more information, see [Guidance on how to log to a message queue for slow data stores (dotnet/AspNetCore.Docs #11801)](https://github.com/dotnet/AspNetCore.Docs/issues/11801). +For logging in a console app without the Generic Host, see [Logging in C# and .NET](/dotnet/core/extensions/logging). For an additional example, see the [Background Tasks sample app](https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/fundamentals/host/hosted-services/samples), which is covered by . - +## No asynchronous logger methods -## Change log levels in a running app +Logging should be so fast that it isn't worth the performance cost of asynchronous code. If a logging data store is slow, don't write to it directly. Consider writing the log messages to a fast store initially, then move the logs to the slower data store later. For example, don't write log messages directly to a SQL Server data store in a `Log` method because `Log` methods are synchronous. Instead, synchronously add log messages to an in-memory queue and have a background worker pull the messages out of the queue to push the data to SQL Server asynchronously. For more information, see [Guidance on how to log to a message queue for slow data stores (dotnet/AspNetCore.Docs #11801)](https://github.com/dotnet/AspNetCore.Docs/issues/11801). -The Logging API doesn't include a scenario to change log levels while an app is running. However, some configuration providers are capable of reloading configuration, which takes immediate effect on logging configuration. For example, the [File Configuration Provider](xref:fundamentals/configuration/index#file-configuration-provider), reloads logging configuration by default. If configuration is changed in code while an app is running, the app can call to update the app's logging configuration. +## Apply log filter rules in code -## ILogger and ILoggerFactory +The preferred approach for setting log filter rules is by [app configuration](xref:fundamentals/configuration/index). -The and interfaces and implementations are included in the .NET SDK. They are also available in the following NuGet packages: +The following example shows how to register filter rules in code by calling on : -* The interfaces are in [`Microsoft.Extensions.Logging.Abstractions`](https://www.nuget.org/packages/Microsoft.Extensions.Logging.Abstractions/). -* The default implementations are in [`Microsoft.Extensions.Logging`](https://www.nuget.org/packages/microsoft.extensions.logging/). +```csharp +using Microsoft.Extensions.Logging.Console; +using Microsoft.Extensions.Logging.Debug; - - +var builder = WebApplication.CreateBuilder(); -## Apply log filter rules in code +builder.Logging.AddFilter("System", LogLevel.Debug); +builder.Logging.AddFilter("Microsoft", LogLevel.Information); +builder.Logging.AddFilter("Microsoft", LogLevel.Trace); +``` + +In the preceding example: + +* The first filter specifies: + * Log filtering rules for all providers because a specific provider isn't configured. + * All categories starting with "`System`". + * Log level and higher. + +* The [`Debug` provider](#debug) () specifies: + * All categories starting with "`Microsoft`". + * Log level and higher. + +* The [`Console` provider](#console) () specifies: + * All categories starting with "`Microsoft`". + * Log level and higher. + +:::moniker range=">= aspnetcore-5.0" + +## Specify the trace context for logging scopes + +:::moniker-end + +:::moniker range=">= aspnetcore-6.0" -The preferred approach for setting log filter rules is by using [Configuration](xref:fundamentals/configuration/index). +The logging libraries implicitly create a scope object with . The following fields indicate the options (): -The following example shows how to register filter rules in code: +* `SpanId` +* `TraceId` +* `ParentId` +* `Baggage` +* `Tags` -[!code-csharp[](~/fundamentals/logging/index/samples/6.x/WebApp/Program.cs?name=snippet_FR)] +`SpanId`, `TraceId`, `ParentId` are enabled by default. -`logging.AddFilter("System", LogLevel.Debug)` specifies the `System` category and log level `Debug`. The filter is applied to all providers because a specific provider was not configured. +In the following example, only the `SpanId` and `TraceId` are specified: -`AddFilter("Microsoft", LogLevel.Information)` specifies: +```csharp +var builder = WebApplication.CreateBuilder(args); + +builder.Logging.AddSimpleConsole(options => +{ + options.IncludeScopes = true; +}); + +builder.Logging.Configure(options => +{ + options.ActivityTrackingOptions = + ActivityTrackingOptions.SpanId | ActivityTrackingOptions.TraceId; +}); + +var app = builder.Build(); -* The `Debug` logging provider. -* Log level `Information` and higher. -* All categories starting with `"Microsoft"`. +app.MapGet("/", () => "Hello World!"); -## Automatically log scope with `SpanId`, `TraceId`, `ParentId`, `Baggage`, and `Tags`. +app.Run(); +``` + +:::moniker-end -The logging libraries implicitly create a scope object with `SpanId`, `TraceId`, `ParentId`,`Baggage`, and `Tags`. This behavior is configured via . +:::moniker range=">= aspnetcore-5.0 < aspnetcore-6.0" -[!code-csharp[](~/fundamentals/logging/index/samples/6.x/WebLog/Program.cs?name=snippet4)] +## Automatically log scope with `SpanId`, `TraceId`, and `ParentId` -If the `traceparent` http request header is set, the `ParentId` in the log scope shows the W3C `parent-id` from in-bound `traceparent` header and the `SpanId` in the log scope shows the updated `parent-id` for the next out-bound step/span. For more information, see [Mutating the traceparent Field](https://www.w3.org/TR/trace-context/#mutating-the-traceparent-field). +The logging libraries implicitly create a scope object with `SpanId`, `TraceId`, and `ParentId`. This behavior is configured via . + + +The logging libraries implicitly create a scope object with . The following fields indicate the options (): + +* `SpanId` +* `TraceId` +* `ParentId` + +`SpanId`, `TraceId`, `ParentId` are enabled by default. + +In the following example, only the `SpanId` and `TraceId` are specified: + +```csharp +var loggerFactory = LoggerFactory.Create(logging => +{ + logging.Configure(options => + { + options.ActivityTrackingOptions = + ActivityTrackingOptions.SpanId | ActivityTrackingOptions.TraceId; + }).AddSimpleConsole(options => + { + options.IncludeScopes = true; + }); +}); +``` + +:::moniker-end + +:::moniker range=">= aspnetcore-5.0" + +If the [W3C Trace Context specification](https://www.w3.org/TR/trace-context/) `traceparent` http request header is set: + +* The [`ParentId`](xref:Microsoft.Extensions.Logging.ActivityTrackingOptions) in the log scope shows the `parent-id` from in-bound `traceparent` header. +* The [`SpanId`](xref:Microsoft.Extensions.Logging.ActivityTrackingOptions) in the log scope shows the updated `parent-id` for the next out-bound step/span. + +For more information, see [Mutating the traceparent Field](https://www.w3.org/TR/trace-context/#mutating-the-traceparent-field). + +:::moniker-end ## Create a custom logger To create a custom logger, see [Implement a custom logging provider in .NET](/dotnet/core/extensions/custom-logging-provider). - +:::moniker range="< aspnetcore-6.0" + +## Log during host construction + +Logging during host construction isn't directly supported. However, a separate logger can be used. In the following example, a [Serilog](https://serilog.net/) logger is used to log in . `AddSerilog` uses the static configuration specified in `Log.Logger`, which is provided by the [Serilog NuGet package](https://www.nuget.org/packages/serilog). + +In the method of the app's `Program` file: + +```csharp +var builtConfig = new ConfigurationBuilder() + .AddJsonFile("appsettings.json") + .AddCommandLine(args) + .Build(); + +Log.Logger = new LoggerConfiguration() + .WriteTo.Console() + .WriteTo.File(builtConfig["Logging:FilePath"]) + .CreateLogger(); + +try +{ + return Host.CreateDefaultBuilder(args) + .ConfigureServices((context, services) => + { + services.AddRazorPages(); + }) + .ConfigureAppConfiguration((hostingContext, config) => + { + config.AddConfiguration(builtConfig); + }) + .ConfigureLogging(logging => + { + logging.AddSerilog(); + }) + .ConfigureWebHostDefaults(webBuilder => + { + webBuilder.UseStartup(); + }); +} +catch (Exception ex) +{ + Log.Fatal(ex, "Host builder error"); + + throw; +} +finally +{ + Log.CloseAndFlush(); +} +``` + +## Configure a service that depends on `ILogger` + +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](xref:fundamentals/host/web-host). For information about why only one container is created for the [Generic Host](xref:fundamentals/host/generic-host), see the [breaking change announcement](https://github.com/aspnet/Announcements/issues/353). + +To configure a service that depends on , use constructor injection or provide a factory method. The factory method approach is recommended only if there's no other option. For example, consider a service that requires a logger instance provided by dependency injection (DI): + +```csharp +services.AddSingleton((container) => +{ + var logger = container.GetRequiredService>(); + return new LoggingService() { Logger = logger }; +}); +``` + +The preceding code is a that runs the first time the DI container constructs an instance of `LoggerService`. Access any registered service using this pattern. + +:::moniker-end + +## Logging bug reports + +File a logging bug report in the [`dotnet/runtime` GitHub repository issues](https://github.com/dotnet/runtime/issues). + +## Common log categories + + + +This section describes common log categories seen in ASP.NET Core app logs. The following isn't a comprehensive list. + +`Microsoft.AspNetCore`: Logs from the ASP.NET Core framework components, such as hosting, routing, and middleware. + +Authentication + +* `Microsoft.AspNetCore.Authentication`: Logs from the authentication middleware and services, including authentication scheme handling. +* `Microsoft.AspNetCore.Authentication.Cookies`: Logs specific to cookie-based authentication. +* `Microsoft.AspNetCore.Authentication.JwtBearer`: Logs related to JWT Bearer token authentication. +* `Microsoft.AspNetCore.Authentication.OpenIdConnect`: Logs concerning OpenID Connect authentication processes. +* `Microsoft.AspNetCore.Authentication.OAuth`: Logs related to OAuth authentication and authorization flows. + +Authorization + +* `Microsoft.AspNetCore.Authorization`: Logs related to authorization operations, including policy evaluation and decision making. +* `Microsoft.AspNetCore.Authorization.DefaultAuthorizationService`: Logs about the default. + +Configuration + +* `Microsoft.Extensions.Configuration.Json`: Logs from classes that obtain configuration data from JSON files. +* `Microsoft.Extensions.Configuration.UserSecrets`: Logs related to loading user secrets configuration data. + +CORS + +* `Microsoft.AspNetCore.Cors`: Logs related to Cross-Origin Resource Sharing (CORS) middleware and policy evaluation. +* `Microsoft.AspNetCore.Cors.Infrastructure`: Logs concerning CORS policy configuration and enforcement. + +Data Protection: + +* `Microsoft.AspNetCore.DataProtection`: Logs from the data protection system, including key management, encryption operations, and which keys were considered, found, and used. +* `Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager`: Logs specific to the XML key manager, including key storage and retrieval. + +Diagnostics + +* `Microsoft.AspNetCore.Diagnostics`: Logs about diagnostics and error handling middleware, including exception handling and status code pages. +* `Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware`: Logs specific to developer exception page middleware processing. +* `Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware`: Logs related to exception handling and error response generation. +* `Microsoft.AspNetCore.Diagnostics.StatusCodePageMiddleware`: Logs related to status code page middleware and response handling. + +Host Filtering + +* `Microsoft.AspNetCore.HostFiltering`: Hosts allowed and denied by the host filtering middleware. +* `Microsoft.AspNetCore.HostFiltering.HostFilteringMiddleware`: Logs related to the host filtering middleware, including allowed and denied hosts. +* `Microsoft.AspNetCore.HostFiltering.HostFilteringOptions`: Logs concerning options for the HostFiltering middleware. + +Hosting + +* `Microsoft.AspNetCore.Hosting.Lifetime`: Logs related to the lifecycle of the web host, including starting and stopping events. +* `Microsoft.AspNetCore.Hosting.Diagnostics`: Logs diagnostics information, such as application startup and shutdown. +* `Microsoft.AspNetCore.Hosting.RequestDelegate`: Logs related to the handling of HTTP requests by the application pipeline. +* `Microsoft.AspNetCore.Hosting.Internal.WebHost`: Internal logs from the web host, useful for debugging host-related issues. +* `Microsoft.AspNetCore.Hosting.Internal.HostedServiceExecutor`: Logs concerning the execution of hosted services by the web host. + +HTTP + +* `Microsoft.AspNetCore.Http.ConnectionLogging`: Related to HTTP connections, including connection establishment and termination. +* `Microsoft.AspNetCore.Http.DefaultHttpContext`: Logs related to the creation and usage of HttpContext instances. +* `Microsoft.AspNetCore.Http.Endpoints.EndpointMiddleware`: Logs about endpoint routing and middleware execution. +* `Microsoft.AspNetCore.Http.Response`: Logs related to HTTP response processing. + +HTTPS + +* `Microsoft.AspNetCore.HttpsPolicy`: Logs from HTTPS redirection middleware, policy enforcement and and HTTP Strict-Transport-Security (HSTS). +* `Microsoft.AspNetCore.HttpsPolicy.HstsMiddleware`: Logs specific to HTTP Strict-Transport-Security (HSTS) middleware processing. +* `Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware`: Logs related to HTTPS redirection middleware execution. +* `Microsoft.AspNetCore.HttpsPolicy.HstsOptions`: Logs concerning HSTS policy configuration and enforcement. + +Identity + +* `Microsoft.AspNetCore.Identity`: Logs from the ASP.NET Core Identity framework, including user management and identity operations. +* `Microsoft.AspNetCore.Identity.RoleManager`: Logs related to role management operations. +* `Microsoft.AspNetCore.Identity.UserManager`: Logs concerning user management activities and lifecycle events. + +Kestrel + +* `Microsoft.AspNetCore.Server.Kestrel`: Logs from the Kestrel web server, covering connection handling and request processing. +* `Microsoft.AspNetCore.Server.Kestrel.Core`: Logs related to core Kestrel operations, such as configuration and resource management. +* `Microsoft.AspNetCore.Server.Kestrel.Transport`: Logs specific to network transport layers used by Kestrel. + +Logging + +* `Microsoft.Extensions.Logging`: Logs from the logging extensions API. +* `Microsoft.Extensions.Logging.Console`: Logs specific to the Console logger. + +MVC + +* `Microsoft.AspNetCore.Mvc`: General logs from MVC framework components, including controller and action execution. +* `Microsoft.AspNetCore.Mvc.Infrastructure`: Logs related to the infrastructure and support services for MVC, such as model binding and action filters. +* `Microsoft.AspNetCore.Mvc.ModelBinding`: Logs concerning model binding operations and data validation. +* `Microsoft.AspNetCore.Mvc.Filters`: Logs about the execution of action filters and filter pipelines. +* `Microsoft.AspNetCore.Mvc.Razor`: Logs specific to Razor view rendering and compilation. +* `Microsoft.AspNetCore.Mvc.ViewFeatures`: Logs concerning view rendering and related features like view components and tag helpers. + +Routing + +* `Microsoft.AspNetCore.Routing.EndpointMiddleware`: Logs related to the routing of HTTP requests to endpoints. +* `Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware`: Logs about the endpoint routing middleware handling requests. +* `Microsoft.AspNetCore.Routing.Matching.DataSourceDependentMatcher`: Logs concerning route matching and selection of endpoints. +* `Microsoft.AspNetCore.Routing.Matching.DfaMatcher`: Logs specific to the DFA (Deterministic Finite Automaton) routing matcher. + +SignalR + +* `Microsoft.AspNetCore.SignalR`: Logs from the SignalR framework, including hub connections and message handling. +* `Microsoft.AspNetCore.SignalR.Hub`: Logs specific to hub invocation and message dispatching. +* `Microsoft.AspNetCore.SignalR.Transports`: Logs related to transport mechanisms used by SignalR. + +Static files + +* `Microsoft.AspNetCore.StaticFiles`: Logs from the static files middleware, including file serving and cache operations. +* `Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware`: Logs related to static file middleware execution and file response handling. ## Additional resources +* * [Improving logging performance with source generators](https://andrewlock.net/exploring-dotnet-6-part-8-improving-logging-performance-with-source-generators/) * [Behind `[LogProperties]` and the new telemetry logging source generator](https://andrewlock.net/behind-logproperties-and-the-new-telemetry-logging-source-generator/) -* [Microsoft.Extensions.Logging source on GitHub](https://github.com/dotnet/runtime/tree/main/src/libraries/Microsoft.Extensions.Logging) -* [View or download sample code](https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/fundamentals/logging/index/samples/6.x) ([how to download](xref:fundamentals/index#how-to-download-a-sample)). +* [`Microsoft.Extensions.Logging` reference source (`dotnet/runtime`) GitHub repository](https://github.com/dotnet/runtime/tree/main/src/libraries/Microsoft.Extensions.Logging) * [High performance logging](/dotnet/core/extensions/high-performance-logging) -* Logging bugs should be created in the [`dotnet/runtime`](https://github.com/dotnet/runtime/issues) GitHub repository. -* - -:::moniker-end - -[!INCLUDE[](~/fundamentals/logging/index/includes/index5.md)] +* [View or download sample code](https://github.com/dotnet/AspNetCore.Docs.Samples/tree/main/fundamentals/logging) ([how to download](xref:fundamentals/index#how-to-download-a-sample)) diff --git a/aspnetcore/fundamentals/logging/index/includes/index5.md b/aspnetcore/fundamentals/logging/index/includes/index5.md deleted file mode 100644 index 0a73787279b6..000000000000 --- a/aspnetcore/fundamentals/logging/index/includes/index5.md +++ /dev/null @@ -1,943 +0,0 @@ -:::moniker range="< aspnetcore-6.0" - -By [Kirk Larkin](https://twitter.com/serpent5), [Juergen Gutsch](https://github.com/JuergenGutsch), and [Rick Anderson](https://twitter.com/RickAndMSFT) - -This topic describes logging in .NET as it applies to ASP.NET Core apps. For detailed information on logging in .NET, see [Logging in .NET](/dotnet/core/extensions/logging). For more information on logging in Blazor apps, see . - -[View or download sample code](https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/fundamentals/logging/index/samples/3.x) ([how to download](xref:fundamentals/index#how-to-download-a-sample)). - - - -## Logging providers - -Logging providers store logs, except for the `Console` provider which displays logs. For example, the Azure Application Insights provider stores logs in Azure Application Insights. Multiple providers can be enabled. - -The default ASP.NET Core web app templates: - -* Use the [Generic Host](xref:fundamentals/host/generic-host). -* Call , which adds the following logging providers: - * [Console](#console) - * [Debug](#debug) - * [EventSource](#event-source) - * [EventLog](#welog): Windows only - -[!code-csharp[](~/fundamentals/logging/index/samples/3.x/TodoApiDTO/Program.cs?name=snippet_TemplateCode&highlight=9)] - -The preceding code shows the `Program` class created with the ASP.NET Core web app templates. The next several sections provide samples based on the ASP.NET Core web app templates, which use the Generic Host. [Non-host console apps](#nhca) are discussed later in this document. - -To override the default set of logging providers added by `Host.CreateDefaultBuilder`, call `ClearProviders` and add the required logging providers. For example, the following code: - -* Calls to remove all the instances from the builder. -* Adds the [Console](#console) logging provider. - -[!code-csharp[](~/fundamentals/logging/index/samples/3.x/TodoApiDTO/Program.cs?name=snippet_AddProvider&highlight=5-6)] - -For additional providers, see: - -* [Built-in logging providers](#bilp) -* [Third-party logging providers](#third-party-logging-providers). - -## Create logs - -To create logs, use an object from [dependency injection](xref:fundamentals/dependency-injection) (DI). - -The following example: - -* Creates a logger, `ILogger`, which uses a log *category* of the fully qualified name of the type `AboutModel`. The log category is a string that is associated with each log. -* Calls to log at the `Information` level. The Log *level* indicates the severity of the logged event. - -[!code-csharp[](~/fundamentals/logging/index/samples/3.x/TodoApiDTO/Pages/About.cshtml.cs?name=snippet_CallLogMethods&highlight=5,14)] - -[Levels](#log-level) and [categories](#log-category) are explained in more detail later in this document. - -For information on Blazor, see . - -[Create logs in Main and Startup](#clms) shows how to create logs in `Main` and `Startup`. - -## Configure logging - -Logging configuration is commonly provided by the `Logging` section of `appsettings.{Environment}.json` files. The following `appsettings.Development.json` file is generated by the ASP.NET Core web app templates: - -[!code-json[](~/fundamentals/logging/index/samples/3.x/TodoApiDTO/appsettings.Development.json)] - -In the preceding JSON: - -* The `"Default"`, `"Microsoft"`, and `"Microsoft.Hosting.Lifetime"` categories are specified. -* The `"Microsoft"` category applies to all categories that start with `"Microsoft"`. For example, this setting applies to the `"Microsoft.AspNetCore.Routing.EndpointMiddleware"` category. -* The `"Microsoft"` category logs at log level `Warning` and higher. -* The `"Microsoft.Hosting.Lifetime"` category is more specific than the `"Microsoft"` category, so the `"Microsoft.Hosting.Lifetime"` category logs at log level "Information" and higher. -* A specific log provider is not specified, so `LogLevel` applies to all the enabled logging providers except for the [Windows EventLog](#welog). - -The `Logging` property can have and log provider properties. The `LogLevel` specifies the minimum [level](#log-level) to log for selected categories. In the preceding JSON, `Information` and `Warning` log levels are specified. `LogLevel` indicates the severity of the log and ranges from 0 to 6: - -`Trace` = 0, `Debug` = 1, `Information` = 2, `Warning` = 3, `Error` = 4, `Critical` = 5, and `None` = 6. - -When a `LogLevel` is specified, logging is enabled for messages at the specified level and higher. In the preceding JSON, the `Default` category is logged for `Information` and higher. For example, `Information`, `Warning`, `Error`, and `Critical` messages are logged. If no `LogLevel` is specified, logging defaults to the `Information` level. For more information, see [Log levels](#llvl). - -A provider property can specify a `LogLevel` property. `LogLevel` under a provider specifies levels to log for that provider, and overrides the non-provider log settings. Consider the following `appsettings.json` file: - -[!code-json[](~/fundamentals/logging/index/samples/3.x/TodoApiDTO/appsettings.Prod2.json)] - -Settings in `Logging.{providername}.LogLevel` override settings in `Logging.LogLevel`. In the preceding JSON, the `Debug` provider's default log level is set to `Information`: - -`Logging:Debug:LogLevel:Default:Information` - -The preceding setting specifies the `Information` log level for every `Logging:Debug:` category except `Microsoft.Hosting`. When a specific category is listed, the specific category overrides the default category. In the preceding JSON, the `Logging:Debug:LogLevel` categories `"Microsoft.Hosting"` and `"Default"` override the settings in `Logging:LogLevel` - -The minimum log level can be specified for any of: - -* Specific providers: For example, `Logging:EventSource:LogLevel:Default:Information` -* Specific categories: For example, `Logging:LogLevel:Microsoft:Warning` -* All providers and all categories: `Logging:LogLevel:Default:Warning` - -Any logs below the minimum level are ***not***: - -* Passed to the provider. -* Logged or displayed. - -To suppress all logs, specify [LogLevel.None](xref:Microsoft.Extensions.Logging.LogLevel). `LogLevel.None` has a value of 6, which is higher than `LogLevel.Critical` (5). - -If a provider supports [log scopes](#logscopes), `IncludeScopes` indicates whether they're enabled. For more information, see [log scopes](#logscopes) - -The following `appsettings.json` file contains all the providers enabled by default: - -[!code-json[](~/fundamentals/logging/index/samples/3.x/TodoApiDTO/appsettings.Production.json)] - -In the preceding sample: - -* The categories and levels are not suggested values. The sample is provided to show all the default providers. -* Settings in `Logging.{providername}.LogLevel` override settings in `Logging.LogLevel`. For example, the level in `Debug.LogLevel.Default` overrides the level in `LogLevel.Default`. -* Each default provider *alias* is used. Each provider defines an *alias* that can be used in configuration in place of the fully qualified type name. The built-in providers aliases are: - * Console - * Debug - * EventSource - * EventLog - * AzureAppServicesFile - * AzureAppServicesBlob - * ApplicationInsights - -## Set log level by command line, environment variables, and other configuration - -Log level can be set by any of the [configuration providers](xref:fundamentals/configuration/index). - -[!INCLUDE[](~/includes/environmentVarableColon.md)] - -The following commands: - -* Set the environment key `Logging:LogLevel:Microsoft` to a value of `Information` on Windows. -* Test the settings when using an app created with the ASP.NET Core web application templates. The `dotnet run` command must be run in the project directory after using `set`. - -```dotnetcli -set Logging__LogLevel__Microsoft=Information -dotnet run -``` - -The preceding environment setting: - -* Is only set in processes launched from the command window they were set in. -* Isn't read by browsers launched with Visual Studio. - -The following [setx](/windows-server/administration/windows-commands/setx) command also sets the environment key and value on Windows. Unlike `set`, `setx` settings are persisted. The `/M` switch sets the variable in the system environment. If `/M` isn't used, a user environment variable is set. - -```console -setx Logging__LogLevel__Microsoft Information /M -``` - -Consider the following `appsettings.json` file: - -```json -"Logging": { - "Console": { - "LogLevel": { - "Microsoft.Hosting.Lifetime": "Trace" - } - } -} -``` - -The following command sets the preceding configuration in the environment: - -```console -setx Logging__Console__LogLevel__Microsoft.Hosting.Lifetime Trace /M -``` - -On [Azure App Service](https://azure.microsoft.com/services/app-service/), select **New application setting** on the **Settings > Configuration** page. Azure App Service application settings are: - -* Encrypted at rest and transmitted over an encrypted channel. -* Exposed as environment variables. - -For more information, see [Azure Apps: Override app configuration using the Azure Portal](xref:host-and-deploy/azure-apps/index#override-app-configuration-using-the-azure-portal). - -For more information on setting ASP.NET Core configuration values using environment variables, see [environment variables](xref:fundamentals/configuration/index#environment-variables). For information on using other configuration sources, including the command line, Azure Key Vault, Azure App Configuration, other file formats, and more, see . - -## How filtering rules are applied - -When an object is created, the object selects a single rule per provider to apply to that logger. All messages written by an `ILogger` instance are filtered based on the selected rules. The most specific rule for each provider and category pair is selected from the available rules. - -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. -* If no rules are selected, use `MinimumLevel`. - - - -## Logging output from dotnet run and Visual Studio - -Logs created with the [default logging providers](#lp) are displayed: - -* In Visual Studio - * In the Debug output window when debugging. - * In the ASP.NET Core Web Server window. -* In the console window when the app is run with `dotnet run`. - -Logs that begin with "Microsoft" categories are from ASP.NET Core framework code. ASP.NET Core and application code use the same logging API and providers. - - - -## Log category - -When an `ILogger` object is created, a *category* is specified. That category is included with each log message created by that instance of `ILogger`. The category string is arbitrary, but the convention is to use the class name. For example, in a controller the name might be `"TodoApi.Controllers.TodoController"`. The ASP.NET Core web apps use `ILogger` to automatically get an `ILogger` instance that uses the fully qualified type name of `T` as the category: - -[!code-csharp[](~/fundamentals/logging/index/samples/3.x/TodoApiDTO/Pages/Privacy.cshtml.cs?name=snippet)] - -To explicitly specify the category, call `ILoggerFactory.CreateLogger`: - -[!code-csharp[](~/fundamentals/logging/index/samples/3.x/TodoApiDTO/Pages/Contact.cshtml.cs?name=snippet)] - -Calling `CreateLogger` with a fixed name can be useful when used in multiple methods so the events can be organized by category. - -`ILogger` is equivalent to calling `CreateLogger` with the fully qualified type name of `T`. - - - -## Log level - -The following table lists the values, the convenience `Log{LogLevel}` extension method, and the suggested usage: - -| LogLevel | Value | Method | Description | -| -------- | ----- | ------ | ----------- | -| [Trace](xref:Microsoft.Extensions.Logging.LogLevel) | 0 | | Contain the most detailed messages. These messages may contain sensitive app data. These messages are disabled by default and should ***not*** be enabled in production. | -| [Debug](xref:Microsoft.Extensions.Logging.LogLevel) | 1 | | For debugging and development. Use with caution in production due to the high volume. | -| [Information](xref:Microsoft.Extensions.Logging.LogLevel) | 2 | | Tracks the general flow of the app. May have long-term value. | -| [Warning](xref:Microsoft.Extensions.Logging.LogLevel) | 3 | | For abnormal or unexpected events. Typically includes errors or conditions that don't cause the app to fail. | -| [Error](xref:Microsoft.Extensions.Logging.LogLevel) | 4 | | For errors and exceptions that cannot be handled. These messages indicate a failure in the current operation or request, not an app-wide failure. | -| [Critical](xref:Microsoft.Extensions.Logging.LogLevel) | 5 | | For failures that require immediate attention. Examples: data loss scenarios, out of disk space. | -| [None](xref:Microsoft.Extensions.Logging.LogLevel) | 6 | | Specifies that a logging category should not write any messages. | - -In the previous table, the `LogLevel` is listed from lowest to highest severity. - -The [Log](xref:Microsoft.Extensions.Logging.LoggerExtensions) method's first parameter, , indicates the severity of the log. Rather than calling `Log(LogLevel, ...)`, most developers call the [Log{LogLevel}](xref:Microsoft.Extensions.Logging.LoggerExtensions) extension methods. The `Log{LogLevel}` extension methods [call the Log method and specify the LogLevel](https://github.com/dotnet/extensions/blob/release/3.1/src/Logging/Logging.Abstractions/src/LoggerExtensions.cs). For example, the following two logging calls are functionally equivalent and produce the same log: - -[!code-csharp[](~/fundamentals/logging/index/samples/3.x/TodoApiDTO/Controllers/TestController.cs?name=snippet0&highlight=6-7)] - -`MyLogEvents.TestItem` is the event ID. `MyLogEvents` is part of the sample app and is displayed in the [Log event ID](#leid) section. - -[!INCLUDE[](~/includes/MyDisplayRouteInfoBoth.md)] - -The following code creates `Information` and `Warning` logs: - -[!code-csharp[](~/fundamentals/logging/index/samples/3.x/TodoApiDTO/Controllers/TodoItemsController.cs?name=snippet_CallLogMethods&highlight=4,10)] - -In the preceding code, the first `Log{LogLevel}` parameter,`MyLogEvents.GetItem`, is the [Log event ID](#leid). 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](#lmt) section later in this document. - -Call the appropriate `Log{LogLevel}` method to control how much log output is written to a particular storage medium. For example: - -* In production: - * Logging at the `Trace` or `Information` levels produces a high-volume of detailed log messages. To control costs and not exceed data storage limits, log `Trace` and `Information` level messages to a high-volume, low-cost data store. Consider limiting `Trace` and `Information` to specific categories. - * Logging at `Warning` through `Critical` levels should produce few log messages. - * Costs and storage limits usually aren't a concern. - * Few logs allow more flexibility in data store choices. -* In development: - * Set to `Warning`. - * Add `Trace` or `Information` messages when troubleshooting. To limit output, set `Trace` or `Information` only for the categories under investigation. - -ASP.NET Core writes logs for framework events. For example, consider the log output for: - -* A Razor Pages app created with the ASP.NET Core templates. -* Logging set to `Logging:Console:LogLevel:Microsoft:Information` -* Navigation to the Privacy page: - -```console -info: Microsoft.AspNetCore.Hosting.Diagnostics[1] - Request starting HTTP/2 GET https://localhost:5001/Privacy -info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0] - Executing endpoint '/Privacy' -info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[3] - Route matched with {page = "/Privacy"}. Executing page /Privacy -info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[101] - Executing handler method DefaultRP.Pages.PrivacyModel.OnGet - ModelState is Valid -info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[102] - Executed handler method OnGet, returned result . -info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[103] - Executing an implicit handler method - ModelState is Valid -info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[104] - Executed an implicit handler method, returned result Microsoft.AspNetCore.Mvc.RazorPages.PageResult. -info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[4] - Executed page /Privacy in 74.5188ms -info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1] - Executed endpoint '/Privacy' -info: Microsoft.AspNetCore.Hosting.Diagnostics[2] - Request finished in 149.3023ms 200 text/html; charset=utf-8 -``` - -The following JSON sets `Logging:Console:LogLevel:Microsoft:Information`: - -[!code-json[](~/fundamentals/logging/index/samples/3.x/TodoApiDTO/appsettings.MSFT.json)] - - - -## Log event ID - -Each log can specify an *event ID*. The sample app uses the `MyLogEvents` class to define event IDs: - - -[!code-csharp[](~/fundamentals/logging/index/samples/3.x/TodoApiDTO/Models/MyLogEvents.cs?name=snippet_LoggingEvents)] - -[!code-csharp[](~/fundamentals/logging/index/samples/3.x/TodoApiDTO/Controllers/TodoItemsController.cs?name=snippet_CallLogMethods&highlight=4,10)] - -An event ID associates a set of events. 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: - -```console -info: TodoApi.Controllers.TodoItemsController[1002] - Getting item 1 -warn: TodoApi.Controllers.TodoItemsController[4000] - Get(1) NOT FOUND -``` - -Some logging providers store the event ID in a field, which allows for filtering on the ID. - - - -## Log message template - -Each log API uses a message template. The message template can contain placeholders for which arguments are provided. Use names for the placeholders, not numbers. - -[!code-csharp[](~/fundamentals/logging/index/samples/3.x/TodoApiDTO/Controllers/TodoItemsController.cs?name=snippet_CallLogMethods&highlight=4,10)] - -The *order of the parameters*, not their placeholder names, determines which parameters are used to provide placeholder values in log messages. In the following code, the parameter names are out of sequence in the placeholders of the message template: - -```csharp -var apples = 1; -var pears = 2; -var bananas = 3; - -_logger.LogInformation("Parameters: {pears}, {bananas}, {apples}", apples, pears, bananas); -``` - -However, the parameters are assigned to the placeholders in the order: `apples`, `pears`, `bananas`. The log message reflects the *order of the parameters*: - -```text -Parameters: 1, 2, 3 -``` - -This approach allows logging providers to implement [semantic or structured logging](https://github.com/NLog/NLog/wiki/How-to-use-structured-logging). The arguments themselves are passed to the logging system, not just the formatted message template. This enables logging providers to store the parameter values as fields. For example, consider the following logger method: - -```csharp -_logger.LogInformation("Getting item {Id} at {RequestTime}", id, DateTime.Now); -``` - -For example, when logging to Azure Table Storage: - -* Each Azure Table entity can have `ID` and `RequestTime` properties. -* Tables with properties simplify queries on logged data. For example, a query can find all logs within a particular `RequestTime` range without having to parse the time out of the text message. - -## Log exceptions - -The logger methods have overloads that take an exception parameter: - -[!code-csharp[](~/fundamentals/logging/index/samples/3.x/TodoApiDTO/Controllers/TestController.cs?name=snippet_Exp)] - -[!INCLUDE[](~/includes/MyDisplayRouteInfoBoth.md)] - -Exception logging is provider-specific. - -### Default log level - -If the default log level is not set, the default log level value is `Information`. - -For example, consider the following web app: - -* Created with the ASP.NET web app templates. -* `appsettings.json` and `appsettings.Development.json` deleted or renamed. - -With the preceding setup, navigating to the privacy or home page produces many `Trace`, `Debug`, and `Information` messages with `Microsoft` in the category name. - -The following code sets the default log level when the default log level is not set in configuration: - -[!code-csharp[](~/fundamentals/logging/index/samples/3.x/MyMain/Program.cs?name=snippet_MinLevel&highlight=10)] - - -Generally, log levels should be specified in configuration and not code. - -### Filter function - -A filter function is invoked for all providers and categories that don't have rules assigned to them by configuration or code: - -[!code-csharp[](~/fundamentals/logging/index/samples/3.x/MyMain/Program.cs?name=snippet_FilterFunction)] - -The preceding code displays console logs when the category contains `Controller` or `Microsoft` and the log level is `Information` or higher. - -Generally, log levels should be specified in configuration and not code. - -## ASP.NET Core and EF Core categories - -The following table contains some categories used by ASP.NET Core and Entity Framework Core, with notes about the logs: - -| Category | Notes | -| ----------------------------------- | ----- | -| Microsoft.AspNetCore | General ASP.NET Core diagnostics. | -| Microsoft.AspNetCore.DataProtection | Which keys were considered, found, and used. | -| Microsoft.AspNetCore.HostFiltering | Hosts allowed. | -| Microsoft.AspNetCore.Hosting | How long HTTP requests took to complete and what time they started. Which hosting startup assemblies were loaded. | -| Microsoft.AspNetCore.Mvc | MVC and Razor diagnostics. Model binding, filter execution, view compilation, action selection. | -| Microsoft.AspNetCore.Routing | Route matching information. | -| Microsoft.AspNetCore.Server | Connection start, stop, and keep alive responses. HTTPS certificate information. | -| Microsoft.AspNetCore.StaticFiles | Files served. | -| Microsoft.EntityFrameworkCore | General Entity Framework Core diagnostics. Database activity and configuration, change detection, migrations. | - -To view more categories in the console window, set *`appsettings.Development.json`* to the following: - -[!code-json[](~/fundamentals/logging/index/samples/3.x/MyMain/appsettings.Trace.json)] - - - - - -## 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. - -A scope: - -* Is an type that's returned by the method. -* Lasts until it's disposed. - -The following providers support scopes: - -* `Console` -* [AzureAppServicesFile and AzureAppServicesBlob](xref:Microsoft.Extensions.Logging.AzureAppServices.BatchingLoggerOptions.IncludeScopes) - -Use a scope by wrapping logger calls in a `using` block: - -[!code-csharp[](~/fundamentals/logging/index/samples/3.x/TodoApiDTO/Controllers/TestController.cs?name=snippet_Scopes)] - - - -## Built-in logging providers - -ASP.NET Core includes the following logging providers as part of the shared framework: - -* [Console](#console) -* [Debug](#debug) -* [EventSource](#event-source) -* [EventLog](#welog) - -The following logging providers are shipped by Microsoft, but not as part of the -shared framework. They must be installed as additional nuget. - -* [AzureAppServicesFile and AzureAppServicesBlob](#azure-app-service) -* [ApplicationInsights](#azure-application-insights) - -ASP.NET Core doesn't include a logging provider for writing logs to files. To write logs to files from an ASP.NET Core app, consider using a [third-party logging provider](#third-party-logging-providers). - -For information on `stdout` and debug logging with the ASP.NET Core Module, see and . - -### Console - -The `Console` provider logs output to the console. For more information on viewing `Console` logs in development, see [Logging output from dotnet run and Visual Studio](#dnrvs). - -### Debug - -The `Debug` provider writes log output by using the class. Calls to `System.Diagnostics.Debug.WriteLine` write to the `Debug` provider. - -On Linux, the `Debug` provider log location is distribution-dependent and may be one of the following: - -* */var/log/message* -* */var/log/syslog* - -### Event Source - -The `EventSource` provider writes to a cross-platform event source with the name `Microsoft-Extensions-Logging`. On Windows, the provider uses [ETW](/windows/win32/etw/event-tracing-portal). - -#### dotnet trace tooling - -The [dotnet-trace](/dotnet/core/diagnostics/dotnet-trace) tool is a cross-platform CLI global tool that enables the collection of .NET Core traces of a running process. The tool collects provider data using a . - -See [dotnet-trace](/dotnet/core/diagnostics/dotnet-trace) for installation instructions. - -Use the dotnet trace tooling to collect a trace from an app: - -1. Run the app with the `dotnet run` command. -1. Determine the process identifier (PID) of the .NET Core app: - - ```dotnetcli - dotnet trace ps - ``` - - Find the PID for the process that has the same name as the app's assembly. - -1. Execute the `dotnet trace` command. - - General command syntax: - - ```dotnetcli - dotnet trace collect -p {PID} - --providers Microsoft-Extensions-Logging:{Keyword}:{Provider Level} - :FilterSpecs=\" - {Logger Category 1}:{Category Level 1}; - {Logger Category 2}:{Category Level 2}; - ... - {Logger Category N}:{Category Level N}\" - ``` - - When using a PowerShell command shell, enclose the `--providers` value in single quotes (`'`): - - ```dotnetcli - dotnet trace collect -p {PID} - --providers 'Microsoft-Extensions-Logging:{Keyword}:{Provider Level} - :FilterSpecs=\" - {Logger Category 1}:{Category Level 1}; - {Logger Category 2}:{Category Level 2}; - ... - {Logger Category N}:{Category Level N}\"' - ``` - - On non-Windows platforms, add the `-f speedscope` option to change the format of the output trace file to `speedscope`. - - The following table defines the Keyword: - - | Keyword | Description | - | :-----: | ----------- | - | 1 | Log meta events about the `LoggingEventSource`. Doesn't log events from `ILogger`. | - | 2 | Turns on the `Message` event when `ILogger.Log()` is called. Provides information in a programmatic (not formatted) way. | - | 4 | Turns on the `FormatMessage` event when `ILogger.Log()` is called. Provides the formatted string version of the information. | - | 8 | Turns on the `MessageJson` event when `ILogger.Log()` is called. Provides a JSON representation of the arguments. | - - The following table lists the provider levels: - - | Provider Level | Description | - | :---------: | --------------- | - | 0 | `LogAlways` | - | 1 | `Critical` | - | 2 | `Error` | - | 3 | `Warning` | - | 4 | `Informational` | - | 5 | `Verbose` | - - The parsing for a category level can be either a string or a number: - - | Category named value | Numeric value | - | :-----: | ----------- | - | `Trace` | 0 | - | `Debug` | 1 | - | `Information` | 2 | - | `Warning` | 3 | - | `Error` | 4 | - | `Critical` | 5 | - - The provider level and category level: - - * Are in reverse order. - * The string constants aren't all identical. - - If no `FilterSpecs` are specified then the `EventSourceLogger` implementation attempts to convert the provider level to a category level and applies it to all categories. - - | Provider Level | Category Level | - | :-----: | ----------- | - | `Verbose`(5) | `Debug`(1) | - | `Informational`(4) | `Information`(2) | - | `Warning`(3) | `Warning`(3) | - | `Error`(2) | `Error`(4) | - | `Critical`(1) | `Critical`(5) | - - If `FilterSpecs` are provided, any category that is included in the list uses the category level encoded there, all other categories are filtered out. - - The following examples assume: - - * An app is running and calling `logger.LogDebug("12345")`. - * The process ID (PID) has been set via `set PID=12345`, where `12345` is the actual PID. - - Consider the following command: - - ```dotnetcli - dotnet trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:5 - ``` - - The preceding command: - - * Captures debug messages. - * Doesn't apply a `FilterSpecs`. - * Specifies level 5 which maps category Debug. - - Consider the following command: - - ```dotnetcli - dotnet trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:5:\"FilterSpecs=*:5\" - ``` - - The preceding command: - - * Doesn't capture debug messages because the category level 5 is `Critical`. - * Provides a `FilterSpecs`. - - The following command captures debug messages because category level 1 specifies `Debug`. - - ```dotnetcli - dotnet trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:5:\"FilterSpecs=*:1\" - ``` - - The following command captures debug messages because category specifies `Debug`. - - ```dotnetcli - dotnet trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:5:\"FilterSpecs=*:Debug\" - ``` - - `FilterSpecs` entries for `{Logger Category}` and `{Category Level}` represent additional log filtering conditions. Separate `FilterSpecs` entries with the `;` semicolon character. - - Example using a Windows command shell: - - ```dotnetcli - dotnet trace collect -p %PID% --providers Microsoft-Extensions-Logging:4:2:FilterSpecs=\"Microsoft.AspNetCore.Hosting*:4\" - ``` - - The preceding command activates: - - * The Event Source logger to produce formatted strings (`4`) for errors (`2`). - * `Microsoft.AspNetCore.Hosting` logging at the `Informational` logging level (`4`). - -1. Stop the dotnet trace tooling by pressing the Enter key or Ctrl+C. - - The trace is saved with the name *trace.nettrace* in the folder where the `dotnet trace` command is executed. - -1. Open the trace with [Perfview](#perfview). Open the *trace.nettrace* file and explore the trace events. - -If the app doesn't build the host with `CreateDefaultBuilder`, add the Event Source provider to the app's logging configuration. - -For more information, see: - -* [Trace for performance analysis utility (dotnet-trace)](/dotnet/core/diagnostics/dotnet-trace) (.NET Core documentation) -* [Trace for performance analysis utility (dotnet-trace)](https://github.com/dotnet/diagnostics/blob/main/documentation/dotnet-trace-instructions.md) (dotnet/diagnostics GitHub repository documentation) -* [LoggingEventSource Class](xref:Microsoft.Extensions.Logging.EventSource.LoggingEventSource) (.NET API Browser) -* -* [LoggingEventSource reference source (3.0)](https://github.com/dotnet/extensions/blob/release/3.1/src/Logging/Logging.EventSource/src/LoggingEventSource.cs): To obtain reference source for a different version, change the branch to `release/{Version}`, where `{Version}` is the version of ASP.NET Core desired. -* [Perfview](#perfview): Useful for viewing Event Source traces. - -#### Perfview - -Use the [PerfView utility](https://github.com/Microsoft/perfview) to collect and view logs. 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. - -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 `*` at the start of the string. - - - -### Windows EventLog - -The `EventLog` provider sends log output to the Windows Event Log. Unlike the other providers, the `EventLog` provider does ***not*** inherit the default non-provider settings. If `EventLog` log settings aren't specified, they [default to LogLevel.Warning](https://github.com/dotnet/extensions/blob/release/3.1/src/Hosting/Hosting/src/Host.cs#L99-L103). - -To log events lower than , explicitly set the log level. The following example sets the Event Log default log level to : - -```json -"Logging": { - "EventLog": { - "LogLevel": { - "Default": "Information" - } - } -} -``` - -[AddEventLog overloads](xref:Microsoft.Extensions.Logging.EventLoggerFactoryExtensions) can pass in . If `null` or not specified, the following default settings are used: - -* `LogName`: "Application" -* `SourceName`: ".NET Runtime" -* `MachineName`: The local machine name is used. - -The following code changes the `SourceName` from the default value of `".NET Runtime"` to `MyLogs`: - -[!code-csharp[](~/fundamentals/logging/index/samples/3.x/MyMain/Program.cs?name=snippetEventLog)] - -### Azure App Service - -The [Microsoft.Extensions.Logging.AzureAppServices](https://www.nuget.org/packages/Microsoft.Extensions.Logging.AzureAppServices) provider package writes logs to text files in an Azure App Service app's file system and to [blob storage](/azure/storage/blobs/storage-quickstart-blobs-dotnet#what-is-blob-storage) in an Azure Storage account. - -The provider package isn't included in the shared framework. To use the provider, add the provider package to the project. - -To configure provider settings, use and , as shown in the following example: - -[!code-csharp[](~/fundamentals/logging/index/samples/3.x/MyMain/Program.cs?name=snippet_AzLogOptions)] - -When deployed to Azure App Service, the app uses the settings in the [App Service logs](/azure/app-service/troubleshoot-diagnostic-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)** -* **Application Logging (Blob)** - -The default location for log files is in the *D:\\home\\LogFiles\\Application* folder, and the default file name is *diagnostics-yyyymmdd.txt*. The default file size limit is 10 MB, and the default maximum number of files retained is 2. The default blob name is *{app-name}{timestamp}/yyyy/mm/dd/hh/{guid}-applicationLog.txt*. - -This provider only logs when the project runs in the Azure environment. - -#### Azure log streaming - -Azure log streaming supports viewing log activity in real time from: - -* The app server -* The web server -* Failed request tracing - -To configure Azure log streaming: - -* Navigate to the **App Service logs** page from the app's portal page. -* Set **Application Logging (Filesystem)** to **On**. -* Choose the log **Level**. This setting only applies to Azure log streaming. - -Navigate to the **Log Stream** page to view logs. The logged messages are logged with the `ILogger` interface. - -### Azure Application Insights - -The [Microsoft.Extensions.Logging.ApplicationInsights](https://www.nuget.org/packages/Microsoft.Extensions.Logging.ApplicationInsights) provider package writes logs to [Azure Application Insights](/azure/azure-monitor/app/cloudservices). Application Insights is a service that monitors a web app and provides tools for querying and analyzing the telemetry data. If you use this provider, you can query and analyze your logs by using the Application Insights tools. - -The logging provider is included as a dependency of [Microsoft.ApplicationInsights.AspNetCore](https://www.nuget.org/packages/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. - -The [Microsoft.ApplicationInsights.Web](https://www.nuget.org/packages/Microsoft.ApplicationInsights.Web) package is for ASP.NET 4.x, not ASP.NET Core. - -For more information, see the following resources: - -* [Application Insights overview](/azure/application-insights/app-insights-overview) -* [Application Insights for ASP.NET Core applications](/azure/azure-monitor/app/asp-net-core) - Start here if you want to implement the full range of Application Insights telemetry along with logging. -* [ApplicationInsightsLoggerProvider for .NET Core ILogger logs](/azure/azure-monitor/app/ilogger) - Start here if you want to implement the logging provider without the rest of Application Insights telemetry. -* [Application Insights logging adapters](/azure/azure-monitor/app/asp-net-trace-logs). -* [Install, configure, and initialize the Application Insights SDK](/training/modules/instrument-web-app-code-with-application-insights) interactive tutorial. - -## Third-party logging providers - -Third-party logging frameworks that work with ASP.NET Core: - -* [elmah.io](https://elmah.io/) ([GitHub repo](https://github.com/elmahio/Elmah.Io.Extensions.Logging)) -* [Gelf](https://go2docs.graylog.org/5-0/getting_in_log_data/gelf.html) ([GitHub repo](https://github.com/mattwcole/gelf-extensions-logging)) -* [JSNLog](https://jsnlog.com/) ([GitHub repo](https://github.com/mperdeck/jsnlog)) -* [KissLog.net](https://kisslog.net/) ([GitHub repo](https://github.com/catalingavan/KissLog-net)) -* [Log4Net](https://logging.apache.org/log4net/) ([GitHub repo](https://github.com/huorswords/Microsoft.Extensions.Logging.Log4Net.AspNetCore)) -* [NLog](https://nlog-project.org/) ([GitHub repo](https://github.com/NLog/NLog.Extensions.Logging)) -* [PLogger](https://www.nuget.org/packages/InvertedSoftware.PLogger.Core/) ([GitHub repo](https://github.com/invertedsoftware/InvertedSoftware.PLogger.Core)) -* [Sentry](https://sentry.io/welcome/) ([GitHub repo](https://github.com/getsentry/sentry-dotnet)) -* [Serilog](https://serilog.net/) ([GitHub repo](https://github.com/serilog/serilog-aspnetcore)) -* [Stackdriver](https://cloud.google.com/dotnet/docs/stackdriver#logging) ([Github repo](https://github.com/googleapis/google-cloud-dotnet)) - -Some third-party frameworks can perform [semantic logging, also known as structured logging](https://softwareengineering.stackexchange.com/questions/312197/benefits-of-structured-logging-vs-basic-logging). - -Using a third-party framework is similar to using one of the built-in providers: - -1. Add a NuGet package to your project. -1. Call an `ILoggerFactory` extension method provided by the logging framework. - -For more information, see each provider's documentation. Third-party logging providers aren't supported by Microsoft. - - - -## Non-host console app - -For an example of how to use the Generic Host in a non-web console app, see the `Program.cs` file of the [Background Tasks sample app](https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/fundamentals/host/hosted-services/samples) (). - -Logging code for apps without Generic Host differs in the way providers are added and [loggers are created](#create-logs). - -### Logging providers - -In a non-host console app, call the provider's `Add{provider name}` extension method while creating a `LoggerFactory`: - -[!code-csharp[](~/fundamentals/logging/index/samples/3.x/LoggingConsoleApp/Program.cs?name=snippet_LoggerFactory&highlight=11-12)] - -### Create logs - -To create logs, use an object. Use the `LoggerFactory` to create an `ILogger`. - -The following example creates a logger with `LoggingConsoleApp.Program` as the category. - -[!code-csharp[](~/fundamentals/logging/index/samples/3.x/LoggingConsoleApp/Program.cs?name=snippet_LoggerFactory&highlight=14)] - -In the following example, the logger is used to create logs with `Information` as the level. The Log *level* indicates the severity of the logged event. - -[!code-csharp[](~/fundamentals/logging/index/samples/3.x/LoggingConsoleApp/Program.cs?name=snippet_LoggerFactory&highlight=15)] - -[Levels](#log-level) and [categories](#log-category) are explained in more detail in this document. - - - -## Log during host construction - -Logging during host construction isn't directly supported. However, a separate logger can be used. In the following example, a [Serilog](https://serilog.net/) logger is used to log in `CreateHostBuilder`. `AddSerilog` uses the static configuration specified in `Log.Logger`: - -```csharp -using System; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; - -public class Program -{ - public static void Main(string[] args) - { - CreateHostBuilder(args).Build().Run(); - } - - public static IHostBuilder CreateHostBuilder(string[] args) - { - var builtConfig = new ConfigurationBuilder() - .AddJsonFile("appsettings.json") - .AddCommandLine(args) - .Build(); - - Log.Logger = new LoggerConfiguration() - .WriteTo.Console() - .WriteTo.File(builtConfig["Logging:FilePath"]) - .CreateLogger(); - - try - { - return Host.CreateDefaultBuilder(args) - .ConfigureServices((context, services) => - { - services.AddRazorPages(); - }) - .ConfigureAppConfiguration((hostingContext, config) => - { - config.AddConfiguration(builtConfig); - }) - .ConfigureLogging(logging => - { - logging.AddSerilog(); - }) - .ConfigureWebHostDefaults(webBuilder => - { - webBuilder.UseStartup(); - }); - } - catch (Exception ex) - { - Log.Fatal(ex, "Host builder error"); - - throw; - } - finally - { - Log.CloseAndFlush(); - } - } -} -``` - - - -## Configure a service that depends on ILogger - -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](https://github.com/aspnet/Announcements/issues/353). - -To configure a service that depends on `ILogger`, use constructor injection or provide a factory method. The factory method approach is recommended only if there is no other option. For example, consider a service that needs an `ILogger` instance provided by DI: - -[!code-csharp[](~/fundamentals/logging/index/samples/3.x/TodoApiSample/Startup2.cs?name=snippet_ConfigureServices&highlight=6-10)] - -The preceding highlighted code is a 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 Main - -The following code logs in `Main` by getting an `ILogger` instance from DI after building the host: - -[!code-csharp[](~/fundamentals/logging/index/samples/3.x/TodoApiDTO/Program.cs?name=snippet_LogProgram)] - -### Create logs in Startup - -The following code writes logs in `Startup.Configure`: - -[!code-csharp[](~/fundamentals/logging/index/samples/3.x/TodoApiDTO/Startup.cs?name=snippet_Configure)] - -Writing logs before completion of the DI container setup in the `Startup.ConfigureServices` method is not supported: - -* Logger injection into the `Startup` constructor is not supported. -* Logger injection into the `Startup.ConfigureServices` method signature is not supported - -The reason for this restriction is that logging depends on DI and on configuration, which in turns depends on DI. The DI container isn't set up until `ConfigureServices` finishes. - -For information on configuring a service that depends on `ILogger` or why constructor injection of a logger into `Startup` worked in earlier versions, see [Configure a service that depends on ILogger](#csdi) - -### No asynchronous logger methods - -Logging should be so fast that it isn't worth the performance cost of asynchronous code. If a logging data store is slow, don't write to it directly. Consider writing the log messages to a fast store initially, then moving them to the slow store later. For example, when logging to SQL Server, don't do so directly in a `Log` method, since the `Log` methods are synchronous. 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. For more information, see [this](https://github.com/dotnet/AspNetCore.Docs/issues/11801) GitHub issue. - - - -## Change log levels in a running app - -The Logging API doesn't include a scenario to change log levels while an app is running. However, some configuration providers are capable of reloading configuration, which takes immediate effect on logging configuration. For example, the [File Configuration Provider](xref:fundamentals/configuration/index#file-configuration-provider), reloads logging configuration by default. If configuration is changed in code while an app is running, the app can call to update the app's logging configuration. - -## ILogger and ILoggerFactory - -The and interfaces and implementations are included in the .NET Core SDK. They are also available in the following NuGet packages: - -* The interfaces are in [Microsoft.Extensions.Logging.Abstractions](https://www.nuget.org/packages/Microsoft.Extensions.Logging.Abstractions/). -* The default implementations are in [Microsoft.Extensions.Logging](https://www.nuget.org/packages/microsoft.extensions.logging/). - - - - -## Apply log filter rules in code - -The preferred approach for setting log filter rules is by using [Configuration](xref:fundamentals/configuration/index). - -The following example shows how to register filter rules in code: - -[!code-csharp[](~/fundamentals/logging/index/samples/3.x/MyMain/Program.cs?name=snippet_FilterInCode)] - -`logging.AddFilter("System", LogLevel.Debug)` specifies the `System` category and log level `Debug`. The filter is applied to all providers because a specific provider was not configured. - -`AddFilter("Microsoft", LogLevel.Information)` specifies: - -* The `Debug` logging provider. -* Log level `Information` and higher. -* All categories starting with `"Microsoft"`. - -:::moniker-end - -:::moniker range=">= aspnetcore-5.0 < aspnetcore-6.0" - -## Automatically log scope with SpanId, TraceId, and ParentId - -The logging libraries implicitly create a scope object with `SpanId`, `TraceId`, and `ParentId`. This behavior is configured via . - -```csharp - var loggerFactory = LoggerFactory.Create(logging => - { - logging.Configure(options => - { - options.ActivityTrackingOptions = ActivityTrackingOptions.SpanId - | ActivityTrackingOptions.TraceId - | ActivityTrackingOptions.ParentId; - }).AddSimpleConsole(options => - { - options.IncludeScopes = true; - }); - }); -``` - -If the `traceparent` http request header is set, the `ParentId` in the log scope shows the W3C `parent-id` from in-bound `traceparent` header and the `SpanId` in the log scope shows the updated `parent-id` for the next out-bound step/span. For more information, see [Mutating the traceparent Field](https://www.w3.org/TR/trace-context/#mutating-the-traceparent-field). - -:::moniker-end - -:::moniker range="< aspnetcore-6.0" - -## Create a custom logger - -To create a custom logger, see [Implement a custom logging provider in .NET](/dotnet/core/extensions/custom-logging-provider). - -## Additional resources - -* [High performance logging](/dotnet/core/extensions/high-performance-logging) -* Logging bugs should be created in the [github.com/dotnet/runtime/](https://github.com/dotnet/runtime/issues) repo. -* - -:::moniker-end diff --git a/aspnetcore/fundamentals/servers/yarp/diagnosing-yarp-issues.md b/aspnetcore/fundamentals/servers/yarp/diagnosing-yarp-issues.md index 120555de870f..c39fe5aae6ce 100644 --- a/aspnetcore/fundamentals/servers/yarp/diagnosing-yarp-issues.md +++ b/aspnetcore/fundamentals/servers/yarp/diagnosing-yarp-issues.md @@ -15,7 +15,7 @@ When using a reverse proxy, there is an additional hop from the client to the pr ## Logging -The first step to being able to tell what is going on with YARP is to turn on [logging](/aspnet/core/fundamentals/logging/#configure-logging). This is a configuration flag so can be changed on the fly. YARP is implemented as a middleware component for ASP.NET Core, so you need to enable logging for both YARP and ASP.NET to get the complete picture of what is going on. +The first step to being able to tell what is going on with YARP is to turn on [logging](/aspnet/core/fundamentals/logging/#configuration). This is a configuration flag so can be changed on the fly. YARP is implemented as a middleware component for ASP.NET Core, so you need to enable logging for both YARP and ASP.NET to get the complete picture of what is going on. By default ASP.NET will log to the console, and the configuration file can be used to control the level of logging. diff --git a/aspnetcore/host-and-deploy/proxy-load-balancer.md b/aspnetcore/host-and-deploy/proxy-load-balancer.md index 18831d273c80..8797047ca3e8 100644 --- a/aspnetcore/host-and-deploy/proxy-load-balancer.md +++ b/aspnetcore/host-and-deploy/proxy-load-balancer.md @@ -532,8 +532,8 @@ You can write to logs instead of the response body. Writing to logs allows the s To write logs rather than to the response body: -* Inject `ILogger` into the `Startup` class as described in [Create logs in Startup](xref:fundamentals/logging/index#create-logs-in-startup). -* Place the following inline middleware immediately after the call to in `Startup.Configure`. +* Inject `ILogger` into the `Startup` class as described in [Create log messages](xref:fundamentals/logging/index#create-log-messages). +* Place the following inline middleware immediately after the call to in `Startup.Configure`. ```csharp app.Use(async (context, next) => diff --git a/aspnetcore/includes/environmentVarableColon.md b/aspnetcore/includes/environmentVarableColon.md index 7227622d81ca..0f147f4ef5c9 100644 --- a/aspnetcore/includes/environmentVarableColon.md +++ b/aspnetcore/includes/environmentVarableColon.md @@ -1,3 +1 @@ -The `:` separator doesn't work with environment variable hierarchical keys on all platforms. For example, the `:` separator is not supported by [Bash](https://linuxhint.com/bash-environment-variables/). The double underscore, `__`, is: -* Supported by all platforms. -* Automatically replaced by a colon, `:`. +The `:` separator doesn't work with environment variable hierarchical keys on all platforms. For example, the `:` separator isn't supported by [Bash](https://linuxhint.com/bash-environment-variables/). The double underscore, `__`, is supported by all platforms and automatically replaced by a colon, `:`. diff --git a/aspnetcore/includes/sql-log.md b/aspnetcore/includes/sql-log.md index 9fe4c4e6d0bf..b8f7bb2388b9 100644 --- a/aspnetcore/includes/sql-log.md +++ b/aspnetcore/includes/sql-log.md @@ -7,4 +7,7 @@ Logging configuration is commonly provided by the `Logging` section of `appsetti With the preceding JSON, SQL statements are displayed on the command line and in the Visual Studio output window. -For more information, see and this [GitHub issue](https://github.com/dotnet/aspnetcore/issues/32977). +For more information, see the following resources: + +* +* [ASP.NET template disables EF Core SQL logging by default (`dotnet/aspnetcore` #32977)](https://github.com/dotnet/aspnetcore/issues/32977) diff --git a/aspnetcore/security/authentication/configure-oidc-web-authentication.md b/aspnetcore/security/authentication/configure-oidc-web-authentication.md index b76264915d2c..0fb88cff5aa9 100644 --- a/aspnetcore/security/authentication/configure-oidc-web-authentication.md +++ b/aspnetcore/security/authentication/configure-oidc-web-authentication.md @@ -362,7 +362,7 @@ IdentityModelEventSource.ShowPII = true; app.Run(); ``` -For more information, see [Logging](xref:fundamentals/logging/index#configure-logging). +For more information, see [Logging](xref:fundamentals/logging/index#configuration). > [!NOTE] > You may want to lower the configured log level to see all the required logs.