如何在 .NET Core 中使用结构化参数记录异常

Posted

技术标签:

【中文标题】如何在 .NET Core 中使用结构化参数记录异常【英文标题】:How to log exceptions with structured arguments in .NET Core 【发布时间】:2021-02-14 09:55:38 【问题描述】:

我找不到在我的 .NET Core 微服务中记录异常的一致方法。 信息性消息记录指南很简单(使用 Microsoft.Extension.Logging):

_logger.LogInformation($"Reading file path..."); // bad
_logger.LogInformation("Reading file Path...", path); // good

第二种变体的好处是结构化信息:通过使用巧妙的日志事件路由器(如带有 RenderedCompactJsonFormatter 的 Serilog),路径被写入日志事件的单独属性。

错误日志记录使事情变得更糟。要求很明显:

    错误作为异常实现。 错误记录在处理它的 catch 块中。 每个错误都以结构化的形式记录。

所以,我希望错误报告看起来像

throw new MyException("Failed to read file Path", path);

和错误记录 - 比如

catch(MyException e)

  _logger.LogError(e, "Processing error");

LogError 方法在这里记录完整的错误描述,但它不是结构化的:路径不是作为属性添加的。 我试图让 MyException 保存消息模板和参数,但这种方法存在两个问题:

    如何基于具有命名参数的模板呈现异常消息? 在 catch 块中处理异常时,可能会释放参数。

请告诉我你是如何处理这个问题的。

【问题讨论】:

【参考方案1】:

.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)
    
    

现在在您的代码中,您可以执行以下操作:

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);

如果您查看您的日志(我在这里使用 InvisionLog),那么您应该会看到它是结构化的。

我认为这是捕获异常并以结构化方式记录它们的唯一方法。

【讨论】:

感谢您的建议,我的方法非常相似。但它不能解决我问题底部的问题 1 和 2。我没有找到比用编号的占位符替换命名占位符更好的方法来呈现消息,但它与 Serilog @name 语法不兼容。 @vivendi 我在 invisionlog.com 中找不到正确的文档来从我的内部 Web 服务器访问日志!我卡住了。使用 Seq,我可以在 appsetting.conf 中添加我的内部 url 服务器,但使用 invisionlog 我在配置文件示例中看不到它。知道怎么做吗? @Kivo 我不是 invisionlog 的所有者,我只是一个用户。我也不确定你的意思?您安装他们的 Nuget 软件包之一。例如 InvisionLog Serilog 包,并在 Startup.cs 中添加配置,您应该能够从他们的在线仪表板中看到日志。您不能离线托管日志。所有内容都存储在云中,因此您无需在服务器上安装任何内容。 @Vivendi 我已经联系了团队支持,他们给了我和你一样的答案,所以我得到了答案。我的服务器是 Intranet,无法访问 Internet。我将不得不找到另一个像 seq 这样的工具,或者继续使用 seq。谢谢

以上是关于如何在 .NET Core 中使用结构化参数记录异常的主要内容,如果未能解决你的问题,请参考以下文章

.NET Core使用Nlog记录日志

如何在 ASP.NET Core MVC 中使用 ADO.NET 向存储过程添加参数?

在 .NET Core 中如何让 Entity Framework Core 在日志中记录由 LINQ 生成的SQL语句

Net Core:在洋葱架构中使用OData,将查询参数转换为Linq

如何使用 ASP.NET Core 更新由依赖表组成的记录 [关闭]

如何在 ASP.NET Core 5 MVC (.NET 5) 中获取记录的用户数据?