【问题标题】:How do I log an exception with a full call stack?如何使用完整的调用堆栈记录异常?
【发布时间】:2011-04-23 18:48:18
【问题描述】:

我想使用 ELMAH 来记录一个异常(而不是把它一直扔到调用堆栈中)并记录整个调用堆栈。

示例代码:

    protected void Page_Load(object sender, EventArgs e)
    {
        DoSomething();
    }

    private void DoSomething()
    {
        try { TrySomething(); }
        catch (Exception ex) { LogException(ex); }
    }

    private void TrySomething()
    {
        throw new NotImplementedException();
    }

    public static void LogException(Exception ex)
    {
        var currentStack = new System.Diagnostics.StackTrace(true);
        Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
    }

现在,在 LogException 方法中,我可以看到调用堆栈告诉我 DoSomething() 调用了 TrySomething(),这引发了异常,但我看不到调用堆栈显示 Page_Load() 调用了 DoSomething()。我希望能够看到完整的调用堆栈。

Ex.StackTrace 在 LogException 方法中的示例:

at WebApplication1._Default.TrySomething() in C:\Projects\test\GeneralTests\WebApplication1\Default.aspx.cs:line 26
at WebApplication1._Default.DoSomething() in C:\Projects\test\GeneralTests\WebApplication1\Default.aspx.cs:line 20

我可以从 System.Diagnostics.StackTrace() 获取完整的调用堆栈,例如:

at WebApplication1._Default.LogException(Exception ex)
at WebApplication1._Default.DoSomething()
at WebApplication1._Default.Page_Load(Object sender, EventArgs e)
[snip]

(我可以通过遍历 StackTrace 的每一帧来获取行号和源文件详细信息)

但是我如何将它注入到异常中或使用此调用堆栈详细信息引发新异常?有没有一种优雅的方式来做到这一点?我错过了一些非常明显的东西吗?!

【问题讨论】:

标签: c# error-handling elmah callstack


【解决方案1】:

当应用程序在没有调试标志的情况下编译时,堆栈不一定会在执行时保留。您只能通过在每个方法中添加 try / catch 来保证记录每个项目。

【讨论】:

  • 你的意思是方法调用可以内联到执行序列中吗?否则我不确定我是否理解你在说什么 - 必须保留调用堆栈!?
  • 是的,我认为它是内联的。 Try / catch 会绕过它,或者总是在调试模式下构建。
  • @Alex:他的意思是编译器(和 JIT)经常通过内联方法来优化你的代码(尽管你可以使用 MethodImplAttribute 来防止这种情况);在这种情况下,您将无法获得完整的堆栈跟踪。
  • 我在发布模式下将调试信息设置为 pdb-only。我不知道编译器是否以某种方式标记内联方法以使其可以被解开/完全调试 - 听起来可能。无论如何,这个问题仍然与完整的调试版本相关,其中完整的调用堆栈绝对可用。非常感谢任何进一步的帮助。谢谢大家
  • 附言。你是绝对正确的,我刚刚阅读了关于在编译为优化(非调试,发布模式)时被内联的代码并且它没有显示在调用堆栈中。因此,它的使用将受到明显限制。再次感谢
【解决方案2】:

你看过 Exception.ToString() 的结果了吗?它包括一个堆栈跟踪。它是否包括您正在寻找的那种?

【讨论】:

  • ex.StackTrace 是当前(内部)调用堆栈的字符串表示形式,但它不会向我显示异常之外的堆栈。我将使用 ex.StackTrace 的结果和我所追求的内容更新问题正文
【解决方案3】:

当发生错误时,您可以执行以下操作来获取完整堆栈:

var currentStack = new System.Diagnostics.StackTrace(true);
return currentStack.ToString();

【讨论】:

    猜你喜欢
    • 2014-01-06
    • 2018-04-24
    • 2013-11-16
    • 2011-03-29
    • 1970-01-01
    • 1970-01-01
    • 2013-02-21
    • 1970-01-01
    • 2011-07-19
    相关资源
    最近更新 更多