views:

1145

answers:

4

I am considering using Postsharp framework to ease the burden of application method logging. It basically allows me to adorn methods with logging attribute and at compile time injects the logging code needed into the il. I like this solution as it keeps the noise out of the deign time code environment. Any thoughts, experiences or better alternatives?

+5  A: 

I apply logging with AOP using Castle Windsor DynamicProxies. I was already using Castle for it's IoC container, so using it for AOP was the path of least resistence for me. If you want more info let me know, I'm in the process of tidying the code up for releasing it as a blog post

Edit

Ok, here's the basic Intercepter code, faily basic but it does everything I need. There are two intercepters, one logs everyhing and the other allows you to define method names to allow for more fine grained logging. This solution is faily dependant on Castle Windsor

Abstract Base class

namespace Tools.CastleWindsor.Interceptors
{
using System;
using System.Text;
using Castle.Core.Interceptor;
using Castle.Core.Logging;

public abstract class AbstractLoggingInterceptor : IInterceptor
{
    protected readonly ILoggerFactory logFactory;

    protected AbstractLoggingInterceptor(ILoggerFactory logFactory)
    {
        this.logFactory = logFactory;
    }

    public virtual void Intercept(IInvocation invocation)
    {
        ILogger logger = logFactory.Create(invocation.TargetType);

        try
        {
            StringBuilder sb = null;

            if (logger.IsDebugEnabled)
            {
                sb = new StringBuilder(invocation.TargetType.FullName).AppendFormat(".{0}(", invocation.Method);

                for (int i = 0; i < invocation.Arguments.Length; i++)
                {
                    if (i > 0)
                        sb.Append(", ");

                    sb.Append(invocation.Arguments[i]);
                }

                sb.Append(")");

                logger.Debug(sb.ToString());
            }

            invocation.Proceed();

            if (logger.IsDebugEnabled && invocation.ReturnValue != null)
            {
                logger.Debug("Result of " + sb + " is: " + invocation.ReturnValue);
            }
        }
        catch (Exception e)
        {
            logger.Error(string.Empty, e);
            throw;
        }
    }
}
}

Full Logging Implemnetation

namespace Tools.CastleWindsor.Interceptors
{
using Castle.Core.Logging;

public class LoggingInterceptor : AbstractLoggingInterceptor
{
    public LoggingInterceptor(ILoggerFactory logFactory) : base(logFactory)
    {
    }
}
}

Method logging

namespace Tools.CastleWindsor.Interceptors
{
using Castle.Core.Interceptor;
using Castle.Core.Logging;
using System.Linq;

public class MethodLoggingInterceptor : AbstractLoggingInterceptor
{
    private readonly string[] methodNames;

    public MethodLoggingInterceptor(string[] methodNames, ILoggerFactory logFactory) : base(logFactory)
    {
        this.methodNames = methodNames;
    }

    public override void Intercept(IInvocation invocation)
    {
        if ( methodNames.Contains(invocation.Method.Name) )
            base.Intercept(invocation);
    }
}
}
Chris Canal
Hi Be great if you could give a quick demo - does it work with attributes over methods
redsquare
I'm not keen on using Attribute's for dealing with cross-cutting concersn like logging, validation, etc. I use an external DSL based on Boo for configuring the IoC Container and I assign logging there. This means I can add/remove logging without chaning C#
Chris Canal
cheers for the quick response. Feels like I will get into a world of xml config pain introducing castle and IOC just for logging.
redsquare
Noooo, just say NO! Castle has a Fluent Interface and a DSL. I'm a huge fan of the DSL, it's called Binsor and you can find more info here: http://www.ayende.com/Blog/archive/7268.aspx If you post any Q's on Binsor I'll prolly be able to help you out
Chris Canal
+3  A: 

Have used it to do exactly this. Works great! I'd highly recommend it!

Joel Lucsy
Hi Joel, any tips or tricks or gotcha's to watch out for
redsquare
+6  A: 

+1 on postsharp. Have been using for several things (including some attempts on adding preconditions and postconditions to C# code) and don't know how I'd make it without it...

Luis Abreu
+4  A: 

It depends to an extent on how long you'll be developing and supporting the project for. Sure, IL weaving is a nice technology, but what happens if the IL and/or assembly metadata format changes again (as it did between 1.1 and 2.0) and those changes make the tool incompatible with the new format.

If you depend on the tool then it prevents you from upgrading your technology until the tool supports it. With no guarantees in place about this (or even that development will continue, though it does seem likely) then I'd be very wary about using it on a long term project.

Short term, no problem though.

Greg Beech
Great point Greg. Thanks
redsquare
Since PostSharp is open source, development can/will continue as long as you depend on it.
Alex Lyman
That's true in theory, but unfortunately theory and practice are not always the same. NDoc is open source, and was once thriving, but now lies dormant. Open source projects still need a community around them, and if you depend on it, then you may be left maintaining it. Do you want that burden?
Greg Beech