Wednesday, August 17, 2011

Tracing aspect for a Rails application

Aspects are modules for crosscutting concerns. Typical crosscutting concerns are: persistence, tracing changes (history), permissions and logging.

Aspect Oriented Programming is not a popular topic in the Ruby community. Partially, it's because Ruby gives us some AOP constructs out-of-the-box (open classes) but also due to some built-in mechanisms in Rails - like filters and callbacks which serve as the dynamic part of AOP.

I think that there are scenarios in which traditional AOP can be very useful. Today, I'm going to show you how to implement logging of chosen method calls, without touching the methods itself.

Aquarium seems to be the best AOP framework with Ruby.

Installation

#the first part is only needed if you want to use ruby 1.9
#otherwise just put gem "aquarium" into the Gemfile and run "bundle install"

cd vendor/gems
git clone https://github.com/deanwampler/Aquarium.git
cd Aquarium
git checkout 1.9.1-port

# edit Gemfile and add:
gem 'aquarium', "0.0.0", :path => 'vendor/gems/Aquarium/aquarium'
bundle install

Creating an aspect


Create config/initializers/tracing_aspect.rb and paste:
require 'aquarium'
include Aquarium::Aspects
Aspect.new :around, :calls_to => :all_methods, 
    :for_types => [User],
    :method_options => :exclude_ancestor_methods do |jp, obj, *args|
  begin
    names = "#{jp.target_type.name}##{jp.method_name}"
    p "Entering: #{names}: args = #{args.inspect}"
    jp.proceed
  ensure
    p "Leaving:  #{names}: args = #{args.inspect}"
  end 
end

If you now run the tests or just use your app, you should see all the method calls on User objects being logged to the output.

I hope it works fine for you, let me know in case of problems.

4 comments:

Tomasz Nazar said...

and "jp, obj" are..?

jp = join_point

Andrzej Krzywda said...

obj is the target object on which the methods are called.

Piotr Szotkowski said...

Have you tried RCapture?

Last time I needed AOP (for logging), I ended up choosing RCapture over Aquarium and it was fairly easy to use: https://github.com/chastell/art-decomp/blob/master/lib/art-decomp/logging.rb#L39

Andrzej Krzywda said...

@Piotr

I didn't know about RCapture, thanks!