How To Implement Serilog In ASP.NET Core Web API

SeriLog is one of developers' most popular and widely used logging libraries for .NET applications. It offers several benefits compared to other logging libraries available on the market.

What is Logging?

Logging is an essential part of any application. It helps developers understand what's happening in the application, diagnose, and troubleshoot problems.

Why do you need to consider Serilog instead of other logging libraries?

Scalability and Performance

Serilog is designed to handle large volumes of log data efficiently. Serilog is well optimized for performance. It was also designed with minimal impact on the application's performance while logging through features such as asynchronous logging, lazy message generation, and support for log message batching.

Extensibility

Serilog is highly extensible, and it has more than 90+ provided sinks, including popular logging services such as

  • Amazon DynamoDB
  • Azure Blob Storage
  • Azure CosmosDB
  • ElasticSearch
  • Google Cloud StackDriver
  • MariaDB
  • MongoDB
  • PostgreSQL
  • SQLite
  • SQL Server and so on

Serilog provides an advanced plug-in architecture that allows developers to extend the library with custom sinks and enrichers. It includes general-purpose sinks such as file and console sinks. In the following example, you will learn how to log messages in a file and on the console.

You can see more details about provided sinks in Serilog here.

Flexible and structured logging

Serilog provides a simple and flexible logging API that allows us to capture structured logs in various formats, including JSON, plain text, and XML.

It helps you and your team analyze the application, and you can use that data to make a more optimized version of your application.

Integration with popular .NET frameworks: 

Serilog is most popularly used within the .NET community, and it has built-in integration with popular .NET frameworks, such as ASP.NET Core, Entity Framework, and Microsoft.Extensions.Logging.

Community Support:

Serilog is backed by a large community of active developers who contribute to the development of the framework. They are always ready to share knowledge and provide support. You can see more about it in Github repos here.

How to Configure the Serilog

In this article, I'm giving two examples. The First example shows how to log the information to a text file using File Sink, and the second example shows how to log the information to Console and a Text file using a separate configuration JSON file for Serilog with the help of Console and File Sinks.

You can clone My Github Repository to try this example here

Open Visual Studio Application → create a new project → select ASP.NET Core Web API Template → Give a name for your Project → Also make sure .NET 6.0 is selected in Framework dropdown additional information page → Click Create 

After the project is created, try to run the project → Debug or Press F5. It will open a Swagger API Web Page in the New Browser window, and you will see the console like in the image below.

How to implement Serilog in ASP.NET Core Web API

How to install Serilog dependencies

You need to install dependencies before implementing the code. You can do this in two ways one is through GUI, and another one is through Package Manager Console.

GUI

In Solution Explorer Window → your project name → Dependencies → right-click Packages → Manage NuGet Packages.

It opens the NuGet package manager in that browse tab → search for Serilog.AspNet.Core → install that package as shown in the image below.

How to implement Serilog in ASP.NET Core Web API

Package Manager Console

You can also install dependencies through Package Manager Console. To do this, click Tools → NuGet Package Manager → Package Manager Console. It brings the console and executes the following commands to install Serilog dependencies.

Install-Package Serilog
Install-Package Serilog.Sinks.Console
Install-Package Serilog.Sinks.File

Log the information to a text file using the serilog file sink

I will log the information to a text file using the serilog file sink in this first example.

Open program.cs file. Change the code in that file, which is given below.

using Serilog;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

var logger = new LoggerConfiguration()
    .ReadFrom.Configuration(builder.Configuration)
    .Enrich.FromLogContext()
    .CreateLogger();
builder.Logging.ClearProviders();
builder.Logging.AddSerilog(logger);
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Open appsettings.json, and Change the code in that file, which is given below.

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "Serilog": {
    "Using": [ "Serilog.Sinks.File" ],
    "MinimumLevel": {
      "Default": "Information"
    },
    "WriteTo": [
      {
        "Name": "File",
        "Args": {
          "path": "../logs/webapi-.log",
          "rollingInterval": "Day",
          "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} {CorrelationId} {Level:u3} {Username} {Message:lj}{Exception}{NewLine}"
        }
      }
    ]
  }
}

In the Solution Explorer window → Controllers → WeatherForecastController.cs. Replace the following code.

using Microsoft.AspNetCore.Mvc;

