DEV Community

Ali MSELMI
Ali MSELMI

Posted on • Updated on • Originally published at mselmi.net

Logging with Serilog

This blog post illustrates structured logging and the goal of using such an approach compared to the traditional way of logging (log2net, NLog),
Another follow-up article demonstrating the use of Serilog with Elasticsearch acting as a log repository and running Docker is here, if you are a Serilog novice, this blog article is for you.

Why Serilog and structured logging?

Structured logging and Serilog are different. We can store the object as it is or finely-tuned to record just the right information for optimal diagnostics depending in our use case and what we need to log, then deconstructing the object using the Serilog framework on your behalf does not need to record all of the object’s fields of interest, get them into desired string format, and then store them in log instructions.

Serilog includes many integrations that cover many cases such as:

  • Logging to console
  • Logging to file
  • Logging to data base
  • Logging to Message queues
  • Logging to logstash and elasticsearch
  • Serilog also controls the way events are captured and enriched

The use of structured logging also has other advantages:

  • We can store our logs in databases like ElasticSearch which offer quite impressive search functions on this type of data.
  • We can build KPIs around stored logs using ElasticSearch
  • We can create a dashboards with nice widgets, pie, graphics.
  • We can store our logs directly in Seq, then we can benefit from the ability to search and filter the logs using SQL like language
  • Great documentation and community
  • C# based configuration

How it works ?

Install the core Serilog package and the File sinks
In Visual Studio, open the Package Manager Console and type:

Install-Package Autofac
Install-Package Autofac.Extensions.DependencyInjection
Install-Package Microsoft.AspNetCore.Mvc.NewtonsoftJson
Install-Package Microsoft.Extensions.DependencyInjection
Install-Package Microsoft.Extensions.Hosting
Install-Package Microsoft.Extensions.Logging
Install-Package Microsoft.Extensions.Options
Install-Package Newtonsoft.Json
Install-Package Serilog
Install-Package Serilog.AspNetCore
Install-Package Serilog.Extensions.Hosting
Install-Package Serilog.Extensions.Logging
Install-Package Serilog.Settings.AppSettings
Install-Package Serilog.Settings.Configuration
Install-Package Serilog.Sinks.File

In the Main method we need to initialize Serilog and for this purpose we need to grab the configuration and configure Serilog inside the CreateSerilogLogger.

var configuration = GetConfiguration();
Log.Logger = CreateSerilogLogger(configuration);

Grab the the configuration from appsettings.json and build the Configuration object:

private static IConfiguration GetConfiguration()
{
    var builder = new ConfigurationBuilder()
        .SetBasePath(Directory.GetCurrentDirectory())
        .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
        .AddJsonFile($"appsettings.Development.json", optional: true)
        .AddEnvironmentVariables();
   return builder.Build();
        }

Configure Serilog like below:

private static ILogger CreateSerilogLogger(IConfiguration configuration)
{
     return new LoggerConfiguration()
          .MinimumLevel.Verbose()
          .Enrich.WithProperty("ApplicationContext", AppName)
          .Enrich.FromLogContext()
          .WriteTo.File("log.txt", rollingInterval: RollingInterval.Day)
          .CreateLogger();
}

Add some configuration in the appsettings.json:

{
  "Serilog": {
    "MinimumLevel": {
      "Default": "Debug",
      "Override": {
        "Microsoft": "Debug",
        "CatalogAPI": "Debug",
        "MYSHOP": "Debug",
        "System": "Warning"
      }
    }
  }
}

And finally the body of the Main method should look like this:

public static int Main(string[] args)
{
    var configuration = GetConfiguration();

    Log.Logger = CreateSerilogLogger(configuration);

    try
    {
       Log.Information("Configuring web host ({ApplicationContext})", AppName);
       var host = CreateHostBuilder(configuration, args);

       Log.Information("Starting web host ({ApplicationContext})", AppName);
       host.Run();

       return 0;
    }
    catch (Exception ex)
    {
       Log.Fatal(ex, "Program terminated unexpectedly ({ApplicationContext})!", AppName);
       return 1;
    }
    finally
    {
       Log.CloseAndFlush();
    }
}

Structured logging

The main benefit from Serilog is the structured logging feature:

The traditionnal way of logging messages into any support (file, database) was always in a unstructured way

But with Serilog we can store my information in a structured way.

In the below example we tell Serilog to replace {FirstName} with Ali and {LastName} with MSELMI, this produces not only a nice log message (as any logging framework does), but also tells Serilog to structure the data in key / value pairs, FirstName/LastName keys and theirs values.

The outcome of this feature is to store structured data into nosql databases like mongodb or Elasticsearch and we can filter, export data, create dashboards and even create useful KPIs for example.

Log.Information("Hello {FirstName} {LasttName}", "Ali", "MSELMI");

As you can see, Seq captured the events coming from Serilog in structured manner.

Seq

And now we can filter the logs using SQL-like language using structured data.

Seq

Conclusion

Log4net has served as default logging choice for the past two decades, but Serilog offered a new way of logging (Structured logging, enrichments) and C# based configuration.

In most cases, I would recommend you to use Serilog logging framework and to continue to use log4net only when you are working on legacy system

Discussion (1)

Collapse
dgouissem profile image
dgouissem

Can we utilize serilog and elastic search to log objects from javascript client side ?