Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Serilog: how to log with String interpolation and keep argument names in message templates?

How to replace this code:

string name = "John";
logger.Information("length of name '{name}' is {nameLength}", name, name.Length);

with C# String interpolation like this or similar

string name = "John";
// :-( lost benefit of structured logging: property names not passed to logger
logger.Information($"length of name '{name}' is {name.Length}");

but keep the property names for structured logging to work?

Benefits would be:

  1. Increased readability
  2. You'll never forget an argument in arguments list or a property name in message template, especially when you make changes to your logging code
  3. You always know what this property name will print to your log
like image 487
Artemious Avatar asked May 15 '20 10:05

Artemious


1 Answers

Add this file to your project. It has ILogger extension methods VerboseInterpolated(), DebugInterpolated() and so on. There are also unit tests here.

Usage with format string

string name = "John";
// add 'Interpolated' to method name: InformationInterpolated() instead of Information()
// add name of the property after the expression. Name is passed to the logger
logger.InformationInterpolated($"length of name '{name:name}' is {name.Length:Length}");

But be careful: it's all too easy to use the wrong method. If you accidentally use the Serilog's method, for example logger.Debug($"length = {length:propertyNameForLogger}"), it will log length = propertyNameForLogger, so no argument value will be logged. This is due to propertyNameForLogger is format for your value.

Usage with anonymous types

string name = "John";
// add 'Interpolated' to method name: InformationInterpolated() instead of Information()
// create an anonymous object with 'new { propertyName }'. 
// It's much slower because of using Reflection, but allows to write the variable name only once. 
logger.InformationInterpolated($"length of name '{new { name }}' is {new { name.Length }}");
// you can also specify other property names
logger.InformationInterpolated($"length of name '{new { userName = name }}' is {new { lengthOfName = name.Length }}");
like image 172
Artemious Avatar answered Sep 28 '22 17:09

Artemious