使用自定义属性冒泡异常并使用 serilog 记录

Bubble up exception with custom properties and log with serilog

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

更新

这是一个示例场景:

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

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

在步骤 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 以指示失败并放弃未来的步骤,但是我发现单位很难正在测试,因为我无法从方法外部确定错误类型。

谢谢

最佳实践很难判断;除了上面的 ForContext() 代码,您还可以这样做:

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

这会将单个 "object" 属性 附加到事件,携带来自 ExtProperties 的数据。