diff --git a/README.md b/README.md index ac1d191..3c6f611 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,7 @@ The s3hub command provides following features: |Name|README|implementation| |:--|:--|:--| |[Lambda batch with EventBridge (CloudWatch Events)](./cloudformation/lambda-batch/README.md)|✅|100%| +|[CloudWatch Real User Monitoring (RUM)](./cloudformation/cloudwatch-rum/README.md)|✅|100%| ## LICENSE diff --git a/cloudformation/Makefile b/cloudformation/Makefile index 2d9e1a3..3fc9e32 100644 --- a/cloudformation/Makefile +++ b/cloudformation/Makefile @@ -5,5 +5,6 @@ help: ## Show this help | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[1;32m%-15s\033[0m %s\n", $$1, $$2}' deploy: ## Deploy CloudFormation Template - cd static-web-site-distribution && ./deploy.sh || { echo "Deployment of static-web-site-distribution failed"; exit 1; } - cd lambda-batch && make deploy || { echo "Deployment of lambda-batch failed"; exit 1; } \ No newline at end of file + cd static-web-site-distribution && make test-deploy || { echo "Deployment of static-web-site-distribution failed"; exit 1; } + cd lambda-batch && make test-deploy || { echo "Deployment of lambda-batch failed"; exit 1; } + cd cloudwatch-rum && make test-deploy || { echo "Deployment of cloudwatch-rum failed"; exit 1; } \ No newline at end of file diff --git a/cloudformation/cloudwatch-rum/Makefile b/cloudformation/cloudwatch-rum/Makefile new file mode 100644 index 0000000..4e0ea67 --- /dev/null +++ b/cloudformation/cloudwatch-rum/Makefile @@ -0,0 +1,18 @@ +.DEFAULT_GOAL := help + +.PHONY: help deploy test-deploy +help: ## Show this help message + @grep -E '^[0-9a-zA-Z_-]+[[:blank:]]*:.*?## .*$$' $(MAKEFILE_LIST) | sort \ + | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[1;32m%-15s\033[0m %s\n", $$1, $$2}' + +test-deploy: ## Deploy CloudFormation Template to localstack + @echo "Deploying CloudWatch RUM Template to localstack" + aws cloudformation create-stack --endpoint-url "http://localhost:4566" --stack-name "cloudwatch-rum-demo" \ + --template-body "file://template.yml" --parameters "file://parameters.json" --region ap-northeast-1 \ + --capabilities CAPABILITY_NAMED_IAM CAPABILITY_AUTO_EXPAND + +deploy: ## Deploy CloudFormation Template + @echo "Deploying CloudWatch RUM Template" + aws cloudformation create-stack --stack-name "cloudwatch-rum-demo" --template-body "file://template.yml" \ + --parameters "file://parameters.json" --region ap-northeast-1 \ + --capabilities CAPABILITY_NAMED_IAM CAPABILITY_AUTO_EXPAND \ No newline at end of file diff --git a/cloudformation/cloudwatch-rum/README.md b/cloudformation/cloudwatch-rum/README.md new file mode 100644 index 0000000..9e37f3d --- /dev/null +++ b/cloudformation/cloudwatch-rum/README.md @@ -0,0 +1,23 @@ +## CloudWatch Real User Monitoring (RUM) +### Overview + +CloudWatch RUM (Real User Monitoring) captures client-side data on app performance in real-time, optimizing user experiences. + +- It visualizes information about performance issues such as page load order and errors in JavaScript/HTTP responses on dashboards. +- Prioritizing fixes becomes easier by presenting the number of user sessions affected by the same issue. +![RUM_performance_monitoring](./cloudwatch-rum-performance.png) + +### How to deploy +> [!NOTE] +> Before running `make deploy`, ensure you have configured AWS credentials and set the correct region. Otherwise, you use single sign-on (SSO). + +```shell +$ make deploy +``` + +### Send data to CloudWatch RUM +To send data from your site to the CloudWatch RUM service, you must install the CloudWatch RUM web client in your application. + +The code examples are located in [CloudWatch] > [RUM] > [Application Name] > [Configuration] > [Javascript snippet]. TypeScript, JavaScript, and HTML sample code are provided. + +![snippet](snippet.png) \ No newline at end of file diff --git a/cloudformation/cloudwatch-rum/cloudwatch-rum-performance.png b/cloudformation/cloudwatch-rum/cloudwatch-rum-performance.png new file mode 100644 index 0000000..cbaa3b9 Binary files /dev/null and b/cloudformation/cloudwatch-rum/cloudwatch-rum-performance.png differ diff --git a/cloudformation/cloudwatch-rum/parameters.json b/cloudformation/cloudwatch-rum/parameters.json new file mode 100644 index 0000000..3511b3b --- /dev/null +++ b/cloudformation/cloudwatch-rum/parameters.json @@ -0,0 +1,10 @@ +[ + { + "ParameterKey" : "ApplicationName", + "ParameterValue" : "CWRumApp" + }, + { + "ParameterKey" : "ApplicationDomain", + "ParameterValue" : "example.com" + } +] \ No newline at end of file diff --git a/cloudformation/cloudwatch-rum/snippet.png b/cloudformation/cloudwatch-rum/snippet.png new file mode 100644 index 0000000..cd12cdd Binary files /dev/null and b/cloudformation/cloudwatch-rum/snippet.png differ diff --git a/cloudformation/cloudwatch-rum/template.yml b/cloudformation/cloudwatch-rum/template.yml new file mode 100644 index 0000000..603dd92 --- /dev/null +++ b/cloudformation/cloudwatch-rum/template.yml @@ -0,0 +1,92 @@ +AWSTemplateFormatVersion: "2010-09-09" +Transform: AWS::Serverless-2016-10-31 +Description: "Setup Cloudwatch RUM using Cognito IdentityPool" + +Parameters: + ApplicationName: + Type: String + Description: "The name of the application" + MinLength: 1 + MaxLength: 255 + Default: "CWRumApp" + ApplicationDomain: + Type: String + Description: "The domain of the application" + MinLength: 1 + MaxLength: 255 + Default: "example.com" + +Resources: + CWRumIdentityPool: + # https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-cognito-identitypool.html + Type: AWS::Cognito::IdentityPool + Properties: + IdentityPoolName: "CWRumIdentityPool" + AllowUnauthenticatedIdentities: true + + CWRumIdentityPoolRoles: + # https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-cognito-identitypoolroleattachment.html + Type: AWS::Cognito::IdentityPoolRoleAttachment + Properties: + IdentityPoolId: !Ref CWRumIdentityPool + Roles: + unauthenticated: !GetAtt CWRumClientRole.Arn + + CWRumClientRole: + # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html + Type: AWS::IAM::Role + Properties: + AssumeRolePolicyDocument: + Version: 2012-10-17 + Statement: + - Effect: Allow + Principal: + Federated: + - cognito-identity.amazonaws.com + Action: + - sts:AssumeRoleWithWebIdentity + Condition: + StringEquals: + cognito-identity.amazonaws.com:aud: !Ref CWRumIdentityPool + ForAnyValue:StringLike: + cognito-identity.amazonaws.com:amr: unauthenticated + Description: Unauthenticated Role for AWS RUM Clients + Path: / + Policies: + - PolicyName: AWSRumClientPut + PolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: Allow + Action: + - "rum:PutRumEvents" + - "log:CreateLogGroup" + - "log:CreateLogStream" + - "log:PutLogEvents" + - "logs:PutResourcePolicy" + Resource: !Sub arn:aws:rum:${AWS::Region}:${AWS::AccountId}:appmonitor/${ApplicationName} + # https://docs.aws.amazon.com/ja_jp/aws-managed-policy/latest/reference/AmazonCloudWatchRUMFullAccess.html + ManagedPolicyArns: + - arn:aws:iam::aws:policy/AmazonCloudWatchRUMFullAccess + + CWRumAppMonitor: + # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-rum-appmonitor.html + Type: AWS::RUM::AppMonitor + Properties: + AppMonitorConfiguration: + AllowCookies: false + EnableXRay: false + IdentityPoolId: !Ref CWRumIdentityPool + GuestRoleArn: !GetAtt CWRumClientRole.Arn + SessionSampleRate: 1 + Telemetries: + - errors + - performance + - http + Domain: !Ref ApplicationDomain + Name: !Ref ApplicationName + +Outputs: + CWRumAppMonitor: + Description: The Cloud Watch RUM App Monitor Name + Value: !Ref CWRumAppMonitor \ No newline at end of file diff --git a/cloudformation/static-web-site-distribution/Makefile b/cloudformation/static-web-site-distribution/Makefile new file mode 100644 index 0000000..e4aea4a --- /dev/null +++ b/cloudformation/static-web-site-distribution/Makefile @@ -0,0 +1,16 @@ +.DEFAULT_GOAL := help + +.PHONY: help deploy test-deploy +help: ## Show this help message + @grep -E '^[0-9a-zA-Z_-]+[[:blank:]]*:.*?## .*$$' $(MAKEFILE_LIST) | sort \ + | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[1;32m%-15s\033[0m %s\n", $$1, $$2}' + +test-deploy: ## Deploy CloudFormation Template to localstack + @echo "Deploying S3 and CloudFront Template" + aws cloudformation create-stack --endpoint-url "http://localhost:4566" --stack-name "static-web-site-distribution" \ + --template-body "file://template.yml" --parameters "file://parameters.json" --capabilities CAPABILITY_NAMED_IAM + +deploy: ## Deploy CloudFormation Template + @echo "Deploying S3 and CloudFront Template" + aws cloudformation create-stack --stack-name "static-web-site-distribution" \ + --template-body "file://template.yml" --parameters "file://parameters.json" --capabilities CAPABILITY_NAMED_IAM \ No newline at end of file diff --git a/cloudformation/static-web-site-distribution/deploy.sh b/cloudformation/static-web-site-distribution/deploy.sh deleted file mode 100755 index 5795a9e..0000000 --- a/cloudformation/static-web-site-distribution/deploy.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -set -euxo pipefail - -aws cloudformation create-stack \ - --endpoint-url "http://localhost:4566" \ - --stack-name "static-web-site-distribution" \ - --template-body "file://template.yml" \ - --parameters "file://parameters.json" \ - --capabilities CAPABILITY_NAMED_IAM