Configuration

The recommended way to configure log4net is through a configuration file. This section explains the structure of a configuration file and how log4net processes it.

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

namespace SampleApp;

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

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

    logger.Info("Entering application.");
    Dog dog = new();
    bar.Bark();
    logger.Info("Exiting application.");
  }
}
csharp

MyApp starts by importing the necessary log4net namespaces. It then declares a static logger for the type MyApp.

MyApp uses the following Dog class:

// Import log4net classes
using log4net;

namespace Animals.Carnivora;

internal sealed class Dog
{
  private static readonly ILog logger = LogManager.GetLogger(typeof(Dog));

  internal void Bark() => logger.Debug("Woof!");
}
csharp

Calling BasicConfigurator.Configure() sets up a simple log4net configuration. This method automatically adds a ConsoleAppender to the root logger, formatting the output using a PatternLayout with the following pattern:

%timestamp [%thread] %level %logger - %message%newline
log

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

The output of MyApp is:

2024-12-21 14:07:41,508 [main] INFO  SampleApp.MyApp - Entering application.
2024-12-21 14:07:41,517 [main] DEBUG Animals.Carnivora.Dog - Woof!
2024-12-21 14:07:41,529 [main] INFO  SampleApp.MyApp - Exiting application.
log

In log4net, child loggers link only to existing ancestors. For example, the logger Animals.Carnivora.Dog is directly linked to the root logger, bypassing the unused Animals and Animals.Carnivora loggers. This improves performance and reduces log4net’s memory footprint.

The MyApp class configures log4net by calling BasicConfigurator.Configure(). Other classes simply need to import the log4net namespace, retrieve the desired loggers, and start logging.

The previous example always produces the same log output. However, MyApp can be modified to allow runtime control over log output. Here’s an improved version:

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

namespace SampleApp;

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

  private static void Main(string[] args)
  {
    // BasicConfigurator replaced with XmlConfigurator.
    XmlConfigurator.Configure();

    logger.Info("Entering application.");
    Dog dog = new();
    bar.Bark();
    logger.Info("Exiting application.");
  }
}
csharp

In this version, MyApp uses XmlConfigurator to load a configuration file and set up logging accordingly.

The following sample configuration file produces the same output as the previous BasicConfigurator example:

<log4net>
  <!-- ConsoleAppender is set to be a ConsoleAppender -->
  <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
    <!-- ConsoleAppender uses PatternLayout -->
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%-4timestamp [%thread] %-5level %logger - %message%newline" />
    </layout>
  </appender>
  <!-- Set root logger level to DEBUG and its only appender to ConsoleAppender -->
  <root>
    <level value="DEBUG" />
    <appender-ref ref="ConsoleAppender" />
  </root>
</log4net>
xml

If we want to suppress logging for all components in the Animals.Carnivora namespace, we can achieve this with the following configuration file:

<log4net>
  <!-- ConsoleAppender is set to be a ConsoleAppender -->
  <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
    <!-- ConsoleAppender uses PatternLayout -->
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%-4timestamp [%thread] %-5level %logger - %message%newline" />
    </layout>
  </appender>
  <!-- Set root logger level to DEBUG and its only appender to ConsoleAppender -->
  <root>
    <level value="DEBUG" />
    <appender-ref ref="ConsoleAppender" />
  </root>
  <!-- Print only messages of level WARN or above in the namespace Animals.Carnivora -->
  <logger name="Animals.Carnivora">
    <level value="WARN" />
  </logger>
</log4net>
xml

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

2024-12-21 14:07:41,508 [main] INFO  SampleApp.MyApp - Entering application.
2024-12-21 14:07:41,529 [main] INFO  SampleApp.MyApp - Exiting application.
log

Since the Animals.Carnivora.Dog logger does not have a specific level assigned, it inherits the WARN level from Animals.Carnivora, as set in the configuration file.

The log statement in Dog.Bark() is at the DEBUG level, which is lower than WARN. As a result, the log request from Bark() is suppressed.

Below is another configuration file that uses multiple appenders:

<log4net>
  <appender name="ConsoleAppender" 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="RollingFileAppender" 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>
  <!-- Set root logger level to DEBUG and its only appender to ConsoleAppender -->
  <root>
    <level value="DEBUG" />
    <appender-ref ref="ConsoleAppender" />
    <appender-ref ref="RollingFile" />
  </root>
</log4net>
xml

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

INFO  [main] (MyApp.cs:17) - Entering application.
DEBUG [main] (Dog.cs:10) - Woof!
INFO  [main] (MyApp.cs:20) - Exiting application.
log

Additionally, since the root logger has a second appender, the output is also written to example.log. This file rolls over once it reaches 100KB, moving the old log to example.log.1.

