Getting Started with Log4Net

December 7th, 2007

Logging isn’t exactly a hot topic, it is one of those after thought topics really.  You have the software half way written, then you think: “I really should be put some logging in this”.  Now what? 

Luckily there are a plethora of solutions: Log4Net, NLog, Microsoft Patterns & Practices Logging Application Block, and others.  (Note to Scott: Get your Application Block post up already, I’m getting tired of waiting). 

Things to consider when picking a logger

As for why you would pick one over the other?  Our rational for using Log4Net is because it is tied in with NHibernate.  If you are using NHibernate, Log4Net will be sitting there anyway, so you might as well use it.  I also have friends using the Patterns & Practices blocks, so they would be wise to use the Logging Application Block.

If you like bullet lists, here is your bullet list:

  • Do any of my third party libraries already use a particular logger (NHibernate = Log4Net)
  • Can I change my logger’s settings without recompiling (turn it on off, change the output location, etc)
  • Does it log the information to the area I need (text file, database, email, netsend, etc)
  • Can I turn logging on for one small piece of my application without turning it on for the entire application

For my group, Log4Net filled all of those criteria.  You don’t need all of those every time, but it is nice to be able to standardize on one logger and just go with it.  Log4Net allows you to do that.

Preliminary Steps

  1. Download Log4Net from the Appache web site.
  2. Add a reference to the Log4Net.dll in every project in your solution that you want to log information in.

In a web Application

Web.Config Changes

First place we are going to go is the web.config.  Every ASP.NET web site should have one of these anyway.  At the top of the config file should be ConfigSections.  We are going to add this text inside that node:

<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />

Next, fly down the the bottom of the web.config and insert this text just above the </configurtion> tag:

    <log4net> 
     <root>
       <level value="ALL" />
       <appender-ref ref="LogFileAppender" />
     </root>
     <appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender,log4net"> 
      <param name="File" value="c:\Logs\SampleLog.txt" /> 
      <param name="AppendToFile" value="true" /> 
      <rollingStyle value="Size" /> 
      <maxSizeRollBackups value="2" /> 
      <maximumFileSize value="100KB" /> 
      <staticLogFileName value="true" /> 
      <datePattern value="yyyyMMdd" /> 
      <layout type="log4net.Layout.PatternLayout"> 
        <conversionPattern value="%date [%thread] %-5level %logger - %message%newline" /> 
      </layout> 
    </appender> 
    </log4net>

OK, this chunk of XML needs some explaining.  Log4Net doesn’t contain just one way of logging text, it has a bunch of them, and they are called Appenders.  You tell Log4Net which appender to use in the web.config — you can do this programmatically as well, but that isn’t nearly as configurable — and I like configurable.

Anyway, you should see an appender node, the node must be named and filled out for that particular appender type.  In this example we are using a RollingFileAppender, which lets a file get to a certain size (100kb in this case) and then move the data to another file.  The conversionPattern tells Log4Net how to format the output of the log messages in the log file (stored at c:\Logs\SampleLog.txt in this case).  When properly setup you should see output that looks like this:

2007-12-07 13:30:04,464 [8] INFO  MyNamespace._Default – My Log Text

The “root” node allows you to specify which log messages get logged (more on that later), and which appenders are in use.

Global.asa.cs changes

Unfortunately, this is still not enough, we also need to tell Log4Net to load up, and where to load up from.  You do this by calling XmlConfigurator.Config() in your Application_Start method.  To do this, you will also need to include log4net.Config in the file.

Logging in a class

To log something in a class, I add one line of code to the top of the class,

private static readonly log4net.ILog _logger 
            = log4net.LogManager.GetLogger( 
                    System.Reflection.MethodBase.GetCurrentMethod() 
                     .DeclaringType);

To help with this line, I have it defined in a snippet named “logger”.  So all I have to do is type “logger” and that line is automatically placed in the class.

Once that line above is declared in your class, in any method you can call one of the following logging methods like this:

_logger.Info("Hi there"); 
_logger.Warn("Danger Will Robinson"); 
_logger.Debug("I like .Net"); 
_logger.Error("Something bad happened here", MyException); 
_logger.Fatal("RUN AWAY! RUN AWAY!");

