Логирование ошибок net core

title author description monikerRange ms.author ms.custom ms.date uid

Logging in .NET Core and ASP.NET Core

tdykstra

Learn how to use the logging framework provided by the Microsoft.Extensions.Logging NuGet package.

>= aspnetcore-3.1

riande

mvc

03/10/2022

fundamentals/logging/index

Logging in .NET Core and ASP.NET Core

:::moniker range=»>= aspnetcore-6.0″

By Kirk Larkin, Juergen Gutsch, and Rick Anderson

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. For more information on logging in Blazor apps, see xref:blazor/fundamentals/logging.

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.
  • Call xref:Microsoft.AspNetCore.Builder.WebApplication.CreateBuilder%2A?displayProperty=nameWithType, which adds the following logging providers:
    • Console
    • Debug
    • EventSource
    • EventLog: Windows only

[!code-csharp]

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, which use the Generic Host.

The following code overrides the default set of logging providers added by WebApplication.CreateBuilder:

[!code-csharp]

Alternatively, the preceding logging code can be written as follows:

[!code-csharp]

For additional providers, see:

  • Built-in logging providers
  • Third-party logging providers.

Create logs

To create logs, use an xref:Microsoft.Extensions.Logging.ILogger%601 object from dependency injection (DI).

The following example:

  • Creates a logger, ILogger<AboutModel>, 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 xref:Microsoft.Extensions.Logging.LoggerExtensions.LogInformation%2A to log at the xref:Microsoft.Extensions.Logging.LogLevel.Information level. The Log level indicates the severity of the logged event.

[!code-csharp]

Levels and categories are explained in more detail later in this document.

For information on Blazor, see xref:blazor/fundamentals/logging.

Configure logging

Logging configuration is commonly provided by the Logging section of appsettings.{ENVIRONMENT}.json files, where the {ENVIRONMENT} placeholder is the environment. The following appsettings.Development.json file is generated by the ASP.NET Core web app templates:

[!code-json]

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.

The Logging property can have xref:Microsoft.Extensions.Logging.LogLevel and log provider properties. The LogLevel specifies the minimum 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.

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]

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:

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 xref:Microsoft.Extensions.Logging.LogLevel.None?displayProperty=nameWithType. LogLevel.None has a value of 6, which is higher than LogLevel.Critical (5).

If a provider supports log scopes, IncludeScopes indicates whether they’re enabled. For more information, see log scopes.

The following appsettings.json file contains all the providers enabled by default:

[!code-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.{PROVIDER NAME}.LogLevel override settings in Logging.LogLevel, where the {PROVIDER NAME} placeholder is the provider name. 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

Log in Program.cs

The following example calls Builder.WebApplication.Logger in Program.cs and logs informational messages:

[!code-csharp]

The following example calls xref:Microsoft.Extensions.Logging.ConsoleLoggerExtensions.AddConsole%2A in Program.cs and logs the /Test endpoint:

[!code-csharp]

The following example calls xref:Microsoft.Extensions.Logging.ConsoleLoggerExtensions.AddSimpleConsole%2A in Program.cs, disables color output, and logs the /Test endpoint:

[!code-csharp]

Set log level by command line, environment variables, and other configuration

Log level can be set by any of the configuration providers.

[!INCLUDE]

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 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 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.

setx Logging__LogLevel__Microsoft Information /M

Consider the following appsettings.json file:

"Logging": {
  "Console": {
    "LogLevel": {
      "Microsoft.Hosting.Lifetime": "Trace"
    }
  }
}

The following command sets the preceding configuration in the environment:

setx Logging__Console__LogLevel__Microsoft.Hosting.Lifetime Trace /M

On Azure 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.

For more information on setting ASP.NET Core configuration values using environment variables, see 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 xref:fundamentals/configuration/index.

How filtering rules are applied

When an xref:Microsoft.Extensions.Logging.ILogger%601 object is created, the xref:Microsoft.Extensions.Logging.ILoggerFactory 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 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<T> to automatically get an ILogger instance that uses the fully qualified type name of T as the category:

[!code-csharp]

To explicitly specify the category, call ILoggerFactory.CreateLogger:

[!code-csharp]

Calling CreateLogger with a fixed name can be useful when used in multiple methods so the events can be organized by category.

ILogger<T> is equivalent to calling CreateLogger with the fully qualified type name of T.

Log level

The following table lists the xref:Microsoft.Extensions.Logging.LogLevel values, the convenience Log{LogLevel} extension method, and the suggested usage:

LogLevel Value Method Description
xref:Microsoft.Extensions.Logging.LogLevel.Trace 0 xref:Microsoft.Extensions.Logging.LoggerExtensions.LogTrace%2A 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.
xref:Microsoft.Extensions.Logging.LogLevel.Debug 1 xref:Microsoft.Extensions.Logging.LoggerExtensions.LogDebug%2A For debugging and development. Use with caution in production due to the high volume.
xref:Microsoft.Extensions.Logging.LogLevel.Information 2 xref:Microsoft.Extensions.Logging.LoggerExtensions.LogInformation%2A Tracks the general flow of the app. May have long-term value.
xref:Microsoft.Extensions.Logging.LogLevel.Warning 3 xref:Microsoft.Extensions.Logging.LoggerExtensions.LogWarning%2A For abnormal or unexpected events. Typically includes errors or conditions that don’t cause the app to fail.
xref:Microsoft.Extensions.Logging.LogLevel.Error 4 xref:Microsoft.Extensions.Logging.LoggerExtensions.LogError%2A For errors and exceptions that cannot be handled. These messages indicate a failure in the current operation or request, not an app-wide failure.
xref:Microsoft.Extensions.Logging.LogLevel.Critical 5 xref:Microsoft.Extensions.Logging.LoggerExtensions.LogCritical%2A For failures that require immediate attention. Examples: data loss scenarios, out of disk space.
xref:Microsoft.Extensions.Logging.LogLevel.None 6 Specifies that a logging category shouldn’t write messages.

In the previous table, the LogLevel is listed from lowest to highest severity.

The xref:Microsoft.Extensions.Logging.LoggerExtensions.Log%2A method’s first parameter, xref:Microsoft.Extensions.Logging.LogLevel, indicates the severity of the log. Rather than calling Log(LogLevel, ...), most developers call the Log{LOG LEVEL} 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:

[!code-csharp]

MyLogEvents.TestItem is the event ID. MyLogEvents is part of the sample app and is displayed in the Log event ID section.

[!INCLUDE]

The following code creates Information and Warning logs:

[!code-csharp]

In the preceding code, the first Log{LOG LEVEL} parameter,MyLogEvents.GetItem, is the Log event ID. The second parameter is a message template with placeholders for argument values provided by the remaining method parameters. The method parameters are explained in the message template section later in this document.

Call the appropriate Log{LOG LEVEL} 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:
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]

Log event ID

Each log can specify an event ID. The sample app uses the MyLogEvents class to define event IDs:

[!code-csharp]

[!code-csharp]

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:

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]

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:

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:

This approach allows logging providers to implement semantic or 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:

_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]

[!INCLUDE]

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]

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]

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]

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 xref:System.IDisposable type that’s returned by the xref:Microsoft.Extensions.Logging.ILogger.BeginScope%2A method.
  • Lasts until it’s disposed.

The following providers support scopes:

  • Console
  • AzureAppServicesFile and AzureAppServicesBlob

Use a scope by wrapping logger calls in a using block:

[!code-csharp]

Built-in logging providers

ASP.NET Core includes the following logging providers as part of the shared framework:

  • Console
  • Debug
  • EventSource
  • EventLog

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
  • ApplicationInsights

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.

For information on stdout and debug logging with the ASP.NET Core Module, see xref:test/troubleshoot-azure-iis and xref:host-and-deploy/aspnet-core-module#log-creation-and-redirection.

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.

Debug

The Debug provider writes log output by using the xref:System.Diagnostics.Debug?displayProperty=fullName 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.

dotnet trace tooling

The 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 xref:Microsoft.Extensions.Logging.EventSource provider data using a xref:Microsoft.Extensions.Logging.EventSource.LoggingEventSource.

For installation instructions, see dotnet-trace.

Use the dotnet trace tooling to collect a trace from an app:

  1. Run the app with the dotnet run command.

  2. Determine the process identifier (PID) of the .NET Core app:

    Find the PID for the process that has the same name as the app’s assembly.

  3. Execute the dotnet trace command.

    General command syntax:

    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 ('):

    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:

    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:

    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.

    dotnet trace collect -p %PID%  --providers Microsoft-Extensions-Logging:4:5:"FilterSpecs=*:1"
    

    The following command captures debug messages because category specifies Debug.

    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:

    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).
  4. 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.

  5. Open the trace with Perfview. Open the trace.nettrace file and explore the trace events.

