Previously, I offered a quick overview of using log4net.
In this post, I'll show you how to use an XML file to configure log4net, and demonstrate some of the basic ways you can control the verbosity of your log.
Using the XML Configurator
Open Visual Studio, create a new console application, and add a reference to the log4net assembly. Add the following code to your Main() method:
using System;
namespace Tutorial2_BasicXmlConfiguration
{
class Program
{
static void Main( string[] args )
{
log4net.Config.XmlConfigurator.Configure();
log4net.ILog log = log4net.LogManager.GetLogger( typeof( Program ) );
log.Info( "beginning loop" );
for( int c = 0; c < 100; ++c )
{
log.DebugFormat( "iteration #{0}", c );
}
log.Info( "loop has completed" );
Console.ReadLine();
}
}
}
On line 9, log4net is bootstrapped using the XmlConfigurator. This configuration strategy relies on an XML document to supply configuration for log4net. The static Configure method is overloaded to accept the configuration XML from a file, stream, URI, or an XmlElement object; the parameterless form of the method used here instructs log4net to load the XML from the application's configuration file.
In addition to the Configure method, the XmlConfigurator offers a static ConfigureAndWatch() method that accepts a FileInfo reference. ConfigureAndWatch() will monitor the configuration XML file and reconfigure log4net when a change is detected. This allows you to alter logging behavior at whim while the application is running - very handy for troubleshooting applications in the field, but it adds overhead in the form of a FileSystemWatcher used to monitor the configuration file.
Add the following application configuration file to the console project:
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>
<log4net>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.SimpleLayout" />
</appender>
<root>
<level value="ALL" />
<appender-ref ref="ConsoleAppender" />
</root>
</log4net>
</configuration>
There are a few important things in there. First is the declaration of the log4net configuration section on line 3; this is mandatory. The log4net configuration takes up lines 6-15. There are two parts to the configuration:
- one or more appender declarations taking the form of <appender /> elements, and
- the root logger declaration, represented by the <root /> XML element.
A real discussion of appenders will have to wait; for now, suffice it to say that a log4net appender is a place where your log entries end up. In this case, the log is being "appended" to the console.
The root logger controls the general behavior of log4net. In this example, the root logger is told to send everything to the console appender.
Time to compile and run. You'll get the following output:
INFO - beginning loop
DEBUG - iteration #0
DEBUG - iteration #1
DEBUG - iteration #2
DEBUG - iteration #3
DEBUG - iteration #4
DEBUG - iteration #5
DEBUG - iteration #6
DEBUG - iteration #7
DEBUG - iteration #8
DEBUG - iteration #9
DEBUG - iteration #10
DEBUG - iteration #11
DEBUG - iteration #12
DEBUG - iteration #13
DEBUG - iteration #14
DEBUG - iteration #15
DEBUG - iteration #16
DEBUG - iteration #17
DEBUG - iteration #18
DEBUG - iteration #19
DEBUG - iteration #20
DEBUG - iteration #21
DEBUG - iteration #22
DEBUG - iteration #23
DEBUG - iteration #24
DEBUG - iteration #25
DEBUG - iteration #26
DEBUG - iteration #27
DEBUG - iteration #28
DEBUG - iteration #29
DEBUG - iteration #30
DEBUG - iteration #31
DEBUG - iteration #32
DEBUG - iteration #33
DEBUG - iteration #34
DEBUG - iteration #35
DEBUG - iteration #36
DEBUG - iteration #37
DEBUG - iteration #38
DEBUG - iteration #39
DEBUG - iteration #40
DEBUG - iteration #41
DEBUG - iteration #42
DEBUG - iteration #43
DEBUG - iteration #44
DEBUG - iteration #45
DEBUG - iteration #46
DEBUG - iteration #47
DEBUG - iteration #48
DEBUG - iteration #49
DEBUG - iteration #50
DEBUG - iteration #51
DEBUG - iteration #52
DEBUG - iteration #53
DEBUG - iteration #54
DEBUG - iteration #55
DEBUG - iteration #56
DEBUG - iteration #57
DEBUG - iteration #58
DEBUG - iteration #59
DEBUG - iteration #60
DEBUG - iteration #61
DEBUG - iteration #62
DEBUG - iteration #63
DEBUG - iteration #64
DEBUG - iteration #65
DEBUG - iteration #66
DEBUG - iteration #67
DEBUG - iteration #68
DEBUG - iteration #69
DEBUG - iteration #70
DEBUG - iteration #71
DEBUG - iteration #72
DEBUG - iteration #73
DEBUG - iteration #74
DEBUG - iteration #75
DEBUG - iteration #76
DEBUG - iteration #77
DEBUG - iteration #78
DEBUG - iteration #79
DEBUG - iteration #80
DEBUG - iteration #81
DEBUG - iteration #82
DEBUG - iteration #83
DEBUG - iteration #84
DEBUG - iteration #85
DEBUG - iteration #86
DEBUG - iteration #87
DEBUG - iteration #88
DEBUG - iteration #89
DEBUG - iteration #90
DEBUG - iteration #91
DEBUG - iteration #92
DEBUG - iteration #93
DEBUG - iteration #94
DEBUG - iteration #95
DEBUG - iteration #96
DEBUG - iteration #97
DEBUG - iteration #98
DEBUG - iteration #99
INFO - loop has completed
Taming log4net Output
This example logs a fair amount of cruft. The DEBUG-level logging inside of the loop overshadows the INFO-level logging outside of the loop. In a real scenario, this DEBUG-level output may be necessary when troubleshooting application behavior, but it becomes a lot noise when instrumenting the application in production.
Thankfully log4net provides a filter on the logging output. In your project's app.config, find the <level /> XML element and alter it like so:
<level value="INFO" />
Compile and run; the program log is significantly truncated:
INFO - beginning loop
INFO - loop has completed
Specifically, all DEBUG-level log entries are missing from the log output. The level value instructs the logger of the minimum level at which log entries should be processed. It can be one of these values:
- ALL: all log entries are appended to the log;
- DEBUG: Debug, Info, Warn, Error, and Fatal messages are appended to the log. This is functionally identical to ALL;
- INFO: Info, Warn, Error, and Fatal messages are appended to the log;
- WARN: Warn, Error, and Fatal messages are appended to the log;
- ERROR: Error and Fatal messages are appended to the log;
- FATAL: only Fatal messages are appended to the log;
- OFF: all log entries are ignored. Logging is effectively disabled in this case.
Coming Up
You have enough knowledge at this point to do some pretty powerful things; however, there's a lot more to be had from log4net. Next time I'll discuss the many varieties of appenders that ship with log4net, and demonstrate how log4net can funnel a single log message to multiple places.