Skip to main content
.NET

Add logging to ASP.NET Core using Serilog - .NET6

Christian Schou

Logs are important, and Serilog makes it easy. Unfortunately, not all log records are created equal, resulting in a more challenging time for developers to debug an application. In a world where software development is crucial for the world to be fully functioning, logging often takes a backseat to unit testing and documentation.

However, logging is a very useful/powerful tool for debugging in production environments, and it provides the backend/ops teams vital data on the usage of the applications by the clients. When an application stops working or a feature suddenly returns errors or starts to crash, the logs are the place to start troubleshooting to find a quick fix for the issue(s).

In this tutorial, I will teach how easy it is to implement logging in ASP.NET Core using Serilog in an ASP.NET Core Console Application. You can of course adapt this into an API, etc... If you are ready, let's log some data from our .NET Apps to the console and a file.

What is Serilog?

Serilog is an easy-to-set-up-and-use logging library for .NET with a very clear API. Serilog adds support for structured logging, which makes it easier to troubleshoot an application.

GitHub - serilog/serilog: Simple .NET logging with fully-structured events
Simple .NET logging with fully-structured events. Contribute to serilog/serilog development by creating an account on GitHub.

With Serilog you get the option to log to multiple targets like:

  • Files
  • The Console
  • An email
  • Elasticsearch
  • Amazon
  • Azure
  • Datadog, and many other "sinks"/options

I always recommend Serilog no matter what size the application is. You can use Serilog in the most simple tiny application and the large complex enterprise solutions.

Prerequisites

All you need to follow along in this tutorial are the following:

# 1 - Create a Console Application

The first thing we have to do is create a new project. The project template I will be using for this tutorial is based on a simple .NET Core Console Application in Visual Studio.

visual studio, serilog, logging in asp.net core, serilog logging
Create new Console Application (.NET 6) macOS

# 2 - Install Dependencies

Before we start implementing code in our application we have to install some dependencies. We can install new dependencies in Visual Studio in various ways. I always prefer to use the Package Manager Console, but you can also do it through the dotnet-CLI or by using the built-in UI package manager in Visual Studio.

You can open up the NuGet Package Manager by clicking Tools --> NuGet Package Manager --> Package Manager Console to bring up the console. Inside the console, you have to run each of the below install commands for our Serilog logging project.

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

Alternatively, you can use the built-in package manager, as shown below.

nuget, package manager, visual studio, serilog, sinks, serilog logging, serilog packages
Install Dependencies in Application through NuGet Package Manager

That's it - let's move on and create a new logger for our demo project.

# 3 - Create a new logger

With the dependencies in place, we can now move on to the part where we begin to implement the Serilog logger in our .NET application. Open Program.cs and add the following code to get started with the bare minimum for Serilog to work.

using Serilog;
using Serilog.Events;
using Serilog.Formatting.Json;

Log.Logger = new LoggerConfiguration()

    // Add console (Sink) as logging target
    .WriteTo.Console()

    // Set default minimum log level
    .MinimumLevel.Debug()

    // Create the actual logger
    .CreateLogger();

Console.WriteLine("Hello, World!");

Log.CloseAndFlush();

The code is quite self-explanatory. We add a new logger with a logging configuration for our Console and set the minimum level of logs to Debug().

You can configure Serilog in six different levels for logging. Below is a list with a short explanation:

  1. Fatal - Is used for reporting errors that force the application to shut down.
  2. Error - Is only used for logging serious problems that occurred while executing some code in your program.
  3. Warning - Is used when you have to report a non-critical event. This could also be a warning about unusual behavior in the application.
  4. Information - The information level is used when you got informative messages from events in a program. This could be logs about step completion in a program or when a user is signed in. Typically a system administrator loves this kind of log level - especially when they are delivered to a Syslog Server (Yeah I have been in that chair too... I know what I am talking about 😅).
  5. Debug - Debug messages are used to extend the information level when processing data in your application.
  6. Verbose - It's in the name. The verbose level is the noisiest level. I only activate this kind of log when I have to troubleshoot an application.

If you don't specify a level inside the LoggerConfiguration(). The Information level will be used by default. As you can see it's very easy to get started implementing Serilog in your .NET Apps.

# 4 - Extend the logger configuration

I promised you to log files both to the console and into a file. To log files into a file, we need to enable that option in our LoggerConfiguration().

Serilog can be configured in two ways. You can either do it using a configuration file or programmatically. I will show you both methods in this tutorial. Personally, I prefer doing it through a configuration file because I can change the logging behavior dynamically without having to update my Program.cs file for each environment.

Extend Logging configuration programmatically

The first option is the one you can go with if you prefer the programmatically way. The below code will add the following configuration to our logging config.

  • Write two different log files. The first one will include warnings and logs based on higher severity.
  • The second log-to-file configuration will create a new log file each day and add all logs with warning levels.
  • By default, all logs from the application with debug level will be shown in the console at runtime.
using Serilog;
using Serilog.Events;
using Serilog.Formatting.Json;

Log.Logger = new LoggerConfiguration()

    // Add console (Sink) as logging target
    .WriteTo.Console()

    // Write logs to a file for warning and logs with a higher severity
    // Logs are written in JSON
    .WriteTo.File(new JsonFormatter(),
        "important-logs.json",
        restrictedToMinimumLevel: LogEventLevel.Warning)

    // Add a log file that will be replaced by a new log file each day
    .WriteTo.File("all-daily-.logs",
        rollingInterval: RollingInterval.Day)

    // Set default minimum log level
    .MinimumLevel.Debug()

    // Create the actual logger
    .CreateLogger();

Console.WriteLine("Hello, World!");

Log.CloseAndFlush();

Configure Serilog using appsettings.json

Create a new file named appsettings.json and appsettings.Development.json in the root of your project. Add the following code inside appsettings.json:

{
  "Serilog": {
    "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
    "MinimumLevel": "Debug",
    "WriteTo": [
      {
        "Name": "Console",
        "Args": {
          "outputTemplate": "[{Timestamp:HH:mm:ss} {SourceContext} [{Level}] {Message}{NewLine}{Exception}"
        } 
      },
      {
        "Name": "File",
        "Args": {
          "path": "Logs/logs.txt",
          "outputTemplate": "[{Timestamp:HH:mm:ss} {SourceContext} [{Level}] {Message}{NewLine}{Exception}",
          "formatter": {
            "type": "Serilog.Formatting.Compact.CompactJsonFormatter, Serilog.Formatting.Compact"
          }
        }
      }
    ],
    "Enrich": [
      "FromLogContext",
      "WithMachineName",
      "WithThreadId"
    ],
    "Properties": {
      "Application": "Serilog Demo"
    }
  }
}

For the appsettings.Development.json file, you just add Logs/test-logs.json instead of the default Logs/logs.json value in the path for File.

Open Program.cs and replace it with the following code.