log4net Manual - Configuration

Configuration

Inserting log requests into the application code requires a fair amount of planning and effort. Observation shows that approximately 4 percent of code is dedicated to logging. Consequently, even moderately sized applications will have thousands of logging statements embedded within their code. Given their number, it becomes imperative to manage these log statements without the need to modify them manually.

The log4net environment is fully configurable programmatically. However, it is far more flexible to configure log4net using configuration files. Currently, configuration files are written in XML.

Let us give a taste of how this is done with the help of an imaginary application MyApp that uses log4net.

using Com.Foo;

// Import log4net classes.
using log4net;
using log4net.Config;

public class MyApp 
{
    // Define a static logger variable so that it references the
    // Logger instance named "MyApp".
    private static readonly ILog log = LogManager.GetLogger(typeof(MyApp));

    static void Main(string[] args) 
    {
        // Set up a simple configuration that logs on the console.
        BasicConfigurator.Configure();

        log.Info("Entering application.");
        Bar bar = new Bar();
        bar.DoIt();
        log.Info("Exiting application.");
    }
}

MyApp begins by importing log4net related classes. It then defines a static logger variable with the name MyApp which happens to be the fully qualified name of the class.

MyApp uses the following Bar class:

// Import log4net classes.
using log4net;

namespace Com.Foo
{
    public class Bar 
    {
        private static readonly ILog log = LogManager.GetLogger(typeof(Bar));

        public void DoIt()
        {
            log.Debug("Did it again!");
        }
    }
}

The invocation of the BasicConfigurator.Configure() method creates a rather simple log4net setup. This method is hardwired to add to the root logger a ConsoleAppender. The output will be formatted using a PatternLayout set to the pattern "%-4timestamp [%thread] %-5level %logger %ndc - %message%newline".

Note that by default, the root logger is assigned to Level.DEBUG.

The output of MyApp is:

0    [main] INFO  MyApp  - Entering application.
36   [main] DEBUG Com.Foo.Bar  - Did it again!
51   [main] INFO  MyApp  - Exiting application.

As a side note, let me mention that in log4net child loggers link only to their existing ancestors. In particular, the logger named Com.Foo.Bar is linked directly to the root logger, thereby circumventing the unused Com or Com.Foo loggers. This significantly increases performance and reduces log4net's memory footprint.

The MyApp class configures log4net by invoking BasicConfigurator.Configure() method. Other classes only need to import the log4net namespace, retrieve the loggers they wish to use, and log away.

The previous example always outputs the same log information. Fortunately, it is easy to modify MyApp so that the log output can be controlled at run-time. Here is a slightly modified version.

using Com.Foo;

// Import log4net classes.
using log4net;
using log4net.Config;

public class MyApp 
{
    private static readonly ILog log = LogManager.GetLogger(typeof(MyApp));

    static void Main(string[] args) 
    {
        // BasicConfigurator replaced with XmlConfigurator.
        XmlConfigurator.Configure(new System.IO.FileInfo(args[0]));

        log.Info("Entering application.");
        Bar bar = new Bar();
        bar.DoIt();
        log.Info("Exiting application.");
    }
}

This version of MyApp instructs the XmlConfigurator to parse a configuration file and set up logging accordingly. The path to the configuration file is specified on the command line.

Here is a sample configuration file that results in exactly same output as the previous BasicConfigurator based example.

<log4net>
    <!-- A1 is set to be a ConsoleAppender -->
    <appender name="A1" type="log4net.Appender.ConsoleAppender">

        <!-- A1 uses PatternLayout -->
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%-4timestamp [%thread] %-5level %logger %ndc - %message%newline" />
        </layout>
    </appender>
    
    <!-- Set root logger level to DEBUG and its only appender to A1 -->
    <root>
        <level value="DEBUG" />
        <appender-ref ref="A1" />
    </root>
</log4net>

Suppose we are no longer interested in seeing the output of any component belonging to the Com.Foo package. The following configuration file shows one possible way of achieving this.

