There are a variety of logging implementations for .NET currently in use, log4net, Enterprise Library Logging, NLog, to name the most popular. The downside of having differerent implementation is that they do not share a common interface and therefore impose a particular logging implementation on the users of your library. To solve this dependency problem the Common.Logging library introduces a simple abstraction to allow you to select a specific logging implementation at runtime.
The library is based on work done by the developers of IBatis.NET and it's usage is inspired by log4net. Many thanks to the developers of those projects!
The core logging library Common.Logging provides the base logging ILog interface as well as the global LogManager that you use to instrument your code:
[C#]
ILog log = LogManager.GetCurrentClassLogger();
log.DebugFormat("Hi {0}", "dude");
To output the information logged, you need to tell Common.Logging, what underlying logging system to use. Common.Logging already includes console and trace based logger implementations usable out of the box. Adding the following configuration snippet to your app.config causes Common.Logging to output all information to the console:
[XML]
<configuration>
<configSections>
<sectionGroup name="common">
<section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging" />
</sectionGroup>
</configSections>
<common>
<logging>
<factoryAdapter type="Common.Logging.Simple.ConsoleOutLoggerFactoryAdapter, Common.Logging">
<arg key="level" value="DEBUG" />
</factoryAdapter>
</logging>
</common>
</configuration>
Hint: When using NET 3.5, you can leverage lambda syntax for logging to avoid any performance penalties:
[C#]
log.Debug( m=>m("value= {0}", obj.ExpensiveToCalculateValue) );
This ensures, that the whole expression is only evaluated when LogLevel.Debug is enabled and thus saves you from having to write
[C#]
if (log.IsDebugEnabled)
{
log.Debug("value={0}", obj.ExpensiveToCalculateValue);
}
Ever had the problem you used frameworks that were tied to different logging systems? Each Common.Logging integration module comes with to plugs: One to route log messages to the 3rd party logging system and one to capture log messages from one logging system and feed it into the Common.Logging infrastructure. So if one of your frameworks uses log4net, another NLog and you want to log everything to System.Diagnostics.Trace, Common.Logging is for you.
The new version of Common.Logging assembly is 100% binary backwards compatible to previous versions of LogManager and ILog interfaces. To upgrade, either you rebuild your project against the new version or you configure an assembly version redirect in your app.config:
<configuration> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="Common.Logging" publicKeyToken="af08829b84f0328e" culture=""/> <bindingRedirect oldVersion="0.0.0.0-65535.65535.65535.65535" newVersion="2.0.0.0"/> </dependentAssembly> </assemblyBinding> </runtime> </configuration>
Those who implemented their own Common.Logging.ILoggerFactoryAdapter and Common.Logging.ILog interfaces, need to update their code to the extended interfaces coming with version 2.0. For convenience Common.Logging comes with a couple of support classes, making this task as easy as possible as described in the reference documentation
In the case you want to integrate your own logging system that is not supported by Common.Logging yet, it is easily possible to implement your own plugin by implementing ILoggerFactoryAdapter. For convenience there is a base AbstractCachingLoggerFactoryAdapter implementation available that usually makes implementing your own adapter a breeze.
If your code or a framework you are using (like Microsoft Enterprise Library's Logging Block) already uses the .NET framework's built-in System.Diagnostics.Trace system, you can use CommonLoggingTraceListener to redirect all trace output to the Common.Logging infrastructure.