Railsのレスポンス遅延を通知する
この記事はRuby on Rails Advent Calendar 2015の13日目です。
Active Support Instrumentationとは
ざっくり言うと「Railsアプリケーションやフレームワーク内のアクションを計測するためのAPI」です。
この仕組みを使うと、コントローラのアクション実行やSQL実行などをフックすることができます。
今回はこのInstrumentationの仕組みを使ってレスポンス遅延の監視を行います。
アクションを監視する
アクションを監視するには提供されているフックをsubscribe
します。
アクションのフックはprocess_action.action_controller
という名前なので
# config/initializers/subscribe_process_action_action_controller.rb
ActiveSupport::Notifications.subscribe "process_action.action_controller" do |*args|
end
という感じのファイルを用意するとアクションを監視できます。
レスポンス遅延の場合に通知する
subscribeした時のブロック引数にレスポンス情報が入っているので、レスポンス時間が長過ぎる場合に通知をしてみます。
ブロック引数はそのままActiveSupport::Notifications::Event.new
の引数になるので、まずはActiveSupport::Notifications::Event
オブジェクトを作成します。
ActiveSupport::Notifications.subscribe "process_action.action_controller" do |*args|
event = ActiveSupport::Notifications::Event.new(*args)
end
event
オブジェクトを取得したら、event.duration
で取得できるレスポンス時間(単位はミリ秒)が10秒以上かかっているか判定します。
ActiveSupport::Notifications.subscribe "process_action.action_controller" do |*args|
event = ActiveSupport::Notifications::Event.new(*args)
if event.duration > 10_000
## ここで通知処理
end
end
メール/チャットで通知
あとは通知処理をすればOKです。
ただし、フック処理が終わるまでアクションが終了しないので、通知処理で邪魔しないように非同期で通知するようにしましょう。
例えばResque
を使っている場合は
ActiveSupport::Notifications.subscribe "process_action.action_controller" do |*args|
event = ActiveSupport::Notifications::Event.new(*args)
if event.duration > 10_000
Resque.enqueue(
SlowResponseNotifyJob,
time: event.time,
duration: "#{(event.duration / 1000).round(3)}sec"}.merge(event.payload)
)
end
end
という感じにすると良いかと思います。
あとはSlowResponseNotifyJob
クラスを実装してメールなりSlackなりHipchatなりに通知するようにしましょう。
おまけ:スロークエリの通知
Instrumentation機能を使うとSQL実行遅延の通知もできます。
SQL実行のhook名はsql.active_record
なので
# config/initializer/subscribe_sql_active_record.rb
ActiveSupport::Notifications.subscribe "sql.active_record" do |*args|
event = ActiveSupport::Notifications::Event.new(*args)
if event.duration > 10_000
Resque.enqueue(
SlowQueryNotifyJob,
time: event.time,
duration: "#{(event.duration / 1000).round(3)}sec"}.merge(event.payload)
)
end
end
という感じにすればOKです。
他にも色々なフックがあるのでActive Support Intrumentationのドキュメントを参考に、必要な監視を設定してみてください。