假设有一个函数使用带有范围的记录器,以便:
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,但我认为这不相关。
是的,有一个技巧,它是在 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此时仍然可用。