log4net过滤器 - 如何编写和过滤以忽略日志消息

时间:2011-12-22 12:45:53

标签: log4net log4net-configuration log4net-filter

我正在努力在log4net中编写一个AND条件过滤器。如果是nLog,我可以这样写:

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

我不确定如何在log4net中编写相同的过滤器。我写了一个条件是迄今为止成功的:

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

如何使用log4net过滤器编写AND条件?请帮忙。

2 个答案:

答案 0 :(得分:23)

支持AND条件的自定义过滤器。此类公开了Filter属性,因此可以在此处使用现有的log4net过滤器,并且如果需要,还可以使用嵌套的AND条件。

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

配置:

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

答案 1 :(得分:8)

您可以根据业务需求创建自定义过滤器:

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

        string userId = (string)loggingEvent.Properties["UserId"];
        string url = (string)loggingEvent.Properties["Url"];

        if (String.IsNullOrEmpty(UserId) || String.IsNullOrEmpty(Url))
            return FilterDecision.Neutral;

        if (UserId.Equals(userId) && Url.Equals(url, StringComparison.CurrentCultureIgnoreCase))
            return AcceptOnMatch ? FilterDecision.Accept : FilterDecision.Deny;

        return FilterDecision.Neutral;
    }

    public bool AcceptOnMatch { get; set; }
    public string UserId { get; set; }
    public string Url { get; set; }
}

配置如下所示:

<filter type="Namespace.UserRequestFilter, Assembly">
  <userId value="TESTUSER"/>
  <url value="/foo/foobar.aspx"/>
  <acceptOnMatch value="true"/>
</filter>

您也可以创建复合过滤器,但我没有找到在配置中使用它的方法。看起来它只能以编程方式附加(这是无用的^ _ ^):

IAppenderAttachable logger = (IAppenderAttachable)_log.Logger;
AppenderSkeleton appender = (AppenderSkeleton)logger.GetAppender("appenderName");
CompoundFilter compoundFilter = new CompoundFilter();
compoundFilter.AddFilter(new PropertyFilter() { Key = "UserId", StringToMatch = "TEST" });
compoundFilter.AddFilter(new PropertyFilter() { Key = "Url", StringToMatch = @"/foo/foobar.aspx" });
appender.AddFilter(compoundFilter);
logger.AddAppender(appender);

[UPDATE]

以下是您可以使用的技巧 - 创建过滤器,它将检查过滤器链中的所有过滤器:

public class DenyAllSubsequentFilter : FilterSkeleton
{
    public override FilterDecision Decide(LoggingEvent loggingEvent)
    {
        IFilter nextFilter = Next;
        if (nextFilter == null)
            return FilterDecision.Accept;

        while (nextFilter != null)
        {
            if (nextFilter.Decide(loggingEvent) != FilterDecision.Deny)
                return FilterDecision.Accept;

            nextFilter = nextFilter.Next;
        }

        return FilterDecision.Deny;
    }
}

用法:

<filter type="Namespace.DenyAllSubsequentFilter, Assembly"/>
<filter type="log4net.Filter.PropertyFilter">
  <key value="UserId" />
  <stringToMatch value="TEST" />
  <acceptOnMatch value="false" />
</filter>
<filter type="log4net.Filter.PropertyFilter">
  <key value="Url" />
  <stringToMatch value="/foo/foobar.aspx" />
  <acceptOnMatch value="false" />
</filter>

如果所有后续过滤器都拒绝它,此过滤器将拒绝记录消息。