阅读&使用log4net在运行时记录HttpSession数据

时间:2012-12-03 20:33:58

标签: c# logging asp.net-mvc-4 log4net

这可能是不可能的,但我想知道是否有办法让它发挥作用。

我有一个大型的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>

效果很好 - 我现在在日志输出中得到一个公司名称。感谢大家的帮助。

3 个答案:

答案 0 :(得分: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"]);
    }
}

将此转换器添加到appender布局,公司名称将显示在输出中(只需在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 :(得分: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"]设置为某个内容,无论何时记录消息,该值都将写入日志。

答案 2 :(得分:0)

我认为你可以使用上下文和模式布局来做到这一点:

http://logging.apache.org/log4net/release/manual/contexts.html

http://logging.apache.org/log4net/release/sdk/log4net.Layout.PatternLayout.html

虽然文档没有多大帮助。