はじめに
いったんメモとして書きなぐる内容、あんまり人に見せることを想定していない
計装(instrumenting) とは
システムやアプリケーションに計測機構を実装し観測を実現すること
o11yを実現するうえで、ログ・メトリクス・トレースといった情報をアプリ等からとれるようにすることだと理解した。
自動計装と手動計装
こういったテレメトリーを取得できるような状態にするには、手動でアプリのソースコードに変更を加え、テレメトリーを送信できる状態にする(=手動計装)か、アプリ側には修正を与えない形で送信できる状態にする(自動計装)がある。
もちろん、自動でやってくれるのがうれしいのは間違いない。
ただ、ISUCON上での問題は、人気のあるGo言語に対しては自動計装のツールはまだ実験的な形でしか存在しないらしい。
かつ、webアプリフレームワークとしてはjinには対応しているものの、ISUCON13の参考実装で使われているechoは対応してなさそう?(下記スライドで言われているオリジナルソースが見当たらない…)
従い、基本的にはGoの場合には手動計装を行うことになりそう。
なお、Pythonの場合は自動計装できて、
opentelemetry-instument python app.py
で起動するだけでいいらしい、すげー。ただ、どこまで拾ってくれるかは動かさないと何とも言えないなと思った。
個人的スコープ
ログ・メトリクス・トレースの3つのうち、ログについてはalp,slpといったISUCONと相性のいいログ解析ツールの存在や、メトリクスについては個人的にnode-exporter,process-exporter+prometheusである程度何とかなるので、残りのトレースに絞る。
トレース
トレースの利点としては、あるHTTPリクエストの中で、ある処理が行われている時間を測定することができ、一つのリクエストにおいてどこに時間がかかったのかを詳細に閲覧できる。この点は、pprofなどの統計情報としてつぶれてしまった場合に見ることができない、特定のリクエストのみ遅いなどの分析には有用なはず。(ただし、マクロに高速化できなければスコアは上がらない気がするので、まずはpprofの方がいいとは思う)
この中で、どこからどこまでどれだけ時間がかかったを示すのがスパンであり、どれだけ多くのスパンを仕込めるかでわかりやすさが変わる。
Go言語の手動計装について
自分で手を動かした感じおおよそ2つの手段があり、出入り口たるウェブエンドポイントやSQLへのアクセスを対象にに仕込む方法と、完全に手動で仕込む方法がある。
トレースに関しては、ISUCON13の4位の方々がjaeger+opentelemetryを使って実現していてこれに倣うことにする。リポジトリも公開してくださっているのでそのあたりから勉強させていただく。
このあたり眺めつつ、自分でもprivate-isuで同様のことができるかトライした。(コードの公開はそのうち…)
ウェブフレームワークへの導入
フレームワークに仕込む方法としては、各種フレームワークのミドルウェアとして仕込む形になる。まず難易度が低いのはウェブフレームワークに仕込むのがよさそう。確認した感じ、echo(isucon13)、chi(private-isu, isucon本の題材)あたりにはありそうだった。変更もすべてのエンドポイントに仕込む必要はなく、(トレースプロバイダーの実装を除けば)修正は少なかった。
ただこれだと各エンドポイントへのリクエスト全体のスパンを見ることしかできず、ちょっと情報に乏しい。
SQLアクセスへの導入
こちらについても、基本的にはDBの初期化時にテレメトリーを送信するようにすればよい。ただし、各クエリの実行時には、「どのHTTPリクエストで発生したスパンなのか?」を判断するために、http contextの情報が必要になる。元の実装でこのcontextをとりまわすようになっていればほとんど修正は不要になる。一方でそういう実装になっていなければ自分で行う必要がある。
ISUCON13のgo言語の参考実装には仕込まれており、必要な修正は少なかった。一方、private-isuのデフォルト実装ではhttp contextをとりまわす実装になっておらず、endpoint冒頭でのcontextの取得から、各関数へのcontextの引き回しのための実装変更はそれなりに修正が求められた。(とは言ってもほぼ機械的なので大したことはないが)
関数への導入
これについては各関数の冒頭にコピペで数行追加する。一応、スパンである以上、開始と終了をするタイミングでコードを記述必要があるが、deferでまとめて書けるので楽だった。
手動計装導入例
いったんできることの確認だけなので中途半端だが下記の感じ。DBの方はどんなクエリだったかも確認できる。makePostsの方は先の関数の導入を行う感じで実装している。
おわりに
コンテスト中にこれをやるかどうかは、特にコンテキストの取り回しがされているかどうかで大変さ・優先順位が変わるので実装みて判断かなあと思った。分析ツールとしては有用だと思うのでうまく使いこなしたい。