Буфер Log4net не работает

Я использую 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.

Я копался и пытался выяснить, что на самом деле происходит в коде. Когда вызывается метод журнала, он переходит к методу добавления в классе приложения ES. Метод унаследован от базового 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);
  }
}

В начале метода он сначала проверяет, используем ли мы буфер. Ответ - да, поэтому он переходит в блок else внешнего If. Затем он добавляет событие в буфер и проверяет, было ли какое-либо событие возвращено из буфера:

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

If оценивается как false, поэтому код продолжается с else if:

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

Условие оценивается как истинное, потому что у меня есть оценщик в моей конфигурации log4net (оценщик уровня), и сообщение находится на правильном уровне. Метод SendFromBuffer немедленно отправляет сообщение в хранилище (в моем случае - Elasticsearch).

После этого разбиения на код log4net я не понимаю, как может работать буферизация и что мне нужно настроить. Мне кажется, что всегда будет какой-то оценщик (по крайней мере, оценщик уровня), поэтому метод SendFromBuffer будет всегда вызываться, заставляя каждое отдельное сообщение отправляться в хранилище отдельно. Я хотел бы знать, как настроить log4net для реального использования буфера.


person Michal    schedule 13.06.2016    source источник
comment
Вы путаете Evaluator и Filter? Оценщик - это триггер, очищающий буфер. Порог INFO означает, что буферизуются только сообщения Debug и Verbose. Возможно, вы хотите фильтровать сообщения?   -  person Panagiotis Kanavos    schedule 13.06.2016
comment
@PanagiotisKanavos да ты прав, спасибо ...   -  person Michal    schedule 13.06.2016


Ответы (1)


log4net работает , как описано: свойство оценщика "получает или устанавливает ITriggeringEventEvaluator, который вызывает немедленную отправку буфера. "

Из это объяснение:

Оценщик - это подключаемый объект, который используется BufferingAppenderSkeleton, чтобы определить, следует ли не буферизовать событие регистрации, а вместо этого немедленно записывать / отправлять. Если оценщик решит, что событие является важным, все содержимое текущего буфера будет отправлено вместе с событием.

Обычно SmtpAppender настраивается для буферизации событий перед отправкой, поскольку стоимость отправки электронного письма может быть относительно высокой. Если приходит важное событие, скажем, ОШИБКА, мы хотели бы, чтобы оно было доставлено немедленно, а не дожидаться заполнения буфера. Здесь на помощь приходит оценщик, который позволяет нам сказать: «когда приходит важное событие, не беспокойтесь о буферизации, просто отправьте все, что у вас есть прямо сейчас».

Таким образом, каждое сообщение с уровнем журнала Info или выше вызовет ваш LevelEvaluator и вызовет отправку буфера.

person stuartd    schedule 13.06.2016