2010-03-28 12 views

Respuesta

14

realidad he encontrado una manera de hacer esto en este tema:

http://www.l4ndash.com/Log4NetMailArchive/tabid/70/forumid/1/postid/18271/view/topic/Default.aspx

He probado el primer método y funciona. En caso de que ese enlace ya no sea bueno, reproduciré el código aquí. Básicamente, el autor afirma que hay dos formas de hacerlo.

Primera forma:

crear un nuevo modelo de bloqueo que sólo adquiere un bloqueo (y crea el archivo) si el umbral apropiado para que las obras del registrador.

public class MyLock : log4net.Appender.FileAppender.MinimalLock 
{ 
     public override Stream AcquireLock() 
     { 
      if (CurrentAppender.Threshold == log4net.Core.Level.Off) 
        return null; 

      return base.AcquireLock(); 
     } 
} 

Ahora en el archivo de configuración, ajuste el umbral para comenzar como:

<threshold value="OFF" /> 

y asegúrese de que establece esta nueva LockingModel como modelo:

<lockingModel type="Namespace.MyLock" /> 

estoy usando esto con un apilador de archivo rodante.

El segundo método se enumera en el enlace. No he probado esta técnica, pero parece ser técnicamente sólida.

+1

Para cualquier persona que intenta seguir las respuestas, creo que la respuesta de Jon Skeet es en realidad un comentario en esta respuesta. –

+1

¿Puede describir cuál es el segundo método ya que el enlace no funciona? No tiene sentido mencionar que un método está en el enlace cuando el enlace ya no funciona. –

+0

Utilicé esta técnica para crear un NoLock. Mi situación era que estaba usando la configuración del archivo de registro en la aplicación web, pero en realidad estoy escribiendo en un servicio de Windows con una configuración similar. La aplicación web estaba bloqueando el archivo y diferentes tipos de bloqueo. Mínimo, InterProcess no ayudó. Ahora la aplicación web usa las configuraciones de log4net para mostrar todo el archivo de registro a admin pero no bloquea el archivo que realmente usa el servicio de Windows. Estoy profundamente agradecido por esta respuesta. Perdí alrededor de 5-6 horas en esto. –

3

El problema con este enfoque es que si el archivo existe pero es de solo lectura, o está en un directorio que no existe, etc., no lo encontrará hasta que otro error ya esté causando problemas. Realmente desea estar seguro de que el registro funciona antes de que comience el resto de la aplicación.

puede ser una forma de hacer esto de todos modos, pero si no sospecho que este es el motivo.

1

Otro método que es bastante simple se describe en this message of the mailing list archive

Básicamente, con log4net, el archivo de registro se crea cuando se configura el registrador. Configurarlo para hacer lo contrario es un poco hacky. La solución es diferir la ejecución de la configuración. El mensaje anterior sugiere hacer lo siguiente cuando configure el registrador:

private static ILog _log = LogManager.GetLogger(typeof(Program)); 
public static ILog Log 
{ 
    get 
    { 
     if(!log4net.LogManager.GetRepository().Configured) 
      log4net.Config.XmlConfigurator.Configure(new FileInfo(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile)); 
     return _log; 
    } 
} 

generalmente configuro log4net con el conjunto atributo , que configura el registrador de forma automática (creando así el archivo de registro), y un captador simple para el log:

[assembly: log4net.Config.XmlConfigurator(Watch = true)] 
... 
public static log4net.ILog Log { get { return _log; } } 
private static readonly log4net.ILog _log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 

Pero eliminar eso y agregar el getter anterior con la lógica adicional en su lugar resolvió el problema para mí.

Nota: en general, estoy de acuerdo en que, en la mayoría de los casos, sería mejor configurar el registrador y crear el archivo (e incluso escribir en él) al iniciar la aplicación.

7

Sé que esta es una pregunta anterior, pero creo que esto puede ser útil para otra persona.

Nos encontramos con una situación similar en la que se requería que la aplicación no dejara un archivo de registro vacío si no ocurría ningún error.

Nos lo resolvió mediante la creación de las siguientes clases de LockingModel personalizado:

public class MinimalLockDeleteEmpty : FileAppender.MinimalLock 
{ 
    public override void ReleaseLock() 
    { 
     base.ReleaseLock(); 

     var logFile = new FileInfo(CurrentAppender.File); 
     if (logFile.Exists && logFile.Length <= 0) 
     { 
      logFile.Delete(); 
     } 
    } 
} 