If the app doesn’t build the host with xref:Microsoft.AspNetCore.Builder.WebApplication.CreateBuilder%2A?displayProperty=nameWithType, add the Event Source provider to the app’s logging configuration.

For more information, see:

  • Trace for performance analysis utility (dotnet-trace) (.NET Core documentation)
  • Trace for performance analysis utility (dotnet-trace) (dotnet/diagnostics GitHub repository documentation)
  • xref:Microsoft.Extensions.Logging.EventSource.LoggingEventSource
  • xref:System.Diagnostics.Tracing.EventLevel
  • Perfview: Useful for viewing Event Source traces.

Perfview

Use the PerfView utility 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 xref:Microsoft.Extensions.Logging.LogLevel.Warning?displayProperty=nameWithType.

To log events lower than xref:Microsoft.Extensions.Logging.LogLevel.Warning?displayProperty=nameWithType, explicitly set the log level. The following example sets the Event Log default log level to xref:Microsoft.Extensions.Logging.LogLevel.Information?displayProperty=nameWithType:

"Logging": {
  "EventLog": {
    "LogLevel": {
      "Default": "Information"
    }
  }
}

xref:Microsoft.Extensions.Logging.EventLoggerFactoryExtensions.AddEventLog%2A overloads can pass in xref:Microsoft.Extensions.Logging.EventLog.EventLogSettings. 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]

Azure App Service

The Microsoft.Extensions.Logging.AzureAppServices provider package writes logs to text files in an Azure App Service app’s file system and to blob storage in an Azure Storage account.

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 xref:Microsoft.Extensions.Logging.AzureAppServices.AzureFileLoggerOptions and xref:Microsoft.Extensions.Logging.AzureAppServices.AzureBlobLoggerOptions, as shown in the following example:

[!code-csharp]

When deployed to Azure App Service, the app uses the settings in the App Service logs section of the App Service page of the Azure portal. When the following settings are updated, the changes take effect immediately without requiring a restart or redeployment of the app.

  • Application Logging (Filesystem)
  • 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 provider package writes logs to Azure Application Insights. 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, 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 package is for ASP.NET 4.x, not ASP.NET Core.

For more information, see the following resources:

  • Application Insights overview
  • Application Insights for ASP.NET Core applications: Start here if you want to implement the full range of Application Insights telemetry along with logging.
  • ApplicationInsightsLoggerProvider for .NET Core ILogger logs: Start here if you want to implement the logging provider without the rest of Application Insights telemetry.
  • Application Insights logging adapters
  • Install, configure, and initialize the Application Insights SDK interactive tutorial.

Third-party logging providers

Third-party logging frameworks that work with ASP.NET Core:

  • elmah.io (GitHub repo)
  • Gelf (GitHub repo)
  • JSNLog (GitHub repo)
  • KissLog.net (GitHub repo)
  • Log4Net (GitHub repo)
  • NLog (GitHub repo)
  • PLogger (GitHub repo)
  • Sentry (GitHub repo)
  • Serilog (GitHub repo)
  • Stackdriver (Github repo)

Some third-party frameworks can perform semantic logging, also known as structured logging.

Using a third-party framework is similar to using one of the built-in providers:

  1. Add a NuGet package to your project.
  2. 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.

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 Guidance on how to log to a message queue for slow data stores (dotnet/AspNetCore.Docs #11801).

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, reloads logging configuration by default. If configuration is changed in code while an app is running, the app can call xref:Microsoft.Extensions.Configuration.IConfigurationRoot.Reload%2A?displayProperty=nameWithType to update the app’s logging configuration.

ILogger and ILoggerFactory

The xref:Microsoft.Extensions.Logging.ILogger%601 and xref:Microsoft.Extensions.Logging.ILoggerFactory 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.
  • The default implementations are in Microsoft.Extensions.Logging.

Apply log filter rules in code

The preferred approach for setting log filter rules is by using Configuration.

The following example shows how to register filter rules in code:

[!code-csharp]

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<DebugLoggerProvider>("Microsoft", LogLevel.Information) specifies:

  • The Debug logging provider.
  • Log level Information and higher.
  • All categories starting with "Microsoft".

Automatically log scope with SpanId, TraceId, ParentId, Baggage, and Tags.

The logging libraries implicitly create a scope object with SpanId, TraceId, ParentId,Baggage, and Tags. This behavior is configured via xref:Microsoft.Extensions.Logging.LoggerFactoryOptions.ActivityTrackingOptions.

  var loggerFactory = LoggerFactory.Create(logging =>
  {
      logging.Configure(options =>
      {
          options.ActivityTrackingOptions = ActivityTrackingOptions.SpanId
                                              | ActivityTrackingOptions.TraceId
                                              | ActivityTrackingOptions.ParentId
                                              | ActivityTrackingOptions.Baggage
                                              | ActivityTrackingOptions.Tags;
      }).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.

Create a custom logger

To create a custom logger, see Implement a custom logging provider in .NET.

Additional resources

  • Microsoft.Extensions.Logging source on GitHub
  • View or download sample code (how to download).
  • High performance logging
  • Logging bugs should be created in the dotnet/runtime GitHub repository.
  • xref:blazor/fundamentals/logging

:::moniker-end

:::moniker range=»< aspnetcore-6.0″

By Kirk Larkin, Juergen Gutsch, and Rick Anderson

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. For more information on logging in Blazor apps, see xref:blazor/fundamentals/logging.

View or download sample code (how to download).

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.
  • Call xref:Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder%2A, which adds the following logging providers:
    • Console
    • Debug
    • EventSource
    • EventLog: Windows only

[!code-csharp]

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 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 xref:Microsoft.Extensions.Logging.LoggingBuilderExtensions.ClearProviders%2A to remove all the xref:Microsoft.Extensions.Logging.ILoggerProvider instances from the builder.
  • Adds the Console logging provider.

[!code-csharp]

For additional providers, see:

  • Built-in logging providers
  • Third-party logging providers.

Create logs

To create logs, use an xref:Microsoft.Extensions.Logging.ILogger%601 object from dependency injection (DI).

The following example:

  • Creates a logger, ILogger<AboutModel>, 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 xref:Microsoft.Extensions.Logging.LoggerExtensions.LogInformation%2A to log at the Information level. The Log level indicates the severity of the logged event.

[!code-csharp]

Levels and categories are explained in more detail later in this document.

For information on Blazor, see xref:blazor/fundamentals/logging.

Create logs in Main and Startup 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]

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.

The Logging property can have xref:Microsoft.Extensions.Logging.LogLevel and log provider properties. The LogLevel specifies the minimum 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.

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]

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. LogLevel.None has a value of 6, which is higher than LogLevel.Critical (5).

If a provider supports log scopes, IncludeScopes indicates whether they’re enabled. For more information, see log scopes

The following appsettings.json file contains all the providers enabled by default:

[!code-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.

[!INCLUDE]

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 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 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.

setx Logging__LogLevel__Microsoft Information /M

Consider the following appsettings.json file:

"Logging": {
    "Console": {
      "LogLevel": {
        "Microsoft.Hosting.Lifetime": "Trace"
      }
    }
}

The following command sets the preceding configuration in the environment:

setx Logging__Console__LogLevel__Microsoft.Hosting.Lifetime Trace /M

On Azure 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.

For more information on setting ASP.NET Core configuration values using environment variables, see 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 xref:fundamentals/configuration/index.

How filtering rules are applied

When an xref:Microsoft.Extensions.Logging.ILogger%601 object is created, the xref:Microsoft.Extensions.Logging.ILoggerFactory 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 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<T> to automatically get an ILogger instance that uses the fully qualified type name of T as the category:

[!code-csharp]

To explicitly specify the category, call ILoggerFactory.CreateLogger:

[!code-csharp]

Calling CreateLogger with a fixed name can be useful when used in multiple methods so the events can be organized by category.

ILogger<T> is equivalent to calling CreateLogger with the fully qualified type name of T.

Log level

The following table lists the xref:Microsoft.Extensions.Logging.LogLevel values, the convenience Log{LogLevel} extension method, and the suggested usage:

LogLevel Value Method Description
Trace 0 xref:Microsoft.Extensions.Logging.LoggerExtensions.LogTrace%2A 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 1 xref:Microsoft.Extensions.Logging.LoggerExtensions.LogDebug%2A For debugging and development. Use with caution in production due to the high volume.
Information 2 xref:Microsoft.Extensions.Logging.LoggerExtensions.LogInformation%2A Tracks the general flow of the app. May have long-term value.
Warning 3 xref:Microsoft.Extensions.Logging.LoggerExtensions.LogWarning%2A For abnormal or unexpected events. Typically includes errors or conditions that don’t cause the app to fail.
Error 4 xref:Microsoft.Extensions.Logging.LoggerExtensions.LogError%2A 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 5 xref:Microsoft.Extensions.Logging.LoggerExtensions.LogCritical%2A For failures that require immediate attention. Examples: data loss scenarios, out of disk space.
None 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 method’s first parameter, xref:Microsoft.Extensions.Logging.LogLevel, indicates the severity of the log. Rather than calling Log(LogLevel, ...), most developers call the Log{LogLevel} extension methods. The Log{LogLevel} extension methods call the Log method and specify the LogLevel. For example, the following two logging calls are functionally equivalent and produce the same log:

[!code-csharp]

MyLogEvents.TestItem is the event ID. MyLogEvents is part of the sample app and is displayed in the Log event ID section.

[!INCLUDE]

The following code creates Information and Warning logs:

[!code-csharp]

In the preceding code, the first Log{LogLevel} parameter,MyLogEvents.GetItem, is the Log event ID. The second parameter is a message template with placeholders for argument values provided by the remaining method parameters. The method parameters are explained in the message template section later in this 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:
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]

Log event ID

Each log can specify an event ID. The sample app uses the MyLogEvents class to define event IDs:

[!code-csharp]

[!code-csharp]

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:

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]

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:

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:

