14

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?

Philipp M
  • 1,877
  • 7
  • 27
  • 38
Dav Evans
  • 4,031
  • 7
  • 41
  • 60
  • Did you try the filter I suggested in my answer? Did it make no difference? – Vinay Sajip Jul 23 '09 at 15:45
  • 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 Jan 28 '14 at 13:11

5 Answers5

11

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...

Göran Roseen
  • 1,193
  • 1
  • 9
  • 13
  • It sounds like you've answered the reverse of the question which has been asked? The question has DEBUG level / priority and a ERROR threshold. – Stephen O Mar 11 '21 at 02:00
6

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.

Philipp M
  • 1,877
  • 7
  • 27
  • 38
Vinay Sajip
  • 95,872
  • 14
  • 179
  • 191
  • @Dav.evans, can you confirm that the above is the complete configuration? What loggers are you using? Is it definite that no configuration changes are being made programmatically in your code? – Vinay Sajip Jul 23 '09 at 15:25
  • same question/answer: http://stackoverflow.com/questions/6007/log4net-configuring-log-level – Dave Thieben Mar 26 '11 at 22:36
6

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>
Community
  • 1
  • 1
Darragh
  • 2,526
  • 1
  • 23
  • 31
3

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).

Community
  • 1
  • 1
Anthony Mastrean
  • 21,850
  • 21
  • 110
  • 188
0

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

kgiannakakis
  • 103,016
  • 27
  • 158
  • 194
  • But logfile is an Appender, and additivity pertains to Loggers. – Vinay Sajip Jul 23 '09 at 13:12
  • I've corrected this. You actually create two loggers, each with one appender and use the additivity property. – kgiannakakis Jul 23 '09 at 13:21
  • surely not. What is the purpose of the threshold element then? – Dav Evans Jul 23 '09 at 13:35
  • Have you tried it? LogFileAppender inherites its parent (root) appenders by default, so it prints DEBUG messages by default. Try to set root's priority to ERROR to see what happens. – kgiannakakis Jul 23 '09 at 14:07
  • @kgiannakakis, that isn't right - Loggers aren't Appenders. As the appenders are attached to the root logger, events logged at every logger will be processed by these appenders, unless the additivity of a particular *logger* is set to false in which case events at that logger and below would not be processed. In such a case the threshold of the appender should be working - which makes me think that perhaps not all the information has been posted? – Vinay Sajip Jul 23 '09 at 15:24