在NServiceBus初始化中设置Log4Net的缓冲区大小

3
在配置我的应用程序中的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
log4net的FileAppender类没有提供BufferSize 属性,因此无法直接在配置或使用扩展方式中设置它。 (然而,这个属性仅由BufferingAppenderSkeleton 基类公开, 但该基类并不是FileAppender类的基类)。
实际上,在log4net代码库中查找,似乎唯一可以控制FileAppender使用的缓冲区大小的方法是编写自己的LockingModelBase实现。 log4net提供的实现,即ExclusiveLockMinimalLock,内部使用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()
    {
    }
 }

感谢您提供创意答案。最终,您指引我找到了答案,因此我会给予您认可。我还将创建另一个回答该问题的答案,并附上我的解决方案。 - Patrick
谢谢 :-) 你应该接受自己的答案作为正确答案。 - Christian.K

1
最终,缓冲不是问题,解决方案非常简单。看起来 RollingFileAppender 默认使用独占锁,因此在应用程序运行时日志文件被锁定。
在这种情况下的解决方法是设置:LockingModel = new FileAppender.MinimalLock(); 更新后的初始化如下:
.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。这个appender包装了非缓冲appender,提供了缓冲服务。

如果我想要将缓冲添加到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
                                           });

                     })

帕特里克。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接