Working With Built-in Logging Framework In ASP.NET Core

Introduction

Logging is a very critical and essential part of any software. It helps us in  the investigation of the essence of problems. Before ASP.NET Core, we had to use third party libraries for logging our application.

ASP.NET Core has built-in support for logging APIs that is able to work with various logging providers. Using these built-in providers, we can send application logs to one or more destinations and also, we can plug in third party logging framework.

To use the built in logging feature of ASP.NET Core, first we need to add dependency of "Microsoft.Extensions.Logging" to project.json file. This dependency has common logging abstractions and a few implementations. We need to add more dependencies for adding the extension of this library.

For example, we need to add "Microsoft.Extensions.Logging.Console" as a dependency for writing log into console and need to add "Microsoft.Extensions.Logging.Debug" as a dependency for writing log in debug window. After updating the project.json file, we need to perform "dotnet restore" command to restore the dependency.

Project.json

  1. {  
  2.     "version" "1.0.0-*",  
  3.     "buildOptions" {  
  4.         "preserveCompilationContext" true,  
  5.         "debugType" "portable",  
  6.         "emitEntryPoint" true  
  7.     },  
  8.     "dependencies" {},  
  9.     "frameworks" {  
  10.         "netcoreapp1.0" {  
  11.             "dependencies" {  
  12.                 "Microsoft.NETCore.App" {  
  13.                     "type" "platform",  
  14.                     "version" "1.0.1"  
  15.                 },  
  16.                 "Microsoft.AspNetCore.Server.Kestrel" "1.0.0",  
  17.                 "Microsoft.AspNetCore.Mvc" "1.0.0",  
  18.                 "Microsoft.Extensions.Logging" "1.1.0",  
  19.                 "Microsoft.Extensions.Logging.Console" "1.1.0",  
  20.                 "Microsoft.Extensions.Logging.Debug" "1.1.0",  
  21.                 "Microsoft.Extensions.Logging.Filter" "1.1.0",  
  22.                 "Microsoft.Extensions.Logging.TraceSource" "1.1.0",  
  23.             },  
  24.             "imports" "dnxcore50"  
  25.         }  
  26.     }  
  27. }  
We can also install this library using NuGet packages. Using the following command, we can install logging framework library.
  1. PM > Install - Package Microsoft.Extensions.Logging  
To enable the service of logging, we need to add the provider extension method on an instance of ILoggerFactory in "Configure" method of startup class.

Startup.cs
  1. using Microsoft.AspNetCore.Builder;  
  2. using Microsoft.AspNetCore.Hosting;  
  3. using Microsoft.AspNetCore.Http;  
  4. using Microsoft.Extensions.DependencyInjection;  
  5. using Microsoft.Extensions.Logging;  
  6. namespace WebApplication {  
  7.     public class Startup {  
  8.         public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) {  
  9.             loggerFactory.AddConsole().AddDebug();...............  
  10.         }...............  
  11.     }  
  12. }  
As we know, ASP.NET Core has built-in support for DI (Dependency Injection). So,  we can get the instance of ILogger object to controller or Middleware. Here, we need to store the instance of ILogger object to the local variable so that we can use this instance anywhere in Controller as we need.
  1. public class HomeController Controller {  
  2.     ILogger _logger;  
  3.     public HomeController(ILogger < HomeController > logger) {  
  4.         _logger = logger;  
  5.     }..........  
  6. }  
Log extension has the following methods to write log using built-in logging framework of ASP.NET Core. 
  • LogCritical    Formats and writes a critical log message.

  • LogDebug    Formats and writes a debug log message.

  • LogError    Formats and writes an error log message.

  • LogInformation    Formats and writes an informational log message.

  • LogTrace    Formats and writes a trace log message.

  • LogWarning    Formats and writes a warning log message.

In the following example, I have logged the some text using LogInformation and LogWarning method.

  1. [Route("home/LogData")]  
  2. public IActionResult LogData() {  
  3.     _logger.LogInformation("Log Information to Debug Window!");  
  4.     _logger.LogWarning("Log Warning to Debug Window!");  
  5.     return View();  
  6. }  
Output

ILoggerFactory

The ILogger interface has method "Log". Using this method, we can also log the warning, information, etc. type of message. We need to specify the log level type to this method as parameter. The log level indicates the level of severity of logging statement. For example, "error" has more severity than the "warning".

The above methods (such as LogCritical, LogInformation etc.) are extension methods of log method. They internally pass the log level. We can also call the log method instead of these extension methods. The syntax of this method is relatively complicated. Log level has following possible values. 
  • Critical
  • Debug
  • Error
  • Information
  • None
  • Trace
  • Warning

Definition of LOG method

void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)

Logging exceptions

Each logger extension method has overloads that accept exceptions as argument. Different providers handle the exception in a different manner. In the  following example, I have used warning provider to log exceptions.

Example

In the following example, the code has generated an error, “Input string was not in a correct format.” and caught and logged it as warning.
  1. [Route("home/LogException")]  
  2. public IActionResult LogException() {  
  3.     try {  
  4.         int i = 0;  
  5.         i = Convert.ToInt32("");  
  6.     } catch (Exception ex) {  
  7.         _logger.LogWarning(1000, ex, "Log exception to Debug Window!");  
  8.     }  
  9.     return View("LogData");  
  10. }  
Output

ILoggerFactory

Log filtering

This feature allows us to specify which messages should be written to a storage medium or which should be ignored, based on the log level and category.

Every extension method (such as - AddDebug and AddConsole) provides overloads that allow us to pass filtering criteria. In the following example, console provider ignores the log's below mentioned warning level.
  1. public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) {  
  2.     loggerFactory.AddConsole(LogLevel.Warning);….….….  
  3. }  
Output

ILoggerFactory

Log scopes

Logging framework allows us to group a set of logical operations within the log scope, in order to assign the same data to each log which is part of this set.

To do this, first we need to enable scope for the provider. In the following example,  I have enabled the scoping for console provider.

Startup.cs
  1. public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) {  
  2.     loggerFactory.AddConsole(includeScopes true).AddDebug();............  
  3. }  
Controller Class
  1. [Route("home/LogScope")]  
  2. public IActionResult LogScope() {  
  3.     using(_logger.BeginScope("Log Scope Example")) {  
  4.         _logger.LogInformation("Log Information to Debug Window!");  
  5.         _logger.LogWarning("Log Warning to Debug Window!");  
  6.     }  
  7.     return View("LogData");  
  8. }  
Output

Here, we can observe that every log message contains the scope information.

ILoggerFactory

Built-in logging providers

ASP.NET Core provides the following built-in providers for logging. 
  • Console
  • Debug
  • EventSource
  • EventLog
  • TraceSource
  • Azure App Service

Following providers work with ASP.NET Core logging framework

  • 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

We can also create our own provider that uses other logging frames internally or has its own logging related requirement.

Summary

ASP.NET Core provides very basic yet powerful built-in logging framework. We can integrate this with third party logging frameworks, such as Nlog, Serilog etc. We can also create our own provider based on our requirement.