はじめに
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を取得することができます。
このセッションIDをCloudWatch RUMの画面で利用すると、該当のセッションが確認できます。
こちらはCloudWatch RUMの画面です。
このように、バックエンドでエラーが起きた際に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に対してはヘッダーを付与しないようにするなどの対策を行いましょう。