如何设置特定于ASP.NET请求的log4net上下文属性?

时间:2012-03-14 12:33:37

标签: asp.net properties log4net httpcontext

我一直在使用log4net来记录我们的ASP.NET网站的日志消息,最近我想添加有关错误发生的页面/处理程序的信息。因此我决定将以下行添加到Global.asax:

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服务器事件记录的基本功能。

3 个答案:

答案 0 :(得分:20)

由于ASP.NET does not guarantee整个页面请求将在同一个线程上处理,我更喜欢从HttpContext.Current as log4net processes获取记录事件的答案。

以下GetCurrentPage类通过覆盖其ToString方法来实现log4net手册调用"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
  }
}

在log4net的GlobalContext中的Global.asax的Application_Start中注册此类。

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

当log4net写入行的%property{page}部分时,它将调用ToString类的GetCurrentPage方法,该方法将查找当前请求中的值。

答案 1 :(得分: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}添加到我们的设置中。

答案 2 :(得分:0)

在ASP.NET上下文HttpContext.Current.Items.Add("yourProperty", value)中存储属性值 它将从log4net布局提供:

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

查找更多详情here.