This approach allows logging providers to implement semantic or 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:

_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]

[!INCLUDE]

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]

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]

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]

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 xref:System.IDisposable type that’s returned by the xref:Microsoft.Extensions.Logging.ILogger.BeginScope%2A method.
  • Lasts until it’s disposed.

The following providers support scopes:

  • Console
  • AzureAppServicesFile and AzureAppServicesBlob

Use a scope by wrapping logger calls in a using block:

[!code-csharp]

Built-in logging providers

ASP.NET Core includes the following logging providers as part of the shared framework:

  • Console
  • Debug
  • EventSource
  • EventLog

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
  • ApplicationInsights

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.

For information on stdout and debug logging with the ASP.NET Core Module, see xref:test/troubleshoot-azure-iis and xref:host-and-deploy/aspnet-core-module#log-creation-and-redirection.

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.

Debug

The Debug provider writes log output by using the xref:System.Diagnostics.Debug?displayProperty=fullName 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.

dotnet trace tooling

The 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 xref:Microsoft.Extensions.Logging.EventSource provider data using a xref:Microsoft.Extensions.Logging.EventSource.LoggingEventSource.

See 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.

  2. Determine the process identifier (PID) of the .NET Core app:

    Find the PID for the process that has the same name as the app’s assembly.

  3. Execute the dotnet trace command.

    General command syntax:

    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 ('):

    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:

    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:

    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.

    dotnet trace collect -p %PID%  --providers Microsoft-Extensions-Logging:4:5:"FilterSpecs=*:1"
    

    The following command captures debug messages because category specifies Debug.

    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:

    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).
  4. 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.

  5. Open the trace with 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) (.NET Core documentation)
  • Trace for performance analysis utility (dotnet-trace) (dotnet/diagnostics GitHub repository documentation)
  • LoggingEventSource Class (.NET API Browser)
  • xref:System.Diagnostics.Tracing.EventLevel
  • LoggingEventSource reference source (3.0): 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: Useful for viewing Event Source traces.

Perfview

Use the PerfView utility 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.

To log events lower than xref:Microsoft.Extensions.Logging.LogLevel.Warning?displayProperty=nameWithType, explicitly set the log level. The following example sets the Event Log default log level to xref:Microsoft.Extensions.Logging.LogLevel.Information?displayProperty=nameWithType:

"Logging": {
  "EventLog": {
    "LogLevel": {
      "Default": "Information"
    }
  }
}

AddEventLog overloads can pass in xref:Microsoft.Extensions.Logging.EventLog.EventLogSettings. 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]

Azure App Service

The Microsoft.Extensions.Logging.AzureAppServices provider package writes logs to text files in an Azure App Service app’s file system and to blob storage in an Azure Storage account.

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 xref:Microsoft.Extensions.Logging.AzureAppServices.AzureFileLoggerOptions and xref:Microsoft.Extensions.Logging.AzureAppServices.AzureBlobLoggerOptions, as shown in the following example:

[!code-csharp]

When deployed to Azure App Service, the app uses the settings in the App Service logs section of the App Service page of the Azure portal. When the following settings are updated, the changes take effect immediately without requiring a restart or redeployment of the app.

  • Application Logging (Filesystem)
  • Application Logging (Blob)

The default location for log files is in the D:homeLogFilesApplication 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 provider package writes logs to Azure Application Insights. 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, 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 package is for ASP.NET 4.x, not ASP.NET Core.

For more information, see the following resources:

  • Application Insights overview
  • Application Insights for ASP.NET Core applications — Start here if you want to implement the full range of Application Insights telemetry along with logging.
  • ApplicationInsightsLoggerProvider for .NET Core ILogger logs — Start here if you want to implement the logging provider without the rest of Application Insights telemetry.
  • Application Insights logging adapters.
  • Install, configure, and initialize the Application Insights SDK interactive tutorial.

Third-party logging providers

Third-party logging frameworks that work with ASP.NET Core:

  • elmah.io (GitHub repo)
  • Gelf (GitHub repo)
  • JSNLog (GitHub repo)
  • KissLog.net (GitHub repo)
  • Log4Net (GitHub repo)
  • NLog (GitHub repo)
  • PLogger (GitHub repo)
  • Sentry (GitHub repo)
  • Serilog (GitHub repo)
  • Stackdriver (Github repo)

Some third-party frameworks can perform semantic logging, also known as structured logging.

Using a third-party framework is similar to using one of the built-in providers:

  1. Add a NuGet package to your project.
  2. 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 (xref:fundamentals/host/hosted-services).

Logging code for apps without Generic Host differs in the way providers are added and loggers are created.

Logging providers

In a non-host console app, call the provider’s Add{provider name} extension method while creating a LoggerFactory:

[!code-csharp]

Create logs

To create logs, use an xref:Microsoft.Extensions.Logging.ILogger%601 object. Use the LoggerFactory to create an ILogger.

The following example creates a logger with LoggingConsoleApp.Program as the category.

[!code-csharp]

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]

Levels and categories 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 logger is used to log in CreateHostBuilder. AddSerilog uses the static configuration specified in Log.Logger:

using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args)
    {
        var builtConfig = new ConfigurationBuilder()
            .AddJsonFile("appsettings.json")
            .AddCommandLine(args)
            .Build();

        Log.Logger = new LoggerConfiguration()
            .WriteTo.Console()
            .WriteTo.File(builtConfig["Logging:FilePath"])
            .CreateLogger();

        try
        {
            return Host.CreateDefaultBuilder(args)
                .ConfigureServices((context, services) =>
                {
                    services.AddRazorPages();
                })
                .ConfigureAppConfiguration((hostingContext, config) =>
                {
                    config.AddConfiguration(builtConfig);
                })
                .ConfigureLogging(logging =>
                {   
                    logging.AddSerilog();
                })
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
        }
        catch (Exception ex)
        {
            Log.Fatal(ex, "Host builder error");

            throw;
        }
        finally
        {
            Log.CloseAndFlush();
        }
    }
}

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.

To configure a service that depends on ILogger<T>, 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<T> instance provided by DI:

[!code-csharp]

The preceding highlighted code is a xref:System.Func%602 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]

Create logs in Startup

The following code writes logs in Startup.Configure:

[!code-csharp]

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<T> or why constructor injection of a logger into Startup worked in earlier versions, see Configure a service that depends on ILogger

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 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, reloads logging configuration by default. If configuration is changed in code while an app is running, the app can call xref:Microsoft.Extensions.Configuration.IConfigurationRoot.Reload%2A?displayProperty=nameWithType to update the app’s logging configuration.

ILogger and ILoggerFactory

The xref:Microsoft.Extensions.Logging.ILogger%601 and xref:Microsoft.Extensions.Logging.ILoggerFactory 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.
  • The default implementations are in Microsoft.Extensions.Logging.

Apply log filter rules in code

The preferred approach for setting log filter rules is by using Configuration.

The following example shows how to register filter rules in code:

