2012-12-03 87 views
2

這可能是不可能的,但我想知道是否有辦法使它工作。在運行時使用log4net讀取並記錄HttpSession數據

我有一個大型的ASP.NET MVC43應用程序已經裝備了日誌語句。

現在,我們需要包括在每個日誌條目Session對象是「公司名稱」值。是否可以配置log4net來讀取會話數據並將其包含在日誌條目中?或者以某種方式強迫它......?

感謝您的任何想法。

[編輯] 這個問題幫了大忙:How can I include SessionID in log files using log4net in ASP.NET?

我結束了這是我的解決方案:

在Global.asax.cs中:

// After the session is acquired, push the organization code into log4net's thread context, in case it has to log anything. 
    protected void Application_PostAcquireRequestState(object sender, EventArgs e) 
    { 
     if (Context.Handler is IRequiresSessionState && Session != null && Session[Constants.EMPLOYEE_DETAILS] != null) 
       log4net.ThreadContext.Properties["Company"] = ((EmployeeDetails)Session[Constants.EMPLOYEE_DETAILS]).Company; 
    } 

在log4net的配置:

<parameter> 
    <parameterName value="@Company"/> 
    <dbType value="String"/> 
    <size value="10"/> 
    <layout type="log4net.Layout.PatternLayout"> 
     <conversionPattern value="%property{Company}" /> 
    </layout> 
    </parameter> 

工程很好 - 我得到一個公司mpany名稱在我的日誌輸出中。感謝大家的幫助。

+0

實現AppenderSkeleton非常容易(請參閱http://logging.apache.org/log4net/release/sdk/log4net.Appender.AppenderSkeleton.html)該實現可以引用靜態Session實例並添加信息。 –

回答

1

看到這個答案對於一些關於如何實現這一點的想法。

Capture username with log4net

你應該能夠做到這一點沒有實現自己的Appender。

這裏是一個自定義PatternLayoutConverter拉動從HttpContext.Current.Session一個參數值的示例。 (我不記得是否測試過它,當我張貼鏈接的答案與否的一部分,但它應該是接近):

namespace Log4NetTest 
{ 
    class HttpContextSessionPatternConverter : PatternLayoutConverter 
    { 
    protected override void Convert(System.IO.TextWriter writer, LoggingEvent loggingEvent) 
    { 
     //Use the value in Option as a key into HttpContext.Current.Session 
     string setting = ""; 

     HttpContext context = HttpContext.Current; 
     if (context != null) 
     { 
     object sessionItem; 
     sessionItem = context.Session[Option]; 
     if (sessionItem != null) 
     { 
      setting = sessionItem.ToString(); 
     } 
     writer.Write(setting); 
     } 
    } 
    } 
} 

另一種更簡單的想法是做這樣的事情...創建對象將檢索所需的Session參數並將該對象放入MDC中,然後在您的佈局中引用MDC。當log4net從MDC訪問對象時,它將調用其ToString方法來獲取要寫入日誌的值。

public class HttpContextSessionParametreProvider 
{ 
    private string _name; 
    private string _notSet; 

    public HttpContextSessionParameterProvider(string name) 
    { 
    _name = name; 
    _notSet = string.Format("{0} not set", _name); 
    } 

    public override string ToString() 
    { 
    HttpContext context = HttpContext.Current; 
    if (context != null && context.Session != null) 
    { 
     object item = context.Session[_name]; 
     if (item != null) 
     { 
     return item.ToString(); 
     } 
    } 
    return _notSet; 
    } 
} 

使用像這樣的地方你的程序的入口點附近:

MDC.Set("CompanyName", new HttpContextSessionParametreProvider("Company Name")); 

(我沒有得心應手如何log4net的配置爲拉離MDC參數的例子,但它不應該很難找到一個)。

編輯:

你可以配置你的PatternLayout是這樣的:

<layout type="log4net.Layout.PatternLayout"> 
    <conversionPattern value="[%thread]|[%property{CompanyName}]|%message%newline"/> 
    </layout> 

現在,假設HttpContext.Session["Company Name"]設置的東西,在您登錄的消息,該值將被寫入日誌。

+0

謝謝。顯然,MDC已被棄用,但您提供的鏈接有一些證明有用的信息。現在,如果我只能找出爲什麼HttpContext.Current始終爲空。可能是因爲我使用spring.net將log4net實例注入到LogManager類中。嗯。 – TimH

+0

很高興幫助。我不做任何ASP.NET開發,所以我害怕我無法幫助null HttpContext.Current。我找到了這個(舊)外部帖子,描述了一些HttpContext.Current可能爲null的情況。 http://www.pcreview.co.uk/forums/can-httpcontext-current-null-t3561352.html也許它會有所幫助。 – wageoghe

2

使用自定義佈局變換

public class CompanyLayoutConverter : PatternLayoutConverter 
{ 
    protected override void Convert(TextWriter writer, LoggingEvent loggingEvent) 
    { 
     var httpContext = HttpContext.Current; 
     if (httpContext == null) 
      return; 

     writer.Write(httpContext.Session["Company Name"]); 
    } 
} 

這個轉換器添加到附加目的地佈局,公司名稱將出現在輸出(只需在conversionPattern值使用%company):

<appender name="RollingLogFileAppender" 
      type="log4net.Appender.RollingFileAppender"> 
    <threshold value="All" /> 
    <file value="C:\LogFile" /> 
    <appendToFile value="true" /> 
    <rollingStyle value="Date" /> 
    <datePattern value="'.'yyyyMMdd'.log.txt'" /> 
    <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> 
    <layout type="log4net.Layout.PatternLayout"> 
    <converter> 
     <name value="company"/> 
     <type value="Foo.Bar.CompanyLayoutConverter"/> 
    </converter> 
    <conversionPattern value="%date %-5level %logger - %company %message%newline" /> 
    </layout> 
</appender> 
+1

這是第二個接近上述答案。我得到它的工作,但無法正確地理清conversionPattern的值。謝謝,不過。 – TimH