Extending Serilog with additional values to log

Adding additional information to log in .NET Core application with Serilog

If you are building .NET Core application your choice for logger library is most likely Serilog. It is really powerful and easy to use library which allows you easy logging in all levels in your application.

One of the best features it has is easy extending of the data you want to have in your logs. There are several ways to enrich your logs with new values.

Use existing enricher

If you go to nuget.org and search for and search for Serilog.Enrichers you will get the list of enricher classes for Serilog which can add additional data which you can log. Fore example, you deiced you need Threading data in your logs, you can add reference to NuGet package Serilog.Enrichers.Thread and then just involve the enricher in your logger setup in Startup.cs class file.

public Startup(IConfiguration configuration, IHostingEnvironment env)
	{
		Log.Logger = new LoggerConfiguration()
							.Enrich.WithThreadId()
							.ReadFrom.Configuration(configuration)
							.CreateLogger();
	}
    

Now to retrieve this value in a file, you just need to add it to your log pattern in the config. I always use appsettings.json config file section to configure Serilog, so my Serilog configuration section in config file would look something like this

{
  "Serilog": {
    "MinimumLevel": "Debug",
    "WriteTo": [
      {
        "Name": "RollingFile",
        "Args": {
          "logDirectory": ".\\Logs",
          "fileSizeLimitBytes": 1024,
          "pathFormat": "Logs/MyApplicationName.{Date}.log",
          "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level}] {ThreadId} {Message}{NewLine}{Exception}"
        }
      }
    ]
  }
}
    

Now we'll have our ThreadId value written out to a log file along with other log info

Add properties to LogContext

If you are not comfortable by keep adding enricher packages to your project or you need something really custom, you can always push values to your LogContext and then you can pull them out the same way you pull out value of enricher. Let's say we want to have currently logged user and the IP address he accessed our endpoint of our MVC application.

We first need to tell Serilog to start using values FromLogContext

public Startup(IConfiguration configuration, IHostingEnvironment env)
	{
		Log.Logger = new LoggerConfiguration()
							.Enrich.WithThreadId()
							.Enrich.FromLogContext()
							.ReadFrom.Configuration(configuration)
							.CreateLogger();
	}
    

Now we need to acquire username string and remote IP value from the HttpContext and push it to our LogContext

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
	{
		app.Use(async (httpContext, next) =>
			{
				//Get username
                var username = httpContext.User.Identity.IsAuthenticated ? httpContext.User.Identity.Name : "anonymous";
                LogContext.PushProperty("User", username);

				//Get remote IP address
                var ip = httpContext.Connection.RemoteIpAddress.ToString();
                LogContext.PushProperty("IP", !String.IsNullOrWhiteSpace(ip) ? ip : "unknown");
				
				await next.Invoke();
			});
		loggerFactory.AddSerilog();
	}
    

Pulling out values that you added from the LogContext is the same as with using log enricher. Just specify the property name in the log line pattern in your config and values from the runtime will start appearing in your log.

Enrichers work pretty much the same way as adding properties to the context. They are just nicer way to re-use your logic and share it among the projects, pretty much the same concept .NET Core uses with extension methods for adding middlewares to the pipeline.

Disclaimer

Purpose of the code contained in snippets or available for download in this article is solely for learning and demo purposes. Author will not be held responsible for any failure or damages caused due to any other usage.


About the author

DEJAN STOJANOVIC

Dejan is a passionate Software Architect/Developer. He is highly experienced in .NET programming platform including ASP.NET MVC and WebApi. He likes working on new technologies and exciting challenging projects

CONNECT WITH DEJAN  Loginlinkedin Logintwitter Logingoogleplus Logingoogleplus

JavaScript

read more

SQL/T-SQL

read more

Umbraco CMS

read more

PowerShell

read more

Comments for this article