7

如何替换此代码:

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

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

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

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

好处是:

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

2 回答 2

4

将此文件添加到您的项目中。它有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}");

但要小心:使用错误的方法太容易了。如果您不小心使用了 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 }}");
于 2020-05-15T10:09:04.913 回答
0

谢谢你的好主意。我看到了一个缺点,那就是与 DI 一起使用时不支持通用记录器。我扩展了@Artemious 解决方案。如果这不是正确的方法,请告诉我。

public static void LogInformationInterpolated<T>(this ILogger<T> logger, FormattableString? message) =>
            WriteInterpolated<T>(logger, null, message, Information);

public static void LogInformationInterpolated<T>(this ILogger<T> logger, Exception? ex, FormattableString? message) =>
            WriteInterpolated<T>(logger, ex, message, Information);

public static void WriteInterpolated<T>(this ILogger<T> logger, Exception? ex, FormattableString? message, Serilog.Events.LogEventLevel logEventLevel)
{
    var contextedLogger = Log.ForContext<T>();
    WriteInterpolated(contextedLogger, ex, message, logEventLevel);
}

ILogger 来自Microsoft.Extensions.Logging命名空间,Serilog 似乎没有。但我不是这方面的专家,因此愿意接受建议。

于 2020-10-09T01:42:55.270 回答