go to content go to search box go to global site navigation

Tech Blog

Monitoring our applications - Ruby - Methods

Fozzie was good, and we were happy with progress. We were monitoring applications in real time, the code was looking ok, and the stats looked good on the big screens. On reflection of the code though, we felt there was room for improvement on the way in which we were referencing Fozzie for the timing of code.

We saw a constant pattern of:

def foo
 S.time_to_do ["class", "foo"] do
  # bla bla bla

We felt this would be a massive improvement on this scenario:

def foo
 # bla bla bla


In order to achieve this we needed to: - Dynamically detect methods being added to classes - Alias the method to allow us to automatically wrap our Fozzie code around the original

Method Added and Singleton Method Added

Ruby supplies a callback for instance and class method declarations; methodadded and singletonmethod_added.

Because we wanted/needed to be choosy about which methods to measure, we wanted a flag to indicate when a method should be processed. To achieve this we implemented our _monitor dsl method, as follows:

def _monitor
 @_monitor_method_flag = true

And reference the @_monitor_method_flag class instance method in our method_added and singleton_method_added methods.

Method Aliasing

Once we had the name of the method we wanted to monitor, and we knew it has been created on the Class, we wanted to alias it.

Aliasing enables Fozzie to wrap it's timing logic around the original method.Ruby facets provides a nice alias_method_chain that we can use to achieve this.

To alias an instance method we can simply call:

self.alias_method_chain 'foo', 'monitor'

To alias a class methods we need to be slightly smarter:

self.singleton_class.class_eval { alias_method_chain 'foo', 'monitor' }

The aliasmethodchain gives us

alias_method :foo_without_monitor, :foo
alias_method :foo, :foo_with_monitor

allowing us to access the original method.

Putting It All Together

Once these elements had been worked out it was all down to tying the pieces together and constructing a neat implementation.

To enable the _monitor method to be referenced in any class, we need to include it into the Ruby Module class, which is required within the main Fozzie class.

class Module
 def _monitor
  # Our code...

This extension includes Fozzie::Sniff into the class, and this then extends the class with the Fozzie::Sniff::ClassMethods to tie together all our nitty-gritty aliasing, etc.