
CloudWatch RUM を使って NuxtJS アプリのクライアント側のエラーをモニタリングしてみた
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
プロフィールビューアーサービス Proflly(プロフリー)の運用にて、エラーが発生している原因を調査することがあります。その際に再現性があるエラーの場合は、原因を突き止めやすいのですが、再現性がないエラーの場合、調査して原因を突き止めるのが難しい場合があります。 そういった場合に、クライアント側のエラー(Javascript のエラーなど)をモニタリングできると、エラー時の挙動がより調査しやすくなるので、CloudWatch RUM を実際に触って試してみました。
やってみること
- CloudWatch RUM にアプリケーションモニターを作成
- NuxtJS アプリ(Single Page Application)に Amazon CloudWatch RUM Web Client を組み込む
- NuxtJS アプリでエラー(例外)を発生させる
- エラー内容をアプリケーションモニターから確認
実行環境
- Amazon CloudWatch RUM Web Client: 1.1.0
- NuxtJS: 2.15.8
- Node.js: 14.17.1
CloudWatch RUM にアプリケーションモニターを作成
エラー情報を収集するためには、CloudWatch RUM にアプリケーションモニターを作成する必要があります。アプリケーションモニターを作成すると、JavaScript コードスニペットが生成されるので、このスニペットをアプリケーションに組み込む必要があります。
CloudWatch から RUM を開き、アプリケーションモニターを追加 ボタンをクリックして、アプリケーションモニターの作成を開始します。
基本的に環境に合わせて設定していけば問題なさそうですが、主な設定値は以下の通り設定しました。
- 詳細の指定
- アプリケーションドメイン
- アプリで利用するドメイン名を指定する
- dev.classmethod.jpというドメイン名を利用したアプリの場合は、- dev.classmethod.jpを指定するか、- classmethod.jpを指定して、- サブドメインを含めるをチェックしておけば大丈夫そうです
 
 
- アプリケーションドメイン
- RUM データ収集を設定する
- JavaScript エラー
- チェック
- 今回 JavaScript のエラーをモニタリングしたいので、チェックを入れる
 
 
- JavaScript エラー
- Cookie を許可する
- チェック- チェックすることで、ユーザーやセッションごとにエラー情報を集約してくれるようです
 
 
- セッションサンプル
- 100
 
- 承諾
- 新しい ID プールを作成する- CloudWatch RUM にデータを送信する際に認証とアクセス許可が必要となりますので、そのプロバイダを設定します。新しい ID プールを作成するを選択すると、Cognito ID プールが新規で作成され、設定されているロールを引き受けることによりPutRumEventsAPI を実行することが許可されるようです。既存の Cognito ID プールの利用することや、サードパーティのプロバイダーを設定することもできるようです。
 
- CloudWatch RUM にデータを送信する際に認証とアクセス許可が必要となりますので、そのプロバイダを設定します。
 
各項目を設定し、作成すると JavaScript コードスニペット が生成されるので、コピーまたはダウンロードすることができます。(後からでもコピーまたはダウンロードすることができます)
また、コードスニペットはアプリケーションモニターにて指定したパラメータを元に作成されていますが、Amazon CloudWatch RUM Web Client に指定するパラメータをカスタマイズすることができます。指定できるパラメータについてはこちらを参照ください。
NuxtJS アプリに Amazon CloudWatch RUM Web Client を組み込む
JavaScript コードスニペットを組み込むことで、Amazon CloudWatch RUM Web Client を CDN からインストールします。NuxtJS アプリのすべての画面に JavaScript コードスニペットを組み込みたいので、nuxt.config.js の head で読み込むように組み込んでみました。
組み込み方法は、アプリケーションの構成によって組み込みやすい方法でよいかと思いますが、body要素またはその他のscript要素より前に組み込む必要があるようです。
今回は、JavaScript コードスニペットをダウンロードし static/rumTracker.js として配置し他ファイルを読み込むようにしました。
なお、ダウンロードしたファイルの中身を確認すると、script タグが含まれていたので、今回のように JavaScript のファイルとして読み込む場合は、script タグを削除しておいたほうが良さそうです。
export default {
  ...
  // Global page headers: https://go.nuxtjs.dev/config-head
  head: {
    ...
    link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }],
    script: [
      {src: '/rumTracker.js'}
    ]
  },
  ...
}
これで基本的に組み込みは良いのですが、NuxtJS のようにフレームワークを利用している場合、ハンドリングしていない JavaScript エラーをインターセプトしていることがあります。エラーの収集は、アプリケーションでハンドリングしていないエラーが収集対象となるので、このままだとエラーとしてデータが収集されません。
そこで、recordError コマンドを利用して、エラーデータを収集します。今回は、エラーをハンドリングするプラグインを作成して、その処理の中で recordError コマンドを実行するように組み込んでみました。
import Vue from 'vue'
declare function cwr(operation: string, payload: any): void
export default (context: any, inject: any) => {
  Vue.config.errorHandler = (err, vm, info) => {
    console.error(err)
    cwr('recordError', err)
    
    // エラーハンドリング処理
  }
}
export default {
  ...
  plugins: [
    {src: '~/plugins/error-handler'}
  ],
  ...
}
NuxtJS アプリをデプロイし、エラー(例外)を発生させる
ここまででアプリケーションへの組み込みは、完了したので、実際にエラーを発生させる処理を実装して、デプロイします。今回は、S3 + CloudFront + Route 53 で独自ドメインにデプロイしました。なお、ドメインはアプリケーションモニターを作成した時に指定したドメインとしています。ここが合っていないと、正しく情報が収集されませんので注意が必要です。 デプロイが完了したら、実際にエラー(例外)を発生させてみます。
エラー内容をアプリケーションモニターから確認
エラーを記録したので、CloudWatch から確認してみます。反映まで最大で15分とドキュメントに記載がありましたが、実際に試してみるとおおよそ1,2分程度で確認することができました。
対象のエラーのセッションをたどっていくと、エラーのスタックトレースを確認することができます。
これくらいの情報がわかれば、クライアントでなにが起こっているのか?を判断するのに役立ちそうですね!
さいごに
今回は調査の際に、サーバー側のログだけでは、なかなか原因がつかめない場合などにクライアント側のエラー情報を確認したいと思い、調査してみました。実際に触ってみると、アプリケーションに組み込むのも簡単ですし、コストも収集する情報やサンプリングするレートである程度調整できるので、プロダクション環境でぜひ利用してみたいなぁと思いました。
いろいろなクライアントエラーの収集方法がある中の、手段の1つとして、どなたかの参考になれば幸いです。

















