Question

I would like to have a specific appender for one specific domain class. When other classes log something it shall not be logged with this specific appender.

For example that logs from the following class shall use the 'OperationalLogFile'. And everything else shall not use this appender.

public class OperationalLogFileAppender
{
  private readonly ILog _log = LogManager.GetLogger("OperationalLogFile");

  public void AppendServiceStartup()
  {
     var text = ..;
     _log.Info(text);
  }
}

My log4net config section looks this way

log4net>
  <root>
     <level value="DEBUG" />
     <appender-ref ref="OtherAppender" />
     <appender-ref ref="OperationalLogFile" />
  </root>

  <appender name="OperationalLogFile" type="log4net.Appender.RollingFileAppender">
     <file value="OperationalLogFileName" />
     <appendToFile value="true"/>
     <countDirection value="-1"/>
     <rollingStyle value="Date" />
     <datePattern value="ddMMyyyy'.log'" />
     <maxSizeRollBackups value="0" />
     <maximumFileSize value="10000KB" />
     <staticLogFileName value="false" />
     <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%message" />
     </layout>
     <filter type="log4net.Filter.LoggerMatchFilter">
        <loggerToMatch value="MyNameSpace.OperationalLogFileAppender" />
     </filter>
  </appender>

  <logger name="MyNameSpace.OperationalLogFileAppender">
     <level value="INFO"/>
     <appender-ref ref="OperationalLogFile"/>
  </logger>

But corrently everything i log in my application shows up in the operationalog file, but i would like that only the stuff that the OperationalLogFileAppender logs shall show up in the operational log file.

Was it helpful?

Solution

You can create multiple appenders and decorate them with Log4Net Filters to include the specific logger or loggers you want.

The particular filter you want is the LoggerMatchFilter — you provide a string to be matched against the logger name via string.StartsWith(). Matching logger(s) are either included or excluded as a as a data source for the appender. That is why the log4net recommended naming convention for loggers is to have each class instantiate it's own logger instancej, name it with the fully qualified type name of the class (Type.FullName):

class Widget
{
  static ILogger log = LogManager.GetLogger(typeof(Widget)) ;
  . . .
}

That creates a logger whose name is the fully qualified name of the class. Note that the logger doesn't have to be a static property: the logger can be instantiated dynamically instead of statically: only once instance of a logger with a given name is ever created.

The notion is that the app as a whole could log only high level event. If there's a problem, while the app is running, you can tweak the log4net config to dial in lower level logging all the way down to the class level.

More on log4net configuration at http://logging.apache.org/log4net/release/manual/configuration.html

Here's a little tutorial on filters: http://www.beefycode.com/post/log4net-tutorial-pt-7-filters.aspx

OTHER TIPS

You can do this through the use of a custom level

private static readonly log4net.Core.Level _customLevel=new
log4net.Core.Level(50000,"Custom");

public void Init()
{
    log4net.Util.LogLog.InternalDebugging=true;
    log4net.LogManager.GetRepository().LevelMap.Add(_customLevel);
}

public void WriteToLog(string message)
{
    log.Logger.log(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType,_customLevel,message,null);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top