Notably, achieving these different logging behaviors required no code recompilation. We could just as easily log to an email address or redirect all Animals.Carnivora output to a remote syslog server.

For more examples of configuring appenders with XmlConfigurator, see Appenders.

Configuration Attributes

log4net can be configured using assembly-level attributes instead of setting it up programmatically.

XmlConfiguratorAttribute

The log4net.Config.XmlConfiguratorAttribute allows log4net to be configured using the following properties:

ConfigFile

Specifies the filename of the configuration file to use with the XmlConfigurator. The file path is relative to the application base directory (AppDomain.CurrentDomain.BaseDirectory). This property cannot be used with the ConfigFileExtension property.

ConfigFileExtension

Specifies the extension for the configuration file. The assembly filename is used as the base name, with this extension appended. For example, if the assembly is TestApp.exe and the ConfigFileExtension is set to log4net, the configuration file will be TestApp.dll.log4net. This is equivalent to setting the ConfigFile property to TestApp.dll.log4net. The path to the configuration file is built using the application base directory (AppDomain.CurrentDomain.BaseDirectory), the assembly file name, and the configuration file extension. This property cannot be used with the ConfigFile property.

Watch

If set to true, this flag will enable the framework to monitor the configuration file and automatically reload it when the file is modified.

If neither the ConfigFile nor the ConfigFileExtension properties are specified, the application configuration file (e.g., TestApp.dll.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.dll.config in the application base
// directory (i.e. the directory containing TestApp.exe)
// The config file will be watched for changes.
csharp
// 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.dll.log4net in the application base
// directory (i.e. the directory containing TestApp.exe)
// The config file will be watched for changes.
csharp

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, note that attributes are passive — they only provide information. Therefore, to trigger log4net to read and process the attributes, you must invoke log4net. A simple call to LogManager.GetLogger will cause the attributes on the calling assembly to be processed.

It is crucial to make a logging call as early as possible during the application startup, and certainly before any external assemblies are loaded and invoked.

AppSettings

If you use attributes to configure log4net, two settings in the appSettings section of your application’s configuration file can override the values specified in your assembly’s attributes.

The setting with the key log4net.Config overrides the configuration file name (relative to your application’s base directory), while the setting with the key log4net.Config.Watch determines whether the configuration file should be monitored for changes.

For example, even though the assembly attribute:

[assembly: log4net.Config.XmlConfigurator(Watch = false)]
csharp

configures your application to use the "TestApp.dll.config" file and not monitor it for changes, you can override this to use the "log4net.config" file and monitor it for changes by adding the following to your application’s configuration file:

<appSettings>
  <add key="log4net.Config" value="log4net.config"/>
  <add key="log4net.Config.Watch" value="True"/>
</appSettings>
xml

to your application’s configuration file.

Configuration Files

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

  • Using the System.Configuration API

  • Reading the file contents directly

.config Files

The System.Configuration API can only be used if the configuration data is stored in the application’s config file (e.g. MyApp.dll.config, MyApp.exe.config, or Web.config).

The System.Configuration API does not support reloading the config file. This means that the configuration settings cannot be watched using the log4net.Config.XmlConfigurator.ConfigureAndWatch methods.

To configure an application using the System.Configuration API, you must call one of the following methods: * log4net.Config.XmlConfigurator.Configure() * log4net.Config.XmlConfigurator.Configure(ILoggerRepository)

To embed the configuration data in the .config file, you must define the log4net section in the configSections element. The section must specify the log4net.Config.Log4NetConfigurationSectionHandler, log4net type.

The following is a simple example configuration file that specifies the correct section handler to use for the log4net section.

<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 - %message%newline" />
      </layout>
    </appender>
    <root>
      <level value="INFO" />
      <appender-ref ref="ConsoleAppender" />
    </root>
  </log4net>
</configuration>
xml

Reading Files Directly

The XmlConfigurator can directly read any XML file and use it to configure log4net. This includes the application’s .config file (e.g. MyApp.dll.config, MyApp.exe.config, or Web.config).

You can specify the configuration file using log4net.Config.XmlConfigurator methods that accept a System.IO.FileInfo object. To auto-reconfigure on changes, use ConfigureAndWatch, which monitors the file for updates.

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:

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

Or it may be nested within other elements:

<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 - %message%newline" />
      </layout>
    </appender>
    <root>
      <level value="INFO" />
      <appender-ref ref="ConsoleAppender" />
    </root>
  </log4net>
</configuration>
xml

The example shows how to embed configuration data in a .config file while allowing log4net to read it directly. Since the .NET config parser throws errors for unregistered elements, the log4net section is registered using System.Configuration.IgnoreSectionHandler. This tells .NET to ignore the section, as it will be processed by log4net instead.

Android

Android does not support .config files.

Instead, you can set AppSettings values as environment variables for your process — this works only on Android.

You must also load the log4net configuration manually, for example by reading it from an XML file at runtime.

Configuration Syntax

log4net provides an XML-based configuration reader, log4net.Config.XmlConfigurator. This section outlines the syntax accepted by the configurator.

A valid XML configuration must have <log4net> as the root element. However, this element can be embedded in another XML document. For details on embedding XML configurations in a file, see the section on .config Files.

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

The <log4net> element supports the following attributes:

Attribute Required Allowed values Default Description

debug

no

true or false

false

Set this attribute to true to enable internal log4net debugging for this configuration.

update

no

Merge or Overwrite

Merge

Set this attribute to Overwrite to reset the configuration of the repository being configured before applying this configuration.

threshold

no

Level (e.g. DEBUG, INFO, WARN, ERROR)

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 Cardinality Description

appender

0..*

Defines an appender.

logger

0..*

Defines the configuration of a logger.

renderer

0..*

Defines an object renderer.

root

0..1

Defines the configuration of the root logger.

param

0..*

Repository-specific parameters.

Appenders

Appenders must be defined as child elements of the <log4net> element. Each appender requires a unique name and a specified implementing type.

The following example defines an appender of type log4net.Appender.ConsoleAppender, named ConsoleAppender.

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

The <appender> element supports the following attributes:

Attribute Required Allowed values Description

name

yes

A unique string name

Used by the <appender-ref> element of a Logger to reference an appender.

type

yes

A fully qualified type name

If the appender is not in the log4net assembly, the type name must be fully assembly qualified.

The <appender> element supports the following child elements:

Element Cardinality Description

appender-ref

0..*

Allows the appender to reference other appenders. Not supported by all appenders.

filter

0..*

Defines the filters used by this appender.

layout

0..1

Defines the layout used by this appender.

param

0..*

Appender-specific parameters.

For examples of configuring appenders see Example Appender Configuration.

Filters

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

The <filter> element supports the following attributes:

Attribute Required Allowed values Description

type

yes

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 Cardinality Description

param

0..*

Filter-specific parameters.

Filters form a chain that the event must pass through. Each filter can either:

  • Accept the event and stop processing.

  • Deny the event and stop processing.

  • Pass the event to the next filter.

If no filter denies the event, it is implicitly accepted and logged.

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

This filter denies events with a level lower than INFO or higher than FATAL. Only events between INFO and FATAL are logged.

To allow only messages containing a specific substring (e.g., 'database'), the following filters must be specified:

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

The first filter checks if the message text contains the substring 'database'. * If found, the filter accepts the message, stops processing, and logs the event. * If not found, the event moves to the next filter.

If there is no next filter, the event would be implicitly accepted and logged. To prevent logging non-matching events, a log4net.Filter.DenyAllFilter must be used at the end of the filter chain. This filter ensures that all unmatched events are denied.

To allow events containing either 'database' or 'ldap', 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" />
xml

Layouts

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

The <layout> element supports the following attributes:

Attribute Required Allowed values Description

type

yes

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 Cardinality Description

param

0..*

Layout-specific parameters.

This example shows how to configure a layout using log4net.Layout.PatternLayout.

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

Root Logger

Only one root logger element may be defined, and it must be a child of the 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>
xml

The <root> element supports no attributes.

The <root> element supports the following child elements:

Element Cardinality Description

appender-ref

0..*

Allows the logger to reference appenders by name.

level

0..1

Defines the logging level for this logger. This logger will only accept event that are at this level or above.

param

0..*

Logger specific parameters

Loggers

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

An example logger:

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

The <logger> element supports the following attributes.

Attribute Required Allowed values Default Description

name

yes

any logger name

Value must be the name of the logger.

additivity

no

true or false

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 Cardinality Description

appender-ref

0..*

Allows the logger to reference appenders by name.

level

0..1

Defines the logging level for this logger. This logger will only accept events that are at this level or above.

param

0..*

Logger specific parameters

Renderers

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

An example renderer:

<renderer renderingClass="Animals.Carnivora.Renderers.DogRenderer" renderedClass="Animals.Carnivora.Dog" />
xml

The <renderer> element supports the following attributes.

Attribute Required Allowed values Description

renderingClass

yes

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

yes

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 - %message%newline" />
xml

The <param> element supports the following attributes.

Attribute Required Allowed values Description

name

yes

Value must be the name of the parameter to set on the parent object.

value

no
(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

no
(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 Cardinality Description

param

0..*

Parameter specific parameters

An example param that uses nested param elements:

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

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.

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.Core.LevelEvaluator">
  <param name="Threshold" value="WARN"/>
<param>
xml

may be written as:

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