2008-12-02 11 views
52

Al jugar con log4net, he visto la posibilidad de usar una pila por cada subproceso de etiquetas de contexto llamado NDC.Cuándo usar 'contexto de diagnóstico anidado' (NDC)?

Las etiquetas presionadas en esta pila se muestran en un PatternLayout especificando el parámetro de formato %x o el %ndc.

El uso es algo así como:

ILog log = log4net.LogManager.GetLogger(...) ; 

//pattern layout format: "[%ndc] - %message%newline" 

log.Info("message 1"); 
using(log4net.NDC.Push("context") 
{ 
    using(log4net.NDC.Push("inner_context") 
    { 
     log.Info("message 2"); 
    } 
    log.Info("message 3"); 
} 
log.Info("message 4"); 

La salida es algo así como:

null - message 1 
context inner_context - message 2 
context - message 3 
null - message 4 

En su experiencia en programación con log4net, cuando se ha encontrado esta característica para ser útil?

+3

Parece que log4net ha desaprobado NDC a favor del contexto de uso general pilas. El consejo en las respuestas sigue siendo cierto, pero http://logging.apache.org/log4net/release/manual/contexts.html dice "El NDC (contexto de diagnóstico anidado) existe para la compatibilidad con versiones anteriores de log4net.Esta clase de ayuda implementa una pila que se almacena en la propiedad de contexto de subproceso llamada NDC. " –

Respuesta

24

En una aplicación de servidor como ASP.NET.

Por ejemplo, puede insertar información sobre la solicitud actual en el NDC.

+3

Un enlace al ejemplo sería útil –

+5

No tengo un enlace, pero piense en la situación en la que tiene una aplicación ASP.NET con muchos solicitudes simultáneas procesadas. Si inserta la ID de solicitud (ya sea generada o usando algún identificador de la solicitud) en el NDC, puede correlacionar todos los mensajes de registro para una solicitud determinada a través de todos los niveles de su aplicación. Así que ahora los mensajes de registro de su aplicación los componentes de bajo nivel que no saben nada sobre ASP.NET pueden correlacionarse con la solicitud de origen. –

+0

@Johnny_D, ejemplo? [enlace al ejemplo a continuación] (http://stackoverflow.com/a/17344012/939250) –

18

Estas características son útiles cuando tienes que atravesar muchos registros. ¿Cuándo tendrías muchos registros? Diagnóstico de errores extraños en un sistema de producción con salidas de entrelazado. Tener más contextos le permite filtrar el resultado o no generar registros innecesarios.

Otro caso de contextos anidados podría ser útil si un método o una característica se llama varias veces en diferentes contextos y necesita una forma de distinguirlos.

71

¿Quiere un ejemplo?

tomar las siguientes API Web escrito usando ASP.NET MVC4:

// GET api/HypervResource 
public string Get() 
{ 
    logger.Debug("Start of service test"); 
    System.Threading.Thread.Sleep(5000); // simulate work 
    logger.Debug("End of service test"); 
    return "HypervResource controller running, use POST to send JSON encoded RPCs"; 
} 

Cuando se realizan servidor HTTP solicitudes simultáneas, el registro puede conseguir intercalada. P.ej.

2013-06-27 13:28:11,967 [10] DEBUG HypervResource.WmiCalls [(null)] - Start of service test 
2013-06-27 13:28:12,976 [12] DEBUG HypervResource.WmiCalls [(null)] - Start of service test 
2013-06-27 13:28:14,116 [13] DEBUG HypervResource.WmiCalls [(null)] - Start of service test 
2013-06-27 13:28:16,971 [10] DEBUG HypervResource.WmiCalls [(null)] - End of service test 
2013-06-27 13:28:17,979 [12] DEBUG HypervResource.WmiCalls [(null)] - End of service test 
2013-06-27 13:28:19,119 [13] DEBUG HypervResource.WmiCalls [(null)] - End of service test 

En este sencillo ejemplo, se puede usar el ID del tema para distinguir las solicitudes, pero que puede ser complicado como el archivo de registro crece en complejidad.

Una mejor alternativa es proporcionar identificadores únicos que agrupen los mensajes de registro para la misma solicitud. Podemos actualizar el código como la siguiente:

// GET api/HypervResource 
public string Get() 
{ 
    using(log4net.NDC.Push(Guid.NewGuid().ToString())) 
    { 
     logger.Debug("Start of service test"); 
     System.Threading.Thread.Sleep(5000); // simulate work 
     logger.Debug("End of service test"); 
     return "HypervResource controller running, use POST to send JSON encoded RPCs"; 
    } 
} 

Esto produce un registro que puede grep para ver los temas asociados a una solicitud específica. P.ej.

2013-06-27 14:04:31,431 [11] DEBUG HypervResource.WmiCalls [525943cb-226a-43c2-8bd5-03c258d58a79] - Start of service test 
2013-06-27 14:04:32,322 [12] DEBUG HypervResource.WmiCalls [5a8941ee-6e26-4c1d-a1dc-b4d9b776630d] - Start of service test 
2013-06-27 14:04:34,450 [13] DEBUG HypervResource.WmiCalls [ff2246f1-04bc-4451-9e40-6aa1efb94073] - Start of service test 
2013-06-27 14:04:36,434 [11] DEBUG HypervResource.WmiCalls [525943cb-226a-43c2-8bd5-03c258d58a79] - End of service test 
2013-06-27 14:04:37,325 [12] DEBUG HypervResource.WmiCalls [5a8941ee-6e26-4c1d-a1dc-b4d9b776630d] - End of service test 
2013-06-27 14:04:39,453 [13] DEBUG HypervResource.WmiCalls [ff2246f1-04bc-4451-9e40-6aa1efb94073] - End of service test 
0

NDC.Push ha quedado obsoleto. La forma preferida ahora (ThreadContext.Stacks["NDC"]) es la siguiente:

var disposable = ThreadContext.Stacks["NDC"].Push("context"); 
try 
{ 
    Log.Info("begin"); // optional, but nice 
    ... 
} 
finally 
{ 
    Log.Info("end"); // optional, but nice 
    disposable.Dispose(); 
} 

recuerde revisar su patrón de conversión para que incluya %property{NDC}:

<layout type="log4net.Layout.PatternLayout"> 
    <conversionPattern 
    value="%date [%2thread] %-5level [%property{NDC}] - %.10240message%newline" /> 
</layout> 
Cuestiones relacionadas