使用自定义属性冒泡异常并使用 serilog 记录
Bubble up exception with custom properties and log with serilog
我遇到过这样一种情况,我认为重新抛出异常并向其附加附加信息(例如在自定义异常中的属性中)是很好的,当进一步捕获时,堆栈将被记录为Serilog 中消息模板属性形式的附加信息——最终目标是这样我就可以在 Seq 中过滤这些属性。这种情况可能是一个警告,我需要重新考虑我的异常处理,但我想我会问这是否已经用 Serilog 完成了? Recommended/discouraged?
更新
这是一个示例场景:
我们使用 serilog 和 Seq 将 "Department" 属性 应用于日志,以便部门可以轻松查看可能由其负责的所有异常。
现在这个场景的应用基本上做了两件事:
- 第一步:查询数据。
- 第 2 步:如果第 1 步中没有异常,post它在其他地方。
在步骤 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
的数据。
我遇到过这样一种情况,我认为重新抛出异常并向其附加附加信息(例如在自定义异常中的属性中)是很好的,当进一步捕获时,堆栈将被记录为Serilog 中消息模板属性形式的附加信息——最终目标是这样我就可以在 Seq 中过滤这些属性。这种情况可能是一个警告,我需要重新考虑我的异常处理,但我想我会问这是否已经用 Serilog 完成了? Recommended/discouraged?
更新
这是一个示例场景:
我们使用 serilog 和 Seq 将 "Department" 属性 应用于日志,以便部门可以轻松查看可能由其负责的所有异常。
现在这个场景的应用基本上做了两件事:
- 第一步:查询数据。
- 第 2 步:如果第 1 步中没有异常,post它在其他地方。
在步骤 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
的数据。