简体   繁体   English

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

[英]Bubble up exception with custom properties and log with serilog

I came across a situation where I thought it'd be good to rethrow an exception, appending additional information to it (for example in properties in a custom exception) that when caught further up the stack would be logged with the additional info in the form of properties of a message template in Serilog - the end goal being so I can then filter on those properties in Seq. 我遇到了一种情况,我认为最好抛出一个异常,向其附加其他信息(例如,在自定义异常中的属性中),以便在堆栈中进一步捕获时将使用以下形式记录附加信息:消息模板在Serilog中的属性-最终目标是让我随后可以在Seq中筛选这些属性。 This scenario might be a warning that I need to rethink my exception handling, but I thought I'd ask if this has been done before with Serilog? 这种情况可能是警告,我需要重新考虑我的异常处理,但是我想问一下,是否已经使用Serilog完成了? Recommended/discouraged? 推荐/气馁?

Update 更新

Here's an example scenario: 这是一个示例方案:

Using serilog and Seq we apply a "Department" property to a log so that a department can easily see all exceptions that are likely their responsibility. 使用serilog和Seq,我们将“部门”属性应用于日志,以便部门可以轻松查看可能属于其职责的所有异常。

Now the app for this scenario basically does two things: 现在,此方案的应用程序基本上执行两件事:

  • Step 1: Query data. 步骤1:查询数据。
  • Step 2: If no exceptions in step 1, post it somewhere else. 步骤2:如果步骤1中没有例外,请将其发布到其他位置。

A few layers deep in step 1 there is a particular exception that I know is the responsibility of a particular department. 在第1步的几层深处,有一个特定的例外情况,我知道这是特定部门的责任。 So I'd like to apply a department property to this exception when it is logged but at the same time have it be caught further up the stack so that the exception prevents continuation of everything else. 因此,我想在记录此异常时将部门属性应用于该异常,但同时又将其捕获到堆栈的上方,以便该异常阻止其他所有事件的继续。 Also, I only want to log the exception once. 另外,我只想记录一次异常。

My current approach is to define a custom exception with a dictionary that can hold properties for the log: 我当前的方法是使用字典定义自定义异常,该字典可以保存日志的属性:

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

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

So when I catch an exception I know is a particular departments responsibility I rethrow it as ExtPropertiesException or as an exception that inherits it, attaching the original exception as the inner exception. 因此,当我捕获到异常时,我知道是部门的特殊职责,因此将其作为ExtPropertiesException或继承它的异常抛出,并将原始异常附加为内部异常。

Then back up the stack where the general steps are I've got a catch: 然后备份堆栈,这里是我要遵循的一般步骤:

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

This seems to be doing what I need, but it'd be great to know whether it's a best practice before repeating it elsewhere. 这似乎可以满足我的需求,但是在其他地方重复此操作之前最好先知道这是否是最佳实践。

I was initially doing the logs and applying the property at the time I catch the exception and then just returning false or null to indicate failure and abandon future steps, however I've found it difficult for unit testing as I can't determine the type of errors from outside the methods. 我最初是在做日志并在捕获异常时应用属性,然后只返回false或null以指示失败并放弃将来的步骤,但是我发现单元测试很困难,因为我无法确定类型方法外部的错误。

Thanks 谢谢

Best practice is hard to judge; 最佳实践很难判断。 rather than the ForContext() code above you can do: 而不是上面的ForContext()代码,您可以执行以下操作:

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

This will attach a single "object" property to the event, carrying the data from ExtProperties . 这会将单个“对象”属性附加到事件,并携带来自ExtProperties的数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM