OpenResty XRay は、プロセスを再起動・再コンパイルすることなく、本番環境で稼働中の Go アプリケーションの panic をトレースします。プロセスをクラッシュさせる panic だけでなく、キャッチされてクラッシュに至らない panic も検出対象です。Go 言語レベルの例外フレームグラフを自動的に解釈し、panic を引き起こした正確なコードパスを特定しつつ、遅延に敏感な本番環境に適した最小限のパフォーマンスオーバーヘッドを実現します。

本チュートリアルでは、XRay の Guided Analysis 機能を使って実際の Go アプリケーションで panic をトレースする手順を、分析の開始から自動生成レポートの確認まで解説します。

XRay の Guided Analysis で Go の Panic をトレースする

XRay コンソールを開いて Go Panic の Guided Analysis を実行する

本文では、実行中の任意の Go アプリケーションにおけるプログラム例外、つまり panic の分析をオンラインで行う方法をご紹介いたします。ここでは、Linux ディストリビューションに標準搭載されている、未修正の Go コンパイラを使用します。

Screenshot

対象となる Go プログラムは、通常の go build コマンドでコンパイルされています。特別な変更や特殊なオプションの追加は必要ありません

Screenshot

OpenResty XRay の Web コンソールに移動します。

Screenshot

現在分析中のマシンが正しいことを確認します。

Screenshot

正しくない場合は、リストから再選択することができます。

Screenshot

「Guided Analysis」ページに移動します。

Screenshot

ここでは、システムが分析可能な様々な種類の問題を確認できます。

Screenshot

「Errors & exceptions」を選択します。

Screenshot

「Next」をクリックします。

Screenshot

先ほどの Go アプリケーションを選択します。

Screenshot

先ほどの対象プロセスを選択します。

Screenshot

アプリケーションのタイプが正しいことを確認します。通常、デフォルト値が正しいです。

Screenshot

ここでの言語レベルは「Go」のみとなっています。

Screenshot

最長分析時間を設定することもできます。ここではデフォルトの 300 秒のままにします。

Screenshot

分析を開始します。

Screenshot

システムは複数回の分析を継続的に実行します。現在、初回の分析を実行中です。

Screenshot

初回の分析が完了し、現在 2 回目のラウンドに入っています。この例では、1 回の分析で十分です。

Screenshot

分析を停止します。

Screenshot

1 つ目の Go Panic をトレースする:gopanic によるゼロ除算エラー

自動生成された分析レポートをご確認しましょう。

Screenshot

これは分析する問題のタイプです。「Errors & exceptions」です。

Screenshot

まず、最初の例外を投げる Go コードのパスを確認しましょう。

Screenshot

Go は最終的に、ランタイムの gopanic 関数を通じて例外を投げます。

Screenshot

このコードパスでは、gopanic 関数はランタイムの panicdivide 関数から呼び出されています。これは、ゼロ除算エラーを意味します。

Screenshot

呼び出しコンテキストによると、calculate 関数がプログラム例外を投げています。この関数はビジネスロジックレベルのコードに属します。

Screenshot

handleHTTPRequest 関数は、Go の Web フレームワークである Gin に属しています。この関数は、受信した HTTP リクエストの処理を担当します。

Screenshot

「More」をクリックしてください。

Screenshot

このホットコードパスは、Go レベルの例外フレームグラフから自動的に導き出されたものです。

Screenshot

以下は、問題に関するより詳細な説明と提案です。上記のプログラム例外がゼロ除算エラーによって引き起こされたことが言及されています。

Screenshot

これは、このエラーを修正できるコード例です。

Screenshot

元のホットコードパスに戻ります。calculate 関数の緑色のボックスにマウスを合わせてください。

Screenshot

ツールチップには、この関数のソースファイル名とフルパスが表示されます。

Screenshot

このソースコードの行番号は 25 です。

Screenshot

このアイコンをクリックして、関数のソースファイルパスをコピーしてください。

Screenshot

vim エディタでソースファイルを開きます。先ほどコピーしたファイルパスを貼り付けてください。お好みのエディタをご使用いただいて構いません。

Screenshot

OpenResty XRayが提案したように、25 行目にジャンプします。

Screenshot

先ほどコードパスで確認したように、このコード行は calculate 関数内部にあります。除数 b がゼロでないかを最初にチェックする必要があります。

Screenshot

2 つ目の Go Panic をトレースする:goPanicIndex による配列インデックスの範囲外アクセス

次に、2 番目のプログラム例外を投げるコードパスを確認しましょう。

Screenshot

これは上記と同様の gopanic 関数です。

Screenshot

goPanicIndex 関数も Go の標準ランタイムに属します。このコードパスでは、このプログラム例外はランタイムの goPanicIndex 関数によってトリガーされています。

Screenshot

