Everybody’s favorite example for AOP is logging. There are a few reasons for that. First, it’s a great problem to solve with AOP and chances are it’s something everyone can relate to. Well, what happens when you actually use it for logging?
I can tell you what happened to me last week. Things were going great until it came time to port our credit card charging program from the stone age to .NET. It occurred to me that our fancy AOP logging would unknowingly log decrypted credit cards!
An obvious solution was to do a regex on log messages and mask credit card numbers – and that’s pretty much what we did, but I didn’t want to perform a regex on every message when I knew only a tiny percentage would contain sensitive data. The solution of course, was to fight fire with fire and use more AOP.
This way I could specifically mark an interface that I knew would accept sensitive data and apply an appropriate filter to it. The log filtering is implemented as a decorator to a log4net-like ILogger interface.
1234567891011121314151617181920212223
[TestFixture]publicclassLoggerWithFilterFixture{ [Test]publicvoidShould_apply_filter_to_message(){varlogger=newInterceptingLogger();varloggerWithFilter=newLoggerWithFilter(logger,newAppendBangToMessage());loggerWithFilter.Debug("This is a message");Assert.AreEqual("This is a message!",logger.LastMessage);}}publicclassAppendBangToMessage:ILogFilter{publicstringFilter(stringmessage){returnmessage+"!";}}
The decorator is then applied in the call handler by looking for custom attributes of type LogFilterAttribute like this: