13
votes

I've set up a logfileAppender and a consoleAppender in my log4net config for my application. I would like the logfile appender to only write ERROR messages and above and the console appender to write DEBUG and above.

My config is:

<log4net debug="false">

<appender name="LogFileAppender" type="log4net.Appender.FileAppender,log4net" >
  <param name="File" value="log.txt" />
  <param name="AppendToFile" value="true" />
  <layout type="log4net.Layout.PatternLayout,log4net">
    <param name="ConversionPattern" value="%d %M - %m%n" />
  </layout>
  <threshold value="ERROR"/>
</appender>

<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender"   >
  <layout type="log4net.Layout.PatternLayout">
    <param name="ConversionPattern" value="%d %m%n" />
  </layout>
</appender>


<root>
  <priority value="DEBUG" />
  <appender-ref ref="ConsoleAppender" />
  <appender-ref ref="LogFileAppender" />
</root>

</log4net>

I'm finding that both ERROR and DEBUG is being output to my logfile appender. How to restrict it to only ERROR?

5
Did you try the filter I suggested in my answer? Did it make no difference?Vinay Sajip
I've created a sample console application using your log4net config and I'm getting the exact behaviour you appear to be wanting....see my answer below.Darragh

5 Answers

11
votes

Note also that the level tag in the logger doesn't work the same way as threshold or a LevelMatchFilter.

Level indicates what log statements that actually will be generated. This is what you can test on in you code.

Threshold on the other hand, filters away all log messages that falls below your threshold.

This means that having a threshold that is higher than the highest logger level makes no sense. I have seen many times how one sets a level of INFO (because that is what most appenders will use), and then create an appender that has a threshold of DEBUG. And then you are surprised when no DEBUG messages actually appears on the appender...

6
votes

To get very specific filtering for an appender, you need to configure a LevelMatchFilter or a LevelRangeFilter for the logfile appender to filter the events which are actually output.
For example:

<filter type="log4net.Filter.LevelRangeFilter">
    <levelMin value="ERROR"/>
    <levelMax value="FATAL"/>
</filter>

or

<filter type="log4net.Filter.LevelMatchFilter">
    <levelToMatch value="ERROR"/>
</filter>

put one of these inside your <appender> tag, and this should work for you:

<appender name="LogFileAppender" type="log4net.Appender.FileAppender,log4net" >
    <filter type="log4net.Filter.LevelMatchFilter">
        <levelToMatch value="ERROR"/>
    </filter>
    <param name="File" value="log.txt" />
    <param name="AppendToFile" value="true" />
    <layout type="log4net.Layout.PatternLayout,log4net">
        <param name="ConversionPattern" value="%d %M - %m%n" />
    </layout>
    <threshold value="ERROR"/>
</appender>

Note: Updated to remove mistake pointed out by kgiannakakis.

5
votes

I've created a sample console application using your log4net config and I'm getting the exact behaviour you appear to be wanting....

using System;
using System.IO;
using log4net;
using log4net.Config;

namespace SO_1171258
{
    class Program
    {
        private static readonly ILog log = LogManager.GetLogger(typeof(Program));
        
        static void Main()
        {
            XmlConfigurator.ConfigureAndWatch(new FileInfo(AppDomain.CurrentDomain.GetData("APP_CONFIG_FILE").ToString()));
            log.Error(new Exception("error log statment"));
            log.Debug("debug log statment");
        }
    }
}

When I run this application, the only thing in the logfile is:

2014-01-27 15:02:51,387 Main - System.Exception: error log statment

And to the screen I see:

2014-01-27 15:05:52,190 System.Exception: error log statment

2014-01-27 15:05:52,218 debug log statment

Here is the entirety of my app.config file:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/>
  </configSections>
  <log4net debug="false">

    <appender name="LogFileAppender" type="log4net.Appender.FileAppender,log4net" >
      <param name="File" value="log.txt" />
      <param name="AppendToFile" value="true" />
      <layout type="log4net.Layout.PatternLayout,log4net">
        <param name="ConversionPattern" value="%d %M - %m%n" />
      </layout>
      <threshold value="ERROR"/>
    </appender>

    <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender"   >
      <layout type="log4net.Layout.PatternLayout">
        <param name="ConversionPattern" value="%d %m%n" />
      </layout>
    </appender>


    <root>
      <priority value="DEBUG" />
      <appender-ref ref="ConsoleAppender" />
      <appender-ref ref="LogFileAppender" />
    </root>

  </log4net>
</configuration>
3
votes

The answers you are receiving are partly correct. The Threshold is only used to set a lower limit on the level appended. A threshold of ERROR will actually receive ERROR and FATAL (which is "above" ERROR).

You do want to implement a LevelMatchFilter with a level value of "ERROR" (and "DEBUG" for the other appender). However, you must also add a DenyAllFilter to the end of your filter chain.
For example:

<appender name="LogFileAppender" type="log4net.Appender.FileAppender,log4net" >
  <param name="File" value="log.txt" />
  <param name="AppendToFile" value="true" />
  <layout type="log4net.Layout.PatternLayout,log4net">
    <param name="ConversionPattern" value="%d %M - %m%n" />
  </layout>
  <filter type="log4net.Filter.LevelMatchFilter">
    <levelToMatch value="ERROR" />
  </filter>
  <filter type="log4net.Filter.DenyAllFilter" />
</appender>

I've had to implement the DenyAllFilter since log4net 1.2.10 (you can see the question I had on this topic here).

0
votes

You need to use additivity property. See here for an example. You need to define two loggers.