Getting the name of the calling method

OK, so this is probably old news to most people, but I only just discovered this, so I thought I’d blog about it before I forget!

As part of the ongoing investigation into a better way to handle exceptions, I was logging exceptions that occurred in the Fallible class. However, log4net (which is the logging framework I am using) logs the name of the method in which the call to the logger was made. In my case, this would be the Fallible.Do() method.

However, I would want to see what called this, as this method is used in many places. I have previously done this using reflection, grabbing the stack frame and looking at the first frame…

StackTrace stackTrace = new StackTrace();
MethodBase methodBase = stackTrace.GetFrame(1).GetMethod();
_logger.Debug("Called from " + methodBase.Name);

This is fine, and works well, but it unnecessarily complex compared to the shiny new way you can do this if you are using .NET 4.5 / C# 5 or higher.

Drum roll please, it’s as simple as this…

public void Do(Func f, [CallerMemberName] string callingMethod = null) {
  // callingMethod holds the name of the method that called Do()
}

You’ll need to add a reference to┬áSystem.Runtime.CompilerServices to make this work.

That was just sooooo easy!

Update 10th July ’18

As clever, neat and useful as this was, it turned out not to be as useful as I’d hoped for Fallible. The problem is that the class methods get called from many places, and ideally I would like the logger to show the calling class, not Fallible.

To be clear, using the code above would result in the following in the log…

2018-07-10 18:29:34,648 [15] DEBUG Fallible - Called by <method name>

What I really wanted was…

2018-07-10 18:29:34,648 [15] DEBUG CustomerService - Called by <method name>

This makes it much easier to scan the log file, and see what actually gave rise to the exception.

This took a bit more work, but wasn’t so hard. I added a helper method as follows…

    private static string GetCallingType() {
      StackTrace stackTrace = new StackTrace();
      string callingType = "";
      for (int i = 0;
        i < stackTrace.FrameCount
        && stackTrace.GetFrame(i).GetMethod().DeclaringType != null;
        i++) {
        callingType = stackTrace.GetFrame(i).GetMethod().DeclaringType.Name;
      }
      return callingType;
    }

Not as neat as I would have liked, but I couldn’t get a Linq version to work.

I then used this when creating the logger…

ILog logger = LogManager.GetLogger(GetCallingType());

This gave the log file the content I wanted. By including the stack trace (which I was doing anyway), I could see the calling method as well.

Still, the CallerMemberName attribute is a good one to know, just not enough in this case.

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.