Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
329 views
in Technique[技术] by (71.8m points)

.net - log4net - any filter for logging only the Nth message?

I have a component that is constantly reading a values from a device. Currently it updates every {n} seconds and logs a debug message with the value to an instance of ILog.

Every second is too frequent for me, I just don't care and it eats up too much log space. However, I would certainly be interested in capturing every 10th or 30th message from that component so I can get the general gist of what it is doing.

Does anyone know any way of doing this that does not involve me witting my own ILog implementation?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This is probably too late to help you, but you could implement a filter. http://www.mail-archive.com/log4net-user%40logging.apache.org/msg02517.html shows how to implement a filter for limiting how often an exception is logged (if exception type is same as last exception type and if less than some specified amount of time has passed).

Here is the actual filter source code from that link:

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; }
  }
}

It would be configured like this:

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

It seems like it would be pretty straightforward to modify it to "throttle" messages that repeat. Maybe something like this (untested):

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;
  }
}

It might be nice to annotate a logged message with how many times it was repeated, but how to do that is not obvious to me:

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

Could generate something like this:

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

Probably some kind of ForwardingAppender or BufferingForwardingAppender. It would always be one message behind. A message comes in. The "RepeatedMessageAppender" would hold that message. The next message comes in. If it is different than last message, forward last message to the "real" Appender (if "repeated count" is > 0, append the number to the last message before forwarding - this is the part that I am not sure about because I think htat it is not easy to modify the LoggingEvent that is passed to the Appender). If it is the same as the last message, increment counter and do not forward. Since the "RepeatedMessageAppender" is one behind, it probably has to be a BufferingForwardingAppender and it must implement Flush.

Maybe you (or someone else) will find this information useful.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...