You are on page 1of 14

Log4net

Log4net
Jayakrishna Janapareddy

Log4net

INTRODUCTION
One of the logging tools out there for .NET is log4net. This software is gold standard for how logging is done. It is simple, powerful and extensible. Log4net is used for debugging or for tracing purpose. Log4net is from the Apache Software Foundation. There are 3 parts for log4net: Configuration, setup and the call. Configuration is typically done in App.config or web.config. Setup is basically a couple of lines of housekeeping that need to be called in order to setup and instantiate a connection to the logger. There are 7 logging levels, 5 of which can be called in code. They are as follows: o OFF nothing gets logged (cannot be called) o FATAL o ERROR o WARN o INFO o DEBUG o ALL- Everything will be logged (cannot be called). These above levels will be used multiple times, both in your code as well as in the config file. Log4net defines above 5 security levels as: o DEBUG fine grained statements concerning program state, typically used for debugging. o INFO informational statements concerning program state, representing program events or behavior tracking. o WARN statements that describe potentially harmful events or states in the program. o ERROR statements that describe non-fatal errors in the application; this level is used quite often for logging handled exceptions. o FATAL statements representing the most severe of error conditions, assumedly resulting in program termination.

2 JayaKrishna Janapareddy

Log4net
CONFIGURATION
There are few pieces of information that needed to be placed in the config file in order to make it work properly with log4net. ConfigSections: The declaration of Log4net configuration section is mandatory.
<configSections> <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/> </configSections>

Appender: An appender is an object that persists your log messages someplace. It specifies where the information will be logged, how it will be logged, and under what circumstances the information will be logged. While each appender has different parameters based upon where the data will be going, there are some common elements. The first is the name and the type of the appender.
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">

Some of the common appenders are: o Console Appender: It writes to the output window or command window if we use a console application.
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender"> </appender>

File Appender: The appender will write to a text file. The big difference to note here are that we have to specify the name of the text file, we have to specify that we have to append to the file, and have to specify that File appender should use the minimal lock which will make the file usable by multiple appenders.
<appender name="FileAppender" type="log4net.Appender.FileAppender"> <file value="mylogfile.txt" /> <appendToFile value="true" /> <lockingModel type="log4net.Appender.FileAppender+MinimalLock" /> </appender>

Common configuration attributes for the FileAppender: file: the full or relative path to the log file. appendToFile: Boolean indicating whether the log file should be appended (true) or overwritten (false). If false, the file overwrite occurs during log4net initialization. If unspecified, the log file is appended. immediateFlush: Boolean indicating whether to flush the log file TextWriter after each log message is written. The default is true (flush each message after its written); lockingModel: allows control over the log file locking strategy. This can be either "log4net.Appender.FileAppender+MinimalLock" to allow for loose file locking or "log4net.Appender.FileAppender+ExclusiveLock" to lock the file during program execution. The default is the exclusive lock, and I highly recommend you stick with that lock for performance reasons.

3 JayaKrishna Janapareddy

Log4net
o Rolling File Appender: This is an appender that should be used in place of File appender whenever possible. The purpose of this appender is to perform the same functions as the file appender but with additional option to only store a certain amount of data before starting a new log file. This way, we need not worry about the logs on a system filling up over time.
<appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender"> <file value="mylogfile.txt" /> <appendToFile value="true" /> <rollingStyle value="Size" /> <maxSizeRollBackups value="5" /> <maximumFileSize value="10MB" /> <staticLogFileName value="true" /> </appender>

