Get exception in Logger method without parsing the stack?

I want to consolidate all my error records into one method, which can be called from all sides of the application when we handle exceptions. I have some uncomfortable restrictions that 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 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 the class and string for the location. To make sure that all this sits on the same line in the magazines.

+5
source share
3 answers

You do not need to analyze the exception yourself, you can use the StackTrace class to get an easily understood stack trace from the 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 a file, row, column, if available, and you can go up to the stack to find one of your classes instead of the framework class (you get all the frames from StrackTrace and find the one which you need).

+3
source

.Net has very useful Caller member attributes that you can use for such things. Put them on a method and the compiler will set the values ​​to the member name, line number or path to the file 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 get the line number and the path to the file where the method was called. This is also very cheap, because the compiler inserts them as constants, instead of pulling them with reflection.

Please note that this log indicates the place where you called the log method, not the original location where the exception was sent, but depending on your needs. That might be enough.

+2
source

One effective way to solve this messy production point of view is to include all the logs in the event viewer, and not in the console.

In addition, the organization helps with the formation of errors very well.

  public void Log(Exception ex) { // Create an instance of StringBuilder. This class is in System.Text namespace StringBuilder sbExceptionMessage = new StringBuilder(); sbExceptionMessage.Append("Exception Type" + Environment.NewLine); // Get the exception type sbExceptionMessage.Append(exception.GetType().Name); // Environment.NewLine writes new line character - \n sbExceptionMessage.Append(Environment.NewLine + Environment.NewLine); sbExceptionMessage.Append("Message" + Environment.NewLine); // Get the exception message sbExceptionMessage.Append(exception.Message + Environment.NewLine + Environment.NewLine); sbExceptionMessage.Append("Stack Trace" + Environment.NewLine); // Get the exception stack trace sbExceptionMessage.Append(exception.StackTrace + Environment.NewLine + Environment.NewLine); // Retrieve inner exception if any Exception innerException = exception.InnerException; // If inner exception exists while (innerException != null) { sbExceptionMessage.Append("Exception Type" + Environment.NewLine); sbExceptionMessage.Append(innerException.GetType().Name); sbExceptionMessage.Append(Environment.NewLine + Environment.NewLine); sbExceptionMessage.Append("Message" + Environment.NewLine); sbExceptionMessage.Append(innerException.Message + Environment.NewLine + Environment.NewLine); sbExceptionMessage.Append("Stack Trace" + Environment.NewLine); sbExceptionMessage.Append(innerException.StackTrace + Environment.NewLine + Environment.NewLine); // Retrieve inner exception if any innerException = innerException.InnerException; } } 

Now sbExceptionMessage contains every detail of your exception, you can easily use this to add the same log to the event viewer or to any specific text file or console. The decision is yours.

0
source

Source: https://habr.com/ru/post/1274964/


All Articles