AddThis Social Bookmark Button

Print

Using log4net
Pages: 1, 2, 3

Configuring log4net Programmatically

Sometimes we are in the mood to code as quickly as possible without getting into configuration files. Normally, that happens when we are trying to test something. In that case, you have another way to do the configuration. All of the long configuration files that we saw in the previous section can be defined programmatically using a few lines of code. See the following code:


// using a FileAppender with a PatternLayout
log4net.Config.BasicConfigurator.Configure(
  new log4net.Appender.FileAppender(
     new log4net.Layout.PatternLayout("%d 
       [%t]%-5p %c [%x] <%X{auth}> - %m%n"),"testfile.log"));

// using a FileAppender with an XMLLayout
log4net.Config.BasicConfigurator.Configure( 
  new log4net.Appender.FileAppender( 
    new log4net.Layout.XMLLayout(),"testfile.xml"));

// using a ConsoleAppender with a PatternLayout
log4net.Config.BasicConfigurator.Configure( 
  new log4net.Appender.ConsoleAppender(
    new log4net.Layout.PatternLayout("%d 
      [%t] %-5p %c [%x] <%X{abc}> - %m%n")));
/
/ using a ConsoleAppender with a SimpleLayout
log4net.Config.BasicConfigurator.Configure(
  new log4net.Appender.ConsoleAppender(new 
    log4net.Layout.SimpleLayout()));

You can see that while it is easy to code here, you can't configure settings for individual loggers. All of the settings that are defined here are applied to the root logger.

The log4net.Config.BasicConfigurator class uses its static Configure method to set an Appender object. The Appender constructor, in turn, requires the Layout object. Other parameters are respective to the type of component you are using.

You can also use BasicConfigurator.Configure() without any parameter to show the output using ConsoleAppender with a specific PatternLayout, as follows:

Code


log4net.Config.BasicConfigurator.Configure();

Output


0 [1688] DEBUG log1 A B C - Test
20 [1688] INFO log1 A B C - Test

Now that the application is configured, you can write the logging code, as shown in the previous section.

Logging in a Multithreaded Application

One of the most noticeable features of log4net is its support for multithreaded applications. This helps you in scenarios where your application is simultaneously accessed by multiple clients. Therefore, to trace requests from different clients, you need a mechanism to identify different clients in your logging framework. This mechanism is provided in log4net through two different methods, Nested Diagnostic Context (NDC) and Mapped Diagnostic Context (MDC).

Nested Diagnostic Context (NDC)

NDC uses a stack per thread to identify different clients. The stack's Push() method is used to set any value that identifies the client. It is the developer's responsibility to put in a unique value for each client. To constrain NDC into a certain block of code, the developer can use the "using" statement to make his task easier, because it automatically pops the respective value from the stack.


using(log4net.NDC.Push("clientid")
{
  log.Info("message"); // output: "clientid – message"        
} // here the value is popped from the stack

NDC class can also be used without the using block.


log4net.NDC.Push("clientid"); // context started here
…. // put client aware log messages here
log4net.NDC.Pop(); // context ended here

The framework provides a special conversion term, "%x," to display the NDC value on the stack using the PatternLayout.

<layout type="log4net.Layout.PatternLayout,log4net">
  <param name="ConversionPattern" value="%x" />
</layout>

If you push multiple values into the stack, then all of those values are concatenated in the output.

If you are using the XMLLayout class as the layout for your appender, then you automatically have the NDC value as a CDATA section inside of the <log4net:NDC> tag.

<log4net:NDC><![CDATA[A B C]]></log4net:NDC>

Mapped Diagnostic Context (MDC)

Instead of using a stack, the MDC class uses a map to store individual user information. It could not be used inside of the using block; therefore, we have to use it in a Get()/Set() combination to manipulate the map values. Values can be deleted from the map using the Remove() method. Similar to NDC, MDC also works on a per-thread model, and requires the conversion term inside of the pattern string, if you are using the PatternLayout. For MDC, the term is "%X" (capital X) with the key concatenated to the character in curly braces. In the following example, %X{clientid} is replaced with the value for the key clientid.

<layout type="log4net.Layout.PatternLayout">
  <param name="ConversionPattern" 
         value="%X{clientid}" 
  />
</layout>

Logging in ASP.NET

Using log4net with ASP.NET is similar to the other applications. Here, you can put the configuration attributes inside of the global.asax file, as well as in any of the WebForms files. Putting it in global.asax is far easier to remember.

More with log4net

There is a lot left to explore in the log4net framework. New features are also integrating into the framework quite frequently. Once you get started using the information provided in this article, the next step would be to experiment with the samples provided with the sources. In order to follow the updates on the framework, I'll try to use the forum to post any changes. I would like to acknowledge Nicko Cadell from www.Neoworks.com for reviewing this article and helping me with some technical details.

Resources

Nauman Leghari


Return to ONDotnet.com