RollingFileAppender includes these parameters: rollingStyle: this controls how log files are "rolled," and can be one of the following values: o Once: the log file is rolled every time log4net is initialized (typically at application startup); o Size: the log file is rolled once it breaches a certain size; o Date: the log file is rolled based on the current date; o Composite: the log file is rolled based on size constraints and the current date; maximumFileSize: the size cap on the log file. This is an expression of size in the form of "#(KB|MB|GB)". For instance, "100KB" or "10MB"; maxSizeRollBackups: the maximum number of rolled log file backups to maintain when rollingStyle is SIZE; when rollingStyle is COMPOSITE, this indicates the maximum number of roll-offs maintained per day; this property has no effect when rollingStyle is ONCE or DATE; datePattern: the date pattern used to roll files based on date. The value of this parameter needs to adhere to the format used by the SimpleDateFormatter class; staticLogFileName: a bit of a misnomer - when true this setting indicates whether log4net should actively write logs to the configured file (log-file.txt in our example configuration) and maintain rolling backups by copy. When false, this setting indicates that log4net will actively log to the latest roll-off file (e.g., log-file1.txt, log-file2.txt, log-file3.txt, etc); countDirection: indicates how roll-off file numbering is managed. When this parameter is >= 0, the newest log file will have the largest number; e.g., logfile.txt.5 will be newer than log-file.txt.4. When countDirection < 0, the newest log file will have the lowest number; e.g., log-file.txt.1 will be newer than logfile.txt.2. If unspecified, countDirection defaults to (-1);

4 JayaKrishna Janapareddy

Log4net
o ADO.NET Appender: This is the tricky one. This specific example writes to SQL, but you can write to just about any database you want using this pattern. Note that the connectionType is basically a connection string, so modifying it is simple. The commandText specified is a simple query. You can modify it to any type of INSERT query that you want
<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender"> <bufferSize value="100" /> <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> <connectionString value="data source= [database server]; initial catalog= [database name]; integrated security=false; persist security info=True; User ID=[user];Password=[password]" /> <commandText value="INSERT INTO Log ([Date],[Thread],[Level],[Logger], [Message],[Exception]) VALUES (@log_date, @thread, @log_level, @logger, @message, @exception)" /> <parameter> <parameterName value="@log_date" /> <dbType value="DateTime" /> <layout type="log4net.Layout.RawTimeStampLayout" /> </parameter> <parameter> <parameterName value="@thread" /> <dbType value="String" /> <size value="255" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%thread" /> </layout> </parameter> <parameter> <parameterName value="@log_level" /> <dbType value="String" /> <size value="50" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%level" /> </layout> </parameter> <parameter> <parameterName value="@logger" /> <dbType value="String" /> <size value="255" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%logger" /> </layout> </parameter>

5 JayaKrishna Janapareddy

Log4net
<parameter> <parameterName value="@message" /> <dbType value="String" /> <size value="4000" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%message" /> </layout> </parameter> <parameter> <parameterName value="@exception" /> <dbType value="String" /> <size value="2000" /> <layout type="log4net.Layout.ExceptionLayout" /> </parameter> </appender>

Colored Console Appender: The color mapping is completely configurable; these appenders are only used for console based applications. Each <mapping /> element must contain a severity level, and can also contain a <foreColor /> and/or <backColor /> element. Color selection is limited to the following choices: Blue, Green , Red, Yellow, Purple, Cyan, White
<appender name="ColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender"> <target value="Console.Error" /> <mapping> <level value="FATAL" /> <foreColor value="Red" /> <backColor value="White" /> </mapping> <mapping> <level value="ERROR" /> <foreColor value="Red, HighIntensity" /> </mapping> <mapping> <level value="WARN" /> <foreColor value="Yellow" /> </mapping> <mapping> <level value="INFO" /> <foreColor value="Cyan" /> </mapping> <mapping> <level value="DEBUG" /> <foreColor value="Green" /> </mapping> <layout type="log4net.Layout.SimpleLayout" /> </appender>

6 JayaKrishna Janapareddy