おそらく、この weekday.Handler 関数内の配列またはスライスのインデックスでアウトオブバウンドアクセスが発生しています。この Go 関数はビジネスコードレベルに属します。

Screenshot

この関数にマウスを合わせると、ツールチップにそのソースファイルパスが表示されます。

Screenshot

このソースコードの行番号は 17 です。

Screenshot

そのソースファイルパスをコピーしてください。

Screenshot

ターミナルでソースファイルを開き、先ほどコピーしたファイルパスを貼り付けてください。

Screenshot

17 行目にジャンプします。確かに、インデックスを使って配列要素にアクセスしていることがわかります。

Screenshot

この配列変数名は weekDays です。

Screenshot

この関数は、インデックス変数 i の値の範囲を確認していません。

Screenshot

この i 変数は、クライアントリクエストから任意の整数値を取得できる可能性があります。

Screenshot

Guided Analysis 不要:Go Panic の自動レポート

OpenResty XRay はオンラインプロセスを自動的に監視し、分析レポートを生成することもできます。

「Insights」ページに切り替えます。

Screenshot

「Insights」ページで、日次および週次の自動レポートを見つけることができます。そのため、「Guided Analysis」機能を使用する必要はありません。

Screenshot

もちろん、「Guided Analysis」はアプリケーションの開発とデモンストレーションに非常に有用です。

Screenshot

よくある質問

Q: OpenResty XRay はアプリケーションを再起動せずにどうやって Go の Panic を検出するのですか? A: XRay は非侵襲的な動的トレーシングを使用します——内部では Y 言語が Stap+、eBPF+、GDB といった複数のランタイムをターゲットに駆動しており、稼働中の未修正の Go プロセスを外部から観測します。特別なビルドオプションや再コンパイルは不要で、通常の go build で生成したバイナリがそのまま使えます。

Q: アプリケーションがすでにキャッチしてしまった Go の panic も、XRay は検出できますか? A: はい。panic がキャッチされてクラッシュに至らない場合でも、XRay はその背後のコードパスを検出します。ログベースの手法の多くはこれを見逃します。

Q: gopanic とは何で、Go の panic のトレースにどう役立ちますか? A: gopanic は、あらゆる panic が最終的に経由する Go ランタイムの関数です。その呼び出し元——ゼロ除算エラーなら panicdivide、範囲外インデックスなら goPanicIndex——を見れば、業務コードを確認する前に panic の種類がわかります。

Q: Guided Analysis を実行せずに Go の panic レポートを確認するには? A: XRay コンソールの「Insights」ページが日次・週次のレポートを自動生成するため、新しい panic を確認するたびに Guided Analysis を実行する必要はありません。

OpenResty XRay について

OpenResty XRay動的トレーシング製品であり、実行中のアプリケーションを自動的に分析して、パフォーマンスの問題、動作の問題、セキュリティの脆弱性を解決し、実行可能な提案を提供いたします。基盤となる実装において、OpenResty XRay は弊社の Y 言語によって駆動され、Stap+、eBPF+、GDB、ODB など、様々な環境下で複数の異なるランタイムをサポートしております。

著者について

章亦春(Zhang Yichun)は、オープンソースの OpenResty® プロジェクトの創始者であり、OpenResty Inc. の CEO および創業者です。

章亦春(GitHub ID: agentzh)は中国江蘇省生まれで、現在は米国ベイエリアに在住しております。彼は中国における初期のオープンソース技術と文化の提唱者およびリーダーの一人であり、Cloudflare、Yahoo!、Alibaba など、国際的に有名なハイテク企業に勤務した経験があります。「エッジコンピューティング」、「動的トレーシング」、「機械プログラミング」 の先駆者であり、22 年以上のプログラミング経験と 16 年以上のオープンソース経験を持っております。世界中で 4000 万以上のドメイン名を持つユーザーを抱えるオープンソースプロジェクトのリーダーとして、彼は OpenResty® オープンソースプロジェクトをベースに、米国シリコンバレーの中心部にハイテク企業 OpenResty Inc. を設立いたしました。同社の主力製品である OpenResty XRay動的トレーシング技術を利用した非侵襲的な障害分析および排除ツール)と OpenResty Edge(マイクロサービスおよび分散トラフィックに最適化された多機能ゲートウェイソフトウェア)は、世界中の多くの上場企業および大企業から高い評価を得ております。OpenResty 以外にも、章亦春は Linux カーネル、Nginx、LuaJITGDBSystemTapLLVM、Perl など、複数のオープンソースプロジェクトに累計 100 万行以上のコードを寄与し、60 以上のオープンソースソフトウェアライブラリを執筆しております。

翻訳

英語版の原文と日本語訳版(本文)をご用意しております。読者の皆様による他の言語への翻訳版も歓迎いたします。全文翻訳で省略がなければ、採用を検討させていただきます。心より感謝申し上げます!