如何确保在出现未处理异常时记录异常日志

3
我希望获得一个崩溃报告,因此我在App.xaml.cs中注册了UnhandledException事件,代码如下。但是出现了两个问题:

  1. 有时候异常没有调用堆栈
  2. 有时候进程终止之前我没有足够的时间将日志记录到文件中。

有什么建议吗?

this.UnhandledException += App_UnhandledException;

private async void App_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
    if (!hasHandledUnhandledException)
    {
        e.Handled = true;
        _logger.Error("Unhandle exception - message = {0}\n StackTrace = {1}", e.Exception.Message, e.Exception.StackTrace);
        await CrashHandler.ReportExceptionAsync(e.Exception.Message, e.Exception.StackTrace);
        hasHandledUnhandledException = true;
        throw e.Exception;
    }
}

记录 e.Exception.ToString() 而不是将消息与堆栈跟踪分开。 - Panagiotis Kanavos
1
@LasseV.Karlsen 我不这么认为,因为记录日志是在异步调用之前发生的。虽然我猜测CrashHandler.ReportExceptionAsync实际上做了什么。我在考虑与UI相关的事情。 - Kevin Gosse
@KooKiz,CrashHandler.ReportExceptionAsync 只是将异常信息写入文件。 - yuxhu
@yuxhu 那你有一个问题。你需要找到一种同步的方式来写入文件,因为当你调用await时,该方法会返回,并且你的应用程序将被终止。 - Kevin Gosse
1个回答

4

确保只访问e.Exception一次。在某些情况下,第二次访问该属性时会丢失有关堆栈跟踪的信息。将异常保存在变量中并直接使用该变量进行操作。另外,如Panagiotis Kanavos在评论中提到的那样,直接记录e.Exception.ToString()以确保不会错过任何信息。这将包括消息、调用堆栈和所有内部异常(这些在您当前的代码中未记录)。

private async void App_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
    if (!hasHandledUnhandledException)
    {
        e.Handled = true;
        var exception = e.Exception;
        _logger.Error("Unhandled exception - {0}", exception);
        await CrashHandler.ReportExceptionAsync(exception.Message, exception.StackTrace);
        hasHandledUnhandledException = true;
        throw e.Exception;
    }
}

关于没有足够时间记录异常的问题,它由运行时控制,因此您无法做任何事情。


谢谢 @KooKiz,我会试一下。 - yuxhu
1
我现在可以获取调用堆栈了。谢谢! - yuxhu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接