Log4net
Appenders available in the Log4net distribution. TYPE NAME log4net.Appender.AdoNetAppender log4net.Appender.AnsiColorTerminalAppender log4net.Appender.AspNetTraceAppender log4net.Appender.BufferingForwardingAppender log4net.Appender.ColoredConsoleAppender log4net.Appender.ConsoleAppender log4net.Appender.DebugAppender log4net.Appender.EventLogAppender log4net.Appender.ForwardingAppender log4net.Appender.FileAppender log4net.Appender.LocalSyslogAppender log4net.Appender.MemoryAppender log4net.Appender.NetSendAppender log4net.Appender.OutputDebugStringAppender log4net.Appender.RemoteSyslogAppender log4net.Appender.RemotingAppender log4net.Appender.SmtpAppender log4net.Appender.RollingFileAppender log4net.Appender.SmtpPickupDirAppender DESCRIPTION Appender that logs to a database. Appends logging events to the terminal using ANSI color escape sequences. Appends log events to the ASP.NET Trace Context system. Buffers events and then forwards them to attached appenders. Appends logging events to the console. Appends logging events to the console. Appends log events to the Debug system. Writes events to the system event log. This appender forwards logging events to attached appenders. Appends logging events to a file. Logs events to a local syslog service. Stores logging events in an array. Logs entries by sending network messages using the NetMessageBufferSend native function. Appends log events to the OutputDebugString system. Logs events to a remote syslog daemon. Delivers logging events to a remote logging sink. Send an e-mail when a specific logging event occurs, typically on errors or fatal errors. Appender that rolls log files based on size or date or both. Send an email when a specific logging event occurs, typically on errors or fatal errors. Rather than sending via smtp it writes a file that another service, such as the IIS SMTP agent, can use to manage sending the messages. Appender that allows clients to connect via Telnet to receive log messages. Appends log events to the Trace system. Sends logging events as connectionless UDP datagrams to a remote host or multicast using the UdpClient class.

log4net.Appender.TelnetAppender log4net.Appender.TraceAppender log4net.Appender.UdpAppender

Using Multiple Appenders: With all the appenders available, we can use as many as we want. Using multiple appenders is a simple task of specifying each appender you need under the root logger.

7 JayaKrishna Janapareddy

Log4net
<root> <level value="ALL" /> <appender-ref ref="DebugAppender" /> <appender-ref ref="ColoredConsoleAppender" /> </root>

The root logger controls the general behavior of Log4net. Layout: A layout is just a template for log message. Layouts are specified per appender, and you can specify only one layout for appender.
<appender name="ColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender"> <layout type="log4net.Layout.SimpleLayout" /> </appender>

Simple layout is the easiest layout to use and yields rather a Spartan log:
DEBUG - this is a debug message INFO - this is an info message WARN - this is a warn message ERROR - this is an error message FATAL - this is a fatal message

Pattern layout allows us to specify a printf style template for log entries using a conversion pattern and gives an opportunity to design each entry with some valuable instance data.
<appender name="ColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender"> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%date [%thread] %-5level %logger %message%newline" /> </layout> </appender>

Produces a log like this


2008-06-20 12:29:03,541 debug message 2008-06-20 12:29:03,556 message 2008-06-20 12:29:03,556 message 2008-06-20 12:29:03,556 error message 2008-06-20 12:29:03,556 fatal message [2684] DEBUG Tutorial4.Program - this is a [2684] INFO Tutorial4.Program - this is an info [2684] WARN Tutorial4.Program - this is a warn [2684] ERROR Tutorial4.Program - this is an [2684] FATAL Tutorial4.Program - this is a

8 JayaKrishna Janapareddy