<log4net>
    <!-- A1 is set to be a ConsoleAppender -->
    <appender name="A1" type="log4net.Appender.ConsoleAppender">

        <!-- A1 uses PatternLayout -->
        <layout type="log4net.Layout.PatternLayout">
            <!-- Print the date in ISO 8601 format -->
            <conversionPattern value="%date [%thread] %-5level %logger %ndc - %message%newline" />
        </layout>
    </appender>
    
    <!-- Set root logger level to DEBUG and its only appender to A1 -->
    <root>
        <level value="DEBUG" />
        <appender-ref ref="A1" />
    </root>
    
    <!-- Print only messages of level WARN or above in the package Com.Foo -->
    <logger name="Com.Foo">
        <level value="WARN" />
    </logger>
</log4net>

The output of MyApp configured with this file is shown below.

2000-09-07 14:07:41,508 [main] INFO  MyApp - Entering application.
2000-09-07 14:07:41,529 [main] INFO  MyApp - Exiting application.

As the logger Com.Foo.Bar does not have an assigned level, it inherits its level from Com.Foo, which was set to WARN in the configuration file. The log statement from the Bar.DoIt method has the level DEBUG, lower than the logger level WARN. Consequently, DoIt() method's log request is suppressed.

Here is another configuration file that uses multiple appenders.

<log4net>
    <appender name="Console" type="log4net.Appender.ConsoleAppender">
        <layout type="log4net.Layout.PatternLayout">
            <!-- Pattern to output the caller's file name and line number -->
            <conversionPattern value="%5level [%thread] (%file:%line) - %message%newline" />
        </layout>
    </appender>
    
    <appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
        <file value="example.log" />
        <appendToFile value="true" />
        <maximumFileSize value="100KB" />
        <maxSizeRollBackups value="2" />

        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%level %thread %logger - %message%newline" />
        </layout>
    </appender>
    
    <root>
        <level value="DEBUG" />
        <appender-ref ref="Console" />
        <appender-ref ref="RollingFile" />
    </root>
</log4net>

Calling the enhanced MyApp with the this configuration file will output the following on the console.

 INFO [main] (MyApp.cs:16) - Entering application.
DEBUG [main] (Bar.cs:12) - Doing it again!
 INFO [main] (MyApp.cs:19) - Exiting application.

In addition, as the root logger has been allocated a second appender, output will also be directed to the example.log file. This file will be rolled over when it reaches 100KB. When roll-over occurs, the old version of example.log is automatically moved to example.log.1.

Note that to obtain these different logging behaviors we did not need to recompile code. We could just as easily have logged to an email address, redirected all Com.Foo output to an NT Event logger, or forwarded logging events to a remote log4net server, which would log according to local server policy.

For more examples of configuring appenders using the XmlConfigurator see the Example Appender Configuration document.

Configuration Attributes

The log4net configuration can be configured using assembly-level attributes rather than specified programmatically.

  • XmlConfiguratorAttribute The log4net.Config.XmlConfiguratorAttribute Allows the XmlConfigurator to be configured using the following properties:
    • ConfigFile If specified, this is the filename of the configuration file to use with the XmlConfigurator. This file path is relative to the application base directory (AppDomain.CurrentDomain.BaseDirectory).

      This property cannot be used in conjunction with the ConfigFileExtension property.

    • ConfigFileExtension If specified, this is the extension for the configuration file. The assembly file name is used as the base name with the this extension appended. For example if the assembly is loaded from the a file TestApp.exe and the ConfigFileExtension property is set to log4net then the configuration file name is TestApp.exe.log4net. This is equivalent to setting the ConfigFile property to TestApp.exe.log4net.

      The path to the configuration file is build by using the application base directory (AppDomain.CurrentDomain.BaseDirectory), the assembly file name and the configuration file extension.

      This property cannot be used in conjunction with the ConfigFile property.

    • Watch If this flag is specified and set to true then the framework will watch the configuration file and will reload the config each time the file is modified.

    If neither of the ConfigFile or ConfigFileExtension properties are specified, the application configuration file (e.g. TestApp.exe.config) will be used as the log4net configuration file.

    Example usage:

    // Configure log4net using the .config file
    [assembly: log4net.Config.XmlConfigurator(Watch=true)]
    // This will cause log4net to look for a configuration file
    // called TestApp.exe.config in the application base
    // directory (i.e. the directory containing TestApp.exe)
    // The config file will be watched for changes.
                                
    // Configure log4net using the .log4net file
    [assembly: log4net.Config.XmlConfigurator(ConfigFileExtension="log4net",Watch=true)]
    // This will cause log4net to look for a configuration file
    // called TestApp.exe.log4net in the application base
    // directory (i.e. the directory containing TestApp.exe)
    // The config file will be watched for changes.
                                

    This attribute may only be used once per assembly.

Using attributes can be a clearer method for defining where the application's configuration will be loaded from. However it is worth noting that attributes are purely passive. They are information only. Therefore if you use configuration attributes you must invoke log4net to allow it to read the attributes. A simple call to LogManager.GetLogger will cause the attributes on the calling assembly to be read and processed. Therefore it is imperative to make a logging call as early as possible during the application start-up, and certainly before any external assemblies have been loaded and invoked.

Configuration Files

Typically the log4net configuration is specified using a file. This file can be read in one of two ways:

  • Using the .NET System.Configuration API
  • Reading the file contents directly

.config Files

The System.Configuration API is only available if the configuration data is in the application's config file; the file named MyApp.exe.config or Web.config. Because the System.Configuration API does not support reloading of the config file the configuration settings cannot be watched using the log4net.Config.XmlConfigurator.ConfigureAndWatch methods. The main advantage of using the System.Configuration APIs to read the configuration data is that it requires less permissions than accessing the configuration file directly. The only way to configure an application using the System.Configuration APIs is to call the log4net.Config.XmlConfigurator.Configure() method or the log4net.Config.XmlConfigurator.Configure(ILoggerRepository) method.

In order to embed the configuration data in the .config file the section name must be identified to the .NET config file parser using a configSections element. The section must specify the log4net.Config.Log4NetConfigurationSectionHandler that will be used to parse the config section. This type must be fully assembly qualified because it is being loaded by the .NET config file parser not by log4net. The correct assembly name for the log4net assembly must be specified. The following is a simple example configuration file that specifies the correct section handler to use for the log4net section.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
    </configSections>
    <log4net>
        <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender" >
            <layout type="log4net.Layout.PatternLayout">
                <conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline" />
            </layout>
        </appender>
        <root>
            <level value="INFO" />
            <appender-ref ref="ConsoleAppender" />
        </root>
    </log4net>
</configuration>

In the above example the log4net assembly is specified. This assembly must be located where the .NET runtime can find it. For example it could be located in the same directory as the application. If the log4net assembly is stored in the GAC then the fully qualified assembly name must be specified including the culture, version and public key.

When using the .config file to specify the configuration the section name and XML element name must be log4net.

Reading Files Directly

The XmlConfigurator can directly read any XML file and use it to configure log4net. This includes the application's .config file; the file named MyApp.exe.config or Web.config. The only reason not to read the configuration file directly is if the application does not have sufficient permissions to read the file, then the configuration must be loaded using the .NET configuration APIs (see above).

The file to read the configuration from can be specified using any of the log4net.Config.XmlConfigurator methods that accept a System.IO.FileInfo object. Because the file system can be monitored for file change notifications the ConfigureAndWatch methods can be used to monitor the configuration file for modifications and automatically reconfigure log4net.

Additionally the log4net.Config.XmlConfiguratorAttribute can be used to specify the file to read the configuration from.

The configuration is read from the log4net element in the file. Only one log4net element can be specified in the file but it may be located anywhere in the XML hierarchy. For example it may be the root element:

<?xml version="1.0" encoding="utf-8" ?>
<log4net>
    <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender" >
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline" />
        </layout>
    </appender>
    <root>
        <level value="INFO" />
        <appender-ref ref="ConsoleAppender" />
    </root>
</log4net>

Or it may be nested within other elements:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <section name="log4net" type="System.Configuration.IgnoreSectionHandler" />
    </configSections>
    <log4net>
        <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender" >
            <layout type="log4net.Layout.PatternLayout">
                <conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline" />
            </layout>
        </appender>
        <root>
            <level value="INFO" />
            <appender-ref ref="ConsoleAppender" />
        </root>
    </log4net>
</configuration>

The above example shows how the configuration data can be embedded inside a .config file even though the file is being read directly by log4net. An important note is that the .NET config file parser will throw an exception if it finds an element that has not been registered using the configSections element. Therefore in the above example the log4net section name is registered, but the type specified to handle the section is System.Configuration.IgnoreSectionHandler. This is a built-in class that indicates that another method for reading the config section will be employed.

