2011-12-22 7 views
11

log4netにAND条件フィルタを書き込むのが苦労しています。log4netフィルタ - ログメッセージを無視するための書き込みとフィルタリングの方法

<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の中で同じフィルタを作成する方法を確認していない:それは、私はそれをこのように書かれている可能性があり、nLogされていました。

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

log4netフィルタを使用してAND条件を書き込むにはどうすればよいですか?助けてください。

答えて

21

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

ええ、私はまた、(あなたのAddFilterのような)複合フィルタを思いついたのですが、configを使って内部フィルタを追加する方法がわかりませんでした。それは本当にクールなトリックです:) public IFilter Filter {set {filters.Add(value); }} –

+2

ありがとうございました。これは標準的なlog4netの機能ではないことが残念です。 –

7

あなたはあなたのビジネスのニーズに合わせてカスタムフィルタを作成できます。また、あなたは、複合フィルタを作成することができます

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

が、私は使用する方法を見つけることができませんでした:

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

の構成は次のようになります。それは構成である。それが(^ _ ^無用である)のみ、プログラムで取り付けることができるようになっています

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

使用法:すべてのsu場合

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

このフィルタは、ロギングメッセージを拒否しますそれ以降のフィルタはそれを否定します。

+0

おかげで@lazyberezovsky!実際には、AND条件をサポートする組み込みフィルタを探していました。しかし、log4netがそれをサポートしていないことを認識した後、私たちのために働くカスタムAndFilterを書きました。 –

関連する問題