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:
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:
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"
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.