views:

278

answers:

1

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.

+1  A: 

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"/>
Stefan Egli
Where / how would m_stringToMatch get passed in?
Mike Kingscott
You configure this new filter the same way as the property filter. You just do not need to have the <key value="LocationInfo.MethodName"/> part. see also my revised answer.
Stefan Egli
Thank you - have a Bounty ;-)
Mike Kingscott
You are welcome. Let me know if you have any problem to make this work...
Stefan Egli