Click here to Skip to main content
15,883,883 members
Articles / Programming Languages / Visual Basic
Article

log4net XmlConfigurator Simplified

Rate me:
Please Sign up or sign in to vote.
4.71/5 (16 votes)
16 Jun 2007CPOL5 min read 95K   990   60   8
This article covers the configuration of log4net using the XmlConfigurator. This article also demonstrates how to create multiple log files for your application.

Contents

Introduction

Many of us from time to time have struggled with configuring log4net. I know that in just about every application that I have worked on, I have taken a log4net configuration file, copied it and changed it to my liking. Well after some research and fiddling around with the configuration options available in log4net, I have come up with some interesting discoveries.

The first is that we can easily create separate log file / appenders for each class, assembly or even namespace if we want. Before I give you the answer, I want to tell you a little bit about the log4net library.

Definitions

log4net is essentially made up of six objects: log4net, log4net.Appender, log4net.Config, log4net.Filter, log4net.Layout and log4net.Repository. Here are their definitions:

  • ILog interface is what is used for logging messages.
  • LogManager is used to keep record of all of the loggers. A logger is an object that wants to log some data.
  • Appender is an object that writes log data to some data store, application or library.
  • Filter is a condition that can be applied to an Appender to restrict the writing of log data.
  • Layout is the display formatting that will be used for the log data when it is written to the Appender.
  • Repository is the central store for the log4net configuration and LogManager.

How the Objects Relate to Each Other

Each repository has one LogManager. Each LogManager has one or more Loggers. Each logger has one or more Appenders. Each Appender has one or more filters and one layout.

Screenshot - log4net_objects.gif

The Configuration

The easiest and most flexible way to configure log4net is with XML files. log4net provides a configuration reader for XML files in the log4net.Config.XmlConfigurator class. The XML file is comprised of two parts (that I know of). The first is one or more Appender definitions, the second defines the loggers and Appender definitions to a logger in the repository.

The <log4net> element supports the following attributes:

AttributeDescription
debugOptional 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.
updateOptional 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.
thresholdOptional 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:

ElementDescription
appenderZero or more elements allowed. Defines an appender.
loggerZero or more elements allowed. Defines the configuration of a logger.
rendererZero or more elements allowed. Defines an object renderer.
rootOptional element, maximum of one allowed. Defines the configuration of the root logger.
paramZero or more elements allowed. Repository specific parameters.

Appender Configuration

Each appender has different configuration options. The XML element looks similar to this:

XML
<appender name="rootRollingFile" type="log4net.Appender.RollingFileAppender,log4net">
 <threshold value="ALL"/>
 <param name="File" value="logs/MasterLog"/>
 <param name="AppendToFile" value="true"/>
 <param name="RollingStyle" value="Date"/>
 <param name="DatePattern" value=".yyyy.MM.dd.'log'"/>
 <param name="StaticLogFileName" value="false"/>
 <layout type="log4net.Layout.PatternLayout,log4net">
  <param name="ConversionPattern" value="%date 
	[%-5thread] %-5level %logger - %message%newline %exception"/>
 </layout>
</appender>

The <appender> element supports the following attributes:

AttributeDescription
nameRequired 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.
typeRequired 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:

ElementDescription
appender-refZero or more elements allowed. Allows the appender to reference other appenders. Not supported by all appenders.
filterZero or more elements allowed. Defines the filters used by this appender.
layoutOptional element, maximum of one allowed. Defines the layout used by this appender.
paramZero or more elements allowed. Appender specific parameters.

Assigning Appenders to Loggers

There are two elements that are used for assigning Appenders to loggers, root and logger. With each of these elements, you can assign two child elements, level and appender-ref.
The <level> element tells log4net what log messages will be sent to this appender, this is the equivalent to the <threshold> element on the appender. The <appender-ref> element is used to assign the appender to the specific logger. The format of the element is <appender-ref ref="nameOfAppender" /> where the nameOfAppender is the name that was specified in the name attribute of the <appender> element.

When the <root> element is used, all logging message for the LogManager / logging Repository will be written to these appenders.
The <logger> element has one attribute, name, the name attribute can be a namespace, class, or object name that you want to attach a special appender to. This is how we are going to be able to attach a different appender for each class or library.

XML
<root>
 <level value="ALL"/>
 <appender-ref ref="rootTrace"/>
 <appender-ref ref="rootConsole"/>
 <appender-ref ref="rootRollingFile"/>
 <appender-ref ref="rootEventLog"/>
</root>
<logger name="MyCompany">
 <level value="WARN" />
 <appender-ref ref="MyCompany_rollingFile" />
</logger>
<logger name="MyCompany.MultipleClasses">
 <level value="WARN" />
 <appender-ref ref="MyCompany_Multiple_rollingFile" />
