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.
Let’s begin.
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.