- Home
- .NET tutorials
- How ASP.NET Core logging works with ILogger and LogLevel
How ASP.NET Core logging works with ILogger and LogLevel
Published: Sunday 13 March 2022
Logging is an essential part of ASP.NET Core applications. Logs can be written with the extension methods that are available in the ILogger
interface.
In-order to use logs, we can use logging providers which inherit off the ILoggerProvider
interface. ASP.NET Core has a number of logging custom providers which are built in. Alternatively, a custom provider can be created which implements the ILoggerProvider
method abstractions.
C# coding challenges
Both the ILogger
and ILoggerProvider
interfaces are in the Microsoft.Extensions.Logging
namespace, and can be used by installing the Microsoft.Extensions.Logging.Abstractions NuGet package.
We will have a look at how ASP.NET Core logging works, the different log levels that are available and how to implement logging in an ASP.NET Core application.
How logging works
When creating an ASP.NET Core project, an appsettings.json
file is created that looks similar to this:
// appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
Inside the Logging
object, there is a LogLevel
object. Within that, there are a number of JSON tokens contained within it. The token's key represents the namespace of the log level, and the value represents at what level do we start writing logs.
In-terms of log levels, it uses the LogLevel
enum which is included in the Microsoft.Extensions.Logging
namespace. These are the LogLevel
enum fields that are available, including their name, value and the ILogger
extension method we can use to write a log:
Enum name | Enum value | ILogger extension method |
---|---|---|
Trace | 0 | LogTrace |
Debug | 1 | LogDebug |
Information | 2 | LogInformation |
Warning | 3 | LogWarning |
Error | 4 | LogError |
Critical | 5 | LogCritical |
None | 6 |
The way it works in appsettings.json
is that the enum value represents the severity of the log. When we specify a LogLevel
, it will write a log at a LogLevel
inside that assembly that is equal or higher to it's enum value. (excluding the None
field). So if we write a log with a Warning
level, it would also write logs that are written with the Error
and Critical
levels.
It's also worth noting that a deeper namespace would take priority. In this example, a log would be written if it was inside the Microsoft.Hosting.Lifetime
with the Information
level.
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
However, if the log event occurred inside the Microsoft.Hosting
namespace, the log would not be written. This is because we have specified not to write logs inside the Microsoft
assembly unless it's level is set to Warning
or higher.
Adding log events
We can use dependency injection to inject the ILogger
interface as a parameter into a class like an MVC controller.
The ILogger
interface has a generic type, and we use the generic type to specify the class type that we are writing logs to.
Here is an example of how we can inject the ILogger
type instance into an MVC controller:
// HomeController.cs
public class HomeController : Controller
{
...
protected readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
...
}
As previously stated, the ILogger
interface has an extension method available for each log level. Here is an example of how to use ILogger
to write a log set with the Information
level.
// HomeController.cs
public class HomeController : Controller
{
protected readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
public IActionResult Index() {
_logger.LogInformation("This is the homepage");
return View();
}
}
Built-in logging providers
ASP.NET Core has a number of built-in logging providers available which are:
- Console
- Debug
- EventSource
- EventLog
With appsettings.json
, we can specify different log levels depending on the logging provider that we are using. Here is an example of setting the log level for all providers, and how to override it for the Console provider.
// appsettings.json
{
"Logging": {
"LogLevel": { // All providers
"Default": "Information",
"Microsoft": "Warning"
}
"Console": {
"LogLevel": { // Console provider
"Default": "Information", // Overrides preceding LogLevel:Default setting.
"Microsoft": "Trace" // Writes at Trace Level inside the Microsoft assembly
}
}
}
}
By default, the Microsoft
namespace has been set so all logging providers write a log where the LogLevel
is set with the Warning
field or higher. However, with the Console logging provider, we have overridden this so Trace
level logs are written.
In-addition, we are able to write our own logging provider by creating a custom provider. Check out the logging provider we created to write logs to text files.
See it in action
Watch our video where we demonstrate how ASP.NET Core logging works and how to configure it in the appsettings.json
file.
Moving forward with logging
Now that we know how ASP.NET Core logging works, we can start to think about what we want to log and how we can go about storing them. Logging is very important, particularly if something happens in the background. It makes it a lot easier to debug an issue with our application, and to ensure that are application is running as it should be.