Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
Logging with Castle Windsor, the Logging Facility and log4net

A discussion on the altdotnet list just came up around logging. After some various suggestions, I asked what was wrong with using optional dependencies and the built in logging facility in Castle Windsor. It seemed the most obvious answer

Of course, I completely forgot that when I first tried to figure this one out, it had me a little stumped and I took a while to find a good example of it. So here is how it happens.

Optional Dependencies in Windsor

When you ask the Windsor container for an instance of a class, it goes off and merrily tries to resolve all of the dependencies your class has. Firstly the constructor parameters, Windsor must find a constructor that it can provide all of the dependencies for - constructor parameters represent non-optional dependencies, they must be able to be fulfilled or Windsor will not give you an instance of the class back. You can have multiple constructors of course, and in this case Windsor will try and find the best match it can.

This lead to one of the early suggestions on the thread, putting the instance of the Logger as a parameter on the class constructor. To me this is a horrible idea, logging, along with things like security and auditing are cross cutting concerns, the class really shouldn't have to care about them - their behaviour lives elsewhere.

But Windsor has a really simple solution to this - optional dependencies. While Windsor must be able to fulfill at least one constructor signature, it will also try and resolve any public properties it can find on the class. These public properties may or may not be set by Windsor, if it has a suitable match for a property it will set it, otherwise it will ignore it.

So the first part of the solution to the problem is to put a public property on the class with the logger interface - now Windsor will populate this property if it has a match in the container.

The Logging Facility 

Next is the magic bit, Castle already has simple integration for logging in the form of the Logging Facility.

While you could just put your own class, that implemented your own logging, and passed this onto log4net, by using the Castle faciltiy you save a lot of messing around, and get a great deal of flexibility. The Castle facility supports:

  • log4net (requires Castle.Services.Logging.Log4netIntegration.dll)
  • NLog (requires Castle.Services.Logging.NLogIntegration.dll)
  • ConsoleLogger
  • DiagnosticsLogger
  • StreamLogger
  • WebLogger (TraceContext)
  • NullLogger (used as placeholder)

Of course in the thread, log4net was the target of choice, but Castle lets you switch this simply, and maintain a single interface.

How To Tie it Together

1) Any class you are going to resolve from the Windsor container that you want to have logging on, add a public property of ILogger:

public class MyClass
{
   private ILogger logger;

   public ILogger Logger
   {
      get
      {
         if (logger == null) logger = NullLogger.Instance;
         return logger;
      }
      set { logger = value; }
   }
}

A key thing here is that we use the NullLogger as the default value - if the facility wasn't put into the container, or if the class was not instantiated via Windsor, then this will mean that logging just doesn't happen, rather than it creating an exception. The NullLogger just swallows the message and carries on. 

2) Setup the Logging Facility in the Windsor container

In the XML configuration:

<?xml version="1.0" encoding="utf-8" ?> 
<configuration>

<facility 
    id="logging"
    type="Castle.Facilities.Logging.LoggingFacility, Castle.Facilities.Logging"
    loggingApi="null|console|diagnostics|web|nlog|log4net|custom"
    customLoggerFactory="type name that implements ILoggerFactory"
    configFile="optional config file location"    />

</configuration>

Or in the code intialization:

   container.AddFacility(
     "logging", 
     new LoggingFacility(LoggerImplementation.Console)); 

3) Use the Logger instance from the class:

   Logger.Debug("Null shipment returned");

That is all there is to it, any object that is resolved via Windsor will now be inspected for ILogger, and if found it will get an instance of the chosen logger. A simple solution, and a perfect example of why an IoC container can simplify your code.

 


Posted 06-18-2008 7:58 PM by Jak Charlton
Filed under: , , ,

[Advertisement]

Comments

Eber Irigoyen wrote re: Logging with Castle Windsor, the Logging Facility and log4net
on 06-18-2008 6:24 PM

get

     {

        if (logger == null) logger = NullLogger.Instance;

        return logger;

     }

-----------

get

     {

        return logger??(logger = NullLogger.Instance);

     }

Trey Thornton wrote re: Logging with Castle Windsor, the Logging Facility and log4net
on 06-19-2008 7:33 AM

Your class is IoC ignorant, but were IoC to change or not be available logging doesn't work.  Are you concerned by that coupling, or is it a safe one?

Jak Charlton wrote re: Logging with Castle Windsor, the Logging Facility and log4net
on 06-19-2008 8:07 AM

@Trey

In the case of logging I don't care - it is an optional dependency. If you create the class via another mechanism, then the factory (for example) can set the ILogger instance.

If you want to make it non optional, then just change the NullLogger.Instance to a "throw" and it becomes mandatory for something to set it if it is to be used - however this would be more relevant where the dependency was something like a secuirty component that has to be provided.

Casey Charlton - Insane World wrote Logging Without Using Castle Windsor and the Logging Facility
on 06-20-2008 3:28 AM

As the discussion on the altdotnet list continued ( some of it around my blog yesterday ), it became

Logging with Ninject wrote Logging with Ninject
on 06-20-2008 1:56 PM

Pingback from  Logging with Ninject

Nauman Leghari's Blog wrote CodeStore - Part 1 of n (TreeSurgeon, Castle Windsor, Log4net)
on 07-16-2008 7:21 PM

What is CodeStore? The idea behind CodeStore is to extract information about .NET assembly and store

DotNetKicks.com wrote Logging with Castle Windsor, the Logging Facility and log4net - Casey
on 08-30-2008 7:42 PM

You've been kicked (a good thing) - Trackback from DotNetKicks.com

Nick wrote re: Logging with Castle Windsor, the Logging Facility and log4net
on 09-24-2008 7:11 AM

I've been using this pattern for some time. There's one issue I have with, though: what happens when you to do logging in the constructor?

Knowledge Base - .NET, C#, SQL Server 2005, PHP and Actionscript 2.0 / 3.0 etc » Blog Archive » » Windsor log4net facility wrote Knowledge Base - .NET, C#, SQL Server 2005, PHP and Actionscript 2.0 / 3.0 etc &raquo; Blog Archive &raquo; &raquo; Windsor log4net facility
on 01-13-2009 9:19 AM

Pingback from  Knowledge Base - .NET, C#, SQL Server 2005, PHP and Actionscript 2.0 / 3.0 etc  &raquo; Blog Archive   &raquo; &raquo; Windsor log4net facility

wowW wrote re: Logging with Castle Windsor, the Logging Facility and log4net
on 07-09-2009 10:16 PM

Wow this is so f reat!!!

Thanks

Uri Goldstein wrote re: Logging with Castle Windsor, the Logging Facility and log4net
on 08-05-2009 9:04 AM

Thanks for the nice introduction to the logging facility.

I'd like to point out that the ILogger you mentioned should be Castle.Core.Logging.ILogger . I just spent a couple of hours because I mistakenly used log4net.Core.ILogger and the logging facility failed to resolve it.

Uri Goldstein wrote re: Logging with Castle Windsor, the Logging Facility and log4net
on 08-05-2009 9:05 AM

Thanks for the nice introduction to the logging facility.

I'd like to point out that the ILogger you mentioned should be Castle.Core.Logging.ILogger . I just spent a couple of hours because I mistakenly used log4net.Core.ILogger and the logging facility failed to resolve it.

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
Umbraco
NServiceBus
RavenDb
Web Sequence Diagrams
Ducksboard<-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)