Logging Best Practices
I have been using Log4Net for all my projects though Logging Application Block from Enterprise Library seems to be equally good. There is a full fledged war out there between two, but I don’t see a major motivation to move to latter (inspite of .NET framework logging being built around tracesources). Log4Net has got many trace levels which you can flip through your config file – FATAL, ERROR, DEBUG, WARN & INFO. They start from most limited logging to maximum.
Normally I see myself using ERROR & DEBUG, as most of the time it’s hard to communicate with developers when they have to draw line between others. My minimum instructions (though not enough see post script at end of this post) are
1) Use ERROR LEVEL for all Exception Logging (ensure that you hook into unhandled exceptions)
2) Use DEBUG level for Activity Logging (this is bit tricky and there are no straight guidelines for this). Activity Logging needs to be more contextual with revlevant information to your domain. Some programmers also use this to find performance bottlenecks in their system during production.
I will briefly elaborate steps to get started with Log4Net for above (skip them if you aren’t looking for them):
1) Add reference to log4net.dll into your project (This is required per project).
2) Modify your config file to add a log4net configsection & specify various appenders. This config is the for the main projects not class library projects. E.g. you have Presentation (ASP.NET) & Data Access Layer (C# Class Library) only web.config of your presentation project should be altered.
<?xml version=”1.0″ encoding=”utf-8″?>
<!–This is a must addition–>
<section name=”log4net” type=”log4net.Config.Log4NetConfigurationSectionHandler,log4net” />
<appender name=”RollingFileAppender” type=”log4net.Appender.RollingFileAppender,log4net”>
<param name=”File” value=”C:\\HRESWeb.log” /><!–File where the log should reside–>
<param name=”AppendToFile” value=”true” />
<!– FOR DATE BASED ROLL BACKUP –>
<param name=”rollingStyle” value=”Date” />
<param name=”datePattern” value=”yyyyMMdd” />
<!–Pattern to add timestamp, type, etc.–>
<param name=”ConversionPattern” value=”%d [%t] %-5p %c [%x] – %m%n” />
<level value=”ERROR” /> <!–Just change the level to DEBUG for informative logging–>
<appender-ref ref=”RollingFileAppender” />
3) Add an entry in the AssemblyInfo.cs of the project whose config you edited in the second step.
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "ConsoleApplication7.exe.config")]
or for Web.config
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "Web.config")]
4) Start logging
Normally you would create a static ILog Object per class by specifying the class type as parameter & then use Debug & Error Methods for Logging
static readonly ILog log = LogManager.GetLogger(typeof(Program));
log.Debug(“Debug Message”); // No need to check if Debug level is enabled. Log4Net does that internally
// A sample method with minimum features
public void SomeActivity()
log.Debug(“Entering”); // Activity Logging; context information here e.g. patient you processing, claim you working
//… Do Something
log.Debug(“Exiting”); // Activity Logging;
catch (Exception ex)
log.Error(“Description : “, ex); // This would also take inner exceptions if any
throw; //Don’t forget this
Logging is also normally implemented via AOP (I had posted a similar article using Unity on CodeProject, though this one deals with transactions).
A recommendation is that exceptions should also be posted in the Windows Event Logs (you can create a category for your application), the motivation being that this increases visibility & is easy for production guys to locate them instead of wading through your text, Udi organizes the same thought here.
I have seen few applications giving preference to Database logging. The same can be enabled via log4net (it’s just an appender). The thought process that goes into selecting database is normally easy search (say you want to retrive all errors occoured during last peek load or corelation queries). Another benefit is security – as DB entries are more secure than file system. But sometimes this additional security may cause delays in getting logs or make the process too rigid. To add to this, you need to consider purging logging records, performance impact on DB Server, license cost (if required), etc. Hence, it’s good to have flat files logging while creating custom applications, and provide multiple choices in case you are architecting a product.
Finally, if you are creating RIA / thin client apps (Silverlight, XBAP, Clickonce), you may not be able to create a log locally on client machine. I recommend that you implement logging for such applications also by sending messages to Web server / App Server, as it becomes quite necessary in few cases to know what’s going wrong on these clients. Checking if activity logging is enabled or not (assuming exception logging is always on) remains a challenge here.
P.S. An effective way to find out how good your logging is, ask developers to debug without breakpoints (IDE) during development. If they can do it just by looking at log file, you are on your way, else you might have to get ready for post production nightmares .