</logger>
<logger name="MyCompany.MultipleClasses.Class1">
 <level value="DEBUG" />
 <appender-ref ref="class1File" />
</logger>
<logger name="MyCompany.MultipleClasses.Class2">
 <level value="DEBUG" />
 <appender-ref ref="class2File" />
</logger>
<logger name="MyCompany.MultipleClasses.Class3">
 <level value="DEBUG" />
 <appender-ref ref="class3File" />
</logger>
<logger name="MyCompany.Library1.MyFirstClass">
 <level value="DEBUG" />
 <appender-ref ref="lib1_MyFirstClass_File" />
</logger>
<logger name="MyCompany.Library2.MySecondClass">
 <level value="DEBUG" />
 <appender-ref ref="lib2_MySecondClass_File" />
</logger>
<logger name="MyCompany.Library2.MyThirdClass">
 <level value="DEBUG" />
 <appender-ref ref="lib2_MyThirdClass_File" />
</logger>

With this in mind, by looking at the configuration above, we can determine the following:

Logger NameLevelWhat gets loggedTo What Appender
MyCompany.<br />MultipleClasses.<br />Class3 DebugAny debug or higher messages within the MyCompany.<br />MulitpleClasses.Class3.class3File
MyCompany.<br />MultipleClasses.<br />Class2 DebugAny debug or higher messages within the MyCompany.<br />MulitpleClasses.Class2.class2File
MyCompany.<br />MultipleClasses.<br />Class1DebugAny debug or higher messages within the MyCompany.<br />MulitpleClasses.Class1.class1File
MyCompany.Library1.<br />MyFirstClassDebugAny debug or higher messages within the MyCompany.<br />Library1.MyFirstClass.lib1_MyFirstClass<br />_File
MyCompany.Library2.<br />MySecondClass DebugAny debug or higher messages within the MyCompany.<br />Library2.MySecondClass.lib2_MySecondClass<br />_File
MyCompany.Library2.<br />MyThirdClassDebugAny debug or higher messages within the MyCompany.<br />Library2.MyThirdClass.lib2_MyThirdClass<br />_File
MyCompany.<br />MulitpleClassesWarnAny warning messages or higher within the MyCompany.<br />MultipleClasses namespace.MyCompany<br />_rollingFile
MyCompanyWarnAny warning messages or higher within the MyCompany namespace
RootAllAny message by the application.rootTrace
rootConsole
rootRollingFile
rootEventLog

Summary

I know this was a lot to digest. If you have any questions, thoughts or comments on this article, please feel free to let me know.

References

History

Version Date What was done
1.06/16/07 Initial release

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
United States United States
I have been in software development for about 15 years or so. I started out with a small book on QuickBASIC, then moved the Visual Basic for DOS, then Visual Basic for Windows, then Visual Basic .NET and eventually Visual C#. When I am not working at my full time job I donate my time to several community efforts like:

Former President of INETA North America, currently Vice President.
President of the Southeast Valley .NET User Group (SEVDNUG) in Chandler, AZ.
Serving on my City's Parks and Recreation board.

I have or have had the following "MVP" awards:

  • Visual Basic MVP in 1996
  • C# MVP since 2009
  • Telerik MVP since 2010

I maintain a Open Source project on CodePlex which wraps the Bing API called BingSharp.

I also help / organize or participate in several community events:

  • Desert Code Camp
  • AZGiveCamp
  • Organizer for the 1st Time MVP event at the MVP Summit
  • MVP 2 MVP Sessions at MVP Summit.
  • Awesome bean pusher at GeekGive at the MVP Summit.

Comments and Discussions

 
GeneralMy vote of 5 Pin
JunfengGuo28-May-12 18:51
JunfengGuo28-May-12 18:51 
GeneralThanks Pin
mordeitaly16-Oct-08 21:45
mordeitaly16-Oct-08 21:45 
GeneralRe: Thanks Pin
Joseph Guadagno17-Oct-08 3:43
Joseph Guadagno17-Oct-08 3:43 
GeneralAdd or change parameter value dynamicly Pin
ArsenMkrt31-Jul-07 2:39
ArsenMkrt31-Jul-07 2:39 
GeneralRe: Add or change parameter value dynamicly Pin
Joseph Guadagno31-Jul-07 7:01
Joseph Guadagno31-Jul-07 7:01 
GeneralRe: Add or change parameter value dynamicly Pin
ArsenMkrt31-Jul-07 22:02
ArsenMkrt31-Jul-07 22:02 
GeneralRe: Add or change parameter value dynamicly Pin
Joseph Guadagno1-Aug-07 4:47
Joseph Guadagno1-Aug-07 4:47 
GeneralRe: Add or change parameter value dynamicly Pin
ArsenMkrt1-Aug-07 19:00
ArsenMkrt1-Aug-07 19:00 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.