Log4net
The conversion pattern string can include literal text and the following format expressions: Expression %appdomain %date %exception %file %identity Value the friendly name of the appdomain from which the log entry was made the local datetime when the log entry was made a formatted form of the exception object in the log entry, if the entry contains an exception; otherwise, this format expression adds nothing to the log entry the file name from which the log entry was made; note that using %file has a significant performance impact and I don't recommend using it the user name of the active user logging the entry; this one is less reliable than %username; note that using %identity has a significant performance impact and I don't recommend using it the severity level of the log entry (DEBUG,INFO, etc) the source code line number from which the log entry was made; slow some rudimentary call stack information, including file name and line number at which the log entry was made; using the name of the logger making the entry; more on this in a bit the name of the method in which the log entry was made; also slow The log message itself (don't forget this part!) the value of Environment.NewLine the milliseconds between the start of the application and the time the log entry was made the full typename of the object from which the log entry was made the Windows identity of user making the log entry; slow the UTC datetime when the log entry was made a percent sign (%)

%level %line %location %logger %method %message %newline %timestamp %type %username %utcdate %%

This sample output is from a single log entry using a conversion pattern containing all of the format expressions above:
%appdomain: Tutorial4_LayoutsAndPatterns.vshost.exe %date: 2008-06-20 13:04:38,020 %exception: %file: D:\Project\Log4NetTutorial\Log4NetTutorial\Tutorial4_LayoutsAndPatterns \Program.cs %identity: %level: INFO %line: 14 %location:Tutorial4_LayoutsAndPatterns.Program.Main(D:\Project\Log4NetT utorial\Log4NetTutorial\Tutorial4_LayoutsAndPatterns\Program.cs:14) %logger: Tutorial4_LayoutsAndPatterns.Program %method: Main %message: this is an info message %timestamp: 1015 %type: Tutorial4_LayoutsAndPatterns.Program %username: MYDOMAIN\username %utcdate: 2008-06-20 17:04:38,020 %%: %

9 JayaKrishna Janapareddy

Log4net

Filters: Filters are applied to the individual appenders via the log4net configuration, and they help the appender determine whether a log event should be processed by the appender. Filters can be mixed and matched, but should be careful doing so. When a message fits inside the criteria for a filter, it is logged and the processing of the filter is finished. List of filters available in log4net configuration TYPE NAME DESCRIPTION log4net.Filter.LevelMatchFilter Filters log events that match a specific logging level; alternatively this can be configured to filter events that DO NOT match a specific logging level. log4net.Filter.LevelRangeFilter Similar to the LevelMatchFilter, except that instead of filtering a single log level, this filters on an inclusive range of contiguous levels. log4net.Filter.LoggerMatchFilter Filters log events based on the name of the logger object from which they are emitted. log4net.Filter.StringMatchFilter Filters log events based on a string or regular expression match against the log message. log4net.Filter.PropertyFilter Filters log events based on a value or regular expression match against a specific context property. log4net.Filter.DenyAllFilter Effectively drops all logging events for the appender. We can define our own filter by implementing the log4net.Filter.IFilter interface or deriving from the log4net.Filter.FilterSkeleton class. We can apply multiple filters to an appender; they will be evaluated as a chain in configuration order. Each filter in the chain can accept the message, deny the message, or put to the next filter in the chain. o Logger Match Filter: It filters against the name of the logger emitting the message. This filter can be configured using the following properties loggerToMatch: a string to match against the messages logger name. The match is made with the String.StartsWith method. acceptOnMatch: a Boolean value indicating whether a matching logger name results in accepting the message (true) or rejecting it (false). This defaults to true, meaning that only matching logger names will be allowed into the appender. o Level Range Filter: A level range filter tells the system to only log entries that are inside of the range specified. This range is inclusive, so in the below example, events with a level of INFO, WARN, ERROR, or FATAL will be logged, but DEBUG events will be ignored.
<filter type="log4net.Filter.LevelRangeFilter"> <levelMin value="INFO" /> <levelMax value="FATAL" /> </filter>

levelMin: the minimum log level to match - either DEBUG, INFO, WARN, ERROR,
or FATAL; levelMax: the minimum log level to match - either DEBUG, INFO, WARN, ERROR, or FATAL;

10 JayaKrishna Janapareddy

Log4net
acceptOnMatch: a boolean value indicating whether to accept log levels matching the levelToMatch property (true), or to punt filtering to the next filter in the chain (false). Defaults to true. Note that any log level outside of the [levelMin, levelMax] range is denied by this filter. Level Match Filter: The level match filter works like the level range filter, only it specifies one and only one level to capture. However, it does not have the deny built into it so you will need to specify the deny all filter after listing this filter.
<filter type="log4net.Filter.LevelMatchFilter"> <levelToMatch value="ERROR"/> </filter>

levelToMatch: the log level to match - either DEBUG, INFO, WARN, ERROR, or FATAL; acceptOnMatch: a Boolean value indicating whether to accept log levels matching the levelToMatch property (true), or reject log levels matching the levelToMatch property (false). Defaults to true. String Match Filter: The string match filter looks to find a specific string inside of the information being logged. We can have multiple string match filters specified. They work like OR statements in a query.
<filter type="log4net.Filter.StringMatchFilter"> <stringToMatch value="test" /> </filter>

This filter can be configured as follows regexToMatch: a regular expression to match against the log message. Note this regex is created with the Compiled option enabled for performance; stringToMatch: a static string to match against the log message. The match is made using the String.IndexOf method to see if the static string exists in the log message, which is a case-sensitive search. acceptOnMatch: a Boolean value indicating whether to accept log messages matching the string or regex (true), or to deny log messages matching the string or regex (false). Defaults to true. Property Filter: It performs the same behavior as String Match Filter, except that the match is made against the value of a context property. key: the name of the property value to match; regexToMatch: a regular expression to match against the specified property value. Note this regex is created with the Compiled option enabled for performance; stringToMatch: a static string to match against the specified property value. The match is made using the String.IndexOf method to see if the static string exists in the property value, which is a case-sensitive search. acceptOnMatch: a Boolean value indicating whether to accept messages with a property value matching the string or regex (true), or to deny messages with a property value matching the string or regex (false). Defaults to true.

11 JayaKrishna Janapareddy

Log4net
o Deny All Filter: This filter simply denies all filtering. When this is used, it's always at the end of a filter chain to block unwanted log messages from the appender.
<filter type="log4net.Filter.DenyAllFilter" />

LOSSY LOGGING
Logging is a very useful tool, but it's not something we want to leave enabled in production if you don't need it. Each log message take a few cycles away from our application, and the persistence of messages does consume system resources. Of course we can configure log4net to disable logging, either by setting the root logger level to OFF or removing all appenders from the root logger. The problem is that by disabling logging altogether, we won't get any juicy details if something goes awry in our application. Lossy logging gives us a great compromise: under normal operation our application will not log any messages; however, if our application logs an error, a small batch of messages leading up to the error is placed into the log, giving you the error and a snapshot of system activity just before it happened. App.config:
<?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.SimpleLayout" /> </appender> <appender name="LossyConsoleAppender" type="log4net.Appender.BufferingForwardingAppender"> <bufferSize value="20" /> <lossy value="true"/> <evaluator type="log4net.Core.LevelEvaluator"> <threshold value="ERROR" /> </evaluator> <appender-ref ref="ConsoleAppender" /> </appender> <root> <level value="DEBUG" /> <appender-ref ref="LossyConsoleAppender" /> </root> </log4net> </configuration>

12 JayaKrishna Janapareddy

Log4net
The logging configuration defines two appenders, one very generic Console appender and a BufferingForwardingAppender. As the name implies, the latter appender buffers log messages and forwards them in batches to one or more other appenders. We can probably tell from the configuration XML that I've set this appender up with a 20-message buffer. The lossy and evaluator parameters work together to define when the log message buffer is forwarded to the "base" appender. Program:
log4net.Config.XmlConfigurator.Configure(); static log4net.ILog Log = log4net.LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod().DeclaringType for( int i = 0; i < 100; ++i ) { Log.DebugFormat( "this is debug msg #{0}", i ); } Log.Error( "error: an error occurred!" ); Log.Warn( "warning: you've been warned" );

Output:
DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG DEBUG ERROR this is debug msg #81 this is debug msg #82 this is debug msg #83 this is debug msg #84 this is debug msg #85 this is debug msg #86 this is debug msg #87 this is debug msg #88 this is debug msg #89 this is debug msg #90 this is debug msg #91 this is debug msg #92 this is debug msg #93 this is debug msg #94 this is debug msg #95 this is debug msg #96 this is debug msg #97 this is debug msg #98 this is debug msg #99 error: an error occurred!

When the BufferingForwardingAppender's lossy property is enabled, the appender will buffer log messages without forwarding them. If the buffer fills up, the oldest messages are dropped from the buffer to make room for the new messages. The evaluator property determines when the appender forwards the messages from the buffer to its base appenders. There is only one evaluator defined in log4net - the LevelEvaluator. The LevelEvaluator triggers the forward when a log message is received that meets or exceeds the configured threshold. The example above is configured so that an ERROR message triggers the appender to forward its buffer to the ConsoleAppender.

13 JayaKrishna Janapareddy

Log4net
Lossy Appender Types: list of appenders in the log4net distribution that can operate "lossy:" o log4net.Appender.AdoNetAppender o log4net.Appender.RemotingAppender o log4net.Appender.SmtpAppender o log4net.Appender.SmtpPickupDirAppender o log4net.Appender.BufferingForwardingAppender

REFERENCES:
http://www.beefycode.com/category/log4net.aspx http://www.codeproject.com/Articles/140911/log4net-Tutorial

14 JayaKrishna Janapareddy

You might also like