Exception Logging Using StackTrace - c#

I wanted to log the Exception details
Filename , FileLineNo, Method Name (where the exception occured)
This is working using the StackTrace class
But some times i am getting the File Line No and Method Name as null
How shall i track Exception Details all the time when an Exception occur
here is my code
Public Shared Sub LogException(ByVal ex As Exception)
Dim trace As Diagnostics.StackTrace = New Diagnostics.StackTrace(ex, True)
LogInfo(String.Format("Error Message :{0} => Error In :{1} => Line Number :{2} => Error Method:{3}",
ex.Message, trace.GetFrame(0).GetFileName(),
trace.GetFrame(0).GetFileLineNumber(),
trace.GetFrame(0).GetMethod().Name))
End Sub

So, the answer to probably all of your questions at once is: "The caught exception will have all of the details it can possibly have."
Your public shared sub LogException is getting an Exception object that is already going to have most of that information. So, you can just do...
LogInfo(ex.ToString())
...and get as much detail as possible.
There are going to be cases where you may not have file name or line numbers, and in some cases the LogInfo statement you have will throw an exception itself. This explains how to reliably get these details, though it comes with potential security risks.
I have found that the type of exception and the stack trace information contained in Exception.ToString() is usually enough to pinpoint the actual errors. When it isn't, its usually a problem with the structure of the code.

The exception already contains the full stack trace. You don't need to create a new one.

1) You can get the stack trace from inside the Exception object using Exception.StackTrace. You don't need to create a new one.
2) If the exception was thrown from somewhere you do not have debugging info (for example inside the framework), you may simply not have a line number or source filename to get.

Related

Is there a way to change the default stack trace depth logged by log4net (ILog.Error)?

By default only 5 first frames of the calling stack are logged by log4net when using Ilog Error(string message, Exception ex) method.
Is there a way to change it (extend it)?
PS. This is not a duplicate of "Does log4net support including the call stack in a log message". It is not about supporting including call stack in every logged message but it reffers to the amount of stack trace frames being logged when calling Error(string message, Exception ex) method.
You have an option to include the callstack in your log message:
stacktrace:
Used to output the stack trace of the logging event The
stack trace level specifier may be enclosed between braces. For
example, %stacktrace{level}. If no stack trace level specifier is
given then 1 is assumed Output uses the format: type3.MethodCall3 >
type2.MethodCall2 > type1.MethodCall1 This pattern is not available
for Compact Framework assemblies.
This way you can include the call stack. I do not know a way of changing the number of frames in the exception. I know it is not limited to 5, it just prints exception ToString(). If you are missing a part of you exception stack, you are probably rethrowing the exception the like throw ex; instread of throw;

Exception of type System.Exception is not handled