[!code-csharp]

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<DebugLoggerProvider>("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 xref:Microsoft.Extensions.Logging.LoggerFactoryOptions.ActivityTrackingOptions.

  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.

:::moniker-end

:::moniker range=»< aspnetcore-6.0″

Create a custom logger

To create a custom logger, see Implement a custom logging provider in .NET.

Additional resources

  • High performance logging
  • Logging bugs should be created in the github.com/dotnet/runtime/ repo.
  • xref:blazor/fundamentals/logging

:::moniker-end

Логгирование

Ведение лога и ILogger

Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core 7

Последнее обновление: 06.11.2019

ASP.NET Core имеет встроенную поддержку логгирования, что позволяет применять логгирование с минимальными вкраплениями кода в функционал приложения.

Для логгирования данных нам необходим объект ILogger<T>. По умолчанию среда ASP NET Core через механизм внедрения зависимостей
уже предоставляет нам такой объект. Например, возьмем стандартный проект по типу Empty и добавим механизм логгирования. Для этого перейдем к классу Startup и изменим его метод Configure():

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace HelloApp
{
    public class Startup
    {
        public void Configure(IApplicationBuilder app, ILogger<Startup> logger)
        {
            app.Run(async (context) =>
            {
                // пишем на консоль информацию
                logger.LogInformation("Processing request {0}", context.Request.Path);
                //или так
                //logger.LogInformation($"Processing request {context.Request.Path}");

                await context.Response.WriteAsync("Hello World!");
            });
        }
    }
}

Средой выполнения в метод Configure передается объект ILogger, который представляет логгер. А метод логгера logger.LogInformation передает на консоль некоторую информацию.
По умолчанию информация логгируется на консоль, поэтому для тестирования логгера нам надо запустить приложение как консольное:

При обращении к приложению с помощью следующего запроса http://localhost:xxxxx/index на консоль будет выведена информация, переданная логгером:

Тестирование логгера в ASP.NET Core

Важно, что, если мы используем класс Startup для логгирования, то получить объект логгера мы можем только в методе Configure(),
но никак не в методе ConfigureServices() или конструкторе класса Startup, поскольку инфраструктура логгирования зависит от конфигурации и контейнера DI, который окончательно устанавливаются
лишь после завершения работы метода ConfigureServices.

Категория логгера

В примере выше в метод передается не просто объект ILogger, а объект ILogger<T> или точнее ILogger<Startup>. В данном случае «Startup»
указывает на категорию логгера. Обычно в качестве категории логгера выступает класс (как в данном случае Startup). В чем смысл категории? Категория задает
текстовую метку, с которой ассоциируется сообщение логгера, и в выводе лога мы ее можем увидеть. Где это может быть полезно? Например, у нас есть несколько
классов, где ведется логгирование — к примеру, класс Startup и несколько контроллеров. Указывая в качестве категории текущий класс, впоследствии в логее мы
можем увидеть, в каком классе именно было создано сообщение лога. Поэтому, как правило, в качестве категории указывается текущий класс, но в принципе это необязательно. Например, мы можем написать так:

public class Startup
{
	public void Configure(IApplicationBuilder app, ILogger<Program> logger)
	{
		app.Run(async (context) =>
		{
			logger.LogInformation("Processing request {0}", context.Request.Path);
			await context.Response.WriteAsync("Hello World!");
		});
	}
}

Категория логгирования в ASP.NET Core

В данном случае в качестве категории выступает класс Program, примем, обратите внимание, полное имя этого класса. Тем не менее в качестве категории, как правило, задается
имя текущего класса.

Уровни и методы логгирования

При настройке логгирования мы можем установить уровень детализации информации с помощью одного из значений перечисления LogLevel.
Всего мы можем использовать следующие значения:

  • Trace: используется для вывода наиболее детализированных сообщений. Подобные сообщения могут нести важную информацию о
    приложении и его строении, поэтому данный уровень лучше использовать при разработке, но никак не при публикации

  • Debug: для вывода информации, которая может быть полезной в процессе разработки и отладки приложения

  • Information: уровень сообщений, позволяющий просто отследить поток выполнения приложения

  • Warning: используется для вывода сообщений о неожиданных событиях, например, ошибках, которые не влияют не останавливают выполнение приложения,
    но в то же время должны быть иследованы

  • Error: для вывода информации об ошибках и исключениях, которые возникли при текущей операции и которые не могут быть обработаны

  • Critical: уровень критических ошибок, которые требуют немедленной реакции — ошибками операционной системы, потерей данных в бд,
    переполнение памяти диска и т.д.

  • None: вывод информации в лог не применяется

Для вывода соответствующего уровня информации у объекта ILogger определены соответствующие методы расширения:

  • LogDebug()

  • LogTrace()

  • LogInformation()

  • LogWarning()

  • LogError()

  • LogCritical()

Так, в примере выше для вывода информации на консоль использовался метод LogInformation().

Вывод сообщений уровня Trace по умолчанию отключен.

Каждый такой метод имеет несколько перегрузок, которые могут принимать ряд различных параметров:

  • string data: строковое сообщение для лога

  • int eventId: числовой идентификатор, который связан с логом. Идентификатор должен быть статическим и специфическим для
    определенной части логгируемых событий.

  • string format: строковое сообщения для лога, которое моет содержать параметры

  • object[] args: набор параметров для строкового сообщения

  • Exception error: логгируемый объект исключения

Также для логгирования определен общий метод Log(), который позволяет определить уровень логгера через один из параметров:

logger.Log(LogLevel.Information, "Requested Path: {0}", context.Request.Path);

При стандартном логгировании на консоль для каждого уровня/метода определен своя метка и цветовой маркер, которые позволяют сразу выделить сообщение
соответствующего уровня. Например, при запуске следующего кода:

public void Configure(IApplicationBuilder app, ILogger<Startup> logger)
{
	app.Run(async (context) =>
	{
		logger.LogCritical("LogCritical {0}", context.Request.Path);
		logger.LogDebug("LogDebug {0}", context.Request.Path);
		logger.LogError("LogError {0}", context.Request.Path);
		logger.LogInformation("LogInformation {0}", context.Request.Path);
		logger.LogWarning("LogWarning {0}", context.Request.Path);
		
		await context.Response.WriteAsync("Hello World!");
	});
}

мы получим следующий лог на консоль:

Уровни логгирования в ASP.NET Core

Какие есть способы вести лог всех ошибок приложения в ASP.NET Core? Например хотелось бы сохранять все исключения со стеком вызова в текстовые файлы или типа того (автоматические, не в обработчике исключений). Если были получены некорректные данные в контроллере хотелось бы добавить информацию о некорректном запросе в лог.

В идеале хотелось бы иметь инструмент, который, например, присылал бы SMS с сообщением о том, что база данных не отвечает, интернет отвалился, пользователи присылают на конкретный метод конкретного контроллера не те данные и тд.

задан 22 ноя 2017 в 9:33

Kunoichi's user avatar

Добавьте в Startup Middleware:

public void Configure(IApplicationBuilder app)
{
    app.UseMiddleware<ExceptionHandlerMiddleware>();
}

В Middleware вы задаёте собственную обработку запросов перед выполнением и после выполнения, так же обработку ошибок.

Реализация ExceptionHandlerMiddleware (не забудьте зарегистрировать ILogger в контейнере):

public sealed class ExceptionHandlerMiddleware
{
    private readonly ILogger _logger;
    private readonly RequestDelegate _next;

    public ExceptionHandlerMiddleware(RequestDelegate next, ILogger logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task Invoke(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        catch (Exception exp)
        {
            _logger.LogError(context, exp);
            await HandleExceptionAsync(context, exp.GetBaseException());
        }
    }

    private static Task HandleExceptionAsync(HttpContext context, Exception exp)
    {
        var code = HttpStatusCode.InternalServerError; // 500 if unexpected
        var result = JsonConvert.SerializeObject(new { Code = code, Message = exp.Message, StackTrace = exp.StackTrace });

        context.Response.ContentType = "application/json";
        context.Response.StatusCode = (int)code;

        return context.Response.WriteAsync(result);
    }
}

Документация с Microsoft

ответ дан 22 ноя 2017 в 9:48

Chloroform's user avatar

ChloroformChloroform

1,0119 серебряных знаков18 бронзовых знаков

Из стандартных: Microsoft.Extensions.Logging.

В Startup.Configure:

loggerFactory.AddConsole(Configuration.GetSection("Logging"));
            loggerFactory.AddFile("C:\log\Лог.log");
            loggerFactory.AddDebug();

Далее через DI их получаем, включая в конструктор ILogger.

Далее в нужных местах пишем Log, обработку. В некоторых местах (где не обработали) может выдать сам ошибку в файл loggerFactory.AddDebug();

Возможно если покапаться, то можно писать в поток, а поток отправлять на сервер, который бы вам отправлял нужные вам сообщения.

P.S. Вопрос выше даже без отдельного сервера работает и кажется предоставляет больше данных. Объедините наши ответы и (думаю) получите то, что хотите.
Ну и стоит немного скурить мануалов по Microsoft.Extensions.Logging

ответ дан 22 ноя 2017 в 9:50

Arantler's user avatar

ArantlerArantler

9587 серебряных знаков22 бронзовых знака

Logging is essential for tracking errors, keeping track of performance, and diagnosing problems with our web application. Effective logging enables developers to quickly locate and fix issues, enhancing application performance and user experiences. Popular logging framework NLog offers logging in ASP.NET Core with a wealth of capabilities and flexibility.

In this article, we will guide you through the process of implementing NLog for logging in ASP.NET Core applications. We’ll explore how to configure NLog with ASP.NET Core and demonstrate best practices for effective logging, ensuring your application remains robust and maintainable.

Before we start please make sure to have this following application installed on your machine.

  • Latest version of Visual Studio
  • Alternatively you can also use Visual Studio Code
  • SQL SERVER
  • .Net Core SDK 3.1

I. Create a new ASP.NET Core Web Application

  1. First, create your ASP.NET Core Web Application. To do that just follow the steps below.
  • Select File > New > Project.
  • Select ASP.NET Core Web Application. Name the project NLogDemo to have the same namespace as my project. Click OK.
  • Select an ASP.NET Core Web Application. and then uncheck Configure for HTTPS.
  • Lastly, Click on Create.

ASP.NET Core Web Applciation Settings

2. Now we need to install required packages for this project. I have listed it all below.

  • NLog.Web.AspNetCore
  • Newtonsoft.Json
  • Microsoft.Data.SqlClient
  • NLog.Appsettings.Standard

Use NuGet Package Manager to install this package. If this is your first time using this, you can visit this article.

NuGet Packages for logging

3. After we gather all the necessary package, we will set up our connection string in appsettings.json, we will use this later on our NLog configuration.

Add connection string
Add connection string inside appsettings.json
"ConnectionStrings": {
     "default": "Data Source=DESKTOP-4DU98BISQLEXPRESS01;Initial Catalog=NlogDemo;User ID=freecode;Password=freecodespot;
   }

II. Configure Logging provider in Program.cs

Creating a new ASP.NET Core Web Application has already included a logging extension injected in the default controller. We need to configure logging in ASP Net Core by adding additional logging provider inside your ASP.NET Core Program.cs

Program.cs configuration
Program.cs

To do that, open your program.cs, as shown above. Then copy the code snippet below under CreateHostBuilder method.

.ConfigureLogging((hostingContext, logging) =>
                   {
                       logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); //appsettings.json
                       logging.AddConsole(); //Adds a console logger named 'Console' to the factory.
                       logging.AddDebug(); //Adds a debug logger named 'Debug' to the factory.
                       logging.AddEventSourceLogger(); //Adds an event logger named 'EventSource' to the factory.
                   // Enable NLog as one of the Logging Provider                   logging.AddNLog();               })

Below is the full code inside my program.cs after I added the code snippet.

using Microsoft.AspNetCore.Hosting;
 using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.Hosting;
 using Microsoft.Extensions.Logging;
 using NLog;
 using NLog.Extensions.Logging;
 using NLog.Web;
 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Threading.Tasks;
 namespace NLogDemo
 {
     public class Program
     {
         public static void Main(string[] args)
         {
             CreateHostBuilder(args).Build().Run();
         }
     public static IHostBuilder CreateHostBuilder(string[] args) =>         Host.CreateDefaultBuilder(args)
               .ConfigureLogging((hostingContext, logging) =>
               {                   logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); //logging settings under appsettings.json
                   logging.AddConsole(); //Adds a console logger named 'Console' to the factory.
                   logging.AddDebug(); //Adds a debug logger named 'Debug' to the factory.
                   logging.AddEventSourceLogger(); //Adds an event logger named 'EventSource' to the factory.
                   // Enable NLog as one of the Logging Provider                   logging.AddNLog(); 
              })
             .ConfigureWebHostDefaults(webBuilder =>
             {
                 webBuilder.UseStartup<Startup>();
             });
 }
 }

III. Create Nlog configuration

As you have observed above, we added Nlog as one of the logging providers. We will use Nlog to write logs to a file and the database. For Nlogs to work, we need to create a separate configuration file that is nlog.config. This steps can also be used on other third-party extensions if you will use logging in ASP NET Core. Let’s go ahead and follow the steps below.

  1. Add new item, by right-clicking on your project. See the image below.
Logging in ASP NET Core - Add new Config file

2. In a new window, search for a text file, then name it as nlog.config, once you did, click on the Add button. See the image below.

Logging in ASP NET Core - nlog.config

3. After adding the config file. Add the snippet below. This code snippet is the default Nlog config found on their GitHub documentation.

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autoReload="true" internalLogLevel="info" internalLogFile="internalLog.txt" internalLogToConsole="true">
  <extensions>
    <add assembly="NLog.Web.AspNetCore" />
  </extensions>
  <!-- the targets to write to -->
  <targets>
        <!--place target here-->
  </targets>
  <!-- rules to map from logger name to target -->
  <rules>
      <!--place rule here-->
  </rules>
</nlog>

Tags and Property Definition

Tags/properties Description
internalLogFile Create a text file for logs provider internal error
internalLogToConsole Enable logging nlog error to a console
<targets> all the logging target found
<rules> Map from logger name to target(Trigers which target to execute)

IV. Setup logging example from HomeController

Now, we have covered most of the necessary configuration for our logging provider. We have to create targets and rules for our logging provider to perform, but before that, let’s add logs to our controller using dependency injection.

  1. Open your controller, which in my case since it’s HomeController.
  2. If you are using the default controller for ASP.NET Core from a newly created project, ILogger is already added. See the code snippet below.
private readonly ILogger _logger;
public HomeController(ILogger<HomeController> logger)
    {
        _logger = logger;
    }

3. Now, this part is just additional data that I want to add in my logs. I created a model class name member_info. Then I added two properties. I will use this to generate a JSON value.

Logging in ASP NET Core - Member_info model properties
public class member_info
     {
         public string FullName { get; set; }
         public string Website { get; set; }
     }

4. Now, Navigate back to your HomeController. Inside your index method copy and paste the code below. This snippet will log the JSON value from the model properties that we created awhile ago.

_logger.LogInformation("This is the homepage!");
 List info = new List();
info.Add(new member_info { FullName = "FreeCode Spot", Website = "freecodespot.com" });
info.Add(new member_info { FullName = "FreeCode Spot", Website = "freecodespot.com" });

string json_value = JsonConvert.SerializeObject(info);

_logger.LogInformation(json_value);

5. I also added logs information and logs error from the privacy page. See the code snippet below.

public IActionResult Privacy()
         {
             _logger.LogInformation("This is the Privacy Page");
         try
         {
             int s = int.Parse("error"); //Test excemption
         }
         catch (Exception ex)
         {
             _logger.LogError(ex, "Exception found in Privacy page");
         }
         return View();
     }

V. Console logging

This time, let’s try to run our application using a console to logging. And see if we can output the logs that we set on our HomeController.

  1. Instead of using IIS Express in running your application, please select the option with your project name on it. See the image below.
Logging in ASP NET Core - Run console application

2. Running your application using this option will open up a new console window and a browser. A console window will log the error and information from our web application. The expected result should be as shown below.

  • _logger.LogInformation(“This is the homepage!”);
  • _logger.LogInformation(json_value);
  • _logger.LogInformation(“This is the Privacy Page”);
  • _logger.LogError(ex, “Exception found in Privacy page”);
Logging in ASP NET Core- Logs
Console logging

VI. Logging To File

Console logging is not an option when you are about to deploy your web application. This is where we need to use a third-party extension to write our logs on a file. It could be a JSON or an actual text file. ?In this tutorial, we are going to use Nlog.

  1. If you remember, we created nlog.config. This is where we will create a target and a rule to write our log in a file. Place the code below inside <targets> tag. See the code snippet below for the target on writing logs to file.
 <target xsi:type="File" name="alldata" 
             fileName="D:test_projectDemoLogsdemo-${shortdate}.log" 
             layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}" /> 

2. Now, add rule to your nlog.config. This rule will execute the target with name alldata.

 <logger name="*" minlevel="Trace" writeTo="alldata" /> 

3. Run your Web Application again. You should be able to see a log file under the directory that you set which in my case it’s in D: » test_project » Demologs. See the image below.

Logging in ASP NET Core - Write to file using Nlog

Nlog configuration should now look like this.

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autoReload="true" internalLogLevel="info" internalLogFile="internalLog.txt" internalLogToConsole="true">
  <extensions>
    <add assembly="NLog.Web.AspNetCore" />
  </extensions>
  <!-- the targets to write to -->
  <targets>
        <target xsi:type="File" name="alldata" 
             fileName="D:test_projectDemoLogsdemo-${shortdate}.log" 
             layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}" /> 
  </targets>
  <!-- rules to map from logger name to target -->
  <rules>
     <logger name="Microsoft.*" minlevel="Info" final="true" /> 
       <logger name="*" minlevel="Trace" writeTo="alldata" /> 
  </rules>
