views:

94

answers:

3

I want to use ELMAH to log an exception (without throwing it all the way up the call stack) and it log the entire call stack.

Example code:

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

Now, within the LogException method I can see the call stack telling me DoSomething() called TrySomething(), and that threw the exception, but I can't see the call stack showing me Page_Load() called DoSomething(). I want to be able to see the full calling stack.

Example of what ex.StackTrace looks like inside LogException method:

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

I can get the full call stack from System.Diagnostics.StackTrace(), for example:

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

(and I can get line numbers and source file details by walking each frame of StackTrace)

But how do I inject this into the Exception or raise a new Exception with this call stack detail? Is there an elegant way to do this? Have I missed something really obvious?!

A: 

When the app is compiled without debug flags, the stack is not necessarily preserved in execution. You can only guarantee each item being recorded by adding try / catch to every method.

ck
Do you mean that method calls could be inlined into the execution sequence? Otherwise I'm not sure I understand what you're saying - the call stack has to be preserved!?
Alex
Yes, I think it is inlining. Try / catch will get around it, or always building in debug mode.
ck
@Alex: he means that the compiler (and the JIT) often optimizes your code by inlining methods (though you can prevent this using the MethodImplAttribute); in this case you won't get a complete stack trace.
ShdNx
I have debug info set to pdb-only when in release mode. I have no idea if the compiler marks inlined methods in some way that it can be unravelled/fully debugged - it sounds possible.. Anyway, the question is still relevant for full debug versions where the full calling stack is definitely available. Any further help much appreciated. Thanks guys
Alex
PS. You're absolutely right, I've just been reading up about code being inlined when compiled as optimised (non-debug, release mode) and it not showing in the call stack. So its use would be clearly limiting. Thanks again
Alex
A: 

Do You want to Log the error in System Log or your own Log File?

KhanZeeshan
This should really be a comment on the original question, not an answer...
Dan Puzey
I want to use ELMAH to log the exception detail and call stack. ELMAH takes an exception and logs it to an event log, plain text or xml log file, sql database, email - or multiple places, wherever you configure it to log. But the mechanism is immaterial really, my question is more how to I get the full calling stack within an exception? Thanks
Alex
A: 

Have you looked at the results of Exception.ToString()? It includes a stack trace. Does it include the kind that you're looking for?

BlueMonkMN
ex.StackTrace is a string representation of the current (inner) call stack, however it doesn't show me the stack outside the exception. I'll update the question body with the results of ex.StackTrace and what I'm after
Alex