2011-12-22 10 views
11

Próbuję napisać filtr warunkowy AND w log4net. Gdyby było NLog, mogę napisać to w ten sposób:filtr log4net - jak pisać i filtrować, aby ignorować logi

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

Nie jestem pewien, jak napisać ten sam filtr w log4net. Byłem do tej pory sukcesem, w formie pisemnej jeden warunek:

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

Jak mogę napisać i warunki korzystania z filtrów log4net? Proszę pomóż.

Odpowiedz

21

Własny filtr obsługujący warunki AND. Ta klasa udostępnia właściwość filtru, więc można używać tutaj istniejących filtrów log4net, a także w razie potrzeby można zagnieżdżać warunki 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;} 
    } 
} 

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

Tak, też wymyśliłem filtr złożony (jak w twoim AddFilter), ale nie wiedziałem, jak dodać wewnętrzne filtry przez config. To jest naprawdę fajna sztuczka :) publiczny filtr IFilter {set {filters.Add (value); }} –

+2

Dzięki, pomogło. Szkoda, że ​​nie jest to standardowa funkcja log4net. –

7

Można utworzyć niestandardowy filtr dla potrzeb Twojego biznesu:

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

konfiguracja będzie wyglądać następująco:

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

Ponadto można utworzyć filtr związek, ale nie znaleźliśmy sposobu korzystania to w konfiguracji. Wygląda to może być dołączony tylko programowo (co jest bezużyteczne^_ ^):

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]

Oto trik, który można używać - stworzyć filtr, który będzie sprawdzał wszystkie filtry dół filtrów łańcuch:

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

Zastosowanie:

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

Ten filtr będzie zaprzeczyć wiadomość rejestrowania jeśli wszystko su bsequent filters odmówi.

+0

Dzięki @lazyberezovsky! Właściwie szukałem wbudowanego filtra, który obsługuje warunki AND. Ale po zdaniu sobie sprawy, że log4net go nie obsługuje, napisałem niestandardowy AndFilter, który działał dla nas. Udostępnię kod dla korzyści innych: –

Powiązane problemy