📅 January 31, 2024

Structured Logging

TLDR: When using structured logging with Serilog, don't log messages like this:

Log.Information($"Logged in {loggedInUserId}");

Log messages in message template syntax like this:

Log.Information("Logged in {UserId}", loggedInUserId);

Why structured logging?

Most web applications will usually use logging of some kind. Structured logging is a way to, well, structure your logs to gain better visibility and querying capabilities.

In the past, I would not have thought twice about adding a log statement like the following using string interpolation:

var user = "John Doe"
Logger.LogInformation($"User {user} has logged in");

Which, when viewed in Seq, results in something like the following:

String Interpolation Logging

However, if you were to log a similar message using message template syntax like the following:

var user = "John Doe"
Logger.LogInformation("User {User} has logged in", user);

This would show up in Seq like the following:

Message Template Logging

Query your logs

The interesting bit here is that we now have an additional User property in the log event. We can run queries on this. Maybe you have multiple applications and you want to track this User property to see all the events logged for a specific user. In Seq, you could query that with something as simple as User = "John Doe"

User Search

Fall into the pit of success

In .NET, there are code quality rules to help you identify log messages to improve.

  • CA2253 identifies placeholders in message template log statements that are only comprised of numeric values.
  • CA2254 identifies log statements that should be using the message template syntax.
#development#dotnet
An unhandled error has occurred. Reload 🗙