Switching to NLog

My application has about 165,000 lines of code, and I have been using log4net for all my logging needs.  However, for a client application that I’m working on I wondered if Log4Net was the best choice.  After doing some research and experimentation I decided it wasn’t.  Instead, NLog wins the new title, and it only took 1 hour to switch my entire 165,000 lines of code over to NLog.

Benefits of NLog over Log4Net:

  • Signs of life!  Log4Net doesn’t seem to be active any more – certainly there hasn’t been a release in ages.
  • Logging methods that accept format strings and parameters.
    This later is why switching to NLog took so long: I was able to go through my code (using VS2008 & searching across the entire solution) and remove all the irritating string concatenation, replacing them with format strings and parameters.  This means that if a logging level is turned off, the string concatenation will never occur!

So instead of:

log.Debug(“Some message ” + pieceOfData + ” and ” + someOtherData );

which ALWAYS results in 3 string concatenations even if debug logging is disabled, I can now do:

log.Debug(“Some message {0} and {1}”,pieceOfData,someOtherData );

which ONLY does a string concatenation if the debugging is enabled.

  • Automatic configuration – just start-up your application and go
  • More powerful configuration!
    Their configuration has LOTS of very cool marcos (which they call Layout Renderers).  This allowed me to eliminate a huge pile of messy C# log4net configuration code (complete with nasty casting to internal classes – which apparently is the “documented” approach) just to configure the output file to go into the user’s AppData local folder.Eliminiating C# code for a single easy-to-understand line of configuration is good!

So instead of all of this:

/// <summary>
/// Setup Log4Net and create a file appender so that it logs to a writable location!
/// (even in Vista where the "Program files" folder is read-only.
/// </summary>
private static void SetupLog4Net( string dataPath ) {
	// Configure Log4Net with the properties from the app.config file
	log4net.Config.XmlConfigurator.Configure();

	// Create the file appender and setup basic options
	var fileAppender = new log4net.Appender.RollingFileAppender();
	fileAppender.AppendToFile = false;
	fileAppender.RollingStyle = log4net.Appender.RollingFileAppender.RollingMode.Once;
	fileAppender.MaxSizeRollBackups = 4;	// The number of log files to keep around
	fileAppender.MaximumFileSize = "10MB";

	// Use an almost standard layout pattern
	const string layout = "%date  %-5level  Thread:[%-23thread]  %logger - %message%newline";
	fileAppender.Layout = new log4net.Layout.PatternLayout(layout);

	// Log data to the location application data directory because it's pretty
        // much guaranteed we can write there.
	string logFilePath = CurrentLogFilePath(dataPath);
	fileAppender.File = logFilePath;

	//Notify the appender on the configuration changes
	fileAppender.ActivateOptions();

	// Get the root logger (bit of a hack, but seems "standard") and add the file appender
	var repository =  LogManager.GetRepository() as log4net.Repository.Hierarchy.Hierarchy;
	if( repository==null ) throw new Exception("Failed to get the log4net hierarchy repository.");
	log4net.Repository.Hierarchy.Logger root = repository.Root;
	root.AddAppender(fileAppender);

	// Very important: Mark the repository as configured and notify it that is has changed
	repository.Configured = true;
	repository.RaiseConfigurationChanged(EventArgs.Empty);
}

I now have this one line of configuration code in the XML configuration file:

fileName=”${specialfolder:folder=LocalApplicationData}\MyApp\MyApp.${shortdate}.log”

That is FANTASTIC!

  • NLog is also supported by Gibraltar!  (Which I WISH I owned…)

The only down side is that padding doesn’t always work, so laying out the log file for easier reading is not there yet (from the NLog blog):

…the use of “padding” attribute on layout renderers. If you used it in v1 you may have found
that it did not work for all renderers (depending on their implementation)

Apparently this is fixed in version 2, but I don’t know when that will be available.

Somebody has also already written an article about NLog and PostSharp which is cool because it means “free” logging.

I also can’t get it to do rolling log files every time the application starts up.  I’ve posted a question on the NLog forum here.

Robert

Advertisements

4 comments so far

  1. Grimace on

    A bit of a late remark, but has this ever bitten you, e.g. when you need NHibernate logs or something?

    • robertmccarter on

      Frankly, I avoid NHibernate like the plauge; I used NHibernate on my most recent very large project, and it worked well for a while, until I needed to do something perfectly reasonable (that the NHibernate purists have decided shouldn’t be done) and then I was up a creek. Without a good GUI tool writing all the XML configuration by hand wasn’t much fun either. In the end, I completely removed NHibernate from the product (fortunately the software had very good separation-of-concerns with an isolated persistence layer, so pulling it out wasn’t too bad) and I went searching for other solutions.

      As for Log4Net verses NLog: Log4Net has now been at release 1.2.10 since 2005; in my books that makes it pretty much dead. According to their Supported Frameworks page they support 2.0 – no mention of v3.5 or v4, and no mention of Silverlight vAnything. There’s also no discussion around support for client profiles verses full framework installs. If I remember (from the last time that I used it) Log4Net has dependencies on System.Web.dll so it will NOT work in the client profile.

      NLog on the other hand is very active, is easier to use, and slightly more performant. There is an active release being built for .NET 4, support for Silverlight, and an engaged community (see http://nlog-project.org/2010/03/04/support-for-net-framework-4-client-profile-in-nlog-2-0.html as an example).

      So yes, I’ve been very happy with NLog and I’ve never looked back.

      Robert

  2. GuiSim on

    ” Logging methods that accept format strings and parameters. ”

    In Log4Net, instead of using

    ” log.Debug(“Some message ” + pieceOfData + ” and ” + someOtherData ); ”

    you should use

    ” log.DebugFormat(“Some message {0} and {1}”,pieceOfData,someOtherData ); ”

    I agree that this isn’t as intuitive as NLog’s approach but saying that log4net can’t decide at runtime whether the string should be formatted or not is false.

  3. robertmccarter on

    Thank you for the update! I didn’t know that…


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: