2009-01-13 24 views
5

Me suelen incluir la siguiente información en cada clase:estrategia de log4net en los registradores con nombre?

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

y utilizar el miembro estático dentro de cada clase para conectarse a diferentes niveles (información, depuración, etc.)

vi que en algún lugar y han sido Usarlo de forma un tanto descuidada, razonando que la configuración es lo suficientemente flexible como para ayudarme a filtrar por espacio de nombres y registrar tipos individuales si quisiera en la resolución de problemas de producción y lo que no.

Pero rara vez tuve que usar ese "nivel" de registro fino. Entonces, me gustaría ver lo que otros están usando. ¿Utiliza lo anterior, ya que tengo la sensación de que muchos están usando exactamente eso, o crea registradores con nombre como "depuración", "rastreo", "error", "módulo A", etc. y comparte el registrador entre diferentes tipos ¿Asambleas?

Respuesta

-1

Últimamente, he creado algo como esto:

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); 
    } 
} 

que me permite usar log4net sin crear su instancia en todas las clases que necesito para usarlo, y sigo teniendo nombre de la clase y el método en el que me conecté la acción .

Ejemplo de uso:

Logger.Log.DebugFormat("Response [{0}]", xmlResponse); 
+0

Excelente. Gracias. – Chasler

+2

¿Has ejecutado un generador de perfiles en esto? La velocidad de ejecución de esta bestia es enorme. E incluso si quisiera cambiar el nivel de registro de DEPURACIÓN en producción, incurrirá en el mismo costo. De alguna manera, puedo ver el punto si realmente necesita el nombre del método en el registrador, pero nuevamente, cuando, por ejemplo, se producen excepciones, usted obtendría ese nombre en la pila de la excepción de todos modos ... –

+1

Bastante seguro de que esto es reemplazado por el nuevo atributo CallerName - vea http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices. callermembernameattribute% 28v = vs.110% 29.aspx – keithl8041

2

El costo de hacer a tu manera original es una instancia de la aplicación ILOG y el tiempo que se tarda en ejecutar "System.Reflection.MethodBase.GetCurrentMethod() DeclaringType." A puesta en marcha.

Recuerdo haberlo visto hace unos años, y nuestro costo inicial era del orden de 1 segundo por cada 10000 clases, y menos de un megabyte por cada 10k clases.

Dado un costo tan bajo, nunca he mirado hacia atrás dada la increíble flexibilidad que ofrece log4net.

Nota: no puede hacer comentarios sobre la otra solución aquí como soy nuevo .. pero esta línea:.

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

Es caro, especialmente si se solicita para cada mensaje de registro.

0

Una herramienta que puede usar con el registro es PostSharp (http://www.postsharp.org/). Hay una versión paga y otra gratis (Express). Solo lo he usado para registrar límites de métodos, pero sé que también puedes usarlo para manejar errores. Entre los dos, eso se ocuparía de la mayoría de sus necesidades de registro sin escribir código en cada clase.

11

básicamente utilizo

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

donde Log.Get es una clase que básicamente hace esto internamente

return LogManager.GetLogger(typeof(T)); 

El costo inicial es incluso más pequeño que el reflejo camino, así como limpiador de la OMI.

Actualización: teniendo en cuenta mi experiencia en los últimos años con la inyección de dependencia, pruebas unitarias y falsificaciones, no puedo decir que apruebo el enfoque descrito anteriormente.El problema con el enfoque (tanto el mío como el de OP) es que el código tiene conocimiento explícito sobre cómo se crea la instancia de registro.

Uno un lado, este aumento de acoplamiento hace que sea más difícil de la prueba: no hay una manera fácil de reemplazar la instancia ILog con uno falso. Por otro lado, los cambios realizados en mi clase Log provocarán cambios en todas las clases que lo utilizan.

Por lo tanto, ir a la ruta de inyectar la instancia ILog, normalmente a través de inyección de constructor, y subcontratar el cómo construir un registrador-my DI framework of choice:

public class MyClass 
{ 
    readonly ILog _log; 

    public class MyClass(ILog log) 
    { 
     _log = log; 
    } 
} 

Esto permite un desacoplamiento adecuado. El código ya no necesita saber cómo se construyen los registradores. La mayoría de los marcos de inyección de dependencias tienen medios para ver el tipo que se inyecta y luego usarlo para construir la instancia de registro. Aquí hay un approach for log4net and Autofac.

+0

¿Qué beneficio le da esto al utilizar 'LogManager.GetLogger (typeof (MyClass))' al obtener la instancia 'ILog'? – MarioVW

+1

Código más corto y más limpio. Pero debería revisar esta respuesta porque hoy en día, utilizo la inyección de dependencia y dejo que el marco DI construya el registrador. –

Cuestiones relacionadas