Log4net缓冲区不起作用

时间:2016-06-13 11:56:45

标签: c# asp.net log4net log4net-configuration log4net-appender

我正在使用log4net和log4net.Elasticsearch插件(这个问题很重要,问题一般是关于log4net缓冲),我正在尝试使用缓冲区。我不希望每个日志事件都单独发送给Elasticsearch。这是我的appender配置:

<appender name="ElasticSearchAppender" type="log4net.ElasticSearch.ElasticSearchAppender, log4net.ElasticSearch">
    <layout type="log4net.Layout.PatternLayout,log4net">
      <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p %c{1}:%L - %m%n" />
    </layout>
    <connectionString value="Server=xxx.xxx.xxx.xxx;Index=api_actions_log;Port=9200"/>
    <lossy value="false" />
    <bufferSize value="100" />
    <evaluator type="log4net.Core.LevelEvaluator">
        <threshold value="INFO"/>
    </evaluator>
    <filter type="log4net.Filter.LoggerMatchFilter">
          <loggerToMatch value="My.Namespace.LoggingFilterAttribute" />
    </filter>
    <filter type="log4net.Filter.DenyAllFilter" />
</appender>

正如您所看到的,我指定bufferSize = 100,但即使每条消息都立即发送到Elasticsearch。

我正在深入研究并试图找出代码中真正发生的事情。当调用Log方法时,在ES appender类上调用Append方法。方法继承自base log4net BufferingAppenderSkeleton,如下所示:

protected override void Append(LoggingEvent loggingEvent)
{
  if (this.m_cb == null || this.m_bufferSize <= 1)
  {
    if (this.m_lossy && (this.m_evaluator == null || !this.m_evaluator.IsTriggeringEvent(loggingEvent)) && (this.m_lossyEvaluator == null || !this.m_lossyEvaluator.IsTriggeringEvent(loggingEvent)))
      return;
    if (this.m_eventMustBeFixed)
      loggingEvent.Fix = this.Fix;
    this.SendBuffer(new LoggingEvent[1]
    {
      loggingEvent
    });
  }
  else
  {
    loggingEvent.Fix = this.Fix;
    LoggingEvent loggingEvent1 = this.m_cb.Append(loggingEvent);
    if (loggingEvent1 != null)
    {
      if (!this.m_lossy)
      {
        this.SendFromBuffer(loggingEvent1, this.m_cb);
      }
      else
      {
        if (this.m_lossyEvaluator == null || !this.m_lossyEvaluator.IsTriggeringEvent(loggingEvent1))
          loggingEvent1 = (LoggingEvent) null;
        if (this.m_evaluator != null && this.m_evaluator.IsTriggeringEvent(loggingEvent))
          this.SendFromBuffer(loggingEvent1, this.m_cb);
        else if (loggingEvent1 != null)
          this.SendBuffer(new LoggingEvent[1]
          {
            loggingEvent1
          });
      }
    }
    else if (this.m_evaluator != null && this.m_evaluator.IsTriggeringEvent(loggingEvent))
      this.SendFromBuffer((LoggingEvent) null, this.m_cb);
  }
}

在方法的开头,它首先检查我们是否使用缓冲区。答案是肯定的,所以它进入了外部If的其他块。然后它将事件添加到缓冲区并检查是否已从缓冲区返回任何事件:

    LoggingEvent loggingEvent1 = this.m_cb.Append(loggingEvent);
    if (loggingEvent1 != null)

如果评估为false,则代码继续使用else if:

    else if (this.m_evaluator != null && this.m_evaluator.IsTriggeringEvent(loggingEvent))
      this.SendFromBuffer((LoggingEvent) null, this.m_cb);

条件被评估为true,因为我在log4net配置(级别评估程序)中有评估程序,并且消息处于适当级别。 SendFromBuffer方法立即向存储发送消息(在我的情况下是Elasticsearch)。

在分解为log4net代码之后,我不明白缓冲如何工作或我需要设置什么。在我看来总会有一些评估器(至少是级别评估器),因此总是会调用SendFromBuffer方法,导致每条消息分别发送到存储器。我想知道如何设置log4net来真正使用缓冲区。

1 个答案:

答案 0 :(得分:3)

log4net工作正常as documented:评估者属性&#34;获取或设置ITriggeringEventEvaluator 导致缓冲区立即发送。&#34;

来自this explanation

  

Evaluator是一个可插入的对象,由   BufferingAppenderSkeleton确定是否不应该记录日志事件   被缓冲,但是立即写入/发送。如果是评估员   决定事件是重要的,然后是整个内容   当前缓冲区将与事件一起发送。

     

通常会设置SmtpAppender以缓冲事件   发送电子邮件的费用可能相对较高。如果   重要的事件到了,比如一个错误,我们希望这样   立即交付,而不是等待缓冲区成为   充分。这是评估员进来的地方,因为它允许我们说:   &#34;当一个重要事件到来时,不要担心缓冲,只是   发送你现在拥有的所有东西&#34;。

因此,每个日志级别为Info或更高的邮件都会触发您的LevelEvaluator并导致缓冲区被发送。