In this article, firstly we will explore how to integrate the Serilog logging package with Microsoft’s ILogger API. We will then compare the output of both logging methods to highlight the difference. If you’re new to Serilog, we recommend reading our article Structured Logging in ASP.NET Core with Serilog to gain a better understanding before proceeding.

To download the source code for this article, you can visit our GitHub repository.

Let’s begin.

Support Code Maze on Patreon to get rid of ads and get the best discounts on our products!
Become a patron at Patreon!

Using Microsoft’s ILogger<T>

Let’s start by creating a .NET 8 Core Web API project.

Navigate to the WeatherForecastController class within the project and open it. Let’s take a look at the predefined code:

private static readonly string[] Summaries = new[]
{
    "Freezing", "Bracing", "Chilly", "Cool", "Mild",
    "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

private readonly ILogger<WeatherForecastController> _logger;

public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
    _logger = logger;
}

Here, we observe that the ILogger<WeatherForecastController> is being injected into the constructor of the WeatherForecastController class. This dependency injection utilizes Microsoft’s ILogger API.

Now let’s add some logging to the Get() method:

[HttpGet(Name = "GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get()
{
    _logger.LogInformation("Processing GetWeatherForecast...");

    return Enumerable.Range(1, 5).Select(index => new WeatherForecast
    {
        Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
        TemperatureC = Random.Shared.Next(-20, 55),
        Summary = Summaries[Random.Shared.Next(Summaries.Length)]
    })
    .ToArray();
}

Let’s run the application and observe the output in the console:

info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://localhost:5066
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
Content root path: CodeMaze\CodeMazeGuides\dotnet-logging\...
info: UsingSerilogWithMicrosoftILogger.Controllers.WeatherForecastController[0]
Processing GetWeatherForecast...

This output confirms that the default logging is functioning as expected. Additionally, if we use Swagger to make a call to /WeatherForecast, we see the log message Processing GetWeatherForecast... displayed in the console.

Installing and Configuring Serilog

Now, let’s add the Serilog to our project by installing the Serilog.AspNetCore NuGet package.

To redirect the ASP.NET Core logs through Serilog, we need to configure it. Let’s open the Program.cs class and insert the highlighted lines:

public static void Main(string[] args)
{
    var builder = WebApplication.CreateBuilder(args);

    builder.Host.UseSerilog((context, loggerConfiguration) =>
    {
        loggerConfiguration.WriteTo.Console();
    });

    builder.Services.AddControllers();
    // .. removed for brevity
}

Now, we can run the application and verify that the console output has changed, providing more detail for every request made when running the application:

[09:43:18] Now listening on: http://localhost:5066
[09:43:18] Application started. Press Ctrl+C to shut down.
[09:43:18] Hosting environment: Development
[09:43:18] Content root path: CodeMaze\CodeMazeGuides\dotnet-logging\...
[09:43:21] Request starting GET http://localhost:5066/swagger/index.html
[09:43:21] Request finished GET http://localhost:5066/swagger/index.html - 200 text/html 214.7841ms
[09:43:21] Request starting GET http://localhost:5066/_framework/aspnetcore-browser-refresh.js
[09:43:21] Request starting GET http://localhost:5066/_vs/browserLink
[09:43:21] Request finished GET http://localhost:5066/_framework/aspnetcore-browser-refresh.js
[09:43:21] Request finished GET http://localhost:5066/_vs/browserLink - 200 text/javascript 34.8047ms
[09:43:21] Request starting GET http://localhost:5066/swagger/v1/swagger.json
[09:43:21] Request finished GET http://localhost:5066/swagger/v1/swagger.json - 200 application/json; 69.9914ms
[09:43:24] Request starting GET http://localhost:5066/WeatherForecast
[09:43:24] Executing endpoint 'UsingSerilogWithMicrosoftILogger.Controllers.WeatherForecastController.Get'
[09:43:24] Route matched with {action = "Get", controller = "WeatherForecast"}. Executing controller action ...
[09:43:24] Processing GetWeatherForecast...
[09:43:24] Executing ObjectResult, writing value of type 'UsingSerilogWithMicrosoftILogger.WeatherForecast[]'.
[09:43:24] Executed action UsingSerilogWithMicrosoftILogger.Controllers.WeatherForecastController.Get in 18.6175ms
[09:43:24] Executed endpoint 'UsingSerilogWithMicrosoftILogger.Controllers.WeatherForecastController.Get'
[09:43:24] Request finished GET http://localhost:5066/WeatherForecast - 200 application/json 56.9516ms

Conclusion

In this article, we have delved into the straightforward process of using Serilog with Microsoft’s ILogger. By leveraging dependency injection in conjunction with the ILogger interface, we can seamlessly integrate Serilog into our solution without requiring extensive modifications to our existing codebase.

Serilog stands out for its extensive features and minimal configuration requirements compared to other logging libraries. It offers structured logging and versatile logging sinks such as to a file, to the console, to a database, and many more.

Liked it? Take a second to support Code Maze on Patreon and get the ad free reading experience!
Become a patron at Patreon!