All of these methods take one or two parameters, but the second parameter (if included) is always an exception.  If you include an exception with the log message you will get a full stack trace in your log output.

Filtering the Output

The “logger” node allows you to filter what specific data is added to a logger.  There can be a bunch of these.  The names of the loggers match up to a namespace or class.  If you don’t have any “logger” nodes everything is logged to the level that the root node states.

So if you have two classes (ClassA and ClassB in namespace MyNamespace) you can turn logging on for ClassA and off for ClassB like this:

<logger name="MyNamespace.ClassA"> 
     <level value="All" /> 
     <appender-ref ref="LogFileAppender" /> 
</logger> 
<logger name="MyNamesapce.ClassB"> 
     <level value="Off" /> 
     <appender-ref ref="LogFileAppender" /> 
</logger>

Or, you can log any error or Fatal message from anywhere in the application, but log everything from ClassB like this:

<logger name="MyNamespace"> 
      <level value="ERROR" /> 
      <appender-ref ref="LogFileAppender" /> 
</logger> 
<logger name="MyNamespace.ClassB"> 
     <level value="All" /> 
     <appender-ref ref="LogFileAppender" /> 
</logger>

Also note, one of the fields that is in the log output is “%logger”, which is the name of the logger.  So if you are getting more log messages that you would like, look at your log file to see which classes you don’t need log message from, and configure them out of the way.

And that is your quick introduction to Log4Net.  There are many more options available, this is a big product, and a few good Google searches should find them out.  Below are some links for learning more information.

Official Log4Net site
Log4Net sdk reference
log4net XmlConfigurator Simplified

  • Pingback: K.I.S.S. Programming » Using log4Net in a Windows Console app

  • JLucca

    Very helpful and welcome explanation for someone accustomed to log4j and wanting to get up to speed fast.

    I did have a moment where I didn’t know where to put the logger nodes. I found it documented on the log4net site. For those also confused, they can only be defined as children of the element. See the log4net manual under configuration (bottom of the page) at file:///C:/lib.net/log4net/log4net-1.2.10/doc/release/manual/configuration.html#loggers

  • JLucca

    oops. Typo above. The xml code got left out and I stupidly put a file:/ link.

    What I meant to say:
    The logger nodes can only be defined as children of the log4net element. See the log4net manual under configuration (bottom of the page). I can’t actually find an online link to the 1.2.10 manual. After you download and unpack log4net, look in the doc/ directory for the manual. The configuration page is there.

  • Paul

    Do you have any idea how to get log4net to write a log file on Vista???

    This is for a windows forms app, and the logger must work for admin and non-admin processes. So far nothing. I can’t get it to work.

  • http://elegantcode.com Chris Brandsma

    The main issue will be in WHERE the log file gets written in vista. You should not write it anywhere in Program Files (Vista doesn’t like that).

    You best bet is to specify in your code where to write the log file to, and use the “SpecialFolders” (I don’t remember what namespace they are in, but you can search on Special Folders), to put the log file in the user’s application data folder.

    The actual path to that directory will look something like: C:\Users\UserName\AppData\Local or C:\Users\UserName\AppData\Roaming

    You want it in Roaming if your users are working on multiple machines and they want the same settings on all those machines.

    Good luck.

  • Paul

    I got it working. It was not at all difficult once I found my real problem which was unrelated (install problems).

    I have been able to use a couple of environment variables directly in log4net.config with success.

    TY.

  • Greenspan

    No text file is being written. Been looking around but can’t figure out what’s causing it. Any help is appreciated. Thanks!

  • http://www.l4ndash.com Georg

    You are using XmlConfigurator.Config() in the global.asa.cs fil, I just want to mention that Log4Net has the possibility to reload configuration when the config is changed.

    Typical used if you change the log level when the application is running, or activate another appender etc.

    To activate this you need to use the XmlConfigurator.ConfigureAndWatch, for example by inserting a assembly-level attribute in the Global.asa.cs, like:

    [assembly: log4net.Config.XmlConfigurator(Watch=true)]

    Instead of using the XmlConfigurator.Config() in the application start event.

    The configuration file will be monitored using a FileSystemWatcher, and reloaded whenever it is changed.

    Best regards
    Georg
    http://www.l4ndash.com – Log4net Dashboard