Logging with Serilog
Ali MSELMI
Posted on April 20, 2020
This blog post illustrates structured logging and the goal of using such an approach compared to the traditional way of logging (log4net, 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 usingSQL
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.
And now we can filter the logs using SQL-like language using structured data.
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
Posted on April 20, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.