【CloudWatch RUM × X-Ray】フロントエンドからバックエンドを一気通貫でトレースする方法

CloudWatch RUMではX-Rayを利用してフロントエンドからのHTTP通信をトレースを確認することができ、さらにX-Rayに対応したバックエンドサービスにトレースIDを送信することで、フロントエンドからバックエンドまで同一のトレースIDで確認することが可能になります。
2024.05.22

はじめに

CloudWatch RUM (Real User Monitoring)はフロントエンドのモニタリングに関するサービスです。 ページを開くまでに掛かる時間やAPI実行時のエラー発生を検知することができます。

CloudWatch RUMではX-Rayを利用してフロントエンドからのHTTP通信をトレースを確認することができ、さらにX-Rayに対応したバックエンドサービスにトレースIDを送信することで、フロントエンドからバックエンドまで同一のトレースIDで確認することが可能になります。

今回はそのための構成と実装についてサンプルコードと共に紹介します。

ソース

今回検証に利用したソースはこちらにあげています。

本記事では紹介しませんが、エラーを起こすためのボタンや外部APIに接続して500Errorを発生させるための画面を用意しているので、CloudWatch RUMの動作を簡単に確認したい時に使ってみてください。

構成

全体の構成を紹介します。 特にひねりのない構成です。

フロントエンド

  • Reactで実装し静的ビルドファイルを配置
  • CloudFront
  • S3

バックエンド

  • ApiGateway(RestApi)
  • Lambda(Node.js, Typescript)

監視

  • CloudWatch RUM
  • X-Ray

IaC

  • AWS CDK

完成イメージ

実際に取得できたトレースを紹介します。

こちらはX-Rayの画面です。

フロントエンドからバックエンドまでトレースが取れている

このように、フロントエンドからバックエンドまで1つのトレースとして表示できます。

さらにX-Rayトレースでメタデータを確認すると、セッションIDを取得することができます。

XRay, RUMでセッションIDを利用する

このセッションIDをCloudWatch RUMの画面で利用すると、該当のセッションが確認できます。

こちらはCloudWatch RUMの画面です。

sessionId

このように、バックエンドでエラーが起きた際にX-Rayで調査し、そのままフロントエンドのページ遷移や離脱も追うことができるので、障害調査で重宝しそうですね。

実装方法

ここからソースを抜粋して紹介します。

動作するコードを見たい場合は以下リポジトリを参考にしてください。

CloudWatch RUMの設定

設定方法はこちらのブログを参考にさせていただきました!

特殊な設定は必要ないですが、X-Rayの設定を有効化する必要があります。

APIGatewayの設定 (AWS CDK)

デフォルトでは X-Amzn-Trace-Id のヘッダーフィールドを受け取るとCORSに引っかかってしまうので、許可設定を追加してあげる必要があります。

    // API Gateway定義
    const defaultAllowHeader = [
      "Content-Type",
      "X-Amz-Date",
      "Authorization",
      "X-Api-Key",
      "X-Amz-Security-Token",
      "X-Amz-User-Agent",
    ];
    const api = new RestApi(scope, "RumSampleApi", {
      restApiName: "RumSampleApi",
      deploy: true,
      defaultCorsPreflightOptions: {
        allowOrigins: ["*"],
        allowMethods: ["GET", "OPTIONS", "POST", "PUT", "DELETE", "PATCH"],
        allowHeaders: [...defaultAllowHeader, "X-Amzn-Trace-Id"], // ⭐️こちらで設定
      },
      deployOptions: {
        stageName: "dev",
        tracingEnabled: true, // ⭐️ X-Rayを有効化
      },
    });

フロントエンドの実装

const SettingRum = () => {
  try {
    const config: AwsRumConfig = {
      sessionSampleRate: 1,
      identityPoolId: "<AwsRumの認証を行うCognitoのID>",
      endpoint: "https://dataplane.rum.ap-northeast-1.amazonaws.com",
      telemetries: [
        "performance",
        "errors",
        [
          "http",
          {
            addXRayTraceIdHeader: true, // ⭐️ 
          },
        ],
      ],
      allowCookies: true,
      enableXRay: true, // ⭐️ 
    };

    const APPLICATION_ID: string = "<AwsRumのアプリケーションID>";
    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
  }
  return <></>;
};
root.render(
  <>
    <SettingRum />  // ⭐  こちらで呼び出し
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Layout />}>
          <Route index element={<App />} />
          <Route path="/about" element={<About />} />{" "}
          <Route path="/api" element={<SampleExternalApi />} />
          <Route path="/api-gateway" element={<SampleApiGateway />} />
          <Route path="/jsError" element={<JsError />} />
        </Route>
      </Routes>
    </BrowserRouter>
  </>
);

※ React Routerを使って実装しています。

addXRayTraceIdHeader: true を設定することで、自動で全てのHTTP通信にX-Rayトレース用のヘッダーフィールドを付与してくれるようになります。 具体的には X-Amzn-Trace-Id というヘッダーフィールドです。 設定値はこちらを参考にしました。 今回は特に制限なくトレースIDを送るように設定していますが、urlsToInclude, urlsToExcludeの設定を行うことで、トレースIDを送る対象のドメインを絞ることが可能です。 基本的には urlsToInclude に対象のAPIGatewayのドメインを設定することになるでしょう。

注意点

X-RayのトレースIDをヘッダーに付与して送信する際に、CORSに引っ掛かる可能性があります。特に、複数のAPIに対してフロントからリクエストを行うサービスでは思わぬところでX-Ray用のヘッダーを送ってしまい、エラーが出る可能性があるので注意が必要です。 必要のないAPIに対してはヘッダーを付与しないようにするなどの対策を行いましょう。