【问题标题】:Lazy evaluation with buffers in AdoNetAppender in Log4Net在 Log4Net 中的 AdoNetAppender 中使用缓冲区进行延迟评估
【发布时间】:2014-12-22 14:37:57
【问题描述】:

我正在使用 Log4Net 自定义属性将一些环境信息添加到我的日志中。我创建了一个具有全局可访问属性的实用程序类,我的程序类使用它来存储上下文信息(订单 ID、用户 ID 等)以及围绕它们的惰性包装器,因此我不需要一直更改 Log4Net ThreadContext。像这样的:

public class LoggerPropertyProvider
{
    private readonly string _value;

    public LoggerPropertyProvider(string value)
    {
        _value = value;
    }

    public override string ToString()
    {
        return _value;
    }
}

无论我想作为属性向 Log4Net 公开什么值,我只需在应用程序开始时使用这个 lazy evaluator 进行注册。

ThreadContext.Properties["ORDER_ID"] = new LoggerPropertyProvider(ContextInformation.OrderId);

它适用于 无缓冲区附加程序(例如滚动文件)或在 AdoNetAppender 中将缓冲区设置为 0 时。但是,当我有 buffer > 1 时,Log4Net 会推迟对属性的评估,直到在应用程序结束时刷新缓冲区或 entries in buffer > bufferSize。。 p>

发生这种情况时,信息不再存在于全局属性中,或者它的值已更改(如循环处理订单),因此我的日志中出现错误或空值。

我可以看到解决此问题的唯一选项是停止使用缓冲区,以便在刷新条目时在所有调用中评估属性值。由于仅在刷新缓冲区时才评估 ThreadContext 中的属性,因此恐怕每个日志调用都不能有不同的属性值。

有什么方法可以让 Log4Net 在缓冲条目而不是刷新条目时评估 ThreadContext(或它具有的其他上下文)?

谢谢

【问题讨论】:

    标签: c# buffer log4net adonetappender


    【解决方案1】:

    看来您必须将该属性放在 log4net 线程上下文中:

    log4net.ThreadContext.Properties["ORDER_ID"] = new LoggerPropertyProvider(ContextInformation.OrderId);
    

    此上下文覆盖全局上下文中的任何属性,并由 log4net 自行管理:

    log4net.ThreadContext

    【讨论】:

      【解决方案2】:

      默认情况下,log4net 不会 fix 缓存附加程序在日志时从上下文中获取属性提供程序值。它们在缓冲区刷新时得到评估。

      要解决这个问题,你必须从 log4net.Core 命名空间实现 IFixingRequired。

      public class LoggerPropertyProvider : IFixingRequired
      {
          private readonly string _value;
      
          public LoggerPropertyProvider(string value)
          {
              _value = value;
          }
      
          public override string ToString()
          {
              return _value;
          }
      
          object IFixingRequired.GetFixedObject()
          {
              return ToString();
          }
      }
      

      (使用我自己的属性提供者进行测试,由于我自己的需要,它依赖于 http 上下文:

      // We can not use log4net ThreadContext or LogicalThreadContext with asp.net, since
      // asp.net may switch thread while serving a request, and reset the call context in
      // the process.
      public class HttpContextValueProvider : IFixingRequired
      {
          private string _contextKey;
          public HttpContextValueProvider(string contextKey)
          {
              _contextKey = contextKey;
          }
      
          public override string ToString()
          {
              var currContext = HttpContext.Current;
              if (currContext == null)
                  return null;
              var value = currContext.Items[_contextKey];
              if (value == null)
                  return null;
              return value.ToString();
          }
      
          object IFixingRequired.GetFixedObject()
          {
              return ToString();
          }
      }
      

      来自piers blog 的总体思路。看到这个my other answer另一个问题 如果您想了解有关此HttpContextValueProvider 的更多最新详细信息。)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-10-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-07
        • 1970-01-01
        • 2011-03-03
        相关资源
        最近更新 更多