Using Serilog with ASP.NET Core 2.0

In case you’re unfamiliar, Serilog is a an open source event library for .NET. Conceptually, Serilog gives you two important components: loggers and sinks (outputs). Most applications will have a single static logger and several sinks, so in this example I’ll use two: the console and a rolling file sink.

Starting with a new ASP.NET Core 2.0 Web Application running on .NET Framework (as in the image to the right), begin by grabbing a few packages off NuGet:

  • Serilog
  • Serilog.AspNetCore
  • Serilog.Settings.Configuration
  • Serilog.Sinks.Console
  • Serilog.Sinks.RollingFile

Next, you will need to modify some files.

Startup.cs

Startup constructor

Create the static Log.Logger by reading from the configuration (see appsettings.json below). The constructor should now look like this:

public Startup(IConfiguration configuration)
{
	Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(configuration).CreateLogger();
	Configuration = configuration;
}

BuildWebHost method

Next, add the .UseSerilog() extension to the BuildWebHost method. It should now look like this:

public static IWebHost BuildWebHost(string[] args) =>
	WebHost.CreateDefaultBuilder(args)
		.UseStartup<Startup>()
		.UseSerilog() // <-- Add this line
		.Build();

The BuildWebHost method might look strange because the body of this method is called an expression body rather than a traditional method with a statement body.

Configure method

At the start of the configure method, add one line at the top to enable the Serilog middleware. You can optionally remove the other loggers as this point as well. Your Configure method should start like this:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
	loggerFactory.AddSerilog(); // <-- Add this line

	...

appsettings.json

At the root level of the appsettings.json (or one of the environment-specific settings files), add something like this:

"Serilog": {
  "Using": [ "Serilog.Sinks.Console" ],
  "MinimumLevel": "Debug",
  "WriteTo": [
    { "Name": "Console" },
    {
      "Name": "RollingFile",
      "Args": {
        "pathFormat": "logs\\log-{Date}.txt",
        "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] {Message}{NewLine}{Exception}"
      }
    }
  ],
  "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
  "Properties": {
    "Application": "My Application"
  }
}

If you’re wondering about the pathFormat and what other parameters you can use, there aren’t that many. {Date} is the only “switch” you can use with this particular sink (though other sinks exist, such as this roll-on-file-size alternative sink). But you can use any environment variable (things like %TEMP%), allowing for a pathFormat of:

"%TEMP%\\logs\\log-{Date}.txt"

The outputTemplate has a LOT of options that I won’t get into here because the official documentation does a great job of explaining it.

As for the event levels, I’ve copied the list below from the official documentation for reference.

  1. Verbose – tracing information and debugging minutiae; generally only switched on in unusual situations
  2. Debug – internal control flow and diagnostic state dumps to facilitate pinpointing of recognised problems
  3. Information – events of interest or that have relevance to outside observers; the default enabled minimum logging level
  4. Warning – indicators of possible issues or service/functionality degradation
  5. Error – indicating a failure within the application or connected system
  6. Fatal – critical errors causing complete failure of the application

You’ll also notice in the above JSON that the “Using” property is set to an array containing “Serilog.Sinks.Console” but not “Serilog.Sinks.RollingFile”. Everything appears to work, so I am not sure what impact this property has. If you know please comment!

Leave a Reply

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