</nlog>

VII. Logging to a JSON File

Now, let’s try to write the logs using a JSON Layout.

  1. Use the target format from the code snippet below.
 <target name='jsonFile' type='File' fileName='D:test_projectDemoLogstry-${shortdate}.json'>
       <layout type='JsonLayout'>
         <attribute name='time' layout='${longdate}' />
         <attribute name='level' layout='${level:upperCase=true}'/>
         <attribute name='Properties' encode='false'  >
           <layout type='JsonLayout'>
             <attribute name='message' layout='${message}' />
             <attribute name='exception' layout='${exception}' />
           </layout>
         </attribute>
       </layout>
     </target> 

2. Add the code snippet rule below.

<logger name="*" minlevel="Info" writeTo="jsonFile" /> 

3. Run your application again. It should create another file, just like the image I added below.

Json Layout of NLog
Json File Logs

Nlog Configuration full code snippet.

<?xml version="1.0" encoding="utf-8" ?>
 <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autoReload="true" internalLogLevel="info" internalLogFile="internalLog.txt" internalLogToConsole="true">
   <extensions>
     <add assembly="NLog.Web.AspNetCore" />
   </extensions>
   <!-- the targets to write to -->
   <targets>
  
     <target name='jsonFile' type='File' fileName='D:test_projectDemoLogstry-${shortdate}.json'>
       <layout type='JsonLayout'>
         <attribute name='time' layout='${longdate}' />
         <attribute name='level' layout='${level:upperCase=true}'/>
         <attribute name='Properties' encode='false'  >
           <layout type='JsonLayout'>
             <attribute name='message' layout='${message}' />
             <attribute name='exception' layout='${exception}' />
           </layout>
         </attribute>
       </layout>
     </target>
   </targets>
   
   <!-- rules to map from logger name to target -->
   <rules>
     <logger name="Microsoft.*" maxLevel="Info" final="true" />
     <logger name="*" minlevel="Info" writeTo="jsonFile" />
     
   </rules>
 </nlog> 

