Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get exception location into Logger method without parsing stack?

Tags:

c#

.net

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.

like image 433
Mr_road Avatar asked Jan 26 '18 10:01

Mr_road


People also ask

Which log file should a developer use to search for exception stack traces?

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.

Should StackTrace be logged?

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.

Does exception message contain stack trace?

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.

How do I get full exception messages in Python?

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.


2 Answers

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).

like image 62
Titian Cernicova-Dragomir Avatar answered Oct 23 '22 13:10

Titian Cernicova-Dragomir


.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.

like image 2
Alex Avatar answered Oct 23 '22 11:10

Alex