Установка BufferSize для Log4Net в инициализации NServiceBus - PullRequest
3 голосов
/ 01 марта 2012

При настройке NServiceBus в моем приложении я настраиваю Log4Net для использования RollingFileAppender:

 .Log4Net<RollingFileAppender>(x=>
         {
              x.AppendToFile = true;
              x.Threshold = Level.Debug;
              x.MaxSizeRollBackups = 10;
              x.RollingStyle = RollingFileAppender.RollingMode.Size;
              x.File = "c:\\Logs\\log.txt";
          })

Я хочу удалить буферизацию для тестирования (установив BufferSize = 1)

Возможно ли это при использовании расширения .Log4Net()?

Ответы [ 2 ]

2 голосов
/ 02 марта 2012

Классы log4net FileAppender не предоставляют свойство BufferSize, поэтому вы не можете установить его - напрямую, в конфигурации или с помощью этого метода расширения. (Это свойство доступно только базовому классу BufferingAppenderSkeleton, который, однако, не является базовым классом для классов FileAppender).

На самом деле, если разобраться в базе кода log4net, похоже, что единственный способ контролировать размер буфера, используемый FileAppender, - это написать собственную реализацию LockingModelBase. Те реализации, которые поставляются с log4net, то есть ExclusiveLock или MinimalLock, внутренне используют конструктор FileStream, который использует размер буфера по умолчанию 0x1000, т.е. 4096.

Сказав это, вы могли бы сделать что-то вроде этого:

.Log4Net<RollingFileAppender>(x=>
     {
          x.AppendToFile = true;
          x.Threshold = Level.Debug;
          x.MaxSizeRollBackups = 10;
          x.RollingStyle = RollingFileAppender.RollingMode.Size;
          x.File = "c:\\Logs\\log.txt";
          x.LockingModel = new MyUnbufferedLockingModel();
      })

С MyUnbufferedLockingModel примерно так:

 public class MyUnbufferedLockingModel : log4net.FileAppender.LockingModelBase
 {
    // This is essentially a rip-off of the default 'ExclusiveLock' class,
    // but when creating the "m_stream", using an explicit buffer size of 1.
    // Depending on your needs you may want to use the 'MinimalLock' class
    // instead.

    private Stream m_stream = null;

    public override Stream AcquireLock()
    {
       return m_stream;
    }  

    public override void CloseFile()
    {
       using (CurrentAppender.SecurityContext.Impersonate(this))
       {
          m_stream.Close();
       }
    }

    public override void OpenFile(string filename, bool append, Encoding encoding)
    {
       try
       {
           using (CurrentAppender.SecurityContext.Impersonate(this))
           {
               string directoryName = Path.GetDirectoryName(filename);
               if (!Directory.Exists(directoryName))
               {
                  Directory.CreateDirectory(directoryName);
               }
               FileMode mode = append ? FileMode.Append : FileMode.Create;
               m_stream = new FileStream(filename, mode, FileAccess.Write,     
                  FileShare.Read,
                  1 /*BufferSize*/);
           }
        }
        catch (Exception exception)
        {
            CurrentAppender.ErrorHandler.Error("Unable to acquire lock on file " + filename + ". " + exception.Message);
        }
    }

    public override void ReleaseLock()
    {
    }
 }
1 голос
/ 02 марта 2012

В конце концов, буферизация не была проблемой, и решение было довольно простым. Похоже, что RollingFileAppender по умолчанию использует эксклюзивную блокировку, поэтому файл журнала был заблокирован во время работы приложения.

Исправление в этом случае должно было установить: LockingModel = new FileAppender.MinimalLock();

Обновленный init выглядит так:

.Log4Net<RollingFileAppender>(x=>
         {
              x.LockingModel = new FileAppender.MinimalLock();
              x.Threshold = Level.Debug;
              x.MaxSizeRollBackups = 10;
              x.RollingStyle = RollingFileAppender.RollingMode.Size;
              x.File = "c:\\Logs\\log.txt";
          })

Пока я искал в документации Log4Net решение для буферизации, я наткнулся на BufferingForwardingAppender . Этот аппендер включает в себя не буферизирующие приложения, предоставляющие сервис буферизации.

Вот как будет выглядеть конфигурация, если я захочу добавить буферизацию в RollingFileAppender:

  .Log4Net<BufferingForwardingAppender>
                (x =>
                     {
                         x.BufferSize = 50; // number of events to buffer                             
                         x.AddAppender(new RollingFileAppender()
                                           {
                                               LockingModel = new FileAppender.MinimalLock(),
                                               Layout = new SimpleLayout(),
                                               Threshold = Level.Debug,
                                               MaxSizeRollBackups = 10,
                                               RollingStyle = RollingFileAppender.RollingMode.Size,
                                               File = "c:\\Logs\\log.txt",
                                               SecurityContext = NullSecurityContext.Instance
                                           });

                     })

Patrick.

...