如何保留未处理异常的日志范围?

a3y*_*3y3 4 c#

假设有一个函数使用带有范围的记录器,以便:

public void HttpFunction(ILogger log)
{
  using log.BeginScope("somescope");
  FunctionA(); // this can throw an exception
}
Run Code Online (Sandbox Code Playgroud)

如果FunctionA引发异常,somescope则不会添加到记录器自动记录的异常中,因为控件将位于功能块之外,并且范围将被释放。

有没有办法自动让记录器记录异常以及添加的范围?我不喜欢仅仅为了将其注销而启用 try catch 块FunctionA(事实上,如果开发人员后来添加了FunctionB,他们可能会犯错误并忘记将其包装在 try-catch 中)。另外,我要添加的 catch 块将通过执行 log-error-and-return-500 来“处理”错误,无论如何都会自动发生。

另外,我正在使用 Serilog,但我认为这不相关。

Nic*_*rdt 5

是的,有一个技巧,它是在 Serilog 自己的请求日志中间件中实现的

在最外面的异常处理程序中,将异常记录在when子句内而不是块中catch

try
{
    function();
}
catch (Exception ex) when (LogException(ex))
{
}
Run Code Online (Sandbox Code Playgroud)

哪里LogException()可以是这样的:

static bool LogException(Exception ex)
{
    Log.Error(ex, "Unhandled excpetion");
    return false; // Don't actually catch the exception
}
Run Code Online (Sandbox Code Playgroud)

异常过滤器(when子句)很特殊 - 它们在抛出异常的上下文中执行,而不是在捕获异常的上下文中执行,因此LogContext此时仍然可用。

  • 同样重要的是要注意,使用这种方法时,仅当代码是同步时,作用域上下文才在 When 子句中可用。如果您的代码是异步的,即异常被抛出到等待的任务中,并在该等待的任务之外的 catch 块中进行处理,则作用域在 When 子句中将不可用。 (2认同)