Se deriva de la clase FileAppender.MinimalLock que liberará el bloqueo en el archivo de registro después de escribir cada mensaje de registro.

Añadimos una funcionalidad adicional que eliminará el archivo de registro si todavía está vacío después de liberarlo. Impide que la aplicación deje archivos de registro de errores vacíos si las aplicaciones se ejecutan y salen sin ningún error.

Pros

  • Todavía creará un archivo de registro vacío durante la fase de configuración de log4net, asegurando que la tala está trabajando antes que el resto de la aplicación se inicia. Sin embargo, el archivo de registro se elimina de inmediato.
  • No es necesario que desactive el registro en su archivo de configuración estableciendo el valor de umbral en "DESACTIVADO" y luego, encienda el registro mediante programación antes de escribir su primer evento de registro.

Contras

  • Esto es más probable un método lento de la gestión de los archivos de registro debido a que el método de ReleaseLock, y la comprobación de la longitud del archivo, será llamado después cada evento registro que se escribe al archivo de registro. Solo utilícelo cuando espere tener muy pocos errores y es un requisito empresarial que el archivo de registro no exista cuando no haya errores.
  • Los archivos de registro se crean y eliminan cuando están vacíos. Esto podría ser un problema si tiene otras herramientas que monitorean el directorio de registro para los cambios en el sistema de archivos. Sin embargo, esto no fue un problema en nuestra situación.
+0

Me gusta más este enfoque y el primer inconveniente puede debilitarse estableciendo un indicador una vez que el archivo contiene datos para que las llamadas subsiguientes a 'ReleaseLock' ya no controlen la información del archivo. – ZoolWay

-2
private static ILog _log = LogManager.GetLogger(typeof(Program)); 
public static ILog Log 
{ 
    get 
    { 
     if(!log4net.LogManager.GetRepository().Configured) 
     log4net.Config.XmlConfigurator.Configure(new FileInfo(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile)); 
     return _log; 
    } 
} 
+0

y? ..... ¿qué hace tu muestra de código en relación con la pregunta? –

0

método AcquireLock y ReleaseLock trabajó para mí, pero me molestaba que se creó el archivo/borrado que muchas veces. Aquí hay otra opción similar que apaga el registrador y elimina el archivo de registro vacío cuando el programa se completó. Simplemente llame a RemoveEmptyLogFile cuando termine de iniciar sesión.

/// <summary> 
/// Sets the logging level for log4net. 
/// </summary> 
private static void RemoveEmptyLogFile() 
{ 
    //Get the logfilename before we shut it down 
    log4net.Appender.FileAppender rootAppender = (log4net.Appender.FileAppender)((log4net.Repository.Hierarchy.Hierarchy)log4net.LogManager.GetRepository()).Root.Appenders[0]; 
    string filename = rootAppender.File; 

    //Shut down all of the repositories to release lock on logfile 
    log4net.Repository.ILoggerRepository[] repositories = log4net.LogManager.GetAllRepositories(); 
    foreach (log4net.Repository.ILoggerRepository repository in repositories) 
    { 
    repository.Shutdown(); 
    } 

    //Delete log file if it's empty 
    var f = new FileInfo(filename); 
    if (f.Exists && f.Length <= 0) 
    { 
    f.Delete(); 
    } 
} // RemoveEmptyLogFile 
3

Me funcionó a continuación. La primera llamada a OpenFile() se produce cuando se configura el registrador. Las llamadas posteriores son cuando se genera un mensaje de registro real.

class CustomFileAppender : RollingFileAppender 
{ 
    private bool isFirstTime = true; 
    protected override void OpenFile(string fileName, bool append) 
    { 
     if (isFirstTime) 
     { 
      isFirstTime = false; 
      return; 
     } 

     base.OpenFile(fileName, append); 
    } 

}

Y en el archivo de configuración, cambiar el appender

<log4net> 
<appender name="RollingFile" type="<your namespace>.CustomFileAppender"> 
... 
</log4net> 

La secuencia de la fuente Log4net es la siguiente:


  • La primera llamada a OpenFile() se debe a ActivateOptions() llamado desde FileAp constructor de pender.
  • Cuando se genera mensaje de registro, de AppenderSkeleton DoAppend() llama PreAppendCheck()
  • PreAppendCheck() se reemplaza en TextWriterAppender, la base de FileAppender.
  • El PreAppendCheck() reemplazado llama a PrepareWriter virtual si el archivo aún no está abierto.
  • PrepareWriter() de FileAppender llama SafeOpenFile() que llama inturn OpenFile()
Cuestiones relacionadas