我正在努力在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条件?请帮忙。
答案 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>
如果所有后续过滤器都拒绝它,此过滤器将拒绝记录消息。