After that rather lengthy post about common appenders, this discussion of patterns and layouts should be short and sweet.
A layout is just a template for your log messages. Layouts are specified per-appender, and you can specify only one layout for an appender:
<appender name="ColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender">
<layout type="log4net.Layout.SimpleLayout" />
</appender>
We've been using the SimpleLayout in the previous tutorials. This 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
The PatternLayout allows you to specify a printf-style template for your log entries using a "conversion pattern," and gives you the opportunity to decorate each entry with some valuable instance data. For instance, this configuration:
<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 that appears like so:
2008-06-20 12:29:03,541 [2684] DEBUG Tutorial4.Program - this is a debug message
2008-06-20 12:29:03,556 [2684] INFO Tutorial4.Program - this is an info message
2008-06-20 12:29:03,556 [2684] WARN Tutorial4.Program - this is a warn message
2008-06-20 12:29:03,556 [2684] ERROR Tutorial4.Program - this is an error message
2008-06-20 12:29:03,556 [2684] FATAL Tutorial4.Program - this is a fatal message
The conversion pattern string can include literal text and the following format expressions:
expression | value |
%appdomain | the friendly name of the appdomain from which the log entry was made |
%date | the local datetime when the log entry was made |
%exception | 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 |
%file | 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 |
%identity | 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 |
%level | the severity level of the log entry (DEBUG,INFO, etc) |
%line | the source code line number from which the log entry was made; slow |
%location | some rudimentary call stack information, including file name and line number at which the log entry was made; using |
%logger | the name of the logger making the entry; more on this in a bit |
%method | the name of the method in which the log entry was made; also slow |
%message | the log message itself (don't forget this part!) |
%newline | the value of Environment.NewLine |
%timestamp | the milliseconds between the start of the application and the time the log entry was made |
%type | the full typename of the object from which the log entry was made |
%username | the Windows identity of user making the log entry; slow |
%utcdate | the UTC datetime when the log entry was made |
%% | a percent sign (%) |
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\Log4NetTutorial\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
%%: %
If you want a highly structured and queryable log, then XMLLayout is for you:
<appender name="ColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender">
<layout type="log4net.Layout.XMLLayout" />
</appender>
The XMLLayout produces a stream of XML elements representing individual log entries:
<log4net:event logger="Tutorial4_LayoutsAndPatterns.Program" timestamp="2008-06-20T13:17:44.2863922-04:00" level="DEBUG" thread="2156" domain="Tutorial4_LayoutsAndPatterns.vshost.exe" username="POKERTEK\jchristopher">
<log4net:message>this is a debug message</log4net:message>
<log4net:global-properties>
<log4net:data name="log4net:HostName" value="nc-jchri-l-3" />
</log4net:global-properties>
</log4net:event>
<log4net:event logger="Tutorial4_LayoutsAndPatterns.Program" timestamp="2008-06-20T13:17:44.3176424-04:00" level="INFO" thread="2156" domain="Tutorial4_LayoutsAndPatterns.vshost.exe" username="POKERTEK\jchristopher">
<log4net:message>this is an info message</log4net:message>
<log4net:global-properties>
<log4net:data name="log4net:HostName" value="nc-jchri-l-3" />
</log4net:global-properties>
</log4net:event>
A few caveats you should note regarding the XMLLayout:
- the log will contain a flat collection XML elements, but no containing root element; this means that you have to do some fernagling to read the XML as a document;
- each log entry will contain the username and identity values (see the table above), which are expensive to read and may have a noticable impact on application performance.
Coming Up
That rounds out a lot of our configuration discussion. Next time I'll jump back into code and discuss logger objects, which are simply sources of log messages. I'll show you how to organize your logging activity by object types to provide a more tractable log.