1

我遇到了一种情况,我认为重新抛出异常会很好,向它附加附加信息(例如在自定义异常中的属性中),当进一步捕获堆栈时,将使用表单中的附加信息进行记录Serilog 中消息模板的属性 - 最终目标是我可以过滤 Seq 中的这些属性。这种情况可能是一个警告,我需要重新考虑我的异常处理,但我想我会问这是否已经用 Serilog 完成了?推荐/不鼓励?

更新

这是一个示例场景:

使用 serilog 和 Seq,我们将“部门”属性应用于日志,以便部门可以轻松查看所有可能由其负责的异常。

现在这个场景的应用程序基本上做了两件事:

  • 第一步:查询数据。
  • 第 2 步:如果第 1 步中没有异常,请将其发布到其他地方。

在第 1 步的几层深处,有一个特殊的例外,我知道这是特定部门的责任。因此,我想在记录该异常时将部门属性应用于该异常,但同时将其进一步捕获到堆栈中,以便该异常阻止其他所有内容的继续。另外,我只想记录一次异常。

我目前的方法是使用可以保存日志属性的字典定义自定义异常:

public class ExtPropertiesException : Exception
{
    // Constructors here...

    /// <summary>
    /// Properties to log with the error message
    /// </summary>
    public Dictionary<string, object> ExtProperties { get; set; }
}

因此,当我捕获一个异常时,我知道这是一个特定部门的职责,我将它作为 ExtPropertiesException 或作为继承它的异常重新抛出,将原始异常作为内部异常附加。

然后备份一般步骤所在的堆栈,我有一个问题:

try
{
    // Step 1
    // Step 2
}
catch (ExtPropertiesException ex)
{
    if (ex.ExtProperties != null)
    {
        foreach (var prop in ex.ExtProperties)
        {
            logger = logger.ForContext(prop.Key, prop.Value);
        }
    }
    logger.Error(ex, ex.Message);
}

这似乎正在做我需要的事情,但是在其他地方重复之前知道这是否是最佳实践会很棒。

我最初是在捕获异常时记录日志并应用属性,然后只返回 false 或 null 以指示失败并放弃未来的步骤,但是我发现单元测试很困难,因为我无法确定类型来自方法之外的错误。

谢谢

4

1 回答 1

3

最佳实践很难判断;而不是ForContext()上面的代码,你可以这样做:

try
{
    // Step 1
    // Step 2
}
catch (ExtPropertiesException ex)
{
    logger.Error(ex, "Exception caught, data is {@ExtProperties}", ex.ExtProperties);
}

这会将单个“对象”属性附加到事件,携带来自ExtProperties.

于 2015-02-15T22:21:26.543 回答