Course Content
About Minimal APIs
0/1
Naming Conventions
0/1
Implementing the Result Pattern in Minimal APIs
0/2
Minimal APIs in ASP.NET Core

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.

0% Complete