2012-03-14 12 views
9

He estado usando log4net para registrar los mensajes de registro de nuestro sitio web ASP.NET, y últimamente quería agregar información sobre la página/controlador donde ocurrió el error. Por lo tanto decidí añadir la siguiente línea a Global.asax:¿Cómo establecer la propiedad de contexto de log4net específica para una solicitud de ASP.NET?

void Application_BeginRequest(object sender, EventArgs e) 
{ 
    log4net.ThreadContext.Properties["page"] = HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath; 
} 

y como sabia añadí %property{page} a mi patrón de conversión:

<conversionPattern value="%newline%date %-5level %property{page} - %message%newline%newline%newline" /> 

Esto funcionó bien para peticiones individuales. Pero luego noté en mis registros que la propiedad de la página puede cambiar durante una solicitud de ASP.NET. Tengo el inicio de sesión en un controlador ASHX, y en medio de su procesamiento, la propiedad de la página cambiará a un valor diferente que apunta a una página ASPX. Llegué a la conclusión de que hay otra solicitud en ASP.NET y se ejecuta BeginRequest y la propiedad de página estática en log4net.ThreadContext cambia a otro valor.

Ahora, me gustaría mantener la propiedad de la página por solicitud, para que pueda tener la ruta de la página de ejecución registrada en el registro de forma coherente. Traté de encontrar una respuesta, pero salí sin nada. ¿Cuál es la forma recomendada de resolver este problema? Estoy seguro de que esta es una funcionalidad muy básica del registro de eventos del servidor web.

Respuesta

20

Desde ASP.NET does not guarantee que toda la solicitud de página se procesará en el mismo subproceso, prefiero obtener la respuesta de HttpContext.Current as log4net processes el evento de registro.

El GetCurrentPage siguiente clase implementa lo que el manual log4net llama un "Active Property Value" anulando su método ToString:

public class GetCurrentPage 
{ 
    public override string ToString() 
    { 
     if (null != HttpContext.Current) 
     { 
      return HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath; 
     } 
     return string.Empty; // or "[No Page]" if you prefer 
    } 
} 

Registro esta clase en Global.asax de Application_Start en GlobalContext de log4net.

protected void Application_Start(object sender, EventArgs e) 
{ 
    XmlConfigurator.Configure(); 
    GlobalContext.Properties["page"] = new GetCurrentPage(); 
} 

Cuando log4net escribe la parte %property{page} de la línea se llamará al método de nuestra clase GetCurrentPageToString que buscar el valor en la solicitud actual.

+2

Esto es genio. –

2

¿Ha intentado utilizar Application_PostAcquireRequestState en lugar de Application_BeginRequest como se describe en este artículo? How can I include SessionID in log files using log4net in ASP.NET?

Nunca hemos sentido la necesidad de añadir la página a la tala ya que nosotros creamos nuestra registrador en cada clase con el nombre del método:

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

y tienen un patrón de conversión de la siguiente manera:

<conversionPattern value="%date %P{user} %P{addr} [%property{SessionID}] %level %logger - %message%newline" /> 

Así que terminamos viendo el nombre de la clase en el resultado del registro. Esto también le permite diferenciar si el registro ocurrió en el archivo de la clase de la página, frente a una clase base de la que hereda. Su solución tendría la ventaja de mostrar el nombre de la página incluso cuando el código se está ejecutando en la clase base. Creo que veremos agregar {página} a nuestra configuración.

+0

Curiosamente esto funciona. BeginRequest se ejecuta de forma asíncrona, pero Application_PostAcquireRequestState se procesa al inicio de una solicitud de página, después de lo cual todos los demás eventos de página se desencadenan de forma síncrona y otra solicitud de página debe esperar hasta que finalice la primera. –

+0

@CraigA No creo que se necesite el 'nuevo' operador en su línea de código 'private static new readonly log4net.ILog'. No se puede editar y eliminar, ya que SO dice "Las ediciones deben tener al menos 6 caracteres" :). –

0

Almacenar valor de propiedad en ASP.NET contexto HttpContext.Current.Items.Add("yourProperty", value) Estará disponible a partir de la disposición log4net:

<layout type="log4net.Layout.PatternLayout"> 
    <conversionPattern value="%aspnet-context{yourProperty}" /> 
</layout> 

encontrar más detalles here.

Cuestiones relacionadas