100

Why do most log4net examples get the logger for a class by doing this:

private static ILog logger = 
    LogManager.GetLogger(
    System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

Rather than just passing typeof(MyClass):

private static ILog logger = LogManager.GetLogger(typeof(MyClass));

Is there any other reason for doing this, beside the fact that the first option does not require you to type a specific class name?

Andy White
  • 86,444
  • 48
  • 176
  • 211

6 Answers6

95

I think you've got the reason. I do it that way so I don't have to worry about the class name and can just copy and paste boiler plate code in a new class.

For the official answer, see: How do I get the fully-qualified name of a class in a static block? at the log4net faq

Warren Stevens
  • 1,047
  • 12
  • 12
Steven Lyons
  • 8,138
  • 1
  • 28
  • 27
  • Ok that clears it up, thanks for that link, I hadn't seen that before – Andy White Mar 25 '09 at 02:56
  • This is as old as it gets, but have a look at my answer in case you still paste that as boiler code :) – Noctis Sep 19 '14 at 02:06
  • You do save a tiny bit of Dev time cutting and pasting this code. However there is a cost to calling ‘GetCurrentMethod()’ as opposed to using a string constant or calling ‘typeof()’. If you add up how many times this will be called over the lifetime of the code against how long it will take you to type the class name in, I think you are just slowing your code down for little benefit. – Youngs Feb 03 '15 at 11:26
  • 1
    You're not slowing down as much as you think, this is a static call so you have one invocation per class per app domain, e.g. if you have 300 classes you have at most 300 calls to this for the lifetime of your app – Paul Hatcher Sep 05 '15 at 12:04
  • There's no point for using reflection to get the type name, and the copy/past is laziness and you get a performance hit, so why not get just the name?! – MeTitus Apr 08 '17 at 23:43
  • One reason is so that you can do your logger instantiation in a base clas, and get it automatically in all sub classes – Jason Coyne Feb 04 '23 at 23:36
  • Reflection also has benefit to shorten log messages. Otherwise, generic classes create a really long "logger" path. – John H Mar 15 '23 at 19:18
9

I'm an NLog user, and usually this boils down to :

var _logger = LogManager.GetCurrentClassLogger();

It seemed a bit strange that you need to go through reflection in Log4Net, so I had a look in the NLog source code, and lo and behold, this is what they do for you:

[MethodImpl(MethodImplOptions.NoInlining)]
public static Logger GetCurrentClassLogger()
{
    string loggerName;
    Type declaringType;
    int framesToSkip = 1;
    do
    {
#if SILVERLIGHT
        StackFrame frame = new StackTrace().GetFrame(framesToSkip);
#else
        StackFrame frame = new StackFrame(framesToSkip, false);
#endif
        var method = frame.GetMethod();
        declaringType = method.DeclaringType;
        if (declaringType == null)
        {
            loggerName = method.Name;
            break;
        }
        framesToSkip++;
        loggerName = declaringType.FullName;
    } while (declaringType.Module.Name.Equals("mscorlib.dll", StringComparison.OrdinalIgnoreCase));
    return globalFactory.GetLogger(loggerName);
}

I guess I would write something similar for Log4Net as an extension or static method instead of pasting the reflection as part of my boiler code :)

Noctis
  • 11,507
  • 3
  • 43
  • 82
7

As you say - its convenient as you can create a logger in a method without knowing the name of the class (trivial I know) but allows you to cut and paste methods between classes without having to rename the call.

Preet Sangha
  • 64,563
  • 18
  • 145
  • 216
3

I think the reason is, that you get the type of the runtime type using the .DeclaringType() method. You can use the logger in a base class and still see the actual type of your object in the loggers output. That makes investigations much more convinient.

PeterB
  • 886
  • 10
  • 18
0

It also makes it easier to create Codesmith templates for code generation purposes.

0

The following portable solution worked for me in .NET Core 6:

private static readonly ILog _log = LogManager.GetLogger(MethodBase.GetCurrentMethod()?.DeclaringType);
Philzen
  • 3,945
  • 30
  • 46
sis707
  • 1
  • 1