【问题标题】:log4net - any filter for logging only the Nth message?log4net - 任何仅记录第 N 条消息的过滤器?
【发布时间】:2010-11-30 05:56:54
【问题描述】:

我有一个不断从设备读取值的组件。目前它每 {n} 秒更新一次,并将带有值的调试消息记录到 ILog 实例。

每一秒对我来说都太频繁了,我不在乎,它占用了太多的日志空间。但是,我肯定有兴趣从该组件中捕获每 10 条或 30 条消息,这样我就可以了解它在做什么的一般要点。

有没有人知道任何不涉及我自己的 ILog 实现的方法?

【问题讨论】:

    标签: .net log4net


    【解决方案1】:

    这可能为时已晚,无法帮助您,但您可以实施过滤器。 http://www.mail-archive.com/log4net-user%40logging.apache.org/msg02517.html 展示了如何实现一个过滤器来限制记录异常的频率(如果异常类型与上一个异常类型相同并且经过的时间少于指定的时间)。

    这是来自该链接的实际过滤器源代码:

    public class ExceptionThrottleFilter : FilterSkeleton
    {
      private DateTime lastException = DateTime.MinValue;
      private Type exceptionType = typeof(Exception);
      private int threshold = 5; // seconds
    
      public override void ActivateOptions()
      {
        base.ActivateOptions();
      }
    
      public override FilterDecision Decide(LoggingEvent loggingEvent)
      {
        if (loggingEvent.ExceptionObject != null &&  loggingEvent.ExceptionObject.GetType) == exceptionType)
        {
          if (loggingEvent.TimeStamp.Subtract(lastException).TotalSeconds > threshold)
          {
            lastException = loggingEvent.TimeStamp;
            return FilterDecision.Accept;
          }
          else
          {
            return FilterDecision.Deny;
          }
        }
        else
        {
          return FilterDecision.Neutral;
        }
      }
    
      public Type ExceptionType
      {
        get { return exceptionType; }
        set { exceptionType = value; }
      }
    
      public int Threshold
      {
        get { return threshold; }
        set { threshold = value; }
      }
    }
    

    应该是这样配置的:

    <filter type="Company.Project.Logging.ExceptionThrottleFilter">
      <threshold value="2" />
      <exceptionType value="System.ApplicationException" />
    </filter>
    

    将其修改为“限制”重复的消息似乎非常简单。也许是这样的(未经测试):

    public class DuplicateMessageThrottleFilter : FilterSkeleton
    {
      private string lastMessage;
    
      public override void ActivateOptions()
      {
        base.ActivateOptions();
      }
    
      public override FilterDecision Decide(LoggingEvent loggingEvent)
      {
        string newMessage;
        if (loggingEvent.MessageObject != null)
        {
          newMessage = loggingEvent.MessageObject.ToString();
        }
    
        if (newMessage.Equals(lastMessage))
        {
          return FilterDecision.Deny;
        }
    
        lastMessage = newMessage;
        return FilterDecision.Accept;
      }
    }
    

    用重复多少次来注释记录的消息可能会很好,但如何做到这一点对我来说并不明显:

    Some message.
    Some message.
    Some message.
    Look, a new message.
    Some message.
    Some message.
    Look, a new message.
    

    可以生成这样的东西:

    Some message. (3 times)
    Look, a new message.
    Some message. (2 times)
    Look, a new message.
    

    可能是某种 ForwardingAppender 或 BufferingForwardingAppender。它永远是一个信息。一条消息进来。“RepeatedMessageAppender”将保存该消息。下一条消息进来。如果它与上一条消息不同,则将最后一条消息转发给“真正的”Appender(如果“重复计数”> 0,则在转发之前将数字附加到最后一条消息 - 这是我的部分不确定,因为我认为修改传递给 Appender 的 LoggingEvent 并不容易)。如果与上一条消息相同,则递增计数器并且不转发。由于“RepeatedMessageAppender”落后,它可能必须是一个 BufferingForwardingAppender 并且它必须实现 Flush。

    也许您(或其他人)会发现此信息很有用。

    【讨论】:

    • 确实非常有用。对于“多少次”标记,我建议使用一个属性来存储次数,然后通过 PatternLayout 显示它,例如 value="%message (%property{numberOfSimilar} times)"。该属性可以由 GlobalContext.Properties["numberOfSimilar"]++; 在 Decide(LoggingEvent) 中设置
    • @wageoghe 这是实现过滤器的线程安全方式吗?
    【解决方案2】:

    取决于您记录的内容。如果每秒都有一些东西要记录,那么也许你应该重新审视你正在记录的东西。

    您可以散列类似的消息并在一段时间后打印出来。

    【讨论】:

    • 好吧,我没有记录它,我禁用了该组件的调试级别记录,但如果我想记录应用程序认为当前在设备上的值,我当然会保留它作为一个选项。散列听起来是个不错的解决方案,有没有简单的配置方法?
    • 我不同意“哈希相似并等待打印”:这是日志记录机制的责任,而不是您的业务代码的责任,以想知道应该打印什么。您的机器每秒都说“我起来了”,并且是您的日志记录逻辑将其转换为“从 13:44 开始”,而不是机器本身,特别是如果您需要两个不同的日志,只有一个被此切断机制。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多