VIII. Logging to a Database

This time, we will add our logs to the database, instead of writing to a file. Below is the table that I created for this tutorial. You can add additional columns if you want, but I only added three columns for the sake of this tutorial.

Database structure

You can use the SQL Query below to create the SQL table shown above.

USE [NlogDemo]
 GO

 SET ANSI_NULLS ON
 GO
 SET QUOTED_IDENTIFIER ON
 GO
 CREATE TABLE [dbo].[Nlogs](
     [Date] [datetime] NOT NULL,
     [Level] [int] NULL,
     [Message] varchar NULL
 ) ON [PRIMARY]
 GO
  1. If you remember, we set our connection string inside appsettings.json. We are going to use this in our Nlog config.
"ConnectionStrings": {
     "default": "Data Source=DESKTOP-4DU98BISQLEXPRESS01;Initial Catalog=NlogDemo;User ID=freecode;Password=freecodespot;
   }

2. Since we added NLog.Appsettings.Standard package. We can call the connection string from appsettings.json using the code snippet below.

${appsettings:name=ConnectionStrings.default}

3. Add code snippet below inside your nlog config <targets> tag.

<target name="dbase" xsi:type="Database"
       dbProvider="Microsoft.Data.SqlClient.SqlConnection, Microsoft.Data.SqlClient"
       connectionString="${appsettings:name=ConnectionStrings.default}">
       <commandtext>INSERT INTO Nlogs VALUES(@date, @lvl, @msg)</commandtext>
       <parameter name="@date" layout="${date}" dbType="SqlDbType.DateTime" />
       <parameter name="@lvl" layout="${level}" dbType="DbType.Int32" />
       <parameter name="@msg" layout="${message}" dbType="SqlDbType.VarChar" size="300" />
   </target> 

4. Add this rule to execute the dbase target.

 <logger name="*" minlevel="Trace" writeTo="dbase" /> 

5. If you could not write to the database, check the error summary inside internalLogFile of your Nlog configuration. Also, check your database connection string if it is pointing to the right database.

Logging in ASP NET Core - internalLog for Nlog exception
internalLog.txt

6. Now, if you run your web application you should now be able to see the logs inside your table.

Logging in ASP NET Core - Database Logs for Nlog

Nlog Configuration full code snippet:

 <?xml version="1.0" encoding="utf-8" ?>
 <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       autoReload="true" internalLogLevel="info" 
       internalLogFile="internalLog.txt" 
       internalLogToConsole="true">
   <extensions>
     <add assembly="NLog.Web.AspNetCore" />
   </extensions>
   <!-- the targets to write to -->
   <targets> 
     <target name="dbase" xsi:type="Database"
       dbProvider="Microsoft.Data.SqlClient.SqlConnection, Microsoft.Data.SqlClient"
       connectionString="${appsettings:name=ConnectionStrings.default}">
       <commandtext>INSERT INTO Nlogs VALUES(@date, @lvl, @msg)</commandtext>
       <parameter name="@date" layout="${date}" dbType="SqlDbType.DateTime" />
       <parameter name="@lvl" layout="${level}" dbType="DbType.Int32" />
       <parameter name="@msg" layout="${message}" dbType="SqlDbType.VarChar" size="300" />
     </target> 
   </targets>
   
   <!-- rules to map from logger name to target -->
   <rules>
     <logger name="Microsoft.*" maxLevel="Info" final="true" />
     <logger name="*" minlevel="Trace" writeTo="dbase" />
     
   </rules>
 </nlog> 

IX. Logging to the Database using SQL Stored Procedure

Another option in writing to the database is using a stored procedure. But before we can proceed, we need to create an actual SQL stored procedure.

Below is the insert SQL Stored Procedure that I created.

USE [NlogDemo]
 GO
 SET ANSI_NULLS ON
 GO
 SET QUOTED_IDENTIFIER ON
 GO
 -- =============================================
 ALTER PROCEDURE [dbo].[insert_NLogs] 
     -- Add the parameters for the stored procedure here
     @date datetime,
     @lvl int,
     @msg varchAR(50)
 AS
 BEGIN
     -- SET NOCOUNT ON added to prevent extra result sets from
     -- interfering with SELECT statements.
     SET NOCOUNT ON;
 -- Insert statements for procedure here INSERT INTO Nlogs VALUES(@date,@lvl,@msg)
 END

This step is similar to the previous step, all you have to do to configure the targets that Instead of using this:

<target name="dbase" xsi:type="Database"
       dbProvider="Microsoft.Data.SqlClient.SqlConnection, Microsoft.Data.SqlClient"
       connectionString="${appsettings:name=ConnectionStrings.default}">
       <commandtext>INSERT INTO Nlogs VALUES(@date, @lvl, @msg)</commandtext>
       <parameter name="@date" layout="${date}" dbType="SqlDbType.DateTime" />
       <parameter name="@lvl" layout="${level}" dbType="DbType.Int32" />
       <parameter name="@msg" layout="${message}" dbType="SqlDbType.VarChar" size="300" />
     </target> 

We will use this:

 <target name="dbase" xsi:type="Database"
       dbProvider="Microsoft.Data.SqlClient.SqlConnection, Microsoft.Data.SqlClient"
       connectionString="${appsettings:name=ConnectionStrings.default}" 
       commandType="StoredProcedure"
       commandText="insert_NLogs">
       
       <parameter name="@date" layout="${date}" dbType="SqlDbType.DateTime" />
       <parameter name="@lvl" layout="${level}" dbType="DbType.Int32" />
       <parameter name="@msg" layout="${message}" dbType="SqlDbType.VarChar" size="300" />
     </target> 

Now, Nlog Configuration will look like this

<?xml version="1.0" encoding="utf-8" ?>
 <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       autoReload="true" internalLogLevel="info" 
       internalLogFile="internalLog.txt" 
       internalLogToConsole="true">
   <extensions>
     <add assembly="NLog.Web.AspNetCore" />
   </extensions>
   <!-- the targets to write to -->
   <targets> 
     <target name="dbase" xsi:type="Database"
       dbProvider="Microsoft.Data.SqlClient.SqlConnection, Microsoft.Data.SqlClient"
       connectionString="${appsettings:name=ConnectionStrings.default}" 
       commandType="StoredProcedure"
       commandText="insert_NLogs">
       
       <parameter name="@date" layout="${date}" dbType="SqlDbType.DateTime" />
       <parameter name="@lvl" layout="${level}" dbType="DbType.Int32" />
       <parameter name="@msg" layout="${message}" dbType="SqlDbType.VarChar" size="300" />
     </target> 
   </targets>
   
   <!-- rules to map from logger name to target -->
   <rules>
     <logger name="Microsoft.*" maxLevel="Info" final="true" />
     <logger name="*" minlevel="Trace" writeTo="dbase" />
     
   </rules>
 </nlog> 

