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.
- Download Log4Net from the Appache web site.
- Add a reference to the Log4Net.dll in every project in your solution that you want to log information in.
In a web Application
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  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.
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.