2

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

我有一个大型 ASP.NET MVC43 应用程序,该应用程序已经配备了日志记录语句。

现在我们需要在每个日志条目中包含来自 Session 对象的“公司名称”值。是否可以将 log4net 配置为读取会话数据并将其包含在日志条目中?或者有什么办法强迫它……?

感谢您的任何想法。

[编辑] 这个问题很有帮助: 如何在 ASP.NET 中使用 log4net 在日志文件中包含 SessionID?

我最终将此作为我的解决方案:

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

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

4

3 回答 3

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 布局中,公司名称将出现在输出中(只需%company在 conversionPattern 值处使用):

<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>
于 2012-12-03T20:51:36.267 回答
1

有关如何实现此功能的一些想法,请参阅此答案。

使用 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"]设置为某个值,每当您记录一条消息时,该值都会写入日志。

于 2012-12-03T20:54:59.570 回答
0

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

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

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

该文档并没有太大帮助。

于 2012-12-03T20:47:41.613 回答