【问题标题】:Programmatically adding and removing log appenders in log4net以编程方式在 log4net 中添加和删除日志附加程序
【发布时间】:2009-10-05 12:14:39
【问题描述】:

我有一个使用 log4net 的组件。我想创建单元测试,以验证某些错误条件会导致正确的日志记录。

我认为最好的方法是创建一个 ILogAppender 实现,例如一个模拟。然后,我会在测试设置期间将日志附加程序添加到 log4net,检查测试验证期间写入的内容,并在测试拆卸期间再次将其删除。

这可能吗?

【问题讨论】:

    标签: .net nunit log4net


    【解决方案1】:

    使用 BasicConfigurator 可以进行单元测试(OP 要求的,但不是主题行中的要求)。其他答案抓取特定记录器的输出。

    我想要它全部(这是网站内的“自测”页面)。最后我基本上做了以下事情:

    var root = ((log4net.Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root;
    var attachable = root as IAppenderAttachable;
    
    var appender = new log4net.Appender.MemoryAppender();
    if(attachable!=null)
        attachable.AddAppender(appender);
    // do stuff
    var loggingEvents = appender.GetEvents();
    foreach (var loggingEvent in loggingEvents)
        loggingEvent.WriteRenderedMessage(writer);
    if(attachable!=null)
        attachable.RemoveAppender(appender);
    

    ...但按照@Pawel 的方法包装为一次性用品

    更新:Pawel 的回答已被删除,所以我在此处添加他的链接: Programmatically check Log4Net log.

    【讨论】:

      【解决方案2】:

      我一直在使用the BasicConfigurator 配置了MemoryAppender。此附加程序可让您访问测试期间记录的内存中消息。

      【讨论】:

      • 我终于实现了这个,它很好地解决了问题
      • +1;使我免于制作ILog 的存根实现并将其注入我的所有类:-)
      【解决方案3】:

      以下代码最初是在apache mailing list archives上找到的,应该可以解决代码中添加和删除log4net appenders的问题

      /// <summary>
      /// dataLog
      /// </summary>
      protected static readonly IDeviceCommunicationsLog dataLog =
      DeviceCommunicationsLogManager.GetLogger("LIS3.Data");
      
      
      Each connection adds and removes a file appender programmatically:
      
      /// <summary>
      /// add connection specific appender
      /// </summary>
      void AddAppender()
      {
          // check if logging is endabled
          if( this.IsLoggingEnabled() )
          {
              try
              {
                  // get the interface
                  IAppenderAttachable connectionAppender = (IAppenderAttachable)this.DataLog.Logger;
                  // need some application configuration settings
                  NameValueCollection appSettings = ConfigurationSettings.AppSettings;
                  // get the layout string
                  string log4netLayoutString = appSettings["log4net.LIS3.LayoutString"];
                  if( log4netLayoutString == null )
                  {
                      // use default setting
                      log4netLayoutString = "%d [%x]%n   %m%n  %P MessageData}%n%n";
                  }
                  // get logging path
                  string log4netPath = appSettings["log4net.Path"];
                  if( log4netPath == null )
                  {
                      // use default path
                      log4netPath = ".\\";
                  }
                  // create the appender
                  this.rollingFileAppender = new RollingFileAppender();
                  // setup the appender
                  this.rollingFileAppender.MaxFileSize = 10000000;
                  this.rollingFileAppender.MaxSizeRollBackups = 2;
                  this.rollingFileAppender.RollingStyle =   RollingFileAppender.RollingMode.Size;
                  this.rollingFileAppender.StaticLogFileName = true;
                  string appenderPath = LogSourceName + ".log";
                  // log source name may have a colon - if soreplace with underscore
                  appenderPath = appenderPath.Replace( ':', '_' );
                  // now add to log4net path
                  appenderPath = Path.Combine( log4netPath, appenderPath );
                  // update file property of appender
                  this.rollingFileAppender.File = appenderPath;
                  // add the layout
                  PatternLayout patternLayout = new PatternLayout(   log4netLayoutString );
                  this.rollingFileAppender.Layout = patternLayout;
                  // add the filter for the log source
                  NDCFilter sourceFilter = new NDCFilter();
                  sourceFilter.StringToMatch = this.LogSourceName;
                  this.rollingFileAppender.AddFilter( sourceFilter);
                  // now add the deny all filter to end of the chain
                  DenyAllFilter denyAllFilter = new DenyAllFilter();
                  this.rollingFileAppender.AddFilter( denyAllFilter );
                  // activate the options
                  this.rollingFileAppender.ActivateOptions();
                  // add the appender
                  connectionAppender.AddAppender( this.rollingFileAppender );
              }
              catch( Exception x )
              {
                  this.ErrorLog.Error( "Error creating LIS3 data log appender for " + LogSourceName, x );
              }
          }
      }
      /// <summary>
      /// remove connection specific appender
      /// </summary>
      void RemoveAppender()
      {
          // check if we have one
          if( this.rollingFileAppender != null )
          {
              // cast to required interface
              IAppenderAttachable connectionAppender = (IAppenderAttachable)this.DataLog.Logger;
              // remove the appendier
              connectionAppender.RemoveAppender( rollingFileAppender );
              // set to null
              this.rollingFileAppender = null;
          }
      }
      

      【讨论】:

      • 请注意,如果您不在任何地方使用 BasicConfigurator 或 XmlConfigurator,则需要将 Hierarchy.Configured 设置为 true 以使 log4net 实际执行任何操作。
      【解决方案4】:

      怎么样:

      ((log4net.Repository.Hierarchy.Logger) theLogger.Logger).RemoveAppender("SomeAppender");
      

      添加相同。

      【讨论】:

      • 您知道如何使添加真正起作用吗?我编写了一个单元测试来测试我创建的自定义 appender 的实现,但不幸的是 Logger 的 Add 方法是一个谎言,因为 LogManager.GetLogger(string) 返回的 ILog 实现有一个只读的 appender 集合。它最终默默地消耗了它在内部抛出的异常,并且从未真正添加 appender。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-02
      • 1970-01-01
      • 1970-01-01
      • 2012-11-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多