You may also check the source code for this tutorial at my GitHub account coderbugzz.

X. Custom Layout Parameter

Now, here’s how you can add a custom layout parameter. You can use the below code snippet to add logs information from your Controller using the logger BeginScope.

  • KeyValuePair(property_Name, Value)

Single custom parameter:

 using (_logger.BeginScope(new[] { new KeyValuePair("referenceNo", refNo) }))
             {
                 _logger.LogInformation("Logon from {0}", refNo);
             }

Multiple Custom Parameter:

KeyValuePair[] logparam = new KeyValuePair[]
              {
                 new KeyValuePair("referenceNo", refNo),  //${mdlc:item=referenceNo}
                 new KeyValuePair("jsonparam", json_value) //${mdlc:item=jsonparam} 
             };
         using (_logger.BeginScope(logparam))         {             _logger.LogInformation("Transaction Number {0}", refNo);  //${message}
         };

Now, to access this logs from your nlog.config, you can use this.

  • ${mdlc:item=property_Name}
 <attribute name='CustomParam' layout='${mdlc:item=referenceNo}' />
 <attribute name='JsonParam' layout='${mdlc:item=jsonparam}' /> 

Your target layout should now look like this.

 <target name='jsonFile' type='File' fileName='D:test_projectDemoLogstry-${shortdate}.json'>
       <layout type='JsonLayout'>
         <attribute name='time' layout='${longdate}' />
         <attribute name='level' layout='${level:upperCase=true}'/>
         <attribute name='Properties' encode='false'  >
           <layout type='JsonLayout'>
             <attribute name='message' layout='${message}' />
             <attribute name='exception' layout='${exception}' />
             <attribute name='CustomParam' layout='${mdlc:item=referenceNo}' />
             <attribute name='JsonParam' layout='${mdlc:item=jsonparam}' />
           </layout>
         </attribute>
       </layout>
     </target> 

This is how the output JSON will look like.

Summary

An effective strategy for application monitoring is to include logging to the console, a database, and a file. Developers can acquire real-time visibility, save data for analysis, and maintain an extensive record of system activity by logging events and failures to various areas.

The effective troubleshooting, performance optimization, and improvement of the general reliability and maintainability of applications are all facilitated by this multidimensional logging method. Logging will make software developer such my self to identify and remediate errors that may occur in our application. I hope this simple how-to tutorial will help you and will be used on your future projects. Share this article if it did help you, Thank you.

KEEP CODING!!

By Steve Smith

ASP.NET Core has built-in support for logging, and allows developers to easily leverage their preferred logging framework’s functionality as well. Implementing logging in your application requires a minimal amount of setup code. Once this is in place, logging can be added wherever it is desired.

Sections:

  • Implementing Logging in your Application
  • Configuring Logging in your Application
  • Logging Recommendations
  • Summary

View or download sample code

Implementing Logging in your Application¶

Adding logging to a component in your application is done by requesting either an ILoggerFactory or an ILogger<T> via Dependency Injection. If an ILoggerFactory is requested, a logger must be created using its CreateLogger method. The following example shows how to do this:

var logger = loggerFactory.CreateLogger("Catchall Endpoint");
logger.LogInformation("No endpoint found for request {path}", context.Request.Path);

When a logger is created, a category name must be provided. The category name specifies the source of the logging events. By convention this string is hierarchical, with categories separated by dot (.) characters. Some logging providers have filtering support that leverages this convention, making it easier to locate logging output of interest. In this article’s sample application, logging is configured to use the built-in ConsoleLogger (see Configuring Logging in your Application below). To see the console logger in action, run the sample application using the dotnet run command, and make a request to configured URL (localhost:5000). You should see output similar to the following:

../_images/console-logger-output.png

You may see more than one log statement per web request you make in your browser, since most browsers will make multiple requests (i.e. for the favicon file) when attempting to load a page. Note that the console logger displayed the log level (info in the image above) followed by the category ([Catchall Endpoint]), and then the message that was logged.

The call to the log method can utilize a format string with named placeholders (like {path}). These placeholders are populated in the order in which they appear by the args values passed into the method call. Some logging providers will store these names along with their mapped values in a dictionary that can later be queried. In the example below, the request path is passed in as a named placeholder:

logger.LogInformation("No endpoint found for request {path}", context.Request.Path);

In your real world applications, you will want to add logging based on application-level, not framework-level, events. For instance, if you have created a Web API application for managing To-Do Items (see Building Your First Web API with ASP.NET Core MVC and Visual Studio), you might add logging around the various operations that can be performed on these items.

The logic for the API is contained within the TodoController, which uses Dependency Injection to request the services it requires via its constructor. Ideally, classes should follow this example and use their constructor to define their dependencies explicitly as parameters. Rather than requesting an ILoggerFactory and creating an instance of ILogger explicitly, TodoController demonstrates another way to work with loggers in your application — you can request an ILogger<T> (where T is the class requesting the logger).

[Route("api/[controller]")]
public class TodoController : Controller
{
    private readonly ITodoRepository _todoRepository;
    private readonly ILogger<TodoController> _logger;

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

    [HttpGet]
    public IEnumerable<TodoItem> GetAll()
    {
        _logger.LogInformation(LoggingEvents.LIST_ITEMS, "Listing all items");
        EnsureItems();
        return _todoRepository.GetAll();
    }

Within each controller action, logging is done through the use of the local field, _logger, as shown on line 17, above. This technique is not limited to controllers, but can be utilized by any of your application services that utilize Dependency Injection.

Working with ILogger<T>¶

As we have just seen, your application can request an instance of ILogger<T> as a dependency in a class’s constructor, where T is the type performing logging. The TodoController shows an example of this approach. When this technique is used, the logger will automatically use the type’s name as its category name. By requesting an instance of ILogger<T>, your class doesn’t need to create an instance of a logger via ILoggerFactory. You can use this approach anywhere you don’t need the additional functionality offered by ILoggerFactory.

Logging Verbosity Levels¶

When adding logging statements to your application, you must specify a LogLevel. The LogLevel allows you to control the verbosity of the logging output from your application, as well as the ability to pipe different kinds of log messages to different loggers. For example, you may wish to log debug messages to a local file, but log errors to the machine’s event log or a database.

ASP.NET Core defines six levels of logging verbosity, ordered by increasing importance or severity:

Trace
Used for the most detailed log messages, typically only valuable to a developer debugging an issue. These messages may contain sensitive application data and so should not be enabled in a production environment. Disabled by default. Example: Credentials: {"User":"someuser", "Password":"P@ssword"}
Debug
These messages have short-term usefulness during development. They contain information that may be useful for debugging, but have no long-term value. This is the default most verbose level of logging. Example: Entering method Configure with flag set to true
Information
These messages are used to track the general flow of the application. These logs should have some long term value, as opposed to Verbose level messages, which do not. Example: Request received for path /foo
Warning
The Warning level should be used for abnormal or unexpected events in the application flow. These may include errors or other conditions that do not cause the application to stop, but which may need to be investigated in the future. Handled exceptions are a common place to use the Warning log level. Examples: Login failed for IP 127.0.0.1 or FileNotFoundException for file foo.txt
Error
An error should be logged when the current flow of the application must stop due to some failure, such as an exception that cannot be handled or recovered from. These messages should indicate a failure in the current activity or operation (such as the current HTTP request), not an application-wide failure. Example: Cannot insert record due to duplicate key violation
Critical
A critical log level should be reserved for unrecoverable application or system crashes, or catastrophic failure that requires immediate attention. Examples: data loss scenarios, out of disk space

The Logging package provides helper extension methods for each LogLevel value, allowing you to call, for example, LogInformation, rather than the more verbose Log(LogLevel.Information, ...) method. Each of the LogLevel-specific extension methods has several overloads, allowing you to pass in some or all of the following parameters:

string data
The message to log.
EventId eventId
A numeric id to associate with the log, which can be used to associate a series of logged events with one another. Event IDs should be static and specific to a particular kind of event that is being logged. For instance, you might associate adding an item to a shopping cart as event id 1000 and completing a purchase as event id 1001. This allows intelligent filtering and processing of log statements.
string format
A format string for the log message.
object[] args
An array of objects to format.
Exception error
An exception instance to log.

Note

The EventId type can be implicitly casted to int, so you can just pass an int to this argument.

Note

Some loggers, such as the built-in ConsoleLogger used in this article, will ignore the eventId parameter. If you need to display it, you can include it in the message string. This is done in the following sample so you can easily see the eventId associated with each message, but in practice you would not typically include it in the log message.

In the TodoController example, event id constants are defined for each event, and log statements are configured at the appropriate verbosity level based on the success of the operation. In this case, successful operations log as Information and not found results are logged as Warning (error handling is not shown).

[HttpGet]
public IEnumerable<TodoItem> GetAll()
{
    _logger.LogInformation(LoggingEvents.LIST_ITEMS, "Listing all items");
    EnsureItems();
    return _todoRepository.GetAll();
}

[HttpGet("{id}", Name = "GetTodo")]
public IActionResult GetById(string id)
{
    _logger.LogInformation(LoggingEvents.GET_ITEM, "Getting item {0}", id);
    var item = _todoRepository.Find(id);
    if (item == null)
    {
        _logger.LogWarning(LoggingEvents.GET_ITEM_NOTFOUND, "GetById({0}) NOT FOUND", id);
        return NotFound();
    }
    return new ObjectResult(item);
}

Note

It is recommended that you perform application logging at the level of your application and its APIs, not at the level of the framework. The framework already has logging built in which can be enabled simply by setting the appropriate logging verbosity level.

To see more detailed logging at the framework level, you can adjust the LogLevel specified to your logging provider to something more verbose (like Debug or Trace). For example, if you modify the AddConsole call in the Configure method to use LogLevel.Trace and run the application, the result shows much more framework-level detail about each request:

../_images/console-logger-trace-output.png

The console logger prefixes debug output with “dbug: ”; there is no trace level debugging enabled by the framework by default. Each log level has a corresponding four character prefix that is used, so that log messages are consistently aligned.

Log Level Prefix
Critical crit
Error fail
Warning warn
Information info
Debug dbug
Trace trce

Scopes¶

In the course of logging information within your application, you can group a set of logical operations within a scope. A scope is an IDisposable type returned by calling the ILogger.BeginScope<TState> method, which lasts from the moment it is created until it is disposed. The built-in TraceSource logger returns a scope instance that is responsible for starting and stopping tracing operations. Any logging state, such as a transaction id, is attached to the scope when it is created.

Scopes are not required, and should be used sparingly, if at all. They’re best used for operations that have a distinct beginning and end, such as a transaction involving multiple resources.

Configuring Logging in your Application¶

To configure logging in your ASP.NET Core application, you should resolve ILoggerFactory in the Configure method of your Startup class. ASP.NET Core will automatically provide an instance of ILoggerFactory using Dependency Injection when you add a parameter of this type to the Configure method.

