AWS X-RayをRailsに導入しようとしてつまづいた話と解決した話

この記事は[Hamee Advent Calendar 2018](https://qiita.com/advent-calendar/2018/hamee) 17日目の記事です。

## AWS X-Rayって何？

AWS公式の説明によると

> AWS X-Ray はアプリケーションが処理するリクエストに関するデータを収集するサービスです。データを表示、フィルタリング、洞察を取得して問題の識別や最適化の機会を識別するために使用するツールを提供します。アプリケーションに対するトレース対象のリクエストの場合、リクエストとレスポンスに関する情報だけではなく、アプリケーションがダウンストリーム AWS リソース、マイクロサービス、データベース、および HTTP ウェブ API に対して行う呼び出しの詳細な情報も表示できます。
https://docs.aws.amazon.com/ja_jp/xray/latest/devguide/aws-xray.html

雑に説明すると、Webアプリケーションのリクエストをいい感じにトレースしてくれるサービスです。

最近ですとfujiwaraさんによるISUCONの解説記事で利用されているのを見て知ったという方もいるのではないでしょうか。（私もそのひとりです。）

> AWS X-Ray による ISUCON8 本選問題の解析
> https://sfujiwara.hatenablog.com/entry/analyze-isucon8-by-xray

### 何がうれしいの？

- パフォーマンス上のボトルネックの発見に利用できる
- ServiceMapというリクエストの流れを可視化してくれるUIによりシステム間の連携が把握しやすい
- 複数アプリケーションの状況を横断的に（大雑把に）把握できる
- マイクロサービス化している場合など、どの部分で問題が発生しているかを把握しやすい

## Railsアプリに導入してみる

普段Railsなアプリケーションを開発していて、いま関わっているプロジェクトがLambdaやFirebaseなども絡めた複数システムを連携させている関係上、どこで問題が発生したのか？どこがボトルネックになっているか？の把握に課題があり、X-Rayはまさに解決策のひとつとして期待できそうだったので導入しようということになりました。

RubyはX-Rayの公式SDKが用意されており、これは楽勝と思って試してみました。

```ruby:Gemfile
gem 'aws-xray-sdk', require: ['aws-xray-sdk/facets/rails/railtie']
```

```ruby:confing/initializers/aws_xray.rb
Rails.application.config.xray = {
  name: 'my app'
}
```

これだけやればええでって[公式ドキュメントに書いてある](https://docs.aws.amazon.com/ja_jp/xray/latest/devguide/xray-sdk-ruby-)ので、そのとおりにやってデプロイしてみたんですよ。

そしたらこんな感じで表示されて楽勝やんと思ったんですが、あれ？DBへの接続情報ってでないの？と思ってドキュメントを見ると、きちんと用意されてました。

<img width="1245" alt="スクリーンショット 2018-12-16 23.41.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/1823/52228872-4e2f-b49e-68da-25211152eb57.png">

```ruby:confing/initializers/aws_xray.rb
Rails.application.config.xray = {
  name: 'my app',
  active_record: true # 追記
}
```

設定ファイルに1行追加するだけとのことなので、反映してみると表示されない・・・なぜ？

### 日本語でおk

意外と日本語でRailsでX-Rayを導入したよ的なサンプルが見つけられず、ローカル環境を構築してみることにしました。

### いきなり結論を書くと

```ruby:Gemfile
gem 'aws-xray-sdk', require: ['aws-xray-sdk/facets/rails/railtie']
gem 'oj', platform: :mri # 追記
gem 'jrjackson', platform: :jruby # 追記
```

この2行を追加すれば解決します。

active_recordの情報を送るためのJSONでパースエラーが発生しており、解決するには追加でgemが必要でした。でも公式ドキュメントには書いてなくない？ひどくない？って思うじゃないですか？（思うことにしておいて）

リファレンスの方には書いてあるんですよ。
https://docs.aws.amazon.com/xray-sdk-for-ruby/latest/reference/

githubのREADMEにも記載がありました。
https://github.com/aws/aws-xray-sdk-ruby

> To install the Ruby gem for your project, add it to your project Gemfile. You must also add either the Oj or JrJackson gems, for MRI and JRuby respectively, for JSON parsing. The default JSON parser will not work properly, currently.

おれの1日を返してほしい

### ライブラリを追加した結果

DBへの接続やnet_httpへのpatchの指定を追加することで外部リクエストもトレースされるようになりました。便利！

```ruby:confing/initializers/aws_xray.rb
Rails.application.config.xray = {
  name: 'rails-xray-sample',
  patch: %I[net_http aws_sdk],
  active_record: true,
  context_missing: 'LOG_ERROR'
}
```

<img width="700" alt="スクリーンショット 2018-12-17 0.00.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/1823/022fa2a2-ad0f-b638-877d-fb13e64bd4ed.png">

<img width="1212" alt="スクリーンショット 2018-12-17 0.01.25.png" src="https://qiita-image-store.s3.amazonaws.com/0/1823/c088ce75-7ee2-a24a-fbbe-7b5f3d61c089.png">

<img width="852" alt="スクリーンショット 2018-12-16 23.43.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/1823/d78e164d-01fc-9b1f-b63a-34314f94691b.png">


画像はサンプルアプリですが、業務で利用しており複数のシステム間の連携が可視化されたことで実際のアプリケーションでもボトルネックの発見につながったりとさっそく効果を発揮しています。

使い方にもよるのですが、導入も簡単でコスト的にも比較的安く利用が可能なのでご利用を検討してみてはいかがでしょうか。

## サンプルコード

意外と日本語でRailsにX-Rayを導入したものが見つからなかったのでサンプルアプリを作成してみました。ローカルでDockerを使ってX-Rayデーモンを立てています。

AWS X-Ray applied Rails sample application
https://github.com/asflash8/rails-xray-sample

（TODO:READMEちゃんと書く）

## まとめ

ドキュメントはちゃんと読もうな

## 参考記事

- [AWS X-Ray による ISUCON8 本選問題の解析](https://sfujiwara.hatenablog.com/entry/analyze-isucon8-by-xray)
- [AWS X-Ray 開発者ガイド ](https://docs.aws.amazon.com/ja_jp/xray/latest/devguide/aws-xray.html)
- [AWS X-Ray SDK for Rubyリファレンス](https://docs.aws.amazon.com/xray-sdk-for-ruby/latest/reference/)