Preface: Please don't refer me to Elmah. I'm trying to understand the MVC exception system for myself, not just use someone else's system for it.
I'm playing with MVC's exception system for my own enrichment, and I've run into an odd exception. I've written an OnException method as follows:
protected override void OnException(ExceptionContext filterContext)
{
if (filterContext.ExceptionHandled == true)
{
return;
}
// log error
ErrorLog(filterContext);
// mark error as handled to prevent rethrow
filterContext.ExceptionHandled = true;
//show custom error page
ViewBag.Code = filterContext.Exception is HttpException ? ((HttpException) filterContext.Exception).GetHttpCode() : 500;
ViewBag.Exception = filterContext.Exception;
filterContext.Result = View("Error");
}
I throw it via a simple enough call in a toy controller:
if(something strange and bad happens)
{
throw new Exception("When in trouble or in doubt, run in circles, scream and shout.");
}
I tested the exception and got the following exception:
An exception of type System.Exception occurred and was not handled in user code.
The string I sent into the constructor enters the exception system as part of the error message. When I continue execution through the error, I get to the error page with that message, but I keep getting the previous error when I try to run the code. The inner exception detail is null and the rest of the exception detail is too sparse for me to be able to use it to figure out what's gone wrong, or I'd read that instead of ask here.
I suspect I'm getting this exception because I'm not letting the base class finish handling the original exception, but I'm afraid I'm not entirely sure why. I've read a variety of articles on exception handling, but I'm not running into anything (that I know of) that has explained to me whether one needs to let the base class finish handling the exception or whether the handling I've done is sufficient. I've seen custom handling that did either or neither.
Or, conversely, if my suspicions are incorrect and it's something else entirely, does anyone know what it might be? The situation in which this is being thrown is very simple, and it's unlikely that anything else could be affecting this.
Does anyone know why I could be getting this error?
The code that we can see looks fine, so I'm left thinking that the exception comes from your ErrorLog method that we can't see.
You might be getting errors because a file is still in use (are you disposing the file streams correctly?) or for a variety of other reasons.
Your OnException method overrides MVC's error handling mechanism so when an exception happens during exception handling all hell breaks loose. The MVC framework probably has a very high level try { ... } catch { ... } somewhere just to save the application from crashing but it can't give you much more information on what happened.
Make sure your visual studio debugger breaks when an exception is thrown (https://msdn.microsoft.com/en-us/library/x85tt0dd.aspx) and then execute your code. Take a look at the exception thrown and the code involved. You'll either find why that specific part breaks or you'll find the subject of your next StackOverflow question. ;)

Get values of parameters in stack trace

I am having trouble reproducing a few errors we are seeing in our error log.
It could be made a lot easier if I knew which record ID a specific method was using when it threw an exception.
All of our unhandled exceptions get handled by our global exception handler, which puts all the details of the exception, as well as all the details of the HTTP request, into a log table.
Is there a way to capture the values of all the parameters for the method that threw an exception? Or even better, all the values up the stack trace?
Unfortunately, this is not possible: at the time when you catch the exception in the handler, all the stack frames with the method parameters are gone. Once the control leaves your function, you can no longer access its parameter values.
Since you know the specific function where the crash happens, you could set up an exception handler there to collect all the parameters of interest, and re-throw a wrapped exception. Once the diagnostics is complete, you could revert the code back to normal:
void SuspiciousFunction(string name, long count) {
try {
// The code of your function goes here
} catch (Exception e) {
var args = new Dictionary<string,object> {
{ "name" , name }
, { "count", count }
};
throw new MySpecialException(e, args);
}
}
I would capture the exception in the method it's thrown, gather your parameters and any other needed info, then rethrow the error with a new ApplicationException or other custom Exception that contains your additional info.
From the documentation Environment.StackTrace i would say it is possible.
They say
The stack trace information for each method call is formatted as follows:
"at FullClassName. MethodName (MethodParams) in FileName :line LineNumber "

How can I add a message to an exception without losing any information in C#?

I have the following code:
catch(Exception ex)
{
throw new FatalException("An error occurred while trying to load the XSLT file.", ex);
}
This unfortunately just swallows up the Exception. I can fix this by doing the following:
catch(Exception ex)
{
throw;
}
But I would still like to include the custom message for help with event logging.
How do I add this message to the exception without losing any information? (stack trace/debug symbols, etc.)
If you just need to add information to the original exception, such as a user-readable message or specific details that will be useful to you in tracking down the error but that won't be useful to the end user, you can make use of the Exception's Data property, which is a key/value pair dictionary.
We use this extensively in order to record information such as the report being executed or file that is being processed so that operations can determine what exactly was happening at the time of the error. The user doesn't need this detail since they are working directly with the cause of the failure.
You could also use this to pass a plain text message that makes sense to the user. The only issue is that you will have to perform some additional work in your logging framework or end-user interface in order to extract the data and make it useful to the consumer.
For example, you could do:
catch (Exception ex)
{
ex.Data.Add("UserMessage", "An error occurred while trying to load the XSLT file.");
throw;
}
Then in the client-side code, you could test to see if UserMessage exists and, if so, present it to the user instead of the Exception:
catch (Exception ex)
{
if (ex.Data.Contains("UserMessage"))
{
MessageBox.Show(ex.Data["UserMessage"].ToString());
}
else
{
MessageBox.Show(ex.Message);
}
}
That original Exception is still there.
When you do your Exception logging, the Exception that you receive will be the FatalException that you made with your message. The original Exception is in ex.InnerException. You can continue to cycle through InnerException until it's null to get all of the Stack Trace information, etc.
In short, don't.
I'm sure you could find some way of getting around this with some reflection, but I would strongly caution you against this. It goes against the original design of exceptions in .NET. Exceptions are not just there to help with logging, they provide information about the original cause of an application failure.
Using the first option is generally preferred as it maintains the stack trace of the original exception but allows you to provide additional information by wrapping it in a separate exception. In my own code, whenever I log exceptions, my logging function will recurse through the InnerException property to find every bit of useful information possible about the error.
Just in case someone needs a good answer. The key is to use AppDomain.CurrentDomain.FirstChanceException
The you can create a custom object with IDisposable to put all info in it. And if exception happens then FirstChanceException handler gets that info and populate Exception.Data.
Use Local Thread Storage to make it thread safe. Then down the line the code that catches it will get the data and log it.
Example:
using(MyCustomMessage.EnterToLocalStorage("Info for logging"") )
{
...code
...exception thrown
.... FirstChanceException examines local thread storage and get's "info for logging" and puts into Exception.Data.
}
//Dispose is called and all messages that were put into LocalStorage are removed.
//So if exception was not thrown before then it like nothing happened.
Google AsyncDiagnosticStack for a good example. https://github.com/StephenCleary/AsyncDiagnostics/blob/master/src/Nito.AsyncEx.AsyncDiagnostics/AsyncDiagnosticStack.cs

Is there a way I can send a stack trace to the console in C# with VS2012

I have C# code that's giving an exception. I have the code within a try - catch and I can see the exception but I am having a problem viewing it in VS2012. Is there a way I can send a stack trace to the console so I can look without having to right click on properties of the exception?
Even better does anyone have any code they use to log out more detailed information to the console?
ToString is overridden in the Exception classes and will return the stack trace.
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
From any piece of code you can access the stack by creating a stackframe object. Lots of information in there and you don't need an exception to access it.
EG.
var callingMethod = new StackFrame(1).GetMethod().Name;
returns the calling method name.
If you have an exception as Joe Daley suggested use
Console.WriteLine(ex); to print it out.

Categories