CloudWatch RUMをNext.jsアプリに組み込んでクライアント側の情報をモニタリングする

ラム酒のカクテルだとモヒートが好きです
2023.07.07

Webサービスやアプリケーションを運用していると、パフォーマンス改善やエラー調査を目的としてクライアント側の情報を収集したいことがあります。
Amazon CloudWatch RUM(以下、CloudWatch RUM)を使うと、CloudWatch上にほぼリアルタイムでクライアント側の情報を収集することができます。

このエントリでは、Next.jsアプリケーションにCloudWatch RUMを導入して、クライアント側の情報をモニタリングする方法を紹介します。

検証環境

  • next 13.4.8
  • react 18.2.0
  • aws-rum-web 1.13.7

CloudWatch RUMとは

CloudWatch RUMは、CloudWatchの機能として提供されているクライアントモニタリングサービスで、Webアプリケーションにおけるクライアント側のデータを収集することができます。

Amazon CloudWatch User Guide - Use CloudWatch RUM

ページの読み込み時間やクライアント側のエラー、およびユーザーの活動などのデータを可視化することができ、サービスの分析やUX改善に役立てることができます。
また、RUMで収集されたデータはすぐにCloudWatch上のダッシュボードで可視化されるので、ダッシュボードの構築など面倒な作業は必要なく、WebアプリケーションにRUMを組み込むだけでクライアントのモニタリングを開始できます。

Next.jsアプリケーションの準備

それでは、実際にWebアプリケーションにCloudWatch RUMを導入して、クライアントのモニタリングを行ってみます。

はじめに、モニタリング対象となるNext.jsのアプリケーションを準備します。
今回は、Next.jsの公式サンプルであるblogを利用します。

$ npx create-next-app --example blog nextjs-rum-blog

構築完了したら、適当にアプリケーションが動作することを確認しておきます。

$ cd nextjs-rum-blog
$ npm run dev

CloudWatch RUMアプリケーションモニターの準備

CloudWatch RUMを導入するためには、事前準備としてAWS側でCloudWatch RUMアプリケーションモニターを作成する必要があります。

マネジメントコンソールを開き、CloudWatchのサービスページから 「RUM」を選択し、「アプリケーションモニターを作成」をクリックします。

アプリケーションモニターの詳細を入力していきます。

今回は以下のような設定としました。
(特に指定がない箇所はデフォルトのまま)

  • 詳細の指定
    • アプリケーションモニター名: NextRumBlog
    • アプリケーションドメイン: localhost
      • アプリケーションがローカル環境で動作するため
  • RUM データ収集を設定する
    • プラグイン
      • パフォーマンステレメトリー: ON
      • JavaScript エラー: ON
      • HTTP エラー: ON
  • Cookie を許可する: ON
  • セッションサンプル: 100%
  • 承諾: 新しい ID プールを作成する
    • アプリケーションがAWSにアクセスするために、新しくCognito IDプールを作成してRUMにデータ送信可能なロールを引き受けさせる(既存のIDプールやサードパーティのプロバイダーを使うことも可能)。

必要な情報を入力後、「アプリケーションモニターを追加」をクリックするとCloudWatch RUMアプリケーションモニターが作成されます。

CloudWatch RUMの導入

CloudWatch RUMアプリケーションモニターが準備できたので、次は実際にアプリケーションへRUMを組み込んでみます。

組み込む方法としては、npmからWeb Clientをインストールするやり方やRUMが発行するコードスニペットを直接 headタグに埋め込むやり方などがありますが、今回はnpmからインストールする方法で進めていきます。

RUMのWeb Clientパッケージ aws-rum-web をインストールします。

$ npm install aws-rum-web

インストールできたら、pages/_app.tsx に先ほど作成したアプリケーションモニターの作成時に表示されていたサンプルコードを参考に組み込んでみます。
(以下の例ではARNAPPLICATION_IDはマスクしています。また実際にアプリケーションへ組み込む際は、これらの値はハードコーディングせずに外部に切り出した方が良いと思います)

pages/_app.tsx

import 'nextra-theme-blog/style.css'
import type { AppProps } from 'next/app'
import Head from 'next/head'
import '../styles/main.css'

import { AwsRum, AwsRumConfig } from 'aws-rum-web';

try {
  const config: AwsRumConfig = {
    sessionSampleRate: 1,
    guestRoleArn: "arn:aws:iam::000000000000:role/RUM-Monitor-ap-northeast-1-000000000000-9999999999999-Unauth",
    identityPoolId: "ap-northeast-1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx",
    endpoint: "https://dataplane.rum.ap-northeast-1.amazonaws.com",
    telemetries: ["performance","errors","http"],
    allowCookies: true,
    enableXRay: false
  };

  const APPLICATION_ID: string = 'xxxxxxxxxxxxxxxxxxxxxxxxxx';
  const APPLICATION_VERSION: string = '1.0.0';
  const APPLICATION_REGION: string = 'ap-northeast-1';

  const awsRum: AwsRum = new AwsRum(
    APPLICATION_ID,
    APPLICATION_VERSION,
    APPLICATION_REGION,
    config
  );
} catch (error) {
  // Ignore errors thrown during CloudWatch RUM web client initialization
}

export default function App({ Component, pageProps }: AppProps) {
  return (
    <>
      <Head>
        <link
          rel="alternate"
          type="application/rss+xml"
          title="RSS"
          href="/feed.xml"
        />
        <link
          rel="preload"
          href="/fonts/Inter-roman.latin.var.woff2"
          as="font"
          type="font/woff2"
          crossOrigin="anonymous"
        />
      </Head>
      <Component {...pageProps} />
    </>
  )
}

これでRUMの導入は完了です!簡単でいい感じですね。
モニタリングのためアプリケーションを起動し、ブラウザで色々とアクセスしてみましょう。

CloudWatch RUMダッシュボードの確認

アプリケーションにRUMが導入できたので、次はCloudWatch RUMのダッシュボードを確認してみます。

概要ページでは、アプリケーションモニター毎にページのロード数や平均ロード速度、Apdexスコアなどが確認できるようになっています。

次に、アプリケーションモニター毎のビューを見ていきます。
パフォーマンス タブでは、主にパフォーマンスに関わるメトリクスを確認できます。

UXの指標であるWeb Vitalsに関するメトリクスもここで確認できます。
LCP/FID/CLSに関する計測結果が表示されていますね。

エラーとセッション タブでは、アプリケーションで発生したJSエラーの詳細を確認できます。
エラーが発生したセッション情報から、スタックトレースも確認できるようになっています。

他にも、ブラウザとデバイス タブからアクセス元のブラウザやデバイスの利用状況を確認したり、ユーザージャーニータブからユーザーのページ遷移の導線を確認したりといったことができるようになっています。

おわりに

Next.jsアプリケーションにCloudWatch RUMを組み込み、クライアント側のモニタリングを行ってみました。

RUMのコードスニペットを埋め込むだけで簡単に導入できるのがいい感じですね。
他にも、CloudWatch上の機能ということでCloudWatch Alarmと連携したり、X-Rayといった他サービスとの連携も容易にできるようになっており、個人的には使いやすそうな印象を受けました。
クライアントモニタリングツールの選択肢として、CloudWatch RUMも検討してみてはいかがでしょうか。

どなたかの参考になれば幸いです。

参考