Tip #83: Did you know… You can get the name of the calling method from the stack using reflection?


Nearly every program needs a logger to log events, errors and exceptions. Sometimes it is also useful to log the name of the method that logged the event. The easiest way to do that is to make the log method take both the calling method name and event as parameters:

[C#]

void Log(string callingMethodName, string eventMessage) 

{
   Console.WriteLine("Event logged by " + callingMethodName);
   Console.WriteLine("Event: " + eventMessage);
}

In this case, every method will need to specify its name when calling Log(). In addition to this, the developer will have to watch if methods name change. However, there is a cleaner way to get the name of the calling method. It can be extracted from the stack. Since the method on top of the stack is the method that is currently being executed, the calling method will be right below it. Thus, by instantiating StackTrace (don’t forget to include System.Diagnostics) and getting the frame with index 1 will result in getting a StackFrame that corresponds to the call from the calling method. Finally, reflection can be used to get method name.

using System.Diagnostics;
	
void Log(string eventMessage) {
   Console.WriteLine("Event logged by " + (new StackTrace()).GetFrame(1).GetMethod().Name);
   Console.WriteLine("Event: " + eventMessage);
}


Katerina Rohonyan
SDET, IIS Team


Comments (6)

  1. Marijn says:

    Indeed, StackTrace.GetFrame.GetMethod is nice for tose things.

    However, beware that an optimizing compiler might optimize away stackframes (due to inlining for example). In .NET you can add a JIT attribute ([Runtime.CompilerServices.MethodImpl(Runtime.CompilerServices.MethodImplOptions.NoInlining)]) but that only instructs the JIT to not inline. The C# compiler can not be told to not inline (but it does not seem to inline currently).

  2. Aaron says:

    You beat me to this comment. I had this experience but I tried to used for something else than just logging and ended up being a nasty bug only present when compiled on release mode, so be cautious when using it as your code might be optimized by the compiler.

  3. Greg says:

    I’ve used this for debugging/logging but avoided it for non-debug code.  

    It still doesn’t beat printable to end user message numbers in error/log messages as you can text search for them right away to get the source line that printed the message.

  4. Casey Barton says:

    I just instinctively reference log4net, even for simple little on-off tools. You can log calling method amongst a hundred other attributes, just by configuring a format string.

  5. Óscar González says:

    How can you get the called method from the constructor?

  6. Referencing Aaron and Marijn, I got burned by this too. It’s prone to error and I recommend not using it, unless you’re positive it will only run in Debug builds.