2012-03-14 12 views
9

Używam log4net do logowania naszych komunikatów w witrynie sieci Web ASP.NET, a ostatnio chciałem dodać informacje o stronie/module obsługi, w którym wystąpił błąd. Postanowiłem więc dodać następującą linię do Global.asax:Jak ustawić właściwość kontekstu log4net specyficzną dla żądania ASP.NET?

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

i jak mądry dodałem %property{page} do mojego wzór konwersji:

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

To działało w porządku dla pojedynczych żądań. Ale potem zauważyłem w moich dziennikach, że właściwość strony może się zmienić podczas żądania ASP.NET. Mam logowanie w jednej procedurze obsługi ASHX, a po jej przetworzeniu właściwość strony zmieni się na inną wartość, która wskazuje stronę ASPX. Doszedłem do wniosku, że jest inne żądanie przychodzące do ASP.NET i jego BeginRequest zostaje wykonane, a statyczna właściwość strony w log4net.ThreadContext zostaje zmieniona na inną wartość.

Chciałbym teraz zachować właściwość strony dla każdego żądania, aby móc konsekwentnie monitorować ścieżkę strony wykonującej logowanie do logu. Próbowałem znaleźć odpowiedź, ale wyszłam z niczym. Jaki jest zalecany sposób rozwiązania tego problemu? Jestem pewien, że jest to bardzo podstawowa funkcjonalność rejestrowania zdarzeń serwera WWW.

Odpowiedz

20

Ponieważ ASP.NET does not guarantee, że całe żądanie strony zostanie przetworzone w tym samym wątku, wolę uzyskanie odpowiedzi z HttpContext.Current as log4net processes zdarzenia rejestrowania.

Poniższy GetCurrentPage klasa implementuje co wywołuje "Active Property Value" podręcznik log4net nadrzędnymi swoją metodę 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 
    } 
} 

Rejestracja ta klasa w Global.asax na Application_Start w log4net za GlobalContext.

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

Kiedy log4net pisze %property{page} część linii będzie wywoływać metodę ToString naszego GetCurrentPage klasy, która będzie Lookup wartość w bieżącym wniosku.

+2

To jest geniusz. –

2

Czy próbowałeś użyć Application_PostAcquireRequestState zamiast Application_BeginRequest, jak opisano w tym artykule? How can I include SessionID in log files using log4net in ASP.NET?

Nigdy nie czułem potrzeby, aby dodać stronę do logowania, ponieważ tworzymy naszą rejestratora w każdej klasy z nazwą metoda:

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

i mają wzór konwersji tak:

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

Widzimy więc nazwę klasy w wynikach dziennika. Pozwala to również rozróżnić, czy rejestracja nastąpiła w pliku klasy strony, w porównaniu z klasą podstawową, z której pochodzi. Twoje rozwiązanie ma tę zaletę, że pokazuje nazwę strony, nawet gdy kod jest wykonywany w klasie bazowej. Myślę, że przyjrzymy się dodaniu {page} do naszej instalacji.

+0

Co ciekawe to działa. BeginRequest jest wykonywany asynchronicznie, ale Application_PostAcquireRequestState jest przetwarzany na początku żądania strony, po którym wszystkie inne zdarzenia strony są uruchamiane synchronicznie, a inne żądanie strony musi czekać do zakończenia pierwszej. –

+0

@CraigA Nie sądzę, że "nowy" operator jest potrzebny w linii kodu "private static new readonly log4net.ILog". Nie można go edytować i usunąć, ponieważ SO mówi "Zmiany muszą mieć co najmniej 6 znaków" :). –

0

Przechowuj wartość właściwości w ASP.NET kontekst HttpContext.Current.Items.Add("yourProperty", value) To będzie dostępny od układu log4net:

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

Znajdź więcej szczegółów here.

Powiązane problemy