Modified: logging/log4net/trunk/xdocs/src/release/manual/contexts.xml URL: http://svn.apache.org/viewvc/logging/log4net/trunk/xdocs/src/release/manual/contexts.xml?view=diff&rev=511694&r1=511693&r2=511694 ============================================================================== --- logging/log4net/trunk/xdocs/src/release/manual/contexts.xml (original) +++ logging/log4net/trunk/xdocs/src/release/manual/contexts.xml Sun Feb 25 18:10:21 2007 @@ -17,117 +17,117 @@ --> <document> - <properties> - <author email="nicko at apache dot org">Nicko Cadell</author> - <title>log4net Manual - Contexts</title> - </properties> + <properties> + <author email="nicko at apache dot org">Nicko Cadell</author> + <title>Apache log4net Manual: Contexts</title> + </properties> - <meta name="keywords" content="building log4net, log4net" /> + <meta name="keywords" content="building log4net, log4net" /> - <body> - <section id="main" name="log4net Manual - Contexts"> - <sectionMenu name="Contents" /> + <body> + <section id="main" name="log4net Manual - Contexts"> + <sectionMenu name="Contents" /> - <p> - Most real-world systems have to deal with multiple clients simultaneously. In a - typical multithreaded implementation of such a system, different threads will - handle different clients. Logging is especially well suited to trace and debug - complex distributed applications. An approach to differentiate the - logging output of one client from another is to instantiate a new separate - logger for each client. However this promotes the proliferation of loggers and - increases the management overhead of logging. - </p> - <p> - A lighter technique is to uniquely stamp each log request initiated from the - same client interaction. - </p> - <p> - Log4net supports different types of contextual logging and contexts with different scopes. - </p> - - <section id="scopes" name="Scopes"> - <p> - Contextual data can be set in different scopes. These contexts have progressively narrower visibility. - In the logging event itself the values from all of the contexts are combined together such that - values specified in a lower scoped context hide values from a higher context. - </p> - - <div class="table"> - <table cellspacing="0"> - <tr> - <th>Scope</th> - <th>Type</th> - <th>Description</th> - </tr> - <tr align="left"> - <td>Global</td> - <td><span class="code">log4net.GlobalContext</span></td> - <td> - The global context is shared by all threads in the current AppDomain. - This context is thread safe for use by multiple threads concurrently. - </td> - </tr> - <tr align="left"> - <td>Thread</td> - <td><span class="code">log4net.ThreadContext</span></td> - <td> - The thread context is visible only to the current managed thread. - </td> - </tr> - <tr align="left"> - <td>Logical Thread</td> - <td><span class="code">log4net.ThreadLogicalContext</span></td> - <td> - The logical thread context is visible to a logical thread. Logical - threads can jump from one managed thread to another. For more details - see the .NET API <span class="code">System.Runtime.Remoting.Messaging.CallContext</span>. - </td> - </tr> - <tr align="left"> - <td>Event</td> - <td><span class="code">log4net.Core.LoggingEvent</span></td> - <td> - Each event captures the current contextual state at the time the event - is generated. Contextual data can be set on the event itself. This context - is only visible to the code generating the event itself. - </td> - </tr> - </table> - </div> - </section> - - <section id="properties" name="Context Properties"> - <p> - The log4net contexts store properties, i.e. name value pairs. The name is a string - the value is any object. A property can be set as follows: - </p> - <source language="c#"><![CDATA[ + <p> + Most real-world systems have to deal with multiple clients simultaneously. In a + typical multithreaded implementation of such a system, different threads will + handle different clients. Logging is especially well suited to trace and debug + complex distributed applications. An approach to differentiate the + logging output of one client from another is to instantiate a new separate + logger for each client. However this promotes the proliferation of loggers and + increases the management overhead of logging. + </p> + <p> + A lighter technique is to uniquely stamp each log request initiated from the + same client interaction. + </p> + <p> + Log4net supports different types of contextual logging and contexts with different scopes. + </p> + + <section id="scopes" name="Scopes"> + <p> + Contextual data can be set in different scopes. These contexts have progressively narrower visibility. + In the logging event itself the values from all of the contexts are combined together such that + values specified in a lower scoped context hide values from a higher context. + </p> + + <div class="table"> + <table cellspacing="0"> + <tr> + <th>Scope</th> + <th>Type</th> + <th>Description</th> + </tr> + <tr align="left"> + <td>Global</td> + <td><span class="code">log4net.GlobalContext</span></td> + <td> + The global context is shared by all threads in the current AppDomain. + This context is thread safe for use by multiple threads concurrently. + </td> + </tr> + <tr align="left"> + <td>Thread</td> + <td><span class="code">log4net.ThreadContext</span></td> + <td> + The thread context is visible only to the current managed thread. + </td> + </tr> + <tr align="left"> + <td>Logical Thread</td> + <td><span class="code">log4net.ThreadLogicalContext</span></td> + <td> + The logical thread context is visible to a logical thread. Logical + threads can jump from one managed thread to another. For more details + see the .NET API <span class="code">System.Runtime.Remoting.Messaging.CallContext</span>. + </td> + </tr> + <tr align="left"> + <td>Event</td> + <td><span class="code">log4net.Core.LoggingEvent</span></td> + <td> + Each event captures the current contextual state at the time the event + is generated. Contextual data can be set on the event itself. This context + is only visible to the code generating the event itself. + </td> + </tr> + </table> + </div> + </section> + + <section id="properties" name="Context Properties"> + <p> + The log4net contexts store properties, i.e. name value pairs. The name is a string + the value is any object. A property can be set as follows: + </p> + <source language="c#"><![CDATA[ log4net.GlobalContext.Properties["name"] = value; ]]></source> - <p> - If properties with the same name are set in more than one context scope then - the value in the narrowest scope (lower down in the list above) will hide the - other values. - </p> - <p> - The property values are stored as objects within the <span class="code">LoggingEvent</span>. - The <span class="code">PatternLayout</span> supports rendering the value of a named - property using the <span class="code">%property{name}</span> syntax. The value is - converted to a string by passing it to the <span class="code">log4net.ObjectRenderer.RendererMap</span> - which will locate any custom renderer for the value type. The default behavior for - custom types is to call the object's <span class="code">ToString()</span> method. - </p> - - <section id="active" name="Active Property Values"> - <p> - An active property value is one who's value changes over time. - </p> - <p> - For example, imagine a custom type that implemented the - <span class="code">ToString()</span> method to return the - number of bytes allocated by the runtime garbage collector. - </p> - <source language="c#"><![CDATA[ + <p> + If properties with the same name are set in more than one context scope then + the value in the narrowest scope (lower down in the list above) will hide the + other values. + </p> + <p> + The property values are stored as objects within the <span class="code">LoggingEvent</span>. + The <span class="code">PatternLayout</span> supports rendering the value of a named + property using the <span class="code">%property{name}</span> syntax. The value is + converted to a string by passing it to the <span class="code">log4net.ObjectRenderer.RendererMap</span> + which will locate any custom renderer for the value type. The default behavior for + custom types is to call the object's <span class="code">ToString()</span> method. + </p> + + <section id="active" name="Active Property Values"> + <p> + An active property value is one who's value changes over time. + </p> + <p> + For example, imagine a custom type that implemented the + <span class="code">ToString()</span> method to return the + number of bytes allocated by the runtime garbage collector. + </p> + <source language="c#"><![CDATA[ public class GCAllocatedBytesHelper { public override string ToString() @@ -135,113 +135,113 @@ return GC.GetTotalMemory(true).ToString(); } }]]></source> - <p> - An instance of this type can be added to the <span class="code">log4net.GlobalContext</span> - during application startup: - </p> - <source language="c#"><![CDATA[ + <p> + An instance of this type can be added to the <span class="code">log4net.GlobalContext</span> + during application startup: + </p> + <source language="c#"><![CDATA[ log4net.GlobalContext.Properties["GCAllocatedBytes"] = new GCAllocatedBytesHelper(); ]]></source> - <p> - Once this property is set in the context all subsequent logging events will have a property - called <i>GCAllocatedBytes</i>. The value of the property will be an instance of the - <span class="code">GCAllocatedBytesHelper</span> type. When this value is rendered to a - string by calling the <span class="code">ToString</span> method the current number of bytes - allocated by the garbage collector will be returned and included in the output. - </p> - - </section> - - </section> - - <section id="stacks" name="Context Stacks"> - <p> - Sometimes simple key value pairs are not the most convenient way of capturing contextual - information. A stack of information is a very convenient way of storing data especially - as our applications tend to be stack based. - </p> - <p> - The <span class="code">ThreadContext</span> and <span class="code">LogicalThreadContext</span> - also support storing contextual data in a stack. The stack is stored in context property, - therefore stacks have names and more than one stack can exist in the same context. A property - value set in a narrower context would override a stack with the same property name set in a - wider scoped context. - </p> - <p> - The stack supports <span class="code">Push</span> and <span class="code">Pop</span> methods. - As more contextual data is pushed onto the stack the stack grows. When the stack is rendered - all the data pushed onto the stack is output with the most recent data to the right hand - end of the string. - </p> - <p> - As the stack is just an object stored in the context properties it is also rendered - using the same <span class="code">PatternLayout</span> syntax: <span class="code">%property{name}</span>. - Where <i>name</i> is the name of the stack. - </p> - <p> - Calls the the stack's <span class="code">Push</span> and <span class="code">Pop</span> - methods must be matched up so that each push has a corresponding pop. The - <span class="code">Push</span> method also returns an <span class="code">IDisposable</span> - object that will perform the required pop operation when it is disposed. This allows - the C# <i>using</i> syntax to be used to automate the stack management. - </p> - <source language="c#"><![CDATA[ + <p> + Once this property is set in the context all subsequent logging events will have a property + called <i>GCAllocatedBytes</i>. The value of the property will be an instance of the + <span class="code">GCAllocatedBytesHelper</span> type. When this value is rendered to a + string by calling the <span class="code">ToString</span> method the current number of bytes + allocated by the garbage collector will be returned and included in the output. + </p> + + </section> + + </section> + + <section id="stacks" name="Context Stacks"> + <p> + Sometimes simple key value pairs are not the most convenient way of capturing contextual + information. A stack of information is a very convenient way of storing data especially + as our applications tend to be stack based. + </p> + <p> + The <span class="code">ThreadContext</span> and <span class="code">LogicalThreadContext</span> + also support storing contextual data in a stack. The stack is stored in context property, + therefore stacks have names and more than one stack can exist in the same context. A property + value set in a narrower context would override a stack with the same property name set in a + wider scoped context. + </p> + <p> + The stack supports <span class="code">Push</span> and <span class="code">Pop</span> methods. + As more contextual data is pushed onto the stack the stack grows. When the stack is rendered + all the data pushed onto the stack is output with the most recent data to the right hand + end of the string. + </p> + <p> + As the stack is just an object stored in the context properties it is also rendered + using the same <span class="code">PatternLayout</span> syntax: <span class="code">%property{name}</span>. + Where <i>name</i> is the name of the stack. + </p> + <p> + Calls the the stack's <span class="code">Push</span> and <span class="code">Pop</span> + methods must be matched up so that each push has a corresponding pop. The + <span class="code">Push</span> method also returns an <span class="code">IDisposable</span> + object that will perform the required pop operation when it is disposed. This allows + the C# <i>using</i> syntax to be used to automate the stack management. + </p> + <source language="c#"><![CDATA[ using(log4net.ThreadContext.Stacks["NDC"].Push("context")) { log.Info("Message"); } ]]></source> - <p> - The INFO level log has a stack stored in its <i>NDC</i> property. The top item in the - stack is the string <i>context</i>. - The <i>using</i> syntax ensures that the value <i>context</i> is popped off the stack - at the end of the block. - </p> - <p> - The <span class="code">using</span> - syntax is recommended because it removes some work load from the developer and - reduces errors in matching up the Push and Pop calls, especially when exceptions - can occur. - </p> - </section> - - <section id="ndc" name="Nested Diagnostic Contexts"> - <p> - The <span class="code">NDC</span> (Nested Diagnostic Context) exists for compatibility - with older versions of log4net. This helper class implements a stack which is stored - in the thread context property named <i>NDC</i>. - </p> - </section> - - <section id="mdc" name="Mapped Diagnostic Contexts"> - <p> - The <span class="code">MDC</span> (MappedDiagnostic Context) exists for compatibility - with older versions of log4net. This helper class implements a properties map which is - mapped directly through to the thread context properties. - </p> - </section> - - <p> - To illustrate this point, let us take the example of a web service delivering - content to numerous clients. The web service can build the <span class="code">NDC</span> at the very - beginning of the request before executing other code. The contextual - information can be the client's host name and other information inherent to the - request, typically information contained in cookies. Hence, even if the web - service is serving multiple clients simultaneously, the logs initiated by the - same code, i.e. belonging to the same logger, can still be distinguished - because each client request will have a different <span class="code">NDC</span> stack. Contrast this with - the complexity of passing a freshly instantiated logger to all code exercised - during the client's request. - </p> - <p> - Nevertheless, some sophisticated applications, such as virtual hosting web - servers, must log differently depending on the virtual host context and also - depending on the software component issuing the request. Log4net supports - multiple logger repositories. This would allow each virtual host to possess its own copy - of the logger hierarchy. Configuring multiple logger hierarchies is beyond the - scope of this document. - </p> + <p> + The INFO level log has a stack stored in its <i>NDC</i> property. The top item in the + stack is the string <i>context</i>. + The <i>using</i> syntax ensures that the value <i>context</i> is popped off the stack + at the end of the block. + </p> + <p> + The <span class="code">using</span> + syntax is recommended because it removes some work load from the developer and + reduces errors in matching up the Push and Pop calls, especially when exceptions + can occur. + </p> + </section> + + <section id="ndc" name="Nested Diagnostic Contexts"> + <p> + The <span class="code">NDC</span> (Nested Diagnostic Context) exists for compatibility + with older versions of log4net. This helper class implements a stack which is stored + in the thread context property named <i>NDC</i>. + </p> + </section> + + <section id="mdc" name="Mapped Diagnostic Contexts"> + <p> + The <span class="code">MDC</span> (MappedDiagnostic Context) exists for compatibility + with older versions of log4net. This helper class implements a properties map which is + mapped directly through to the thread context properties. + </p> + </section> + + <p> + To illustrate this point, let us take the example of a web service delivering + content to numerous clients. The web service can build the <span class="code">NDC</span> at the very + beginning of the request before executing other code. The contextual + information can be the client's host name and other information inherent to the + request, typically information contained in cookies. Hence, even if the web + service is serving multiple clients simultaneously, the logs initiated by the + same code, i.e. belonging to the same logger, can still be distinguished + because each client request will have a different <span class="code">NDC</span> stack. Contrast this with + the complexity of passing a freshly instantiated logger to all code exercised + during the client's request. + </p> + <p> + Nevertheless, some sophisticated applications, such as virtual hosting web + servers, must log differently depending on the virtual host context and also + depending on the software component issuing the request. Log4net supports + multiple logger repositories. This would allow each virtual host to possess its own copy + of the logger hierarchy. Configuring multiple logger hierarchies is beyond the + scope of this document. + </p> - </section> - </body> + </section> + </body> </document>
Modified: logging/log4net/trunk/xdocs/src/release/manual/internals.xml URL: http://svn.apache.org/viewvc/logging/log4net/trunk/xdocs/src/release/manual/internals.xml?view=diff&rev=511694&r1=511693&r2=511694 ============================================================================== --- logging/log4net/trunk/xdocs/src/release/manual/internals.xml (original) +++ logging/log4net/trunk/xdocs/src/release/manual/internals.xml Sun Feb 25 18:10:21 2007 @@ -17,245 +17,245 @@ --> <document> - <properties> - <author email="nicko at apache dot org">Nicko Cadell</author> - <title>log4net Manual - Internals</title> - </properties> + <properties> + <author email="nicko at apache dot org">Nicko Cadell</author> + <title>Apache log4net Manual: Internals</title> + </properties> - <meta name="keywords" content="log4net internals, log4net" /> + <meta name="keywords" content="log4net internals, log4net" /> - <body> - <section id="main" name="log4net Manual - Internals"> - <sectionMenu name="Contents" /> + <body> + <section id="main" name="log4net Manual - Internals"> + <sectionMenu name="Contents" /> - <section id="perf" name="Performance"> - <p> - One of the often-cited arguments against logging is its computational cost. - This is a legitimate concern as even moderately sized applications can generate - thousands of log requests. Much effort was spent measuring and tweaking logging - performance. Log4net claims to be fast and flexible: speed first, flexibility - second. - </p> - <p> - The user should be aware of the following performance issues. - </p> - <ol> - <li> - <strong>Logging performance when logging is turned off.</strong> - <p> - When logging is turned off entirely or just for a set of levels, the cost of a - log request consists of a method invocation plus an integer comparison. - </p> - <p> - However, The method invocation involves the "hidden" cost of parameter - construction. - </p> - <p> - For example, for some logger - <span class="code">log</span>, writing, - </p> - <div class="syntax"><pre class="code"> + <section id="perf" name="Performance"> + <p> + One of the often-cited arguments against logging is its computational cost. + This is a legitimate concern as even moderately sized applications can generate + thousands of log requests. Much effort was spent measuring and tweaking logging + performance. Log4net claims to be fast and flexible: speed first, flexibility + second. + </p> + <p> + The user should be aware of the following performance issues. + </p> + <ol> + <li> + <strong>Logging performance when logging is turned off.</strong> + <p> + When logging is turned off entirely or just for a set of levels, the cost of a + log request consists of a method invocation plus an integer comparison. + </p> + <p> + However, The method invocation involves the "hidden" cost of parameter + construction. + </p> + <p> + For example, for some logger + <span class="code">log</span>, writing, + </p> + <div class="syntax"><pre class="code"> log.Debug("Entry number: " + i + " is " + entry[i].ToString());</pre></div> - <p> - incurs the cost of constructing the message parameter, i.e. converting both - integer - <span class="code">i</span> - and - <span class="code">entry[i]</span> - to strings, and concatenating intermediate strings, regardless of whether the - message will be logged or not. This cost of parameter construction can be quite - high and it depends on the number and type of the parameters involved. - </p> - <p> - To avoid the parameter construction cost write: - </p> - <div class="syntax"><pre class="code"> + <p> + incurs the cost of constructing the message parameter, i.e. converting both + integer + <span class="code">i</span> + and + <span class="code">entry[i]</span> + to strings, and concatenating intermediate strings, regardless of whether the + message will be logged or not. This cost of parameter construction can be quite + high and it depends on the number and type of the parameters involved. + </p> + <p> + To avoid the parameter construction cost write: + </p> + <div class="syntax"><pre class="code"> if(log.IsDebugEnabled) { - log.Debug("Entry number: " + i + " is " + entry[i].ToString()); + log.Debug("Entry number: " + i + " is " + entry[i].ToString()); }</pre></div> - <p> - This will not incur the cost of parameter construction if debugging is - disabled. On the other hand, if the logger is debug-enabled, it will incur - twice the cost of evaluating whether the logger is enabled or not: once in - <span class="code">IsDebugEnabled</span> - and once in - <span class="code">Debug</span>. This is an insignificant overhead because - evaluating a logger takes about 1% of the time it takes to actually log. - </p> - <p> - Certain users resort to pre-processing or compile-time techniques to compile - out all log statements. This leads to perfect performance efficiency with - respect to logging. However, since the resulting application binary does not - contain any log statements, logging cannot be turned on for that binary. In - many people's opinion this is a disproportionate price to pay in exchange for a - small performance gain. - </p> - </li> - <li> - <strong>The performance of deciding whether to log or not to log when logging is - turned on.</strong> - <p> - This is essentially the performance of walking the logger hierarchy. When - logging is turned on, log4net still needs to compare the level of the log - request with the level of the request logger. However, loggers may not have an - assigned level; they can inherit them from the logger hierarchy. Thus, before - inheriting a level, the logger may need to search its ancestors. - </p> - <p> - There has been a serious effort to make this hierarchy walk to be as fast as - possible. For example, child loggers link only to their existing ancestors. In - the - <span class="code">BasicConfigurator</span> - example shown earlier, the logger named - <span class="code">Com.Foo.Bar</span> - is linked directly to the <i>root</i> logger, thereby circumventing the nonexistent - <span class="code">Com</span> - or - <span class="code">Com.Foo</span> - loggers. This significantly improves the speed of the walk, especially in - "sparse" hierarchies. - </p> - <p> - The typical cost of walking the hierarchy is typically 3 times slower than when - logging is turned off entirely. - </p> - </li> - <li> - <strong>Actually outputting log messages</strong> - <p> - This is the cost of formatting the log output and sending it to its target - destination. Here again, a serious effort was made to make layouts (formatters) - perform as quickly as possible. The same is true for appenders. - </p> - </li> - </ol> - <p> - Although log4net has many features, its first design goal was speed. Some - log4net components have been rewritten many times to improve performance. - Nevertheless, contributors frequently come up with new optimizations. You - should be pleased to know that when configured with the - <span class="code">SimpleLayout</span> - performance tests have shown log4net to log within an order of magnitude of - <span class="code">System.Console.WriteLine</span>. - </p> - </section> + <p> + This will not incur the cost of parameter construction if debugging is + disabled. On the other hand, if the logger is debug-enabled, it will incur + twice the cost of evaluating whether the logger is enabled or not: once in + <span class="code">IsDebugEnabled</span> + and once in + <span class="code">Debug</span>. This is an insignificant overhead because + evaluating a logger takes about 1% of the time it takes to actually log. + </p> + <p> + Certain users resort to pre-processing or compile-time techniques to compile + out all log statements. This leads to perfect performance efficiency with + respect to logging. However, since the resulting application binary does not + contain any log statements, logging cannot be turned on for that binary. In + many people's opinion this is a disproportionate price to pay in exchange for a + small performance gain. + </p> + </li> + <li> + <strong>The performance of deciding whether to log or not to log when logging is + turned on.</strong> + <p> + This is essentially the performance of walking the logger hierarchy. When + logging is turned on, log4net still needs to compare the level of the log + request with the level of the request logger. However, loggers may not have an + assigned level; they can inherit them from the logger hierarchy. Thus, before + inheriting a level, the logger may need to search its ancestors. + </p> + <p> + There has been a serious effort to make this hierarchy walk to be as fast as + possible. For example, child loggers link only to their existing ancestors. In + the + <span class="code">BasicConfigurator</span> + example shown earlier, the logger named + <span class="code">Com.Foo.Bar</span> + is linked directly to the <i>root</i> logger, thereby circumventing the nonexistent + <span class="code">Com</span> + or + <span class="code">Com.Foo</span> + loggers. This significantly improves the speed of the walk, especially in + "sparse" hierarchies. + </p> + <p> + The typical cost of walking the hierarchy is typically 3 times slower than when + logging is turned off entirely. + </p> + </li> + <li> + <strong>Actually outputting log messages</strong> + <p> + This is the cost of formatting the log output and sending it to its target + destination. Here again, a serious effort was made to make layouts (formatters) + perform as quickly as possible. The same is true for appenders. + </p> + </li> + </ol> + <p> + Although log4net has many features, its first design goal was speed. Some + log4net components have been rewritten many times to improve performance. + Nevertheless, contributors frequently come up with new optimizations. You + should be pleased to know that when configured with the + <span class="code">SimpleLayout</span> + performance tests have shown log4net to log within an order of magnitude of + <span class="code">System.Console.WriteLine</span>. + </p> + </section> - <section id="flow" name="Logging Event Flow"> - <p> - The following is the series of steps and checks that a messages goes through while being logged. - For the purposes of this example we will document an <span class="code">INFO</span> level - message being logged on logger <i>ConsoleApp.LoggingExample</i>. This logger is configured - to use the <span class="code">log4net.Appender.ConsoleAppender</span>. The repository used - in this example is a <span class="code">log4net.Repository.Hierarchy</span> object. - </p> - <ol> - <li> - <p> - The user logs a message using the <span class="code">ILog.Info</span> method on the logger - obtained using a call to <span class="code">log4net.LogManager.GetLogger("ConsoleApp.LoggingExample")</span>. - For example: <span class="code">log4net.LogManager.GetLogger("ConsoleApp.LoggingExample").Info("Application Start");</span> - The <span class="code">ILog</span> interface is actually an extension to log4net that provides level - specific logging methods (i.e. Debug, Info, Warn, Error, and Fatal). - </p> - </li> - <li> - <p> - The message is then logged through to the <span class="code">ILogger.Log</span> method on the - appropriate <span class="code">log4net.Repository.Hierarchy.Logger</span> object. The - <span class="code">ILogger.Log</span> method takes the <span class="code">Level</span> to - log at as a parameter and therefore works for all levels. - </p> - </li> - <li> - <p> - The repository threshold level is compared to the message level to determine if the message - can be logged. If the message level is below the threshold level the message is not logged. - In this case the repository is a <span class="code">log4net.Repository.Hierarchy</span> object. - </p> - </li> - <li> - <p> - The <span class="code">Logger</span> level is compared to the message level to determine if the - message can be logged. Note that the <span class="code">Logger</span> level is inherited from a - parent <span class="code">Logger</span> if not specified explicitly for this <span class="code">Logger</span>. - If the message level is below the <span class="code">Logger</span> level the message is not logged. - </p> - </li> - <li> - <p> - A <span class="code">LoggingEvent</span> instance is created to encapsulate the message being logged. - </p> - </li> - <li> - <p> - The list of appenders for the <span class="code">Logger</span> is built. This includes appenders - attached to parent <span class="code">Logger</span>s except where excluded by the - <span class="code">Logger.Additivity</span> property. - </p> - </li> - <li> - <p> - The <span class="code">LoggingEvent</span> object is passed to the - <span class="code">IAppender.DoAppend</span> method for each appender. - </p> - </li> - </ol> - <p> - For Each Appender that the <span class="code">LoggingEvent</span> is delivered to the following - actions take place: - </p> - <ol> - <li> - <p> - The appender threshold level is compared to the message level to determine if the message - can be logged. If the message level is below the threshold level the message is not logged. - </p> - </li> - <li> - <p> - If the appender has a filter chain the <span class="code">LoggingEvent</span> is passed down the - filter chain which can decide if the message can be logged or not. - </p> - </li> - <li> - <p> - Next an appender specific check is performed. Usually this check will verify that all the - required properties are set for the appender (e.g. a <span class="code">Layout</span> is set if required). - </p> - </li> - <li> - <p> - The <span class="code">LoggingEvent</span> is passed to the appender specific - <span class="code">Append</span> method. What happens now is specific to the appender. - </p> - </li> - </ol> - <p> - The following actions take place in the <span class="code">ConsoleAppender.Append</span> method: - </p> - <ol> - <li> - <p> - The <span class="code">ConsoleAppender</span> uses a <span class="code">Layout</span> to - format the message as a string for display. - </p> - </li> - <li> - <p> - The <span class="code">Layout</span> uses the <span class="code">LoggingEvent.RenderedMessage</span> - property to get the string for the message object. This uses the registered - <span class="code">IObjectRenderer</span> for the type of the message object. - </p> - </li> - <li> - <p> - The message text is displayed on the console using the <span class="code">Console.WriteLine</span> method. - </p> - </li> - </ol> - </section> + <section id="flow" name="Logging Event Flow"> + <p> + The following is the series of steps and checks that a messages goes through while being logged. + For the purposes of this example we will document an <span class="code">INFO</span> level + message being logged on logger <i>ConsoleApp.LoggingExample</i>. This logger is configured + to use the <span class="code">log4net.Appender.ConsoleAppender</span>. The repository used + in this example is a <span class="code">log4net.Repository.Hierarchy</span> object. + </p> + <ol> + <li> + <p> + The user logs a message using the <span class="code">ILog.Info</span> method on the logger + obtained using a call to <span class="code">log4net.LogManager.GetLogger("ConsoleApp.LoggingExample")</span>. + For example: <span class="code">log4net.LogManager.GetLogger("ConsoleApp.LoggingExample").Info("Application Start");</span> + The <span class="code">ILog</span> interface is actually an extension to log4net that provides level + specific logging methods (i.e. Debug, Info, Warn, Error, and Fatal). + </p> + </li> + <li> + <p> + The message is then logged through to the <span class="code">ILogger.Log</span> method on the + appropriate <span class="code">log4net.Repository.Hierarchy.Logger</span> object. The + <span class="code">ILogger.Log</span> method takes the <span class="code">Level</span> to + log at as a parameter and therefore works for all levels. + </p> + </li> + <li> + <p> + The repository threshold level is compared to the message level to determine if the message + can be logged. If the message level is below the threshold level the message is not logged. + In this case the repository is a <span class="code">log4net.Repository.Hierarchy</span> object. + </p> + </li> + <li> + <p> + The <span class="code">Logger</span> level is compared to the message level to determine if the + message can be logged. Note that the <span class="code">Logger</span> level is inherited from a + parent <span class="code">Logger</span> if not specified explicitly for this <span class="code">Logger</span>. + If the message level is below the <span class="code">Logger</span> level the message is not logged. + </p> + </li> + <li> + <p> + A <span class="code">LoggingEvent</span> instance is created to encapsulate the message being logged. + </p> + </li> + <li> + <p> + The list of appenders for the <span class="code">Logger</span> is built. This includes appenders + attached to parent <span class="code">Logger</span>s except where excluded by the + <span class="code">Logger.Additivity</span> property. + </p> + </li> + <li> + <p> + The <span class="code">LoggingEvent</span> object is passed to the + <span class="code">IAppender.DoAppend</span> method for each appender. + </p> + </li> + </ol> + <p> + For Each Appender that the <span class="code">LoggingEvent</span> is delivered to the following + actions take place: + </p> + <ol> + <li> + <p> + The appender threshold level is compared to the message level to determine if the message + can be logged. If the message level is below the threshold level the message is not logged. + </p> + </li> + <li> + <p> + If the appender has a filter chain the <span class="code">LoggingEvent</span> is passed down the + filter chain which can decide if the message can be logged or not. + </p> + </li> + <li> + <p> + Next an appender specific check is performed. Usually this check will verify that all the + required properties are set for the appender (e.g. a <span class="code">Layout</span> is set if required). + </p> + </li> + <li> + <p> + The <span class="code">LoggingEvent</span> is passed to the appender specific + <span class="code">Append</span> method. What happens now is specific to the appender. + </p> + </li> + </ol> + <p> + The following actions take place in the <span class="code">ConsoleAppender.Append</span> method: + </p> + <ol> + <li> + <p> + The <span class="code">ConsoleAppender</span> uses a <span class="code">Layout</span> to + format the message as a string for display. + </p> + </li> + <li> + <p> + The <span class="code">Layout</span> uses the <span class="code">LoggingEvent.RenderedMessage</span> + property to get the string for the message object. This uses the registered + <span class="code">IObjectRenderer</span> for the type of the message object. + </p> + </li> + <li> + <p> + The message text is displayed on the console using the <span class="code">Console.WriteLine</span> method. + </p> + </li> + </ol> + </section> - </section> - </body> + </section> + </body> </document>