Tech Racho エンジニアの「?」を「!」に。
  • Ruby / Rails関連

ruby/debugのChrome Devtools連携をRailsで動かす

morimorihogeです。涼しくなってようやく生きていける感じになって何よりです。

今回はruby/debugに新しく導入されたChrome Devtools連携リモートデバッグ機能を動かしてみたので、そちらを紹介してみようと思います。

ことの起こり

新しいRuby標準デバッガとして開発が進んでいるruby/debugですが、先日こんなTweetがありました。

なにこれすごくない!?と思い、今回の記事を書くに至りました。

動きとしては、デバッガのコンソールで open chrome コマンドを実行するとURLが表示され、そのURLにChromeでアクセスすると、Chrome搭載のChrome Devtools(JavaScriptデバッグなどで使えるやつ)を使ってRubyのデバッガにアタッチできる、というもののようです。発想がすごい。

今回はこれを普段使っているRailsアプリで実際に使ってみよう、という話になります。

まずは動作確認

まずは最もシンプルな形で動かしてみましょう。今回の動作環境はWindows 10 WSL2上のUbuntu環境ですが、macOSでも同じことができるはずです。

以下のような sample.rb を用意します。 debugger がデバッガ呼び出しに当たります。

require 'debug'

test_var = 'test'

debugger

そうしたら、debug gemをインストールして実行します(ruby 3.0.2p107で動作確認していますが、2.7等でも動作します)。

$ gem install debug
$ ruby sample.rb

すると、下図のように debugger 部分でコードが停止し、rdbgコンソールが開きます。

ここで open chrome 命令を実行すると、devtools:// で始まるURLが表示されます。

このURLにアクセスするとChromeが開発者コンソールの画面を開きますので「Sources」タブを開いてみましょう。

はい。いい感じにデバッガが開きました。右上の方にstep over他一般的なデバッガ用の操作ボタンがあるので、ソースを見ながらこの辺りを見ていくことができます。
また「Console」タブに移動すると、デバッガが停止している状態のコンテキストで任意のRubyコードを実行できます。

ChromeのデバッグコンソールでRubyのコードを動かせる、というところでなんか楽しくなってきましたね 🎉

Railsで動かす: テストコード編

さて、うまいこと動いたので次は手持ちのRailsのコードでやってみましょう。
※今回普通に手元の業務で使ってるコードでやったのでモザイク多めですが、それだけ普通のRailsプロジェクトでももう使えると思っていただければ幸いです

まずはbyebugの代わりにdebug gemに入れ替えるため、Gemfileを編集します。Bye-bye buybug!今までありがとう!

group :development, :test do
  # gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
  gem 'debug'

あとは普通にbundleしましょう。

ローカルでrspecなどのテストコードを動かしている場合、もうあとはデバッガ起動したい部分にdebuggerを埋め込み、open chromeするだけで対応できます。
一方で、使っている環境がDockerを使っている場合、追加の設定が必要になります。

open chrome コマンドはデフォルト設定では127.0.0.1、ポートは任意でLISTENするようになっていますが、これだとローカルのブラウザ環境からアクセスするのにはうまくいきません。
docker-composeコマンドでRailsコンテナに入ってrspecなどの実行を行っている場合には、以下のようなコマンドでコンテナを立ち上げましょう。
これでコンテナ外からruby/debugの開いたポートにアクセスすることができるようになります。

docker-compose run --rm -p '23456:23456' \
  -e RUBY_DEBUG_HOST=0.0.0.0 \
  -e RUBY_DEBUG_PORT=23456 \
  rails bash

この状態でdebuggerを含むテストを実行し、開いたrdbgコンソールからopen chromeすると、以下のように指定したホスト:ポートでLISTENしてくれます。

あとは先ほどと同じようにアクセスしますが、Windows/WSL2環境ではChromeで開く際にURL末尾のホストIPを0.0.0.0から127.0.0.1にする必要がありました
これは、アプリケーションコンテナからは 0.0.0.0:23456 でLISTENしていますが、ホストからはコンテナに繋ぐ必要があるためかなと思うのですが、docker psの結果では 0.0.0.0:23456->23456/tcp で開いているようにもなっており、WSL2のポート開放周りの問題というか仕様?かもしれません。

というわけで、attachできました。sample.rbの場合と同様に操作可能です。

step intoでライブラリコードに潜っていくことももちろんできます。

Consoleタブでputsするとちゃんとrpsec側の実行中コンソールに出ます。

Railsで動かす:Railsサーバー編

さて、今度は実際に動かしているRailsサーバー中でデバッガをアタッチしてみます。

まず、pumaを使っている場合(恐らく現代の大多数のRails)、少なくとも現行のdebugバージョン(1.3.1)だとmultiple worker環境でうまく動かない(後述)ようなので、puma.rbを修正する、または環境変数WEB_CONCURRENCYを1に指定します。

# config/puma.rb の該当行をよしなに編集する
# Worker数を1プロセスに指定(threadsは複数でも動作するようだ)
workers 1
# preload_app!が有効になっている場合、コメントアウトする
#preload_app!

この状態でPumaを起動するとPuma起動時に「in single mode...」と出ますので、こうなっていればOKです。

あとはこれまで通りにやればOKです。docker-composeからRailsサーバーを起動するようにしている場合は以下のように環境変数、公開ポートを指定してやれば良いでしょう。

services:
  rails:
    environment:
      # use ruby/debug
      - RUBY_DEBUG_HOST=0.0.0.0
      - RUBY_DEBUG_PORT=23456
    ports:
      - '23456:23456'

docker-compose up で起動したら、docker attach #{コンテナ名} とすることでRailsサーバーのプロセスに接続できます。
この状態でdebuggerを含む処理が実行されるとその時点でデバッグコンソールが立ち上がります。

※docker attachしたコンソールから抜けたい場合はCtrl-CではなくCtrl-P Ctrl-Qで抜けましょう。Ctrl-Cだとプロセスが終了してしまいます。このあたりはDockerの使い方に関する部分なので、よく分からなければDockerのドキュメントなどを参照して下さい。

Railsサーバーあれこれ
今回pumaで最初うまくいかなくて色々試しましたが、Webrick(rails s -u 'webrick')は問題なし、pumaはmultiple workerの時のみChrome Devtoolでアタッチした直後に接続が切れてしまいうまくいきませんでした。
ReaderThreadError等が出ているので、pumaがcluster modeの場合の何かが問題なのかもしれません。

まとめ

debug gemは今まさに活発に開発が進行中で、どんどん新機能や対応が進んでいます。今回のChrome Devtools連携機能についてもOpen Chrome automaticallyというPRが上がっていたりなどまだまだ改善が進みそうな気配です。

お使いのRailsプロジェクトでもサクッと気軽に使い始められるdebug gem、皆さまもぜひ試してみましょう 😊


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。