2008-10-01 12 views
24

he envuelto en un envoltorio Log4net estática y desea iniciar sesiónCómo registrar MethodName al ajustar Log4net?

loggingEvent.LocationInformation.MethodName 
loggingEvent.LocationInformation.ClassName 

Sin embargo, todo lo que consigo es el nombre de mi envoltura.

¿Cómo puedo registrar esa información utilizando un forwardingappender y una clase de contenedor estático como

Logger.Debug("Logging to Debug"); 
Logger.Info("Logging to Info"); 
Logger.Warn("Logging to Warn"); 
Logger.Error(ex); 
Logger.Fatal(ex); 
+0

Si recuerdo bien, log4net puebla el 'LocationInformation' de el 'Tipo' que está pasando a la llamada' LogManager.GetLogger (Type) ', por lo que es razonable que presente la información de su contenedor (supongo que su contenedor hace esto:' ILog log = LogManager.GetLogger (typeof (MyLogWrapper) '). – Panos

+1

En realidad lo envuelvo como LoggerManager.GetLogger (Asse mbly.GetCallingAssembly(), "MyDefaultLoggger"), para evitarlo –

+0

Posible duplicado de [¿Cuándo se usa wrapper, cómo preservar la clase y el nombre del método para que Log4Net inicie sesión?] (http://stackoverflow.com/questions/2049992/when-using-wrapper-how-to-preserve-class-and-method-name-for-log4net-to-log) –

Respuesta

21

bien el error fue en algún lugar de mi appender sino por la totalidad enfermos incluyen la respuesta a lo mejor de mi conocimiento:

la fachada que necesita debe envolver ILogger y NO ILOG

public static class Logger 
{ 
    private readonly static Type ThisDeclaringType = typeof(Logger); 
    private static readonly ILogger defaultLogger; 

    static Logger() 
    { 
     defaultLogger = 
     LoggerManager.GetLogger(Assembly.GetCallingAssembly(),"MyDefaultLoggger"); 

...

public static void Info(string message) 
    { 
     if (defaultLogger.IsEnabledFor(infoLevel)) 
     { 
      defaultLogger.Log(typeof(Logger), infoLevel, message, null); 
     } 
    } 
0

La única cosa que puedo pensar en hacer (como yo no utilizan actualmente log4net) es solicitar una StackTrace (nueva StackTrace), y retroceda un marco para obtener la información que necesita. Sin embargo, no estoy seguro del impacto en el rendimiento del tiempo de ejecución de esto.

+0

log4net allready tiene esto en la clase LocationInformation, pero no funciona cuando se aplica Ilog –

+1

log4net las escenas haciendo lo mismo cuando el diseño del patrón contiene las variables% my% c. Advierten sobre el uso de ellos por razones obvias de rendimiento. – bryanbcook

7

Sólo declarar la variable de registro así ...

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

Entonces puede usarlo normalmente.

+8

No funcionó, ¡pero desearía que fuera así de fácil! –

4

Este post me ayudó a encontrar la manera de escribir mi propio envoltorio, a cambio, pensé que podría gustarle mi clase completa para envolver el registrador que parece funcionar muy bien y que realmente lleva más de la mitad del tiempo que usar un ILog ¡directamente!

Todo lo que se necesita es el XML adecuado para configurar el registro en el fichero de configuración y

[assembly: log4net.Config.XmlConfigurator(Watch = true)] 

en sus AssemblyInfo.cs y debería funcionar fácilmente.

Una nota: Estoy usando Log4NetDash con una configuración muy simple, así que he estafado y puesto algo de información en los campos incorrectos (por ejemplo, seguimiento de pila en el campo Dominio), esto todavía funciona para mí ya que no me importa donde se muestra la información, pero es posible que desee corregir esto si está configurando cosas correctamente si tiene tiempo libre.

using System; 
using System.ComponentModel; 
using System.Diagnostics; 
using System.Reflection; 
using System.Threading; 
using log4net; 
using log4net.Core; 

namespace Utility 
{ 
    public class Logger 
    { 
     static Logger() 
     { 
      LogManager.GetLogger(typeof(Logger)); 
     } 

     public static void Debug(string message, params object[] parameters) 
     { 
      Log(message, Level.Debug, null, parameters); 
     } 

     public static void Info(string message, params object[] parameters) 
     { 
      Log(message, Level.Info, null, parameters); 
     } 

     public static void Warn(string message, params object[] parameters) 
     { 
      Log(message, Level.Warn, null, parameters); 
     } 

     public static void Error(string message, params object[] parameters) 
     { 
      Error(message, null, parameters); 
     } 

     public static void Error(Exception exception) 
     { 
      if (exception==null) 
       return; 
      Error(exception.Message, exception); 
     } 

     public static void Error(string message, Exception exception, params object[] parameters) 
     { 
      string exceptionStack = ""; 

      if (exception != null) 
      { 
       exceptionStack = exception.GetType().Name + " : " + exception.Message + Environment.NewLine; 
       Exception loopException = exception; 
       while (loopException.InnerException != null) 
       { 
        loopException = loopException.InnerException; 
        exceptionStack += loopException.GetType().Name + " : " + loopException.Message + Environment.NewLine; 
       } 
      } 

      Log(message, Level.Error, exceptionStack, parameters); 
     } 



     private static void Log(string message, Level logLevel, string exceptionMessage, params object[] parameters) 
     { 
      BackgroundWorker worker = new BackgroundWorker(); 
      worker.DoWork += LogEvent; 
      worker.RunWorkerAsync(new LogMessageSpec 
             { 
              ExceptionMessage = exceptionMessage, 
              LogLevel = logLevel, 
              Message = message, 
              Parameters = parameters, 
              Stack = new StackTrace(), 
              LogTime = DateTime.Now 
             }); 
     } 

     private static void LogEvent(object sender, DoWorkEventArgs e) 
     { 
      try 
      { 
       LogMessageSpec messageSpec = (LogMessageSpec) e.Argument; 

       StackFrame frame = messageSpec.Stack.GetFrame(2); 
       MethodBase method = frame.GetMethod(); 
       Type reflectedType = method.ReflectedType; 

       ILogger log = LoggerManager.GetLogger(reflectedType.Assembly, reflectedType); 
       Level currenLoggingLevel = ((log4net.Repository.Hierarchy.Logger) log).Parent.Level; 

       if (messageSpec.LogLevel<currenLoggingLevel) 
        return; 

       messageSpec.Message = string.Format(messageSpec.Message, messageSpec.Parameters); 
       string stackTrace = ""; 
       StackFrame[] frames = messageSpec.Stack.GetFrames(); 
       if (frames != null) 
       { 
        foreach (StackFrame tempFrame in frames) 
        { 

         MethodBase tempMethod = tempFrame.GetMethod(); 
         stackTrace += tempMethod.Name + Environment.NewLine; 
        } 
       } 
       string userName = Thread.CurrentPrincipal.Identity.Name; 
       LoggingEventData evdat = new LoggingEventData 
              { 
               Domain = stackTrace, 
               Identity = userName, 
               Level = messageSpec.LogLevel, 
               LocationInfo = new LocationInfo(reflectedType.FullName, 
                       method.Name, 
                       frame.GetFileName(), 
                       frame.GetFileLineNumber().ToString()), 
               LoggerName = reflectedType.Name, 
               Message = messageSpec.Message, 
               TimeStamp = messageSpec.LogTime, 
               UserName = userName, 
               ExceptionString = messageSpec.ExceptionMessage 
              }; 
       log.Log(new LoggingEvent(evdat)); 
      } 
      catch (Exception) 
      {}//don't throw exceptions on background thread especially about logging! 
     } 

     private class LogMessageSpec 
     { 
      public StackTrace Stack { get; set; } 
      public string Message { get; set; } 
      public Level LogLevel { get; set; } 
      public string ExceptionMessage { get; set; } 
      public object[] Parameters { get; set; } 
      public DateTime LogTime { get; set; } 
     } 
    } 
} 
+1

La reflexión es bastante costosa especialmente para fines de registro. No quiere decir que su código es lento debido al registro. Prefiero usar CallerMemberName y otros atributos similares si utilizo C# 5 – Junaid

+0

Muy cierto. Tiendo a usar la versión enhebrada de Log donde sea posible para que el registro pase lejos de la ruta crítica. Sin embargo, no siempre es posible, realmente debería actualizar mi registro ya que ahora tiene más de cinco años. Ta – Stu

22

¿Qué pasa con las variables %M y %C? http://logging.apache.org/log4net/release/sdk/log4net.Layout.PatternLayout.html

uso, algo así como:

<layout type="log4net.Layout.PatternLayout"> 
    <conversionPattern value="%date [%thread] %-5level %logger [%M %C] - %message%newline" /> 
</layout> 

¿Eso no hacen lo que está después?

+0

+1 por ser (al menos para mí) lo que debería ser la respuesta a la pregunta. ¿Algún comentario sobre si esto sería más o menos eficiente que las respuestas anteriores? – Josep

+8

Nota "al envolver" en el asunto. En la pregunta, el ejemplo del autor (al ajustar ILog)% M será equivalente a "Depurar", "Información", etc., lo cual no es útil. – nightcoder

3

yo simplemente usar algo como %stacktrace{2} como un patrón de conversión.

Ejemplo de salida:

MyNamespace.ClassName.Método> Common.Log.Warning

donde MyNamespace.ClassName.Method es un método que está llamando mi envoltura y Common.Log.Warning es un método de la clase contenedora.

Los patrones de conversión se pueden encontrar here.

0

sólo voy a escribir más código de la respuesta correcta de Noel

En la clase contenedora

public static class Logger 
{ 
    private static readonly ILogger DefaultLogger; 

    static Logger() 
    { 
     defaultLogger = LoggerManager.GetLogger(Assembly.GetCallingAssembly(), "MyDefaultLoggger"); // MyDefaultLoggger is the name of Logger 
    } 

    public static void LogError(object message) 
    { 
     Level errorLevel = Level.Error; 
     if (DefaultLogger.IsEnabledFor(errorLevel)) 
     { 
      DefaultLogger.Log(typeof(Logger), errorLevel, message, null); 
     } 
    } 

    public static void LogError(object message, Exception exception) 
    { 
     Level errorLevel = Level.Error; 
     if (DefaultLogger.IsEnabledFor(errorLevel)) 
     { 
      DefaultLogger.Log(typeof(Logger), errorLevel, message, exception); 
     } 
    } 

y así sucesivamente para el resto de los métodos.

en web.config o app.config log4net.Layout.PatternLayout puede utilizar algunos patrones de conversión como:

%location %method %line 

<layout type="log4net.Layout.PatternLayout"> 
    <conversionPattern value="%date{dd/MM/yyyy hh:mm:ss.fff tt} [%thread] %level %logger [%location %method %line] [%C %M] - %newline%message%newline%exception"/> 
    </layout> 
Cuestiones relacionadas