Tracing controller filters in New Relic
Yet another New Relic goodie today.
One thing I was kind of surprised that New Relic didn’t already have instrumentation around out of the box was controller filters. We had noticed some occasional gaps after the main processing of an action, where all the templates would be rendered, but the execution still went on for a few hundred milliseconds (or sometimes more). Finally, it dawned that it is probably one of the after_filters.
So we aded tracing around filter execution, and lo and behold, we had one that from time to time would misbehave and execute slow.
To instrument the filters, the simplest way seemed to be by tacking on to the ‘call’ method of each filter type.
::ActionController::Filters::BeforeFilter.class_eval do
add_method_tracer :call, 'Custom/BeforeFilter/#{method.to_s}'
end
::ActionController::Filters::AfterFilter.class_eval do
add_method_tracer :call, 'Custom/AfterFilter/#{method.to_s}'
end
::ActionController::Filters::AroundFilter.class_eval do
add_method_tracer :call, 'Custom/AroundFilter/#{method.to_s}'
end
And one more goodie while I’m looking at my list of New Relic tracers… ActionMailer. Have seen this time and time again, that sending email synchronously with the HTTP request can drastically slow down performance. SMTP server can be slow, can be mailing a number of recipients, submission fails, etc. For us, most email delivery is asynchronous in the background, but one or two are triggered in line.
To trace ActionMailer delivery:
::ActionMailer::Base.class_eval do add_method_tracer :deliver!, 'Custom/ActionMailer/deliver!' end
Will maybe sometime look at email processing more, but email templates are often far simpler and their action methods do less loading.
Is there some code omitted here? I keep getting NoMethodError for the #{method.to_s} calls … I don’t see where ‘method’ is defined anywhere.
jD
18 Jun 10 at 12:43pm
thanks for the write-up
jD
18 Jun 10 at 12:43pm
JD, the way the add_method_tracer works is that the string you pass in is evaluated at run time, so if you include #{method.to_s}, it will include the method variable that is passed into call.
Which version of Rails are you using? It is possible that the method was rename or something changed with the filters. We are on Rails 2.2.2 and have that snippet working in production.
krobertson
18 Jun 10 at 9:30pm
hi Ken,
we use REE 1.8.7 and we’ve tried this on rails 2.3.5 through 2.3.9 vendor using rpm 2.10.6 through 2.12.3 with no success. something must’ve changed… bummer, we could really use this right now!
jD
18 Jun 10 at 11:51pm
ugh, nevermind. our quotes got transposed to double quotes and the initializer was trying to interpolate the method.to_s call. single quotes fixed it. thanks for this!
jD
19 Jun 10 at 2:28am
Ahh yes, the single quotes are very important so that New Relic interprets the method.to_s, and not your initializer.
krobertson
21 Jun 10 at 10:41am