C# Serilog:如何使用字符串插值进行记录并将参数名称保留在消息模板中?

Art*_*ous 6 c# logging string-interpolation serilog formattablestring

如何替换此代码:

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

像这样或类似的 C# 字符串插值

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

但保持结构化日志的属性名称工作?

好处是:

  1. 提高可读性
  2. 您永远不会忘记参数列表中的参数或消息模板中的属性名称,尤其是当您更改日志记录代码时
  3. 您始终知道此属性名称将打印到您的日志中

Art*_*ous 6

将此文件添加到您的项目中。它有ILogger扩展方法VerboseInterpolated()等等DebugInterpolated()。这里也有单元测试

与格式字符串一起使用

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}");
Run Code Online (Sandbox Code Playgroud)

但要小心:很容易使用错误的方法。例如,如果您不小心使用了 Serilog 的方法,logger.Debug($"length = {length:propertyNameForLogger}")它将记录length = propertyNameForLogger,因此不会记录任何参数值。这是由于您的值的格式propertyNameForLogger所致。

与匿名类型一起使用

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 }}");
Run Code Online (Sandbox Code Playgroud)