CloudWatch RUMでサンプルアプリケーションをモニタリングしてみた
はじめに
こんにちは!最近とても暑いですね、バテ気味です。
クラウド事業本部コンサルティング部のぐっさんです。
RUMの設定方法を確認したかったため、簡単なログイン操作が可能なサンプルアプリケーションを作って動作検証をしてみました。
CloudWatch RUMとは
「リアルユーザーモニタリング」と呼ばれ、アプリケーションにおける実際のユーザー操作に関するデータの可視化・分析を実現するサービスです。
ユーザー体験向上のために活用していきましょう!
公式ドキュメント
コスト
このサービスを使用すると「RUM イベント」が発生します。
東京リージョンでは、リージョンにおける10万件のイベントごとにUSD1.00の課金となります。
その他オプションでログ保管やX-Ray等と連携する場合はそれらサービスの料金も追加でかかります。
検証用アプリケーション
今回Claude Codeに依頼してベースアプリケーションを作成してもらいましたが、ものの10分ほどで最低限のアプリが出来上がりローカルテストまで通してくれる優れものです。
※あくまで検証用のためアプリケーション上のサンプルログイン情報はハードコードされていますのでご留意ください。
ログイン機能を有するフロントエンドのアプリケーションで、色指定などは特にしていませんがいい感じにグラデーションに仕上がっていました!
ローカル検証環境
項目 | 環境情報 |
---|---|
OS | macOS |
Node.js | v22.1.0 |
npm | 10.7.0 |
Docker | Rancher Desktop 1.18.2 |
イメージの準備とリソースのデプロイ
検証アプリケーションをECSコンテナで動かしてみます。
VPC・ALB・ECSクラスターをCDKで作成します。ECRとイメージ、タスク定義は手動作成しSSMパラメータストアからタスク定義のARNをCDKより取得する設計です。
注意点としては、コンテナアーキテクチャがX86_64であることに対しローカル(macOS)開発環境のアーキテクチャがARM64 (Apple Silicon)のためそのままデプロイするとエラーになりました。
この場合、イメージビルド時のオプションに--platform linux/amd64
を付与することで回避可能です。
CDKのコードは以下のリポジトリに格納しています。
環境パラメータファイルも一応作成しましたが、最小構成ですので検証用で参考までにしていただけたらと思います!
手動で設定した項目
- ECR
項目 | 値 | 備考 |
---|---|---|
ECRリポジトリ名 | demo-js-app |
プライベートリポジトリ |
- SSM
項目 | 値 | 備考 |
---|---|---|
SSMパラメータ名 | /ecs/aws-ecs-demo-js-app/dev/task-definition-arn |
種類: String |
SSMパラメータ値 | ECSのタスク定義ARN |
- ECSタスク定義(json)
{
"taskDefinitionArn": "arn:aws:ecs:ap-northeast-1:AWSアカウントID:task-definition/demo-js-app-task-definition:1",
"containerDefinitions": [
{
"name": "nginx",
"image": "AWSアカウントID.dkr.ecr.ap-northeast-1.amazonaws.com/demo-js-app:latest",
"cpu": 0,
"portMappings": [
{
"name": "nginx-80-tcp",
"containerPort": 80,
"hostPort": 80,
"protocol": "tcp",
"appProtocol": "http"
}
],
"essential": true,
"environment": [],
"environmentFiles": [],
"mountPoints": [],
"volumesFrom": [],
"ulimits": [],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/demo-js-app-task-definition",
"awslogs-create-group": "true",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "ecs"
},
"secretOptions": []
},
"systemControls": []
}
],
"family": "demo-js-app-task-definition",
"executionRoleArn": "arn:aws:iam::AWSアカウントID:role/ecsTaskExecutionRole",
"networkMode": "awsvpc",
"revision": 1,
"volumes": [],
"status": "ACTIVE",
"requiresAttributes": [
{
"name": "com.amazonaws.ecs.capability.logging-driver.awslogs"
},
{
"name": "ecs.capability.execution-role-awslogs"
},
{
"name": "com.amazonaws.ecs.capability.ecr-auth"
},
{
"name": "com.amazonaws.ecs.capability.docker-remote-api.1.19"
},
{
"name": "ecs.capability.execution-role-ecr-pull"
},
{
"name": "com.amazonaws.ecs.capability.docker-remote-api.1.18"
},
{
"name": "ecs.capability.task-eni"
},
{
"name": "com.amazonaws.ecs.capability.docker-remote-api.1.29"
}
],
"placementConstraints": [],
"compatibilities": [
"EC2",
"FARGATE"
],
"requiresCompatibilities": [
"FARGATE"
],
"cpu": "512",
"memory": "1024",
"runtimePlatform": {
"cpuArchitecture": "X86_64",
"operatingSystemFamily": "LINUX"
},
"registeredAt": "2025-07-07T08:08:58.626Z",
"registeredBy": "arn:aws:sts::AWSアカウントID:assumed-role/IAMロール名",
"enableFaultInjection": false,
"tags": []
}
ベースアプリケーションのアクセス確認
今回、簡単な検証のみのためドメイン/証明書の作成やCloudFront等は作成せずALBのDNS名でアクセステストを行います。
そのためCDK上ではALBセキュリティグループでインバウンドルールに許可ルールを何も設定しておらず、アクセステスト実施時にマイIPからのアクセスのみを手動許可します。
- ALBのセキュリティグループでマイIPからのHTTPアクセスのみ許可
- アクセス確認 ALBのDNS名をブラウザに入力しアクセス
- ログイン確認のため認証情報入力
- ログイン成功を確認 ※今回エラー時の挙動も確認したかったためエラー発生用のボタンも用意しています。
RUMの設定
下準備が整ったところで早速コンソールからCloudWatch RUMを設定していきます!
- アプリケーションモニターを選択
- 任意のモニター名を入力し、ドメイン名を追加(今回はALBのDNSパターンで登録) その他はデフォルト
- 引き続き他の設定もデフォルトで進める
- 認証オプション(今回は新規でCognitoのIDプールを作成)、ページ指定のオプション(パスによって収集対象のページを選択可能)、およびタグを設定
- Resource Based Policyを設定しないため確認メッセージが出力されるが検証用途のためそのままContinue
- モニターを追加すると各種サンプルコードスニペットを取得できる TypeScript版
- コードスニペット JavaScript版
- コードスニペット HTML版
今回は手軽なHTMLへの組み込みを試してみます。
JavaScriptなどアプリケーションコードへ適用の場合は、RUM ウェブクライアントパッケージをnpmでインストールする必要があります。
npmインストールで実施する場合は以下の記事が参考になるかと思います!
サンプルアプリケーションのindex.htmlの<head>要素内に、取得した<script>タグを組み込みます。
index.html(例)
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ログインアプリ</title>
<link rel="stylesheet" href="styles.css">
<script>
(function(n,i,v,r,s,c,x,z){x=window.AwsRumClient={q:[],n:n,i:i,v:v,r:r,c:c};window[n]=function(c,p){x.q.push({c:c,p:p});};z=document.createElement('script');z.async=true;z.src=s;document.head.insertBefore(z,document.head.getElementsByTagName('script')[0]);})(
'cwr',
'<アプリケーションID>',
'1.0.0',
'ap-northeast-1',
'https://client.rum.us-east-1.amazonaws.com/1.19.0/cwr.js',
{
sessionSampleRate: 1 ,
identityPoolId: "ap-northeast-1:<Cognito ID>" ,
endpoint: "https://dataplane.rum.ap-northeast-1.amazonaws.com" ,
telemetries: ["performance","errors","http"] ,
allowCookies: true ,
enableXRay: false ,
signing: true // If you have a public resource policy and wish to send unsigned requests please set this to false
}
);
</script>
</head>
組み込んだコードを再度ECRリポジトリにプッシュし、ECSのサービスを更新して新たなイメージでコンテナを起動します。
- 設定直後のモニターダッシュボード まだ組み込み後のアクセスがないためデータなし
アクセステスト
では実際にアクセスをしてダッシュボードを確認します。
- パフォーマンスタブ
ロード時間を中心にデータが取れています!体感、割とリアルタイムに反映されました。
「ポジティブ」「許容できる」「イライラする」などのユーザー視点で評価をしてくれるようですね。今回のアクセスはポジティブ判定されました!
ウェブバイタルやページロードのステップデータ等、細かなデータも可視化してくれています。
- エラーとセッションタブ
Javascriptエラーに関する情報が表示されます。
今回はアプリケーション上でエラー発生用のボタンをそれぞれクリックすると画面上では何も起きませんが、内部で各種エラーが発生するように設定しています。
それぞれボタンを押した結果、エラーがカウントされました。エラーメッセージと共にグラフも提供されて見やすいです。
- HTTP Requestsタブ
エラーが最も多いリクエストURL、エラーが最も多いデバイスとブラウザなどのリクエストエラーに関する情報が表示されます。今回のアプリケーションの場合、ログイン情報をわざと間違えて401のステータスコードが返る場合に記録されました。
- Sessionsタブ
セッション情報に関するデータです。
セッションIDを押下すると、そのセッションで発生したイベント情報などを確認できました。こちらは反映に少し時間がかかりそうです。
- Eventsタブ
ここで収集されたRUM イベントの一覧を確認出来ます。イベント件数ベースで課金となるため、実装の際には要確認です。
今回のような簡素なアプリケーションで数回のアクセスでも、割と取得イベントが嵩む印象です。
- ブラウザとデバイスタブ
アクセス元のブラウザの種類やデバイスに関する情報を確認出来ます。
Chromeアクセスのみ行っていましたが、Safariでもアクセスしてみます。
ブラウザの種類が追加されています!
その他、ブラウザに関する比較情報やデバイス情報も確認出来ました。
- ユーザージャーニータブ
こちらはCookie利用を設定すると利用可能な項目です。
今回特にページを作り込んでいないためだいぶ簡素な結果ですが、ユーザーのパス遷移の動線を辿ることができます。
その他機能
- X-Ray
オプションのX-Rayを有効化してみます。アクションで、後から追加可能でした。
コードスニペットが更新され、「enableXRay: true」となりました。
アプリケーションコードを再度ECRへプッシュしてECSサービスを更新します。
再度アクセスを行うと、トレース情報が取得できました!
- CloudWatch Logsへのログ配信
通常、RUMで収集されたエンドユーザーデータは30日間保持された後で自動的に削除されます。
これよりも長くログを残したい場合は、イベントのコピーをCloudWatch Logsに送信するオプションを有効化することが可能です。
- コスト調整
サンプリングレートの調整を行い、収集するデータの一部をサンプリングすることで、包括的にデータ量を削減してコストを抑えることができます。
具体的には以下の設定で、パーセンテージを調整します。
最後に
実際に試してみると、割と手軽に実装できる割に細かいダッシュボードが提供されて反映も案外すぐで使いやすそうな機能に感じました。
リクエスト数によっては想定以上の課金となる可能性もあるので、様子を見つつ導入できれば良いのかと思います。
※検証で作成したリソースは忘れず綺麗に削除しましょう!
この記事が少しでも検証のお役に立てれば幸いです。お読みいただきありがとうございました!