Simple Serilog Tutorial

By | June 3, 2016

This is going to be a simple Serilog tutorial . I will keep this very brief because already there is enough documentation on the project website. I am writing this Serilog tutorial hoping that it might motivate people to take logging seriously. As usual I will start with WHY followed by HOW.

Update
Part 2 of this tutorial where I discuss structured logging using Serilog is now live.

WHY

One thing which always has stuck me in Software industry is the step-motherly treatment meted out to Logging and to some extent to Error handling. It is almost as if these are after thoughts.

Let us implement this cool feature.
Is it working mate?
Yeah.
Well then slap some Logging and Error handling around it mate, Won’t ya?

Error handling is a long and sad story. Which I will defer for later. But Logging? 10 years ago it “might” have been difficult to put a decent logging functionality in your code. But in today’s world it is easy. And in my books it is a criminal offence to give it step motherly treatment. Logging has come a long way. Applications now generate vast amount of logs. There are now tools to analyse these vast troves of logs to gain insights. ElasticSearchLogStashKibana (ELK stack in short) is an example.

HOW

This is the easy bit. Actually too easy. But then a few code samples will not hurt. So here we go.
I will create a simple application BatMobile.cs where I will be logging stuff.
I will be adding SeriLog package via Nuget package manager.
Serilog Tutorial

using Serilog;

namespace BatManRocks
{
    public class BatMobile
    {
        public BatMobile()
        {
            Log.Logger = new LoggerConfiguration()
                .WriteTo.File("BatMobileLogs.txt", fileSizeLimitBytes: 100)
                .CreateLogger();
        }

        public void StartEngine()
        {
            Log.Logger.Information("Engine Started");
        }

        public void LoadAmmunitions()
        {
            Log.Logger.Information("Rockets loaded");
            Log.Logger.Information("LASER armed");
            Log.Logger.Information("Guns loaded");
        }

        public void DeployTracingRadar()
        {
            Log.Logger.Information("RADAR activated");
        }

        public void TrackAndDestroy()
        {
            Log.Logger.Information("Target locked");
            Log.Logger.Information("Target locked");
        }
    }
}

The highlighted lines show a little bit of configuration that is needed.
As you can see we are going to write to a file. And then we give the name of the log file. fileSizeLimitBytes tells Serilog till what size the logs file grow. Here I am limiting it to 100 bytes. If I pass null then Serilog does not impose any limits on the log file size. Default is 1 GB.
We need to create a logger object. We can store that in the Log class itself so that it is available all across the program. Otherwise feel free to new up an instance and then use it.
Serilog supports fluent syntax and as you can see I have chosen the option of writing to a file.

I will create a simple program and will use my application there.

using BatManRocks;

namespace SerilogDemo
{
    public class JustAnotherDayInOffice
    {
        public static void Main(string[] args)
        {
            BatMobile myDailyDrive = new BatMobile();
            myDailyDrive.StartEngine();
            myDailyDrive.LoadAmmunitions();
            myDailyDrive.DeployTracingRadar();
            myDailyDrive.TrackAndDestroy();
        }
    }
}

Serilog will then generate the logs. (In the bin folder since I did not specify explicit path). Here are the contents.

2016-06-03 14:09:52.307 +10:00 [Information] Engine Started
2016-06-03 14:09:52.330 +10:00 [Information] Rockets loaded
2016-06-03 14:09:52.330 +10:00 [Information] LASER armed
2016-06-03 14:09:52.330 +10:00 [Information] Guns loaded
2016-06-03 14:09:52.330 +10:00 [Information] RADAR activated
2016-06-03 14:09:52.331 +10:00 [Information] Target locked
2016-06-03 14:09:52.331 +10:00 [Information] Target locked

See!! It is that easy. Now if you have reached here then congratulations to me and to this Serilog tutorial. Purpose has been served.

But what if you wanted more control over logging. Or want to configure where the logs are stored? Or what should be the format? Then read on.

Deep Dive

Now that we are able to log data in files what should we be doing next?

Rolling log files of course !!!
In world of Serilog it means that by default a single log file will be created everyday and data for that day will be put in that file. We just change the constructor in BatMobile.cs as shown below.

public BatMobile()
{
    Log.Logger = new LoggerConfiguration()
        .WriteTo.RollingFile("BatMobileLogs.txt", retainedFileCountLimit: 10)
        .CreateLogger();
}

Note 1: The log file created will have date stamp suffixed to the name. Something like: BatMobileLogs-20160607.txt. That way we can know what date it was generated on. Thanks Serilog.
Note 2: Serilog will keep generating files. Parameter retainedFileCountLimit tells Serilog how many log files you want in any given time. Here it is set to 10. So on 11th day, Serilog will be generating a log as usual. But to keep the log files count to 10, it will delete the day 1 log file.
Note 3: retainedFileCountLimit if passed as null will lead to unlimited retention of log files. Nothing gets deleted. Default value is 31. So if you skip this value, total count of log files will be kept at 31.

Configuring via App.config
The creators of Serilog are not very happy about configuring the logging abilites of Serilog via App.config or Web.config. They prefer doing it via code (as shown in examples above). There must be a good reason for that. And I do not know that:). To me the ability to change the logging configurations via App.config is valuable. It allows us to change logging behaviour without need to recompile the code. So the next thing we deal with is how to go about this.

First we add App.config to the application where we do the logging. This is what I will be starting off with. I am still logging to the files so as to keep continuity.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="serilog:minimum-level" value="Verbose" />
    <add key="serilog:write-to:RollingFile.pathFormat" value="C:\lab\chk\log-{Date}.txt" />
    <add key="serilog:write-to:RollingFile.retainedFileCountLimit" value="10" />
    <add key="serilog:write-to:RollingFile.fileSizeLimitBytes" value="100" />
  </appSettings>
</configuration>

The key are prefixed by serilog keyword which allows Serilog to process them without needing the introduction of any Serilog specific tag. See how I am specifying where the files will be stored and under what name.
The contents of the file BatMobile.cs now changes.

using Serilog;

namespace BatManRocks
{
    public class BatMobile
    {
        public BatMobile()
        {
            Log.Logger = new LoggerConfiguration()
                .ReadFrom.AppSettings()
                .CreateLogger();
        }

        public void StartEngine()
        {
            Log.Logger.Information("Engine Started");
        }

        public void LoadAmmunitions()
        {
            Log.Logger.Information("Rockets loaded");
            Log.Logger.Information("LASER armed");
            Log.Logger.Information("Guns loaded");
        }

        public void DeployTracingRadar()
        {
            Log.Logger.Information("RADAR activated");
        }

        public void TrackAndDestroy()
        {
            Log.Logger.Information("Target locked");
            Log.Logger.Information("Target locked");
        }
    }
}

And needless to say, the log file appears.

This is a Serilog Tutorial is a living tutorial. I will keep updating it as I get time. I will keep this Simple Serilog Tutorial simple. I have written a new post which is deep dive into the world of Advanced Structured Logging using Serilog with Elasticsearch as backend. Structured logging using Serilog is now live.

One thought on “Simple Serilog Tutorial

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.