StackDriverDebuggerで本番環境のソースコードをデバッグ

こんにちは! grasysの注目若手エンジニア川﨑です。(grasys内では若手ポジション)

今回僕はGCPが無料で提供しているStackDriverDebuggerを使用して、 本番環境で実際に動いているソースコードのデバッグを 実行する手順を書きたいと思ってます。

Stackdriver Debuggerとは

公式サイトでは下記のように書いてあります。

Google Cloud Platform の機能である Stackdriver Debugger を使うと、コードの任意の位置でのアプリケーションの状態を調べることができます。その際、ログ ステートメントを使用したり、アプリケーションを停止したりする必要はなく、アプリケーションの処理速度が低下することもありません。デバッグ中に、お客様のユーザーに影響を与えることはありません。本番環境でのデバッガにより、ローカル変数とコールスタックをキャプチャして、ソースコードの特定の行の位置に再度リンクすることができます。また、これを使って、アプリケーションの本番状態を分析し、本番環境でのコードの動作を理解することもできます。

要は本番環境で動いているソースに対してブレイクポイント貼って変数の中身や動作を確認できるという事みたいです。 その際にパフォーマンスの低下やアプリケーションの停止が起きないみたいです。 まだbetaとなっていますがこれから楽しみな機能ですね。

要件

早速試してみようと思いますが、まず大事なのが対応している言語が下記となっている事です。

App Engine フレキシブル環境で実行されているものを含む、App Engine で実行されている Java アプリケーション。

App Engine 上で実行されている Python アプリケーション。

Google Compute Engine インスタンス上で実行されている、Java、Python、Go のアプリケーション。

概要のTopではこのようにかかれてますが、AppEngineはNode.jsも対応しているみたいです。

また、ComputeEngineは64 ビット Debian Linux イメージとなっているのでご注意ください。

今回はPythonで簡単なWebアプリケーションを作成してそのソースコードをデバッグしてみたいと思ってます。

サーバー構築

まず GCEのインスタンスを作成します。 要件が64 ビット Debian Linux イメージとなっているのでそれに沿ったインスタンスを作成します。 ID と API へのアクセスは全てを選択するようにと記載があったので選択します。

さてサーバーに接続したらStackdriver Debugger エージェントをインストールします。

まずpipがインストールされていなかったのでインストールします。

 $sudo apt-get install python-pip

その後

 $pip install google-python-cloud-debugger

でインストール完了です。

今回はwebのフレームワークとしてFlaskを使用してすごく簡単なPtyhonアプリケーションを作成しBitBucketにレポジトリを作成します。

Flaskのインストールや実行はFlaskに入門を参考に構築しました。

ソースの中身はこんな感じです

# coding: utf-8

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello Grasys!'

@app.route('/for')
def hello_world_ja():
    n = 1000
    nay = [i for i in xrange(n)]
    for i in xrange(n):
        nay.pop(0)
    return 'end'

@app.route('/error')
def errortest():
    a = 1 + 1
    b = 1 / 0
    return 'end'


if __name__ == '__main__':
   app.run()

Flaskでアプリケーションを動かせることができたらソース コンテキスト ファイルの生成をしましょう。

これを行うことでビルドするアプリケーションの情報をGCPに連携します。 下記コマンドを打てと書いてあります。

$gcloud beta debug source gen-repo-info-file \
  --output-directory=[MODULE_PACKAGE_DIR]

今回私は「/usr/local/etc/stackdriver」でアプリケーションを動かしているので

$gcloud beta debug source gen-repo-info-file \
  --output-directory=/usr/local/etc/stackdriver

と打ちます。 上記コマンドですが、日本語訳がまだない公式ページでより詳しく書かれています。しかもbetaの文字が消えています。 ちなみにこのコマンドはバージョンを変更するたびに打つ必要があります。

ここまで準備したらStackdriverDebuggerエージェントを動かしましょう。

StackdriverDebuggerを動かすにはソースに手を加える方法と実行方法を変えるのと2通りのあるみたいです。

今回は実行方法を変える方法でいこうと思います。

$python -m googleclouddebugger \
  --version=[VERSION] \
  --module=[MODULE] \
  -- myapp.py

を打てとサイトには書いてあるので

$python -m googleclouddebugger \
  --version=v3 \
  --module=testapp \
  -- stackdriver.py

と打ちます。 [MODULE]と[VERSION]は 後ほどのデバッグ画面で[MODULE]-[VERSION]と表示されます。

下記出力からDebuggeeが立ち上がったのがわかります。

I0602 03:54:08.623488  4601 gcp_hub_client.py:335] Debuggee registered successfully, ID: gcp:ハッシュ値:ハッシュ値

デバッグ画面

ブラウザでデバッグ画面を開きましょう。

アプリケーションとソースのコミットが一致していることを確認します。

では早速今回のアプリケーションにスナップショットを追加して実行時の変数などを行きましょう。

スナップショットには条件や式を入れることが可能です。

今回は先ほどのソースに条件を入れて何個かスナップショットを追加しました。

追加した状態で実行環境をのURLを叩いて実行します。 するとスナップショットが取得されます。

右側に変数やコールスタックが表示されます。

おお!実行時の状態が確認できる!

見えるぞ!私にも変数が見える!!

ちなみにスナップショットの上から二つ目のエラーですが、i > 900の条件を指定したのですが、 パフォーマンスに影響が出る可能生があるのでスナップショットを取りませんとエラーが出ています。気が利きますね。

WindowsでもVisualStudioでWebAppが提供している機能やIISのプロセスにアタッチする事で同様の事が出来ますが、 スナップショットでメンバーと共有できるのは非常に楽だなと思いました。

本番環境でのみ起きる謎バグなどの解決に大いに役立つと思います。 ソースコードの連携などを自動でやってくれるCLOUD SOURCE REPOSITORIESで作成したレポジトリならより簡単にできそうですね。

ちょっと思ったのが、ソースのバージョンを変更すると前バージョンのスナップショットが消えてしまいデバッグのした情報も消えます。 ソースコードの前のバージョンの状態を取って見比べたいケースなどがもしかしたらあるかなと思いましたので、これからバージョン毎の状態が取っておけたらいいのにと思いました。

まだbetaとの事ですが正式リリースされるのが楽しみな機能ですね。