Nik*_*ker 6 .net c# logging exception structured-data
我找不到一致的方法来记录 .NET Core 微服务中的异常。信息消息日志记录准则很简单(使用 Microsoft.Extension.Logging):
_logger.LogInformation($"Reading file {path}..."); // bad
_logger.LogInformation("Reading file {Path}...", path); // good
Run Code Online (Sandbox Code Playgroud)
第二种变体的好处是结构化信息:通过使用巧妙的日志事件路由器(例如带有 RenderedCompactJsonFormatter 的 Serilog),路径被写入日志事件的单独属性。
错误记录会让事情变得更糟。要求很明显:
所以,我希望错误报告看起来像
throw new MyException("Failed to read file {Path}", path);
Run Code Online (Sandbox Code Playgroud)
和错误记录 - 就像
catch(MyException e)
{
_logger.LogError(e, "Processing error");
}
Run Code Online (Sandbox Code Playgroud)
这里的 LogError 方法记录了完整的错误描述,但它不是结构化的:路径没有添加为属性。我尝试让 MyException 保存消息模板和参数,但这种方法有两个问题:
请告诉我你是如何处理这个问题的。
.NET 中的异常不支持这样的结构化参数。由于您使用的是自定义异常,因此您可以将此功能添加到您自己的异常类中。
例如:
public class MyException : Exception
{
public object[] Props { get; }
public MyException()
{
}
public MyException(string message)
: base(message)
{
}
// Add custom "props" parameter to your exception class
public MyException(string message, params object[] props)
: base(message)
{
Props = props;
}
public MyException(string message, Exception inner)
: base(message, inner)
{
}
}
Run Code Online (Sandbox Code Playgroud)
现在在您的代码中您可以执行以下操作:
try
{
var file = "image.png";
var path = "./my/path/";
throw new MyException("Failed to read file '{file}' in path '{path}'", file, path);
}
catch (MyException e)
{
_logger.LogError(e, e.Message, e.Props);
}
Run Code Online (Sandbox Code Playgroud)
如果您查看日志(我在这里使用 InvisionLog),那么您应该会看到它是结构化的。
我认为这是捕获异常并以结构化方式记录它们的唯一方法。