はじめに
まだ beta 版のようですが、気になってた opentelemetry-ruby を使って Rails アプリケーションへのリクエストをトレースし、Jaeger で可視化するところまでやってみようと思います。
Opentelemetry とは
OpenCensus と OpenTracing の2つのプロジェクトが統合されたもので、Tracing だけでなく Metrics、Logs といった Observavility 全体を実現するための標準化された API およびライブラリが提供されています。今回は、Opentelemetry のなかの Tracing を使ってみようと思います。
公式ページの絵がかわいくてほっこりしますよね。
なお、Opentelemetry のアーキテクチャについては、New Relic 社の『OpenTelemetry: 計装器を長く使い続けるために』が図示されていてわかりやすかったです。
環境
Docker for Mac
Ruby on Rails 6.0.3.4
MySQL 5.7
Jaeger 1.20
Jaeger を起動する
Jaeger の Getting Started の All in One を使用します。
それぞれのポート役割については こちら に記載されています。
docker run --rm --name jaeger \
-p 5775:5775/udp \
-p 6831:6831/udp \
-p 6832:6832/udp \
-p 5778:5778 \
-p 16686:16686 \
-p 14268:14268 \
-p 14250:14250 \
-p 9411:9411 \
jaegertracing/all-in-one:1.20
これで Jaeger の GUI に下記の URL からアクセスできるようになりました。
Rails アプリ
Rails アプリケーションは、 Rails チュートリアルの Toy アプリケーションで作ったものを使用します。
今回は簡単にユーザの一覧と詳細ページにアクセスし、トレースできるか確認してみようと思います。
opentelemetry-ruby の使い方
opentelemetry-ruby に関連する Gem は全てこのリポジトリにあるようです。
そして、Jaeger にトレースデータを Export するには、opentelemetry-ruby リポジトリ内にある opentelemetry-exporter-jaeger を Gem インストールすれば良さそうです。
また opentelemetry-ruby リポジトリ内に instrumentation ディレクトリがあり、Rails や mysql2、faraday など様々な Instrumentation 機能が用意されてるようです。
今回は、Rails と mysql2 の Instrumentation 機能を使ってみようと思います。
これを使うことで、Controller・Action の処理時間や実行されたクエリなどがトレースできそうです。
Rails の Instrumentation は opentelemetry-instrumentation-rails、mysql2 の Instrumentation は opentelemetry-instrumentation-mysql2 を Gem インストールすれば良さそうですが、opentelemetry-instrumentation-rails はまだ rubygems.org に公開されていないようでした。
なので、opentelemetry-instrumentation-rails は opentelemetry-ruby を git clone して、Gemfile で path 指定をして使ってみようと思います。
(執筆時点(11/27)では公開されていませんでしたが、現在は公開されているようです。)
実装
opentelemetry-ruby を git clone してきます。
$ git clone git@github.com:open-telemetry/opentelemetry-ruby.git
次に、Rails アプリ の Gemfile に下記を追加します。
gem 'opentelemetry-sdk'
gem 'opentelemetry-exporter-jaeger'
gem 'opentelemetry-instrumentation-mysql2'
gem 'opentelemetry-instrumentation-rails', path: '/path/to/opentelemetry-ruby/instrumentation'
opentelemetry-instrumentation-rails だけ clone してきた path を指定します。
また Docker を使う場合は、clone してきた opentelemetry-ruby を Volume マウントした先の path を指定します。
ここで、path を/path/to/opentelemetry-ruby/instrumentation/rails
ではなく、/path/to/opentelemetry-ruby/instrumentation
とすることで、依存関係にある opentelemetry-instrumentation-rack も clone してきた opentelemetry-ruby のinstrumentation/rack
から取得してきてくれます。
次に、config/appliction.rb に下記を追加します。
require 'opentelemetry/sdk'
require 'opentelemetry/exporter/jaeger'
OpenTelemetry::SDK.configure do |c|
c.use 'OpenTelemetry::Instrumentation::Rails'
c.use 'OpenTelemetry::Instrumentation::Mysql2'
c.add_span_processor(
OpenTelemetry::SDK::Trace::Export::BatchSpanProcessor.new(
exporter: OpenTelemetry::Exporter::Jaeger::AgentExporter.new(host: 'host.docker.internal', port: 6831)
)
)
c.service_name = 'toy-app'
c.service_version = '0.1.0'
end
この use の部分ですが、
c.use 'OpenTelemetry::Instrumentation::Rails'
c.use 'OpenTelemetry::Instrumentation::Mysql2'
use_all とも書けるようです。
c.use_all
use_all すると利用可能な Instrumentation を全て use してくれるようです。
そして、Jaeger にトレースデータを Export する方法は、UDP を介した ThriftCompact 形式 で Jaeger Agent に Export する方法と、HTTP を介した ThriftBinary 形式で Jaeger Collector に Export する方法の2種類用意されているようです。
今回は、Jaeger のアーキテクチャ的に自然な UDP で Jaeger Agent に Export する方法でやってみます。
host は、Docker for Mac で検証しているためhost.docker.internal
を指定します。
port は、Jaeger の UDP の ThriftCompact 形式の公開ポートである 6831 を指定します。
OpenTelemetry::Exporter::Jaeger::AgentExporter.new(host: 'host.docker.internal', port: 6831)
service_name は、アプリケーションの名前を指定します。
service_version は、アプリケーションのバージョンを指定します。今回は適当に 0.1.0 を指定しました。
実装はこれで完了です。
動作確認
それでは bundle install 後、Rails アプリケーションを再起動して、Toy アプリケーション の ユーザ一覧とユーザの詳細ページにアクセスしてみます。
アクセスすると、Jaeger の Service のところに service_name で設定した toy-app が出現するので選択して、Find Traces をクリックします。
ちゃんとトレースできてそうですね。
SQL も確認できました。
<ユーザ一覧>
<ユーザ詳細>
うまくできました!
さいごに
とても簡単に opentelemetry-ruby を使って Rails アプリケーションのトレースデータを Jaeger で確認することができました!
公式リリースが待ち遠しいですね!
明日は、@tsukasa_oishi さんの「どれだけリクエストをさばけるのかを待ち行列理論で考えてみた」です。お楽しみに!!