2012-05-08 7 views
11

Quiero cerrar mi aplicación y escribir cualquier mensaje de registro pendiente. Entonces llamo al LogManager.Flush() durante el proceso de cierre. Sin embargo, no veo todos los mensajes escritos. En cambio, si espero unos segundos (usando Thread.Sleep()) veo los mensajes.¿Debería NLog purgar todos los mensajes en cola en AsyncTargetWrapper cuando se llame a Flush()?

Después de examinar NLog's code on GitHUB, encuentro que el método AsyncTargetWrapper.FlushAsync() solo está programando el hilo del escritor diferido para escribir todos los mensajes pendientes en el siguiente lote. No está escribiendo mensajes de registro sincrónicamente.

¿Es este el comportamiento esperado? Estoy esperando que LogManager.Flush() sea síncrono, es decir: para bloquear hasta que se escriban todos los mensajes pendientes (o se exceda el tiempo de espera).


Código utilizo en el apagado:

LogManager.Flush(ex => { }, TimeSpan.FromSeconds(15)); 

y luego el código para inicializar Nlog (esta es una aplicación de Silverlight, así que no estoy usando los archivos de configuración).

public static void InitialiseNLog(LogLevel forLevel) 
    { 
     var config = new LoggingConfiguration(); 

     // Add targets. 
     // We need an async target wrapping a custom web service call back to the server. 
     var serverTarget = new RemoteServiceTarget(); 
     var asyncWrapper = new AsyncTargetWrapper(serverTarget, 10000, AsyncTargetWrapperOverflowAction.Discard); 
     asyncWrapper.TimeToSleepBetweenBatches = (int)TimeSpan.FromSeconds(2).TotalMilliseconds; 
     asyncWrapper.BatchSize = 200; 

     // Add rules. 
     var rule = new LoggingRule("Company.Application.SilverlightApp.*", forLevel, asyncWrapper); 
     config.LoggingRules.Add(rule); 

     // Activate the configuration. 
     LogManager.Configuration = config; 
     LogManager.GlobalThreshold = forLevel; 
    } 

Respuesta

-1

Implementé una corrección al editar el código fuente actual de NLog.

En AsyncTargetWrapper.cs, cambie el método de FlushAsync():

protected override void FlushAsync(AsyncContinuation asyncContinuation) 
{ 
    this.flushAllContinuation = asyncContinuation; 
} 

Para:

protected override void FlushAsync(AsyncContinuation asyncContinuation) 
{ 
    this.flushAllContinuation = asyncContinuation; 
    this.ProcessPendingEvents(null);  // Added to make this flush synchronous. 
} 
+1

Como resultado de la función FlushAsync convertirse sincronización ;-) Esta no es una solución. –

+0

Esto es un poco viejo ahora, así que no puedo recordar todo el contexto. Pero llamar 'Thread.Sleep()' al apagar es difícilmente una mejor alternativa. Hay un método 'LogManager.Shutdown()' en NLog actual, que podría ser una mejor alternativa (aunque no lo he probado). – ligos

0

aún no es perfecto, pero ¿qué tal esto:

var reset = new ManualResetEventSlim(false); 
LogManager.Flush(ex => reset.Set(), TimeSpan.FromSeconds(15)); 
reset.Wait(TimeSpan.FromSeconds(15)); 
3

El comentario de ligos está en el camino correcto. El método AsyncTargetWrapper.CloseTarget() se modificó como resultado de NLog issue 134, donde un archivo anidado BufferingTargetWrapper no se vaciaba en descarga de dominio.

LogManager.Shutdown() en efecto obligar al AsyncTargetWrapper a ras efectivamente de forma sincrónica, pero tendría que ser utilizado después LogManager.Flush() debido a objetivos tales como la BufferingTargetWrapper en realidad no ras en una estrecha. Puede ser mejor configurar LogManager.Configuration = null ya que esto realiza una descarga y luego cierra los objetivos con un golpe y la configuración se volverá a cargar (si se usa el archivo de configuración) la próxima vez que se necesite usar.

He probado ambos y he ido con este último como que estoy queriendo mi registro de nuevo en marcha después de que yo he puesto las cosas bien, pero teniendo en cuenta la cuestión está en Silverlight yo recomendaría:

LogManager.Flush(); 
LogManager.Shutdown(); 

Editar

LogManager establece la configuración para anular el dominio de descarga o de salida del proceso por lo que no deberíamos estar viendo este problema a menos que utilice una versión antigua Nlog. El problema de NLog se corrigió en octubre de 2012. Ha sido probado sin un cierre explícito o sin configuración de configuración y puede confirmar que llamar al LogManager.Flush() es suficiente.

Cuestiones relacionadas