Configuration Syntax

log4net includes a configuration reader that parses an XML DOM, the log4net.Config.XmlConfigurator. This section defines the syntax accepted by the configurator.

This is an example of a valid XML configuration. The root element must be <log4net>. Note that this does not mean that this element cannot be embedded in another XML document. See the section above on Configuration Files for more information on how to embed the XmlConfigurator XML in a configuration file.

<log4net>
    <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender" >
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline" />
        </layout>
    </appender>
    <root>
        <level value="INFO" />
        <appender-ref ref="ConsoleAppender" />
    </root>
</log4net>

The <log4net> element supports the following attributes:

Attribute Description
debug Optional attribute. Value must be either true or false. The default value is false. Set this attribute to true to enable internal log4net debugging for this configuration.
update Optional attribute. Value must be either Merge or Overwrite. The default value is Merge. Set this attribute to Overwrite to reset the configuration of the repository being configured before applying this configuration.
threshold Optional attribute. Value must be the name of a level registered on the repository. The default value is ALL. Set this attribute to limit the messages that are logged across the whole repository, regardless of the logger that the message is logged to.

The <log4net> element supports the following child elements:

Element Description
appender Zero or more elements allowed. Defines an appender.
logger Zero or more elements allowed. Defines the configuration of a logger.
renderer Zero or more elements allowed. Defines an object renderer.
root Optional element, maximum of one allowed. Defines the configuration of the root logger.
param Zero or more elements allowed. Repository specific parameters

Appenders

Appenders may only be defined as child elements of the <log4net> element. Each appender must be uniquely named. The implementing type for the appender must be specified.

This example shows an appender of type log4net.Appender.ConsoleAppender being defined. The appender will be known as ConsoleAppender.

<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender" >
    <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline" />
    </layout>
</appender>

The <appender> element supports the following attributes:

Attribute Description
name Required attribute. Value must be a string name for this appender. The name must be unique among all the appenders defined in this configuration file. This name is used by the <appender-ref> element of a Logger to reference an appender.
type Required attribute. Value must be the type name for this appender. If the appender is not defined in the log4net assembly this type name must be fully assembly qualified.

The <appender> element supports the following child elements:

Element Description
appender-ref Zero or more elements allowed. Allows the appender to reference other appenders. Not supported by all appenders.
filter Zero or more elements allowed. Defines the filters used by this appender.
layout Optional element, maximum of one allowed. Defines the layout used by this appender.
param Zero or more elements allowed. Appender specific parameters.

For examples of configuring appenders see the Example Appender Configuration document.

Filters

Filters elements may only be defined as children of <appender> elements.

The <filter> element supports the following attributes:

Attribute Description
type Required attribute. Value must be the type name for this filter. If the filter is not defined in the log4net assembly this type name must be fully assembly qualified.

The <filter> element supports the following child elements:

Element Description
param Zero or more elements allowed. Filter specific parameters.

Filters form a chain that the event has to pass through. Any filter along the way can accept the event and stop processing, deny the event and stop processing, or allow the event on to the next filter. If the event gets to the end of the filter chain without being denied it is implicitly accepted and will be logged.

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

This filter will deny events that have a level that is lower than INFO or higher than FATAL. All events between INFO and FATAL will be logged.

If we want to only allow messages through that have a specific substring (e.g. 'database') then we need to specify the following filters:

<filter type="log4net.Filter.StringMatchFilter">
    <stringToMatch value="database" />
</filter>
<filter type="log4net.Filter.DenyAllFilter" />

The first filter will look for the substring 'database' in the message text of the event. If the text is found the filter will accept the message and filter processing will stop, the message will be logged. If the substring is not found the event will be passed to the next filter to process. If there is no next filter the event would be implicitly accepted and would be logged. But because we don't want the non matching events to be logged we need to use a log4net.Filter.DenyAllFilter that will just deny all events that reach it. This filter is only useful at the end of the filter chain.

If we want to allow events that have either 'database' or 'ldap' in the message text we can use the following filters:

<filter type="log4net.Filter.StringMatchFilter">
    <stringToMatch value="database"/>
