I'm wanting to consolidate all my error logging down to a single method that can call from all over my application when we handle exceptions. I have a few awkward constraints I will describe below.
public void Log(Exception ex)
{
string innerMessage = "";
if (ex.InnerException != null)
{
innerMessage = ex.InnerException.Message;
}
Console.WriteLine($"Message: {ex.Message} # Location: { ex.StackTrace} # InnerMessasge: {innerMessage}" );
}
I have parsed the stack before but the code ends up ugly and depending on the stack it can mess up.
All I really want is where the exception was thrown, the class and method or class and line for the location. To ensure that the whole thing sits neatly on a single line in the logs.
Initially, developers should look in the application logs for the stack trace, because often, the stack trace tells you the exact line or function call that caused a problem.
Therefore, you should log a stacktrace if, and only if, and always if, the exception indicates a bug in the program. However, that does not always indicate that a method you write should catch and log the exception.
This may be one of the built-in Exception types, or a custom Exception created by a program or a library. The stack trace contains the Exception's type and a message, and a list of all the method calls which were in progress when it was thrown.
The most common method to catch and print the exception message in Python is by using except and try statement. You can also save its error message using this method. Another method is to use logger.
You don't need to parse the exception yourself, you can use the StackTrace
class to get an easy to understand stack trace from an exception:
try
{
int.Parse("dd");
}
catch (Exception e)
{
var s = new StackTrace(e); // Gets the stack trace where the exception was thrown not where it was caught.
var frame = s.GetFrame(0);
var sourceMethod = frame.GetMethod();
Console.WriteLine($"Method: {sourceMethod.Name} - Class {sourceMethod.DeclaringType.FullName} : Location: {frame.GetILOffset()}");
}
You can get other information from the frame, such as file, line, column if they are available, also you can walk up the stack to find one of your classes instead of a framework class (you get all the frames from the StrackTrace
and find the one you need).
.Net has some very useful Caller Member attributes you can use for things like this. Put these on a method and the compiler will set the values to the member name, line number or file path where the method was called.
public void Log(Exception ex, [CallerFilePath]string callerFilePath = null, [CallerMemberName]string callerMemberName = null, [CallerLineNumber]int callerLineNumber = 0)
{
Console.WriteLine($"Message: {ex.Message} # File: {callerFilePath} # Line: {callerLineNumber} # Member: {callerMemberName}" );
}
So, every time you call the Log
method you will get the line number and file path where the method was called. This is also very cheap performane wise, because the compiler inserts them as constants, rather than having to pull them out with reflection.
Note, this log the location at which you called the Log method, not the original location the exception was thrown at, but depending on your needs, that may be sufficient.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With