Wednesday, November 26, 2008

log4net and appenders for different levels

The log4net uses different logging levels, ALL, DEBUG, INFO, WARN, ERROR and FATAL.

What I wanted to have is to log debugging, information and warnings into an appender and errors and fatal errors to another appender.

Here's how to define two appenders for different levels:

   1: <?xml version="1.0" standalone="yes"?>
   2: <log4net>
   3:     <appender name="RSLogFileAppenderInfo" type="log4net.Appender.RollingFileAppender">
   4:         <file value="PATHTOFILE\info.log" />
   5:         <appendToFile value="true" />
   6:         <rollingStyle value="Size" />
   7:         <filter type="log4net.Filter.LevelRangeFilter">
   8:             <acceptOnMatch value="true" />
   9:             <levelMin value="DEBUG" />
  10:             <levelMax value="WARN" />
  11:         </filter>
  12:         <maxSizeRollBackups value="10" />
  13:         <maximumFileSize value="10MB" />
  14:         <staticLogFileName value="true" />
  15:         <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
  16:         <layout type="log4net.Layout.PatternLayout">
  17:             <conversionPattern value="%newline%date [%thread] %-5level - %message" />
  18:         </layout>
  19:     </appender>
  20:     <appender name="RSLogFileAppenderFatal" type="log4net.Appender.RollingFileAppender">
  21:         <file value="PATHTOFILE\error.log" />
  22:         <appendToFile value="true" />
  23:         <rollingStyle value="Size" />
  24:         <filter type="log4net.Filter.LevelRangeFilter">
  25:             <acceptOnMatch value="true" />
  26:             <levelMin value="ERROR" />
  27:             <levelMax value="FATAL" />
  28:         </filter>
  29:         <maxSizeRollBackups value="10" />
  30:         <maximumFileSize value="10MB" />
  31:         <staticLogFileName value="true" />
  32:         <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
  33:         <layout type="log4net.Layout.PatternLayout">
  34:             <conversionPattern value="%newline%date [%thread] %-5level - %message" />
  35:         </layout>
  36:     </appender>
  37:     <root>
  38:         <level value="ALL" />
  39:         <appender-ref ref="RSLogFileAppenderInfo" />
  40:         <appender-ref ref="RSLogFileAppenderFatal" />
  41:     </root>
  42: </log4net>

Note that there are two appenders with different filters, the former raning from DEBUG to WARN and the latter ranging from ERROR to FATAL.


The simple helper class I've found somewhere and use to simplify the logging:



   1: public class Log
   2: {
   3:     public static ILog For( object LoggedObject )
   4:     {
   5:         if ( LoggedObject != null )
   6:             return For( LoggedObject.GetType() );
   7:         else
   8:             return For( null );
   9:     }
  10:  
  11:     public static ILog For( Type ObjectType )
  12:     {
  13:         if ( ObjectType != null )
  14:             return LogManager.GetLogger( ObjectType );
  15:         else
  16:             return LogManager.GetLogger( string.Empty );
  17:     }
  18: }

To test different levels defined for these two appenders just call:



   1: class LogTest
   2: {
   3:   public void Test()
   4:   {
   5:       Log.For( this ).Fatal( "fatal" );
   6:       Log.For( this ).Error( "error" );
   7:       Log.For( this ).Warn ( "warn" );
   8:       Log.For( this ).Info ( "info" );
   9:       Log.For( this ).Debug( "debug" );
  10:   }
  11: }
  12: ...
  13: LogTest test = new LogTest();
  14: test.Test();

Note that logs with different levels are correctly directed to appropriate appenders.