log4net filter - how to write AND filter to ignore log messages

Narayan Akhade picture Narayan Akhade · Dec 22, 2011 · Viewed 12.6k times · Source

I am struggling to write an AND conditional filter in log4net. Had it been nLog, I could have written it this way:

<logger name="*" minlevel="Info" xsi:type="NLogLoggerRule" writeTo="FooLogger" >
  <filters>
    <when condition="equals('${event-context:item=UserID}', 'TESTUSER') 
                 and equals('${event-context:item=URL}','/foo/foobar.aspx')" 
          action="Ignore" />
  </filters>
</logger>

I am not sure how to write the same filter in log4net. I have been so far successful, in writing a single condition:

<appender>
   ....
   <filter type="log4net.Filter.PropertyFilter">
      <key value="URL" />
      <stringToMatch value="/foo/foobar.aspx" />
      <acceptOnMatch value="false" />
   </filter>
</appender>

How can I write AND conditions using log4net filters? Please help.

Answer

Narayan Akhade picture Narayan Akhade · Jan 14, 2012

A custom filter supporting AND conditions. This class exposes Filter property so existing log4net filters can be used here and also one can have nested AND conditions if required.

public class AndFilter : FilterSkeleton
{
    private bool acceptOnMatch;
    private readonly IList<IFilter> filters = new List<IFilter>();

    public override FilterDecision Decide(LoggingEvent loggingEvent)
    {
        if (loggingEvent == null)
            throw new ArgumentNullException("loggingEvent");

        foreach(IFilter filter in filters)
        {
            if (filter.Decide(loggingEvent) != FilterDecision.Accept)
                return FilterDecision.Neutral; // one of the filter has failed
        }

        // All conditions are true
        if(acceptOnMatch)
            return FilterDecision.Accept;
        else
            return FilterDecision.Deny;
    }

    public IFilter Filter 
    { 
        set { filters.Add(value); }
    }

    public bool AcceptOnMatch
    {
        get { return acceptOnMatch;}
        set { acceptOnMatch = value;}
    }
}

Config:

<filter type="Namespace.AndFilter, Assembly">
  <filter type="log4net.Filter.PropertyFilter">
    <key value="URL" />
    <stringToMatch value="/foo/foobar.aspx" />
  </filter>
  <filter type="log4net.Filter.PropertyFilter">
    <key value="UserID" />
    <stringToMatch value="TESTUSER" />
  </filter>
  <acceptOnMatch value="false" />
</filter>