2011-12-22 11 views
11

Tengo dificultades para escribir un filtro AND condicional en log4net. Si hubiera sido Nlog, podría haber escrito esta manera:filtro log4net - cómo escribir Y filtrar para ignorar los mensajes de registro

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

No estoy seguro de cómo escribir el mismo filtro en log4net. He sido hasta ahora un éxito, por escrito una sola condición:

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

¿Cómo puedo escribir y condiciones de uso de filtros log4net? Por favor ayuda.

Respuesta

21

Un filtro personalizado que admite AND conditions. Esta clase expone la propiedad Filtro para que los filtros log4net existentes se puedan usar aquí y también se pueden anidar las condiciones AND si es necesario.

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

Sí, también inventé el filtro compuesto (como su AddFilter), pero no pensé cómo agregar filtros internos a través de config. Eso es realmente genial truco :) public IFilter Filter {set {filters.Add (value); }} –

+2

Gracias, ayudado. Es una pena que esta no sea una característica estándar de log4net. –

7

Puede crear filtros personalizados para las necesidades de su negocio:

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

configuración se verá así:

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

También puede crear filtro compuesto, pero no he encontrado manera de utilizar en la configuración. Parece que podría fijarse únicamente mediante programación (que es inútil^_ ^):

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

[ACTUALIZACIÓN]

Aquí es truco que puede utilizar - crear filtro, que verificará todos los filtros abajo los filtros cadena:

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

Uso:

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

Este filtro negará el registro de mensajes si todo su los filtros posteriores lo negarán.

+0

Gracias @lazyberezovsky! En realidad, estaba buscando un filtro incorporado que soporte las condiciones AND. Pero, después de darme cuenta de que log4net no es compatible con uno, escribí un AndFilter personalizado que funcionó para nosotros. Compartiré el código para beneficio de los demás: –

Cuestiones relacionadas