Contents
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.
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
.
Each repository has one LogManager
. Each LogManager
has one or more Loggers. Each logger has one or more Appender
s. Each Appender
has one or more filters and one layout.
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:
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. |
Each appender
has different configuration options. The XML element looks similar to this:
<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:
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 appender s. Not supported by all appender s. |
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. |
There are two elements that are used for assigning Appender
s 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 appender
s.
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.
<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 Name |
Level |
What gets logged |
To What Appender |
MyCompany. MultipleClasses. Class3 |
Debug |
Any debug or higher messages within the MyCompany. MulitpleClasses.Class3 . |
class3File |
MyCompany. MultipleClasses. Class2 |
Debug |
Any debug or higher messages within the MyCompany. MulitpleClasses.Class2 . |
class2File |
MyCompany. MultipleClasses. Class1 |
Debug |
Any debug or higher messages within the MyCompany. MulitpleClasses.Class1 . |
class1File |
MyCompany.Library1. MyFirstClass |
Debug |
Any debug or higher messages within the MyCompany. Library1.MyFirstClass. |
lib1_MyFirstClass _File |
MyCompany.Library2. MySecondClass |
Debug |
Any debug or higher messages within the MyCompany. Library2.MySecondClass . |
lib2_MySecondClass _File |
MyCompany.Library2. MyThirdClass |
Debug |
Any debug or higher messages within the MyCompany. Library2.MyThirdClass . |
lib2_MyThirdClass _File |
MyCompany. MulitpleClasses |
Warn |
Any warning messages or higher within the MyCompany. MultipleClasses namespace . |
MyCompany _rollingFile |
MyCompany |
Warn |
Any warning messages or higher within the MyCompany namespace |
|
Root |
All |
Any message by the application. |
rootTrace
rootConsole
rootRollingFile
rootEventLog |
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.
Version |
Date |
What was done |
1.0 |
6/16/07 |
Initial release |