</filter>
<filter type="log4net.Filter.StringMatchFilter">
    <stringToMatch value="ldap"/>
</filter>
<filter type="log4net.Filter.DenyAllFilter" />

Layouts

Layout elements may only be defined as children of <appender> elements.

The <layout> element supports the following attributes:

Attribute Description
type Required attribute. Value must be the type name for this layout. If the layout is not defined in the log4net assembly this type name must be fully assembly qualified.

The <layout> element supports the following child elements:

Element Description
param Zero or more elements allowed. Layout specific parameters.

This example shows how to configure a layout that uses the log4net.Layout.PatternLayout.

<layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline" />
</layout>

Root Logger

Only one root logger element may only be defined and it must be a child of <log4net> element. The root logger is the root of the logger hierarchy. All loggers ultimately inherit from this logger.

An example root logger:

<root>
    <level value="INFO" />
    <appender-ref ref="ConsoleAppender" />
</root>

The <root> element supports no attributes.

The <root> element supports the following child elements:

Element Description
appender-ref Zero or more elements allowed. Allows the logger to reference appenders by name.
level Optional element, maximum of one allowed. Defines the logging level for this logger. This logger will only accept event that are at this level or above.
param Zero or more elements allowed. Logger specific parameters.

Loggers

Logger elements may only be defined as children of the <log4net> element.

An example logger:

<logger name="LoggerName">
    <level value="DEBUG" />
    <appender-ref ref="ConsoleAppender" />
</logger>

The <logger> element supports the following attributes.

Attribute Description
name Required attribute. Value must be the name of the logger.
additivity Optional attribute. Value may be either true or false. The default value is true. Set this attribute to false to prevent this logger from inheriting the appenders defined on parent loggers.

The <logger> element supports the following child elements:

Element Description
appender-ref Zero or more elements allowed. Allows the logger to reference appenders by name.
level Optional element, maximum of one allowed. Defines the logging level for this logger. This logger will only accept event that are at this level or above.
param Zero or more elements allowed. Logger specific parameters.

Renderers

Renderer elements may only be defined as children of the <log4net> element.

An example renderer:

<renderer renderingClass="MyClass.MyRenderer" renderedClass="MyClass.MyFunkyObject" />

The <renderer> element supports the following attributes.

Attribute Description
renderingClass Required attribute. Value must be the type name for this renderer. If the type is not defined in the log4net assembly this type name must be fully assembly qualified. This is the type of the object that will take responsibility for rendering the renderedClass.
renderedClass Required attribute. Value must be the type name for the target type for this renderer. If the type is not defined in the log4net assembly this type name must be fully assembly qualified. This is the name of the type that this renderer will render.

The <renderer> element supports no child elements.

Parameters

Parameter elements may be children of many elements. See the specific elements above for details.

An example param:

<param name="ConversionPattern" value="%date [%thread] %-5level %logger [%ndc] - %message%newline" />

The <param> element supports the following attributes.

Attribute Description
name Required attribute. Value must be the name of the parameter to set on the parent object.
value Optional attribute. One of value or type attributes must be specified. The value of this attribute is a string that can be converted to the value of the parameter.
type Optional attribute. One of value or type attributes must be specified. The value of this attribute is a type name to create and set as the value of the parameter. If the type is not defined in the log4net assembly this type name must be fully assembly qualified.

The <param> element supports the following child elements:

Element Description
param Zero or more elements allowed. Parameter specific parameters.

An example param that uses nested param elements:

<param name="evaluator" type="log4net.spi.LevelEvaluator">
    <param name="Threshold" value="WARN"/>
<param>

Extension Parameters

Configuration parameters map directly to writable properties on an object. The properties available depend on the actual type of the object being configured. The log4net SDK documentation contains the API reference for all the components included in the log4net assembly.

For 3rd party components please see their relevant API reference for details of the properties available.

Compact Parameter Syntax

All parameters may alternately be specified using the parameter name as the element name rather than using the param element and name attribute.

For example a param:

<param name="evaluator" type="log4net.spi.LevelEvaluator">
    <param name="Threshold" value="WARN"/>
<param>

may be written as:

<evaluator type="log4net.spi.LevelEvaluator">
    <threshold value="WARN"/>
<evaluator>