New Relic APMをNode.jsのアプリケーションに導入してパフォーマンス解析をする

## 背景
- Webアプリケーションのパフォーマンスチューニングコンテスト「ISUCON10」の予選に参加した。  
  → [チームメイトの参加ブログ](https://rso.hateblo.jp/entry/2020/09/13/181343)
- New Relicから [ISUCON10参加チーム向けNew Relic特別無料ライセンス](https://blog.newrelic.co.jp/developers/how-to-utilize-isucon-special-license/) が提供されていたので使ってみた。

## 導入方法
前提として、NewRelicのAPMライセンス適用済みのアカウントが作成されていること

- NewRelicポータル > APM > Add More で `Node js` を選択
- 画面の案内に沿って導入する
  1. アプリケーション名を決めて入力する
  2. Node.jsアプリケーションのディレクトリでnewrelicのNPMパッケージを導入  
    `$ npm install newrelic --save`
  3. NewRelicの設定ファイル(newrelic.js)をダウンロードし、Node.jsアプリケーションのディレクトリ直下に配置  
    (NewRelicのライセンスキーと1.で入力したアプリケーション名が記載されている)
  4. Node.jsのアプリケーション本体(app.jsなど)にrequireを追加する
    `require('newrelic');`
  5. Node.jsのアプリケーションを再起動する。(`$npm start`など)
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94938/e97f4db1-207a-12c6-fa89-8795f19335c2.png)

## どんな情報が見えるのか？
ISUCONの中でどのようなパフォーマンス解析に使っていたかのメモです。
（アプリケーションはコンテスト中で改修した後のもの）

### Summary
- アプリケーションのトランザクション処理時間のグラフが確認できる。
- トランザクション全体の時間の中でMySQLの処理時間の割合がわかる
- スループット、エラーレート、Apdexスコア（レスポンスタイムベースのユーザ満足度）
- 下部にはアプリケーションを処理しているサーバ別のレスポンス・スループット・エラーレート・CPU使用率・メモリ使用率の平均値が表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94938/74814835-c143-288f-57af-d02185812b35.png)


### Distributed Tracing
- アプリケーションのトランザクションのサンプリング一覧を表示する。  
  全体の処理時間・バックエンドの処理時間でソートし遅いトランザクションを特定することができる。
- 更にドリルダウンすることでトランザクションの中でのバックエンドの呼び出し時間の割合（MySQLならテーブル単位）を確認することができる。キャプチャの例ではトランザクション中でMySQLのchairテーブルに2回selectを発行し、Redisに1回setしていることがわかる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94938/1d71f88b-f5c7-96d7-8ad3-447cf867ef32.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94938/c8c359b5-de5e-a3ef-fcbf-aeb373e8d287.png)


### Service Map
- アプリケーションが依存している外部サービスがマップ上に表示される。
- キャプチャの例ではアプリケーションから2ノードのRedisと1ノードのMySQLにアクセスしていることがわかる
- データベースをクリックするとクエリの処理時間のグラフも表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94938/7567f728-5883-ea5e-05e6-7dd43f200c64.png)


### Dependencies
- Service Mapに表示されていた外部サービスが一覧表示される

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94938/69a49e41-b713-bacd-b36a-1be01f82a44e.png)


### Transactions
- 初期表示の「Sort by Most time consuming」でアプリケーションのトランザクションの中で「処理時間 × リクエスト数」が多い順に表示される。(キャプチャ1枚目)
- 特定機能にフォーカスすると処理時間の内訳がグラフ表示される。キャプチャ2枚目の例ではMySQLのchairテーブルのselectが支配的なことがわかる。
- パフォーマンス改善の効果が高い機能を特定しチューニングの方向性を決めるために利用できる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94938/06d7244c-60db-48d4-6ba9-d7f262e63da4.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94938/2fd13b03-bae7-70f5-4269-723522d5187f.png)

### Databases
- 初期表示の「Sort by Most time consuming」でアプリケーションが接続しているデータベースのクエリの「処理時間 × リクエスト数」が多い順に表示される。
- テーブル単位のselect/insertの処理時間の外観をつかむことができるのでDBチューニングの方向性を決めるために利用できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94938/55819525-e514-5c96-3892-c028f75cfe81.png)

## 感想
- NewRelicの導入簡単すぎ。（Node.jsの場合）
- アプリケーションの機能単位での処理時間、データベースのテーブル単位のselect/insertの処理時間が確認できるため、パフォーマンス低下の原因を速やかに特定できる。とても便利。
- ISUCONのスコアベースでは100-200点程度の影響しかなかったので、New Relic APM Agentによるパフォーマンス影響よりも可観測性のメリットの方が大きいと思われる。（競技の最終盤では外しましたが）本番運用しているアプリケーションではNewRelicでモニタリングし続けたほうがいいと思いました。