Back to: ASP.NET Core Web API Tutorials
Logging in ASP.NET Core Web API
In this article, I will discuss Logging in ASP.NET Core Web API Application with Examples using Built-in Logging Providers. Please read our previous article discussing HTTP Methods in ASP.NET Core Web API with Examples.
What is Logging?
Logging is the process of recording information about the execution of an application. It helps developers diagnose issues, monitor application behavior, and analyze performance. These records (or logs) can include errors, warnings, informational messages, debugging details, and critical events. By maintaining a record of these activities, logging provides developers and administrators with valuable information about how their application behaves in various environments, making it easier to identify and fix issues quickly.
What is Logging in ASP.NET Core?
In ASP.NET Core, logging is a built-in framework feature that enables developers to record information about application behavior during runtime. The framework provides a structured way to capture log messages and route them to various output targets.
ASP.NET Core’s logging system is extensible, allowing developers to integrate with multiple logging providers (both Built-in and external logging providers), adjust log levels (Trace, Debug, Information, Warning, Error, Critical, etc.), and different outputs (Console, Debug, File, Database, etc.).
What Are the Logging Providers Supported in ASP.NET Core?
ASP.NET Core supports a wide range of logging providers (both built-in and from third parties). Each logging provider sends the log output to a different storage system or viewer, such as a console, debug, file, or database.
Built-in Providers:
- Console Provider: This Provider logs messages to the console (typically your terminal or the output window in Visual Studio). It is great for local development and debugging.
- Debug Provider: This Provider logs messages to the Debug output window in Visual Studio or any debugger. It is useful for local debugging scenarios.
- EventLog Provider: This Provider logs to Windows Event Log (available only on Windows). It is useful for on-premises Windows server deployments.
- Azure App Service Provider: Writes logs to Azure’s built-in logging system when hosting in Azure App Service. Allows us to view logs in the Azure portal.
Third-Party Providers:
Enables integration with popular logging frameworks for extended features and better control over log formats and destinations.
- Serilog: A popular third-party library with advanced features like structured logging, custom sinks, and various output formats.
- NLog: Another third-party library similar to Serilog, known for its rich features and flexibility.
- Log4Net: A highly configurable library used widely in .NET applications.
Note: It is also possible to create our own Custom Logging Provider. We will also discuss how to create a Custom Logging Provider in ASP.NET Core Web API Application.
What are the Different Log Levels in ASP.NET Core?
ASP.NET Core defines several built-in log levels to categorize the severity and importance of log messages. These levels help developers filter logs and identify critical issues quickly. In ASP.NET Core, the Loglevel Enum is defined in Microsoft.Extensions.Logging namespace, as shown in the image below.
The standard log levels are:
- Trace: This Log Level contains the most detailed messages. Typically used for development or troubleshooting.
- Debug: This logs information (less detailed than Trace) that is useful during development and debugging but not essential for production.
- Information: Logs general application flow details, often used to record significant events. These logs typically have long-term value.
- Warning: Messages indicating potential issues that do not currently prevent functionality but might require attention.
- Error: Logs errors that occurred during application execution and need resolution but do not cause a crash. The application can still continue running.
- Critical: The highest severity, logging critical failures that may result in data loss or application crashes, requiring immediate attention.
- None: Special level that turns off logging.
Note: When configuring logging, we can set a minimum log level. For example, if you set the minimum log level to Information, then Trace and Debug messages will be suppressed.
How Do We Implement Logging in ASP.NET Core Web API?
Implementing logging in an ASP.NET Core Web API involves setting up logging providers, injecting the logger services into the controllers or services, and using the logger service to log various types of log information. To implement logging in an ASP.NET Core Web API application, you can use the built-in logging providers provided by the framework or third-party logging providers.
Using Built-in Logging Provider in ASP.NET Core Web API:
First, we will discuss how to use the built-in logging providers and then integrate third-party logging providers like Serilog and Nlog for advanced scenarios. So, create a new ASP.NET Core Web API Project named LoggingDemo.
Configure Logging in appsettings.json
In ASP.NET Core, logging settings are typically managed within the appsettings.json file. This file allows us to define how and where log messages are recorded, and it enables us to specify different logging levels for various parts of our application or specific logging providers (like Console, Debug, etc.). By setting minimum log levels, we control which log messages are captured. So, please modify the appsettings.json file as follows:
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.AspNetCore": "Trace", "System": "Error" } }, "AllowedHosts": "*" }
Understand the Logging Configuration:
Logging: This top-level section contains the overall logging configuration. It defines how the application captures and handles log messages. By adjusting the settings in this section, we can control the detail and scope of logs generated by our application and its dependencies.
LogLevel:
Under the Logging section, the LogLevel specifies the minimum severity level that should be logged for each namespace or category. The valid log levels (from lowest to highest severity) are:
- Trace
- Debug
- Information
- Warning
- Error
- Critical
- None (disables logging)
Note: Please remember that messages at or above the specified level are captured, while messages below that level are ignored.
Default: Information:
The Default setting defines the fallback logging level for any category (particularly namespaces) not explicitly listed. Setting it to Information ensures that Information, Warning, Error, and Critical messages will be logged, but Debug and Trace messages will not. This level is commonly used to log key events without excessive detail.
Microsoft: Warning
This configuration applies to all log messages generated by components within the Microsoft namespace (which includes many of the underlying .NET and ASP.NET Core libraries). Setting this to Warning means only Warning, Error, or Critical Severity messages will be logged from these sources. This helps reduce noise from less critical informational messages provided by the framework.
Microsoft.AspNetCore: Trace
This specific setting targets Microsoft.AspNetCore namespace, which includes the ASP.NET Core web framework. Setting this to Trace captures everything, including middleware execution, routing decisions, and model binding. It is useful for in-depth debugging and troubleshooting of ASP.NET Core-specific components when you need to see precisely how requests flow through the pipeline. Note that this can generate a very high volume of logs, so it’s generally recommended only during active debugging sessions.
System: Error
This setting controls the logging behavior for components within the System namespace (core .NET runtime libraries). By setting it to Error, only error and critical logs are captured, filtering out less important messages. This helps focus on significant issues from the core libraries without being overwhelmed by messages of lower severity.
Default Logging Providers in ASP.NET Core
By default, the following built-in logging providers are configured in ASP.NET Core, where we can see the log messages:
- Console: Logs to the console window.
- Debug: Logs to the debug output.
Inject ILogger into the Web API Controller
To use logging in ASP.NET Core, we need to inject an instance of the ILogger<T> interface to the constructor of the controller or services where we want logging. So, create an empty API Controller named TestController within the Controllers folder and copy and paste the following code. This ILogger instance is type-specific, making it easy to filter logs by class.
using Microsoft.AspNetCore.Mvc; namespace LoggingDemo.Controllers { [Route("api/[controller]")] [ApiController] public class TestController : ControllerBase { // A private readonly field to hold the logger instance. // The ILogger interface allows logging at various levels (Information, Warning, Error, etc.). private readonly ILogger<TestController> _logger; public TestController(ILogger<TestController> logger) { // Constructor dependency injection to provide an ILogger instance specific to the TestController. // ASP.NET Core automatically injects the appropriate logger. // Assigns the injected logger to the private field. _logger = logger; // Logs an informational message when the controller instance is created. // Useful for confirming that the controller is up and running. _logger.LogInformation("TestController Started"); } [HttpGet] public IActionResult Get() { // Logs an informational message indicating that the "Get" method is being executed. // Helps in tracing the request flow through the application. _logger.LogInformation("Executing TestController.Get Method"); return Ok(); } } }
As you can see in the above code, we have added two log messages, one within the constructor and one within the controller’s Get action method.
Checking the Console Window:
Now, run the application using HTTP or HTTPS Launch (NOT IIS Express) Profile and access the Get endpoint. It should log the information as expected. After invoking the above endpoint, verify the Console window, and you should see the following information log message:
Checking the Debug Window:
Now, to verify the Debug window, please select Debug => Windows => Output option from the context menu, again access the endpoint and check the debug output window. You should see the log messages as shown in the below image:
ILogger<T> in ASP.NET Core Web API
In ASP.NET Core, ILogger<T> is a generic interface provided by Microsoft.Extensions.Logging namespace that simplifies integrating logging into ASP.NET Core application. The generic parameter T represents the class where the logger is being used, allowing logs to include the class name for easier traceability automatically. This makes it simple to identify where log messages originate. The following are the key features:
- Record messages at different severity levels (Trace, Debug, Information, Warning, Error, Critical).
- Include the class name in each log entry by specifying the class type T in ILogger<T>. This automatically tags each log with the name of the originating class, making it much easier to trace the message’s source.
- Integrate with multiple log providers so logs can be directed to the console, debug output window, files, databases, or third-party logging systems (like Serilog, NLog, etc.).
ILogger<T> offers a set of methods corresponding to different severity levels, each of which can be used for different diagnostic messages. The following are the available logging methods:
LogTrace()
It is used for highly detailed logs, typically for debugging purposes. It records low-level information like method entry/exit points, variable values, or other detailed trace information. This level is ideal for development and testing environments to help understand the internal state of the application. However, due to the high volume of logs, this level is generally disabled in production.
LogDebug()
LogDebug is generally used for diagnostic information but with less detail than LogTrace. Use this level to log the internal state and operations during development or testing. Debug logs provide valuable insights during troubleshooting but are typically unnecessary in production.
LogInformation()
LogInformation is designed to log general application events. It’s best suited for tracking the application’s high-level progress, such as when a service starts, when a request is successfully handled, or when a key operation is completed. These logs are often enabled in production to give an overview of the application’s behavior.
LogWarning()
LogWarning indicates a potential issue or unexpected event that isn’t critical but could lead to problems if not addressed in the future, so it requires attention. For example, if an external service takes longer to respond or if a non-critical configuration file is missing, you might log a warning.
LogError()
LogError is used when an operation fails due to an error. For example, if a database connection fails or an external API returns an unexpected status code, you would log an error. While the application might continue running, LogError entries indicate situations that require investigation and likely need fixing.
LogCritical()
LogCritical is reserved for the most serious issues and situations where the application may crash, experience significant downtime, or lose critical functionality. These logs indicate crucial issues that could impact the entire application.
Example to Understand All Methods:
The following example shows how to use the various logging methods (LogTrace, LogDebug, LogInformation, LogWarning, LogError, and LogCritical) within an ASP.NET Core Web API Controller.
using Microsoft.AspNetCore.Mvc; namespace LoggingDemo.Controllers { [Route("api/[controller]")] [ApiController] public class TestController : ControllerBase { private readonly ILogger<TestController> _logger; public TestController(ILogger<TestController> logger) { _logger = logger; } [HttpGet("all-logs")] public IActionResult LogAllLevels() { _logger.LogTrace("LogTrace: Entering the LogAllLevels endpoint with Trace-level logging."); // Simulate a variable and log it at Trace level int calculation = 5 * 10; _logger.LogTrace("LogTrace: Calculation value is {calculation}", calculation); _logger.LogDebug("LogDebug: Initializing debug-level logs for debugging purposes."); // Log some debug information var debugInfo = new { Action = "LogAllLevels", Status = "Debugging" }; _logger.LogDebug("LogDebug: Debug information: {@debugInfo}", debugInfo); _logger.LogInformation("LogInformation: The LogAllLevels endpoint was reached successfully."); // Simulate a condition that might cause an issue bool IsTakingMoreTime = true; if (IsTakingMoreTime) { _logger.LogWarning("LogWarning: External API taking More Time to Respond. Action may be required soon."); } try { // Simulate an error scenario int x = 0; int result = 10 / x; } catch (Exception ex) { _logger.LogError(ex, "LogError: An error occurred while processing the request."); } // Log a critical error scenario bool criticalFailure = true; if (criticalFailure) { _logger.LogCritical("LogCritical: A critical system failure has been detected. Immediate attention is required."); } return Ok("All logging levels demonstrated in this endpoint."); } } }
Code Explanations:
This single LogAllLevels method uses each logging level:
- Trace: Logs a detailed entry and exit point of the action method and the value of a simple calculation.
- Debug: Logs additional information useful for debugging, such as the current action and debug status.
- Information: Logs general information about the successful access to the endpoint.
- Warning: Logs a potential issue (External API taking more time to respond) to give a heads-up before it becomes a problem.
- Error: Simulates an error (division by zero) and logs it using the LogError method.
- Critical: Logs a critical failure scenario requiring immediate action, such as a critical system fault.
Now, run the application and invoke the /api/Test/all-logs endpoints. You will see the following logs in the command prompt.
Why are we not getting Trace and Debug Log messages?
You can see that we are getting the information, warning, error, and Critical log messages. But we are not getting the Trace and Debug log messages. This is because we are setting the Default Log level to Information in the appsettings.json file, as shown in the image below. So, only Information and higher log-level messages will be displayed.
Configuring Log Levels to Show All Types of Logs
Now, if you want to display all types of logs, including the Trace and Debug, you need to set the lowest log level (Trace) in the configuration file for the Default key. So, modify the appsettings.json file as follows:
{ "Logging": { "LogLevel": { "Default": "Trace", "Microsoft": "Warning", "Microsoft.AspNetCore": "Trace", "System": "Error" } }, "AllowedHosts": "*" }
After the above changes, if you are still not getting the log messages as expected, we need to check the environment-specific appsettings.json file and correct it accordingly.
ASP.NET Core supports environment-specific configuration files, such as appsettings.Development.json, appsettings.Production.json, etc. The application picks up the configuration settings from the file that matches the current environment.
Ensure the logging level is also set to Trace in the correct environment-specific configuration file. For example, if you’re running the application in development mode, please ensure appsettings.Development.json contains the appropriate logging level settings. So, please modify the appsettings.Development.json as follows:
{ "Logging": { "LogLevel": { "Default": "Trace", "Microsoft.AspNetCore": "Warning" } } }
Now, with the above changes in place, run the application, and this time, you should see the log messages as expected, as shown in the image below:
Logging Configuration Settings in the Program.cs Class File
In ASP.NET Core, we can also configure logging settings in the Program.cs class file (NOT Recommended). This approach allows us to programmatically set up log levels and logging providers according to the environment or specific requirements. So, for a better understanding, please modify the Program class as follows. The following code is self-explained, so please read the comment lines for a better understanding.
namespace LoggingDemo { public class Program { public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); // Configure logging provider builder.Logging.ClearProviders(); // Optional: Clears default loggingproviders builder.Logging.AddConsole(); // Adds console logging provider builder.Logging.AddDebug(); // Adds Debug logging provider // Set specific log levels for different librarues builder.Logging.SetMinimumLevel(LogLevel.Information); // Default minimum level builder.Logging.AddFilter("Microsoft", LogLevel.Warning); // For Microsoft.* namespaces builder.Logging.AddFilter("Microsoft.AspNetCore", LogLevel.Warning); // For ASP.NET Core builder.Logging.AddFilter("System", LogLevel.Warning); // For System.* namespaces builder.Logging.AddFilter("YourApp.Namespace", LogLevel.Trace); // For your custom namespace var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run(); } } }
Logging Configuration Code Explanation
- ClearProviders(): This method clears all the logging providers added by default. It’s optional but can be useful if you want to have full control over which logging providers are being used.
- AddConsole(), AddDebug(): These methods add console and debug logging providers.
- SetMinimumLevel(): This method sets the application’s default minimum log level. Only logs at this level and higher will be included.
- AddFilter(): This method allows you to specify log levels for specific categories or namespaces.
So, with the above changes in place, run the application, access the API endpoint, and verify the console window. You should see the following messages.
We see all the log messages, including Debug and Trace levels. This is due to the logging configuration in the appsettings.json file. Specifically, the “Default” log level is set to “Trace” in the appsettings.json file, which overrides the minimum log level we have set in the Program class. So, you can remove the logging configuration from the app settings and environment-specific app setting file and then run the application, and you should see the expected output.
Performance Implications of Logging in ASP.NET Core
While logging is essential, it can introduce some performance overhead. While it is generally lightweight, excessive logging (e.g., extensive use of Trace or Debug levels) can slow down the application and increase resource consumption. It’s crucial to:
- Use appropriate log levels for different environments (e.g., Information or Warning in production).
- Avoid logging inside tight loops or performance-critical code paths.
- Consider asynchronous logging approaches and offloading logs to external storage or processing systems.
- If you log into files, plan how frequently to rotate logs and how long you keep them. Excessive logs can eat up disk space.
- Writing logs to external resources (like files or databases) might involve expensive I/O operations. Buffering or batching log writes can help improve performance.
Note: Third-party logging frameworks like Serilog and NLog can improve performance by supporting features like batching and asynchronous logging. However, they also introduce complexity.
Can we store the log in a file or database using the Default Logging Provider?
By default, ASP.NET Core’s built-in providers (e.g., Console, Debug) do not directly support writing logs to files or databases. To store logs in files or databases, you’ll typically:
- Use Third-Party Providers: Integrate with frameworks like Serilog, NLog, or Log4Net, which provide robust support for writing logs to various destinations, including files, databases, and remote logging services.
- Custom Implementation: Write your own logging provider that implements ILoggerProvider and ILogger. This approach allows you to route logs to any storage medium but requires additional effort and maintenance.
Logging in ASP.NET Core is a powerful tool that, when used effectively, can significantly improve your application’s maintainability, performance monitoring, and troubleshooting capabilities. By using built-in logging providers, we can build a robust logging infrastructure. While the default providers do not support file or database logging directly, third-party integrations like Serilog and NLog provide extensive options to meet your needs.
In the next article, I will discuss How to Implement a Custom Logging Provider in ASP.NET Core Web API with an Example. In this article, I explain how to log in to the ASP.NET Core Web API Application with examples. I hope you enjoy this article, Logging in ASP.NET Core Web API.
how to ennable the nlog