LoginSignup
25
23

More than 5 years have passed since last update.

rbtrace で ruby のメソッドコールをトレースする

Last updated at Posted at 2016-01-22

アプリケーションを運用していると、実行中のrubyプロセスで何が起こっているのか知りたくなることがあります。

例えば、「なんかbugがあって無限ループに陥ってるっぽいが、どの部分か特定できてない」とか「時間が掛かってるメソッドがあるはずなんだけど、どこか分からない」とか。

rbtrace はそのような状況で使える道具の一つかもしれません。

rbtrace

rbtrace shows you method calls happening inside another ruby process in real time.

rbtrace works on ruby 1.8 through 2.2 (and beyond), running on linux or mac osx.

rbtrace is designed to have minimal overhead, and should be safe to run in production.

Github からそのまま引用ですが、ruby プロセス中のメソッドコールを表示するツールです。

使ってみた

使い方も README の通りなんですが、Rails であれば Gemfile に

gem 'rbtrace'

と書いておけば ok です。

--firehose オプション

firehose は 全てのメソッドコールを出力するオプションで、下記例は unicorn の worker プロセス(リクエストを待っている状態)にアタッチしたものです。

$ bundle exec rbtrace --pid 123456 --firehose

** attached to process 123456
Thread.current <0.000012>
Thread#[] <0.000009>
Kernel#sleep <10.000179>
Thread.current <0.000011>
Thread#[] <0.000010>
Kernel#sleep <1.467024>
Time.now
  Time#initialize
    Fixnum#+ <0.000009>
  Time#initialize <0.000043>
Time.now <0.000071>

Time#to_i
  Fixnum#divmod <0.000012>
Time#to_i <0.000085>

Unicorn::Worker#tick=
  Raindrops#[]= <0.000011>
Unicorn::Worker#tick= <0.000139>

--methods オプション

実際に worker プロセスがリクエストを受けると、すごい勢いで出力されるので適宜絞ってあげる必要があります。
例えば、SQL の実行だけに絞りたい時は --methods オプションを使うとよいです。

$ bundle exec rbtrace --pid 123456 -m 'ActiveRecord::ConnectionAdapters::Mysql2Adapter#execute(sql)'

*** attached to process 123456
ActiveRecord::ConnectionAdapters::Mysql2Adapter#execute(sql="SELECT  `users`.* FROM `users` WHERE `users`.`id` = 123 LIMIT 1") <0.001091>
ActiveRecord::ConnectionAdapters::Mysql2Adapter#execute(sql="SHOW FULL FIELDS FROM `users`") <0.012188>
ActiveRecord::ConnectionAdapters::Mysql2Adapter#execute(sql="SHOW TABLES ") <0.000827>
ActiveRecord::ConnectionAdapters::Mysql2Adapter#execute(sql="SELECT `resources`.* FROM `resources` WHERE `resources`.`id` = 456 <0.001423>

※ mysql2 アダプタの例なので、利用しているアダプタに応じて適宜読み替えてください。

slow オプション

指定の時間(ミリセカンド単位)を要したメソッドコールに絞り込むことが可能です。以下は 100ms の例。

$ bundle exec rbtrace --pid 123456 --slow=100

ActiveRecord::ConnectionAdapters::Mysql2Adapter#execute(sql="SELECT  `users`.* FROM `users` WHERE `users`.`id` = 123 LIMIT 1") <0.001091>
ActiveRecord::ConnectionAdapters::Mysql2Adapter#execute(sql="SHOW FULL FIELDS FROM `users`") <0.012188>

ただし、トレースに表示される時間(例:<0.012188> )は秒単位であることに注意。

--eval オプション

eval もできます。

$ bundle exec rbtrace --pid 123456 -e 'p Rails.env'

*** attached to process 123456
>> p Rails.env
=> "sandbox"

Production で使って ok ?

rbtrace is designed to have minimal overhead, and should be safe to run in production.

README に書かれている通り、production での利用が想定されてます。
Author の Aman Gupta 氏 は GitHub, Inc 勤務で、Rubyコミッタ でもあるので、safe to run in production は額面通りに受け取って大丈夫でしょう。

Aman Gupta, GitHubでのRubyの使われ方と高速化のテクニックを紹介 ~ RubyKaigi 2014 基調講演 3日目

As a newcomer to a large codebase, I often found myself wondering what was happening inside various ruby processes running in production.
Out of this curiosity was born rbtrace, one of first tools I wrote at github that we continue to use to this day. If you haven’t used retrace I highly highly recommend checking it out. It has a number of features that allow live introspection of running ruby processes.

引用元: Ruby 2.1 in Production, Ruby Kaigi 2014 発表資料

まとめ

素晴らしいツールなのに、意外と日本語記事がないので書いてみました。

25
23
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
25
23