    public void Configure(IApplicationBuilder app,
        IHostingEnvironment env,
        ILoggerFactory loggerFactory)

Once you’ve added ILoggerFactory as a parameter, you configure loggers within the Configure method by calling methods (or extension methods) on the logger factory. We have already seen an example of this configuration at the beginning of this article, when we added console logging by calling loggerFactory.AddConsole.

Note

You can optionally configure logging when setting up Hosting, rather than in Startup.

Each logger provides its own set of extension methods to ILoggerFactory. The console, debug, and event log loggers allow you to specify the minimum logging level at which those loggers should write log messages. The console and debug loggers provide extension methods accepting a function to filter log messages according to their logging level and/or category (for example, logLevel => logLevel >= LogLevel.Warning or (category, loglevel) => category.Contains("MyController") && loglevel >= LogLevel.Trace). The event log logger provides a similar overload that takes an EventLogSettings instance as argument, which may contain a filtering function in its Filter property. The TraceSource logger does not provide any of those overloads, since its logging level and other parameters are based on the SourceSwitch and TraceListener it uses.

A LoggerFactory instance can optionally be configured with custom FilterLoggerSettings. The example below configures custom log levels for different scopes, limiting system and Microsoft built-in logging to warnings while allowing the app to log at debug level by default. The WithFilter method returns a new ILoggerFactory that will filter the log messages passed to all logger providers registered with it. It does not affect any other ILoggerFactory instances, including the original ILoggerFactory instance.

loggerFactory
    .WithFilter(new FilterLoggerSettings
    {
        { "Microsoft", LogLevel.Warning },
        { "System", LogLevel.Warning },
        { "ToDoApi", LogLevel.Debug }
    })
    .AddConsole();

Configuring TraceSource Logging¶

When running on the full .NET Framework you can configuring logging to use the existing System.Diagnostics.TraceSource libraries and providers, including easy access to the Windows event log. TraceSource allows you to route messages to a variety of listeners and is already in use by many organizations.

First, be sure to add the Microsoft.Extensions.Logging.TraceSource package to your project (in project.json), along with any specific trace source packages you’ll be using (in this case, TextWriterTraceListener):

  "Microsoft.AspNetCore.Mvc": "1.0.0",
  "Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
  "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
  "Microsoft.AspNetCore.StaticFiles": "1.0.0",
  "Microsoft.Extensions.Logging": "1.0.0",
  "Microsoft.Extensions.Logging.Console": "1.0.0",
  "Microsoft.Extensions.Logging.Filter": "1.0.0",
  "Microsoft.Extensions.Logging.TraceSource": "1.0.0"
},
"tools": {
  "Microsoft.AspNetCore.Server.IISIntegration.Tools": {

The following example demonstrates how to configure a TraceSourceLogger instance for an application, logging only Warning or higher priority messages. Each call to AddTraceSource takes a TraceListener. The call configures a TextWriterTraceListener to write to the console window. This log output will be in addition to the console logger that was already added to this sample, but its behavior is slightly different.

// add Trace Source logging
var testSwitch = new SourceSwitch("sourceSwitch", "Logging Sample");
testSwitch.Level = SourceLevels.Warning;
loggerFactory.AddTraceSource(testSwitch,
    new TextWriterTraceListener(writer: Console.Out));

The sourceSwitch is configured to use SourceLevels.Warning, so only Warning (or higher) log messages are picked up by the TraceListener instance.

The API action below logs a warning when the specified id is not found:

[HttpGet("{id}", Name = "GetTodo")]
public IActionResult GetById(string id)
{
    _logger.LogInformation(LoggingEvents.GET_ITEM, "Getting item {0}", id);
    var item = _todoRepository.Find(id);
    if (item == null)
    {
        _logger.LogWarning(LoggingEvents.GET_ITEM_NOTFOUND, "GetById({0}) NOT FOUND", id);
        return NotFound();
    }
    return new ObjectResult(item);
}

To test out this code, you can trigger logging a warning by running the app from the console and navigating to http://localhost:5000/api/Todo/0. You should see output similar to the following:

../_images/trace-source-console-output.png

The yellow line with the “warn: ” prefix, along with the following line, is output by the ConsoleLogger. The next line, beginning with “TodoApi.Controllers.TodoController”, is output from the TraceSource logger. There are many other TraceSource listeners available, and the TextWriterTraceListener can be configured to use any TextWriter instance, making this a very flexible option for logging.

Configuring Other Providers¶

In addition to the built-in loggers, you can configure logging to use other providers. Add the appropriate package to your project.json file, and then configure it just like any other provider. Typically, these packages include extension methods on ILoggerFactory to make it easy to add them.

  • elmah.io — provider for the elmah.io service
  • Loggr — provider for the Loggr service
  • NLog — provider for the NLog library
  • Serilog — provider for the Serilog library

You can create your own custom providers as well, to support other logging frameworks or your own internal logging requirements.

Logging Recommendations¶

The following are some recommendations you may find helpful when implementing logging in your ASP.NET Core applications.

  1. Log using the correct LogLevel. This will allow you to consume and route logging output appropriately based on the importance of the messages.
  2. Log information that will enable errors to be identified quickly. Avoid logging irrelevant or redundant information.
  3. Keep log messages concise without sacrificing important information.
  4. Although loggers will not log if disabled, consider adding code guards around logging methods to prevent extra method calls and log message setup overhead, especially within loops and performance critical methods.
  5. Name your loggers with a distinct prefix so they can easily be filtered or disabled. Remember the Create<T> extension will create loggers named with the full name of the class.
  6. Use Scopes sparingly, and only for actions with a bounded start and end. For example, the framework provides a scope around MVC actions. Avoid nesting many scopes within one another.
  7. Application logging code should be related to the business concerns of the application. Increase the logging verbosity to reveal additional framework-related concerns, rather than implementing yourself.

Summary¶

ASP.NET Core provides built-in support for logging, which can easily be configured within the Startup class and used throughout the application. Logging verbosity can be configured globally and per logging provider to ensure actionable information is logged appropriately. Built-in providers for console and trace source logging are included in the framework; other logging frameworks can easily be configured as well.


  • Логико семантические ошибки примеры
  • Логическая ошибка манхва арты
  • Логико речевая ошибка ложное основание
  • Логическая ошибка манга читать мангахаб
  • Логика управления ошибками управление проектами