2012-03-14 24 views
9

我一直在使用log4net來記錄我們的ASP.NET網站的日誌消息,最近我想添加有關發生錯誤的頁面/處理程序的信息。因此,我決定將下列行添加到Global.asax中:如何設置特定於ASP.NET請求的log4net上下文屬性?

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

和喜歡聰明的我加%property{page}到我的轉換模式:

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

這對於單一申請工作的罰款。但後來我注意到在我的日誌中,頁面屬性可能會在ASP.NET請求期間發生更改。我登錄了一個ASHX處理程序,在處理過程中,頁面屬性將更改爲指向ASPX頁面的不同值。我得出結論,ASP.NET有另一個請求,它的BeginRequest被執行,log4net.ThreadContext的靜態頁面屬性被更改爲另一個值。

現在,我想維護每個請求的頁面屬性,以便我可以將執行頁面的路徑始終記錄到日誌中。我試圖找到答案,但我什麼都沒有出來。建議如何解決這個問題?我確定這是Web服務器事件日誌的基本功能。

回答

20

由於ASP.NET does not guarantee表示整個頁面請求將在同一個線程上處理,所以我更願意從HttpContext.Current as log4net processes獲取答案,記錄事件。

以下GetCurrentPage類實現什麼log4net的手冊通過重寫其ToString方法調用的"Active Property Value"

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 
    } 
} 

註冊這個類在Global.asax中的Application_Start在log4net的的GlobalContext。

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

當log4net的寫入線它將調用我們的GetCurrentPage類的ToString方法,這將在查找當前請求的值的%property{page}一部分。

+2

這是天才。 – 2016-10-22 06:23:13

2

您是否嘗試過使用Application_PostAcquireRequestState而不是Application_BeginRequest,如本文所述? How can I include SessionID in log files using log4net in ASP.NET?

我們從來沒有感到有必要,因爲我們在方法名各類創建我們的記錄器頁面添加到日誌:

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

,並有一個這樣的轉換模式:

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

所以我們最終在日誌輸出中看到類名。這也可以讓您區分日誌記錄是否發生在頁面類文件本身中,而不是它從中繼承的基類。即使代碼在基類中執行,您的解決方案也會顯示頁面名稱的優勢。我想我們會考慮在我們的設置中添加{page}。

+0

有趣的是這個作品。 BeginRequest異步執行,但Application_PostAcquireRequestState在頁面請求開始時處理,之後所有其他頁面事件同步觸發,並且另一個頁面請求必須等待,直到第一個頁面結束。 – 2012-03-15 12:10:56

+0

@CraigA我不認爲你的代碼行'private static new readonly log4net.ILog'需要'new'運算符。無法編輯和刪除它,因爲SO說「編輯必須至少有6個字符」:)。 – 2014-03-28 19:57:37

0

以ASP方式存儲屬性值。NET方面HttpContext.Current.Items.Add("yourProperty", value) 這將可從log4net的佈局:

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

查找更詳細here.

相關問題