namespace SerilogTutorial.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        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;
        }

        [HttpGet(Name = "GetWeatherForecast")]
        public IEnumerable<WeatherForecast> Get()
        {

            _logger.LogInformation("Seri Log is Working");

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

Debug the project Press F5.

It opens a SwaggerAPI Page in the browser, try to hit the GetWeatherForecast Endpoint. 

How to implement Serilog in ASP.NET Core Web API

It creates a logs folder in your Project folder and a webapi txt file inside it. If you open that webapi txt file, it contains the project log.

How to implement Serilog in ASP.NET Core Web API

How to implement Serilog in ASP.NET Core Web API

How to configure Serilog Properties in a separate JSON file instead of an appsettings.json file?

In this example, It will log information in the file and console using a separate configuration file for Serilog properties. If you want to try the second example, please follow the steps of the first example. It contains the basic configuration of the Serilog, or you can clone my Github repo using the link given above.

You need to add one JSON file for this scenario. In the Solution explorer window → right-click the project name → add → New Item → select JSON file. I added a JSON file name as seri-log.config.json.

How to implement Serilog in ASP.NET Core Web API

I added the code in the given code snippet. Paste this code into that file

{
  "Serilog": {
    "Using": [ "Serilog.Sinks.File", "Serilog.Sinks.Console" ],
    "MinimumLevel": {
      "Default": "Information"
    },
    "WriteTo": [
      {
        "Name": "File",
        "Args": {
          "path": "../logs/webapi-.log",
          "rollingInterval": "Day",
          "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} {CorrelationId} {Level:u3} {Username} {Message:lj}{Exception}{NewLine}"
        }
      },
      {
        "Name": "Console",
        "Args": {
          "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] {Message}{NewLine}{Exception}"
        }
      }
    ]
  }
}

It has two sinks one is a file that will log the information in a text file, and another is a console that will log the information in the console.

Also, you need to change the program.cs file code that will read the configuration from the newly created json file. That code is also given in the code snippet.

using Serilog;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

//logger 

var logger = new LoggerConfiguration()
    .ReadFrom.Configuration(new ConfigurationBuilder()
    .AddJsonFile("seri-log.config.json")
    .Build())
    .Enrich.FromLogContext()
    .CreateLogger();
builder.Logging.ClearProviders();
builder.Logging.AddSerilog(logger);

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

After following the steps, press F5

Now the log information shows in the console, too.

How to implement Serilog in ASP.NET Core Web API

Methods and Serilog Properties Explanations

new LoggerConfiguration() - This method creates a new LoggerConfiguration object that will be used to configure the Serilog logger.

ReadFrom.Configuration(builder.Configuration) - This method configures the logger based on the application's configuration. This method uses the builder.Configuration object to read the configuration settings and apply them to the logger.

Enrich.FromLogContext() - This method adds contextual information to log events. This will allow log events to be enriched with additional information, such as the name of the current method or the user that initiated the event.

CreateLogger() - This method is used to create the Serilog logger.

builder.Logging.ClearProviders() - It can be called on an instance of ILoggerFactory in a .NET application to remove all the logging providers from the logging pipeline.

builder.Logging.AddSerilog(logger) - This method is used to add a Serilog logger to the logging pipeline of a .NET application.

AddJsonFile("seri-log.config.json") - Configuration object that reads from a JSON file named "seri-log.config.json" (using the AddJsonFile() method) and then passes that configuration object to the ReadFrom.Configuration() method.

Build() - After loading the configuration file, it can be built into a Configuration object by calling the Build().

Using: This property is an array of strings specifying the Serilog packages the logger will use.

MinimumLevel: This is an important property you must remember while configuring the Serilog. This property specifies the minimum logging level for the logger. Serilog has 6 level minimum levels.

  • Verbose: It is used to track the low level of severity. It is the noisiest level. It is rarely enabled for a production app.
  • Debug: Debug is mostly used by the developer team to know about your application's internal events that are not necessarily observable from the outside.
  • Information: Information is used for logging the general information on how the flow happens in your application.
  • Warning: Warning is used for logging the information not needed to take immediate action now, but those may need attention future.
  • Error: Error is used for logging functionality not working or broken. These types need immediate attention.
  • Fatal: Fatal logs critical level that will cause an application crash. This types also need immediate attention.

Example: If you choose a higher level, it will log the lower level by default. If you choose minimum level as Warning, it logs warning, information, Debug, and Verbose level Details.

WriteTo: This property is an array of objects that specifies the log sinks to which the log events will be written.

Name: This property specifies the name of the sink.

Path: the property is used to specify the path to the log file that the File sink will write.

RollingInterval - property is used to specify how often to create a new log file. The log file name will include the date in the format specified by the rollingInterval property, with the specified file path and extension.

OutputTemplate - property accepts a string value that can include placeholders for various information associated with each log event. It contains the following placeholders in this example,

{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}: The date and time of the log event, in the format yyyy-MM-dd HH:mm:ss.fff zzz.

{CorrelationId}: A unique identifier for the request or operation associated with the log event, if one is available.

{Level:u3}: The log level of the event, abbreviated to three characters.

{Username}: The username associated with the request or operation, if one is available.

{Message:lj}: The log message associated with the event is left-justified and trimmed to fit within the maximum message length.

{Exception}: Any exception that is associated with the log event.

{NewLine}: A new line character.

Summary

Serilog is easy to use and configure and implement the structured logging in your .net application. It provides a wide variety of sinks that allow us to log your application information based on your needs easily. You will understand your application's events, errors, and performance metrics based on that information. In hard times it helps to troubleshoot application issues. If you are looking for a good logging framework, it's worth giving it a try to Serilog.


Similar Articles