Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Filtering log4net on method name - can't quite get it

I'm using log4net to log my web app's progress, using Log4PostSharp to AOP-injectify all methods. This has the desired effect of logging (almost) everything and is fine.

I now have a requirement to log JUST Page_Load methods to a file / console. I can obviously hamstring the log4postsharp class to do that, but then I'd be losing all the other logging.

I've been looking at filters in log4net, starting with the StringMatch filter, but that only looks at the message being logged, and I'm after the method name. This put me onto the PropertyFilter, but still with no joy. My log4net.config snippet is thus:

<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
  <filter type="log4net.Filter.PropertyFilter">
    <key value="LocationInfo.MethodName"/>
    <stringToMatch value="Page_Load"/>
  </filter>
  <filter type="log4net.Filter.DenyAllFilter" />
  <file value="d:\\xxxx\\yyyyy\\zzzzLog"/>

As you can see, I'm trying to key into the MethodName of the logging event via LocationInfo, but I'm still getting everything logged. EDIT: As mentioned in the comments, I've now included the DenyAllFilter that I added after RTFM ;-)

Can anyone assist?

Thank you,

Mike K.

like image 532
Mike Kingscott Avatar asked Apr 14 '10 11:04

Mike Kingscott


1 Answers

As far as I can tell log4net does not know a property LocationInfo.MethodName. I am not using Log4PostSharp, so I cannot tell for sure if Log4PostSharp would create this property.

I would write my own filter like this to filter by method names (regex part omitted):

public class MethodNameFilter : StringMatchFilter
{       
     override public FilterDecision Decide(LoggingEvent loggingEvent) 
     {
         if (loggingEvent == null)
         {
              throw new ArgumentNullException("loggingEvent");
         }

         var locationInfo = loggingEvent.LocationInformation;

         // Check if we have been setup to filter
         if (locationInfo == null || (m_stringToMatch == null && m_regexToMatch == null))
         {
             // We cannot filter so allow the filter chain
             // to continue processing
              return FilterDecision.Neutral;
         }

         if (m_stringToMatch != null)
         {
             // Check substring match
             if (locationInfo.MethodName.IndexOf(m_stringToMatch) == -1) 
             {
                  // No match, continue processing
                  return FilterDecision.Neutral;
             }

             // we've got a match
             if (m_acceptOnMatch) 
             {
                  return FilterDecision.Accept;
             } 
             return FilterDecision.Deny;
         }
         return FilterDecision.Neutral;
    }
} 

Note: Accessing LocationInfo is expensive and can have a noticeable effect on performance. You could consider to modify Log4PostSharp to extract the method name during weaving and store it in some property. In that case you could use the property filter as you intended and you would not have any impact on performance. Not sure if this really works but I would expect that this is possible.

The configuration would look something like this:

<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
     <filter type="YourNameSpace.MethodNameFilter">
         <stringToMatch value="Page_Load"/>
     </filter>
     <filter type="log4net.Filter.DenyAllFilter" />
     <file value="d:\\xxxx\\yyyyy\\zzzzLog"/>
like image 155
Stefan Egli Avatar answered Oct 27 '22 00:10

Stefan Egli