2010-03-16 1 views
7

Я создал пользовательский log4net-appender. Он сходит с log4net.Appender.SmtpAppender, который спускается из log4net.Appender.BufferingAppenderSkeleton.Почему моя буферизация app log4net app?

Я программно настроить следующие параметры в своем конструкторе:

this.Lossy = false; //don't drop any messages 
this.BufferSize = 3; //buffer up to 3 messages 
this.Threshold = log4net.Core.Level.Error; //append messages of Error or higher 
this.Evaluator = new log4net.Core.LevelEvaluator(Level.Off); //don't flush the buffer for any message, regardless of level 

я ожидаю это будет буфером 3 события ошибки уровня или выше, и поставить те события, когда буфер заполнен. Однако я обнаружил, что события не буферизованы вообще; вместо этого SendBuffer() вызывается немедленно каждый раз, когда регистрируется ошибка.

Ошибка:

Благодаря

ответ

8

Эта линия:

this.Evaluator = new log4net.Core.LevelEvaluator(Level.Off); 

говорит Appender очищать буфер, когда сообщение с уровнем равным или выше the evaluator получен. Поэтому Level.Off блокирует все события.

Обновление: после трассировки по источнику log4net еще раз. Я не понимаю, почему буферизация не работает для вас.

Update2: Я был озадачен, но опять же, я обнаружил, забыв о Log4Net appenders нужно для the ActivateOptions называться после того, как настройки были изменены. Пока не вызывается ActivateOptions, внутренний циклический буфер не создается, и буферизация не произойдет.

Таким образом, делая быстрый тест Appender:

public sealed class MyBufferingAppender: BufferingAppenderSkeleton 
    { 
     public MyBufferingAppender() 
     { 
      BufferSize = 3; 
      ActivateOptions(); 
     } 

     public readonly List<LoggingEvent> SentEvents = new List<LoggingEvent>(); 
     protected override void SendBuffer(LoggingEvent[] events) 
     { 
      SentEvents.AddRange(events); 
     } 
    } 

... и быстрый тест:

[Test] 
    public void DoAppend_BuffersEvents() 
    { 
     var appender = new MyBufferingAppender(); 

     appender.DoAppend(new LoggingEvent(
      new LoggingEventData {Level = Level.Error, Message = "Hello world"})); 

     Assert.That(appender.SentEvents, Has.Count(0)); 
    } 

тест проходит (на моей машине, по крайней мере :).

+1

Мое понимание заключается в том, что он сообщает приложению, чтобы он скрылся, когда получено сообщение, превышающее указанный порог. http://logging.apache.org/log4net/release/sdk/log4net.Core.LevelEvaluator.html Я также понимаю, что Level.Off является самым высоким порогом. http://logging.apache.org/log4net/release/sdk/log4net.Core.Level.Off.html Являются ли они неправильными? – Eric

+0

@ Эрик: см. Мой обновленный ответ. –

+0

красиво сделано. Это работает для меня. Спасибо. – Eric

3

То, что вы хотите сделать, может быть сделано со следующей конфигурацией:

<bufferSize value="3" /> 
<lossy value="false" /> 
<filter type="log4net.Filter.LevelRangeFilter"> 
    <levelMin value="ERROR" /> 
    <levelMax value="FATAL" /> 
</filter> 

Я понимаю, что Threshold говорит log4net, когда очищать буфер (он также будет вровень, если вы достигнете размер буфера). Если вы хотите исключить сообщения из журнала, вам нужно использовать фильтр. В коде это работает следующим образом:

this.BufferSize = 3; 
this.Lossy = false; 

var filter = new log4net.Filter.LevelRangeFilter(); 
filter.LevelMin = log4net.Core.Level.Error;   
this.AddFilter(filter); 

КПП. буфер заполняется, а на четвертом сообщении об ошибке отправляются сообщения. Так что если вы хотите, 3 сообщения только в электронном письме вы должны установить размер буфера 2 ...

+0

Эй, Стефан. Это дает мне такое же поведение. То есть сообщения об ошибках доставляются немедленно, а не буферизуются. – Eric

+0

вы удалили строку «Порог» в своем коде? –

+0

Я удалил строку Порог. – Eric