In our project, we’ll use the Serilog
library.
Of course, we need to install it before we implement our logging service. To do that, let’s navigate to the ProjectManagement.LoggingService
project, right-click on it, and select Open in Terminal
to install three packages:
dotnet add package Serilog.Sinks.Console --version 6.0.0 dotnet add package Serilog.Sinks.File --version 6.0.0 dotnet add package Serilog.AspNetCore --version 8.0.3
As we want to log our messages to a file and the console, the first two packages, Serilog.Sinks.Console
and Serilog.Sinks.File
, will help us with that.
Next, we install the Serilog.AspNetCore
package. We’ll inject an ILogger
instance in our custom logging class and need the latter package to route ASP.NET Core log messages to get information about ASP.NET’s internal operations written to the same Serilog
sinks as our application events.
Alternatively, you can use the Package Manager to install the required libraries. To open the Package Manager Console in Visual Studio, select Tools > NuGet Package Manager > Package Manager Console from the top menu:
Install-Package Serilog.Sinks.Console -Version 6.0.0 Install-Package Serilog.Sinks.File -Version 6.0.0 Install-Package Serilog.AspNetCore -Version 8.0.3
Another option would be to open the NuGet Package Manager and install the packages via the user interface.
Once, we have the packages installed, let’s navigate to our main project, open the appsettings.json
file, and configure how logging will work:
{ "Serilog": { "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ], "MinimumLevel": { "Default": "Information" }, "WriteTo": [ { "Name": "Console", "Args": { "OutputTemplate": "[{Timestamp:HH:mm:ss} {Level:u11}] {Message:lj}{NewLine}" } }, { "Name": "File", "Args": { "Path": "logs/log-.txt", "RollingInterval": "Day", "OutputTemplate": "[{Timestamp:HH:mm:ss} {Level:u11}] {Message:lj}{NewLine}" } } ] }, "AllowedHosts": "*" }
We start by removing the Logging
section and creating a new one called Serilog
. Then, in the Using
section, we specify the two sinks – Serilog.Sinks.Console
for logging into the console and Serilog.Sinks.File
for logging into a file. In the next section, we set the minimum log level to information. This is a good practice when we are still developing our API, in production, the debug level is preferred when we want to debug the flow. This can be very useful when something breaks in production and of course, we can’t debug the app there.
Next, in the WriteTo
section, we define the destinations of our log messages. For the console, we want logs to be output with a specific template that includes the timestamp in hours, minutes, and seconds ({Timestamp:HH:mm:ss}
), the log level is formatted to a width of 11 characters ({Level:u11}
), the log message ({Message:lj}
), and a new line after the log message ({NewLine}
).
Similarly, for the file logging, we want the logs to be written to a path specified as logs/log-.txt
. This will save the log files inside the logs
folder in our main project. We also want a new file created each day so we configure this with the RollingInterval
set to Day
. Finally, we specify that the file log entries should follow the same template as the console logs.
Next, let’s open the Program
class:
using ProjectManagement.Contracts; using ProjectManagement.LoggingService; using Serilog; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Host.UseSerilog((hostContext, configuration) => { configuration.ReadFrom.Configuration(hostContext.Configuration); }); var app = builder.Build(); // Configure the HTTP request pipeline. app.UseHttpsRedirection(); app.Run();
We call the UseSerilog()
method overload with the Action<HostBuilderContext, LoggerConfiguration>
parameter. Inside the method’s body, we use the configuration parameter with the ReadFrom
property and call the Configuration()
method to read all the necessary configurations for the logger. To provide that configuration, we use the Configuration
property that represents the source configuration file – our appsettings.json
file. This will apply all of our configurations to Serilog
.
NOTE: As you can see, Serilog
uses something called “sinks” to configure where our logs will be written to. In our case, we use the Console
and the File
sinks but there are a lot more options available. For example, we can opt to log into databases as well as various AWS and Azure services.
By using Serilog
we also get HTTP
request logging by default which helps us easily see what requests are made to our application.