Serilog vs NLog
Serilog is often referred to as the new logging framework on the .NET platform, while NLog is considered "the old one" (together with log4net). With Serilog introduced back in 2013 and NLog in 2006, they both have a long history and a great community around them. I have worked with both logging frameworks and in this post, I will try to give you an overview of each framework, the differences, and some recommendations to look for when choosing a logging framework.
Let's start with a bit of information about each framework.
Serilog
Serilog was initially created by Nicholas Blumhardt back in 2013. When it came out, it sort of revolutionized the .NET logging space by introducing structured logging. All previous frameworks more or less treated log messages as concatenated strings. With more NoSQL databases like MongoDB and Elasticsearch beginning to pop up, the community was in need of something able to utilize the new features and ways of structure data that came a long the NoSQL-movement.
Over the years, Serilog is, without a doubt, the .NET logging framework that has grown the fastest. New commits are happening daily and there is a large community around the framework.
NLog
NLog has a similar story to Serilog. Back in 2006, log4net was the dominant framework and no real alternatives existed. NLog changed that with a cleaner API and better ways of configuring what to log where. I remember back in 2007 when I first heard about NLog. I have a background in Java (feels so dirty, I know!) and was using the log4j framework, which log4net was heavily inspired by. NLog was the first framework that really started using .NET features and not just another Java to .NET migration.
Over the years, NLog also developed a lot. I must admit that I gave up following and using the framework a few years back and I expected the project to die. But, as it turns out, I was wrong and the framework is as strong as ever with recent additions like support for structured logging.
Configuration
To start looking into similarities and differences, let us dive into the first part you will need to start logging: configuration.
Serilog
One of the nice features about Serilog is its strongly typed (written in C#) configuration language. While XML configuration is also supported, I don't see much benefit in using it. This is a very simple example of how to configure Serilog to write log messages to a file:
Log.Logger = new LoggerConfiguration()
.WriteTo.File("log-.txt", rollingInterval: RollingInterval.Day)
.CreateLogger();
The configuration is built using the LoggerConfiguration
class and by calling one or more WriteTo.*
methods. Most logging frameworks refer to logging destinations as appenders or targets. In Serilog, this is simply named "Sink". Finally, I call CreateLogger
and set the output on the static property Log.Logger
. This enables easy access to logging as we will see in a following section of this post.
NLog
Like Serilog, NLog can use both XML and C# based configuration. Here is an example of writing log messages to a file:
<nlog>
<targets>
<target xsi:type="File" name="file" fileName="log-file.log"
layout="${longdate} ${level} ${message}" />
</targets>
<rules>
<logger name="*" minlevel="Trace" writeTo="file" />
</rules>
</nlog>
And a similar example in C#:
var config = new NLog.Config.LoggingConfiguration();
var logfile = new NLog.Targets.FileTarget("logfile") { FileName = "log-file.log" };
config.AddRule(LogLevel.Debug, LogLevel.Fatal, logfile);
NLog.LogManager.Configuration = config;
It's my impression that most people still use XML, but it wouldn't be a fair comparison to Serilog without an example in C# as well.
Logging Messages
The next step is to start logging some messages. Let's look at how it is done in each framework.
Serilog
Remember the static property from above? Logging from Serilog is dead easy:
Log.Information("Hello World");
Using the static Log
class, you will always have easy access to logging. If you don't like static calls, you can use dependency injection to inject Serilog's ILogger
as well. The great thing about using the static class is that it will never fail with internal null reference exceptions. Other logging frameworks require you to set up logging in your unit tests.
Logging structured log messages is using a special syntax:
Log.Information("Hello World from {FirstName}", "Thomas");
Notice how the string includes the {FirstName}
variable. Serilog will automatically replace this with the value Thomas
when writing the log message to the configured store. When logging to a file, you may not see the benefit of including variable names inside the log message. But when logging messages to a database, each sink typically both write the generated log messages as well as individual variable keys and values. For example, when logging to Elasticsearch, you can search log messages like this:
fields.FirstName:"Thomas"
This queries all log messages with the FirstName
of Thomas
. Pretty clever.
NLog
NLog logging works pretty much like Serilog:
var logger = NLog.LogManager.GetCurrentClassLogger();
logger.Info("Hello World");
Since version NLog 4.5, structured logging is supported as well:
logger.Info("Hello World from {FirstName}", "Thomas");
The output is identical to that of Serilog. The FirstName
variable is replaced with the value Thomas
. Depending on which target you have configured, NLog will store at least the generated message, but in most cases, also individual variable keys and names.
Sinks and Targets
The days where you would write log messages to the console or a file are pretty much over. In order to store, query, and create notifications on your log messages, you need some kind of store. This can be a cloud-based store like elmah.io (we support both Serilog and NLog) or a local store like SQL Server or Elasticsearch. Both logging frameworks have support for a lot of different data stores.
As of the writing of this post, Serilog has 81 available sinks and NLog has 82. When comparing the two, the number of sinks isn't really important, but it's a good indicator of a popular and well-supported framework.
When evaluating logging frameworks, pick a framework that supports the logging destination you are looking into using. In the cases of Serilog and NLog which both support a lot of stores, try out each framework and evaluate what works best. In my experience, there is a huge difference in the way sinks and targets are implemented.
Conclusion
Picking between Serilog and NLog is hard since both have a lot of features like structured logging and C# based configuration. We are using Serilog on elmah.io since we are logging to both elmah.io and Elasticsearch. Both sinks work great and are actively maintained. While NLog also offers structured logging, it's easy to see that Serilog has had this feature longer. If I were to choose a logging framework today, I would go with Serilog.
With that said, I don't have anything bad to say about NLog. If you are already using NLog, I'm not sure that there would be enough benefits of switching to Serilog. Most of the features in Serilog are available in some form or another in NLog. As always, I recommend that you try both and pick the one you like the most. Serilog has some new concepts that may be harder to understand if you are migrating from log4net.
Serilog
Advantages
- Widely adopted
- A lot of documentation
- Great community
Disadvantages
- A bit harder to learn when coming from log4net
NLog
Advantages
- A lot of documentation
- Having been around a long time, there are lots of blog posts
- Easy to get started when coming from other logging frameworks
Disadvantages
- Structured logging is still a bit behind Serilog
- C#-based API is harder to use than Serilog's fluent API