views:

869

answers:

4

I typically declare the following in every class:

private static readonly log4net.ILog log = log4net.LogManager.GetLogger(
            System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

and use the static member within each class to log at different levels (info, debug, etc.)

I saw that somewhere and have been using it somewhat mindlessly, reasoning that the setup is flexible enough to help me filter by namespace and log individual types if I wanted to in troubleshooting production issues and what not.

But I've rarely had to use that "level" of fine logging. So, I would like to see what others are using. Do you use the above, as I have a feeling many are using just that, or do you create named loggers such as "debug", "trace", "error", "moduleA", etc. and share the logger among different types, assemblies?

A: 

Lately, i created something like this:

public static class Logger
{
 private static bool isLoaded = false;  

 public static ILog Log
 {
  get
  {
   System.Reflection.MethodBase method;
   method = new System.Diagnostics.StackTrace().GetFrame(1).GetMethod();
   StringBuilder loggerName = new StringBuilder();
   loggerName.AppendFormat("{0}.{1}(", method.ReflectedType.FullName, method.Name);

   ParameterInfo[] parameters = method.GetParameters();
   string[] parametersStr = new string[parameters.Length];

   if (parameters.Length > 0)
   {
    for (int i = 0; i < parameters.Length; i++)
    {
     parametersStr[i] = parameters[i].ToString();
    }
    loggerName.Append(String.Join(", ", parametersStr));
   }

   loggerName.Append(")");

   return GetLogger(loggerName.ToString());
  }
 }


 private static ILog GetLogger(string loggerName)
 {
  if (!isLoaded)
  {
   log4net.Config.XmlConfigurator.Configure();
  }
  return LogManager.GetLogger(loggerName);
 }
}

it lets me use log4net without creating its instance in every class i need to use it, and i still get class name and method where i logged the action.

Sample usage:

Logger.Log.DebugFormat("Response [{0}]", xmlResponse);
empi
Excellent. Thanks.
rathkopf
Have you run a profiler on this? The execution speed of this beast is huge. And even if you wanted to turn of the DEBUG logging level in production you will incur the same cost. I can somewhat see the point if you really need the method name in the logger but then again, when e.g. exceptions occur you would get that name in the exception stacktrace anyway...
Peter Lillevold
A: 

The cost of doing it your original way is an instance of the ILog implementation and the time it takes to run "System.Reflection.MethodBase.GetCurrentMethod().DeclaringType" at startup.

I remember looking into it a few years back, and our startup cost was on the order of 1 second per 10000 classes, and less than a megabyte per 10k classes.

Given such a low cost, I've never looked back given the incredibe flexibility log4net provides.

Note: I can't comment on the other solution here as I'm new.. but this line:

method = new System.Diagnostics.StackTrace().GetFrame(1).GetMethod();

Is expensive, especially if called for every log message.

Peter Drier
A: 

An open source tool you can use with logging is PostSharp (http://www.postsharp.org/). I have only used it to log method boundaries, but I know you can also use it for error-handling. Between the two, that would take care of most of your logging needs without writing code in each class.

Leslie
+3  A: 

I basically use

public class MyClass
{
    private static readonly ILog log = Log.Get<MyClass>();
}

where Log.Get is a class that basically does this internally

return LogManager.GetLogger(typeof(T));

The startup cost is even smaller than the reflection way as well as cleaner imo.

Peter Lillevold