Open kirin-ri opened 1 week ago
btrikra:~/environment $ npm install -g aws-cdk@2.84.0 npm error code EACCES npm error syscall mkdir npm error path /usr/local/lib/node_modules/aws-cdk npm error errno -13 npm error [Error: EACCES: permission denied, mkdir '/usr/local/lib/node_modules/aws-cdk'] { npm error errno: -13, npm error code: 'EACCES', npm error syscall: 'mkdir', npm error path: '/usr/local/lib/node_modules/aws-cdk' npm error } npm error npm error The operation was rejected by your operating system. npm error It is likely you do not have the permissions to access this file as the current user npm error npm error If you believe this might be a permissions issue, please double-check the npm error permissions of the file and its containing directories, or try running npm error the command again as root/Administrator. npm error A complete log of this run can be found in: /home/ec2-user/.npm/_logs/2024-11-07T00_31_46_911Z-debug-0.log
btrikra:~/environment $ sudo npm install -g aws-cdk@2.84.0 npm error code EEXIST npm error path /usr/local/bin/cdk npm error EEXIST: file already exists npm error File exists: /usr/local/bin/cdk npm error Remove the existing file and try again, or run npm npm error with --force to overwrite files recklessly. npm error A complete log of this run can be found in: /root/.npm/_logs/2024-11-07T00_36_30_609Z-debug-0.log
btrikra:~/environment $ git clone https://git-codecommit.us-east-2.amazonaws.com/v1/repos/FBS-viz-trial Cloning into 'FBS-viz-trial'... fatal: unable to access 'https://git-codecommit.us-east-2.amazonaws.com/v1/repos/FBS-viz-trial/': The requested URL returned error: 403
https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cloudwatch.GraphWidget.html グラフ等Widgetを作っていく ※prposは別ページに遷移 https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_cloudwatch.GraphWidgetProps.html ここでグルーピングが出来ると思っている。。。 ※折れ線と棒グラフを同じグループで取り扱い時どうするの?とかが謎 leftとrightがあるんだけど、説明文がほぼ同じでちゃんと理解出来ない。 多分右にY軸か、左にY軸なのかだとは思うんだが。。
配置はIMetrics[]に入れた順に表示されると思うんだが。。。
という具合にはっきり分からないからサンプルで組んでみたいです。
CloudWatch DashBoard作り方調査
∟L2で作れるけど、具体的にサンプル描いて作り方をfix
・構成検討
∟configから必要な情報(Metric名とか)とる?
メインコード側(標準アーキ側)でSSMに入れて、可視化APPでfromで取得するのもあり
※fromでmetricまで取れるか不明 要確認
調査結果から後者で行きたい
検討結果をまとめて、やり方のfix
import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
import * as cloudwatch from "aws-cdk-lib/aws-cloudwatch";
export class CustomDashboard extends Construct {
constructor(scope: Construct, id: string, envName: string) {
super(scope, id);
// CloudWatch Dashboardの作成
const dashboard = new cloudwatch.Dashboard(this, "CustomDashboard", {
dashboardName: `custom-${envName}-dashboard`,
});
// EC2インスタンスのCPU使用率メトリクスを設定
const cpuUtilizationMetric = new cloudwatch.Metric({
namespace: "AWS/EC2",
metricName: "CPUUtilization",
dimensionsMap: { InstanceId: "i-0123456789abcdef0" }, // インスタンスIDを指定
statistic: "Average",
period: cdk.Duration.minutes(5),
});
// グラフウィジェットの作成
const cpuWidget = new cloudwatch.GraphWidget({
title: "CPU Utilization",
left: [cpuUtilizationMetric],
});
// ウィジェットをダッシュボードに追加
dashboard.addWidgets(cpuWidget);
}
}
aws ec2 describe-instances --query "Reservations[].Instances[].InstanceId" --output text
#!/usr/bin/env node
import "source-map-support/register";
import * as cdk from "aws-cdk-lib";
import { GcStdArchi1Stack } from "../lib/gc-std-archi1-stack";
import * as nag from "cdk-nag"; // cdk-nagモジュールのインポート
import * as config from "config"; // node-configモジュールのインポート
/**
* 環境変数設定確認
* Deploy環境の環境変数を参照し、紐つけるパラメータファイルを制御するため、環境変数"NODE_ENV"に値が設定されているか確認
*/
const envName = process.env.NODE_ENV;
if (envName == null) {
console.error(
"Error: 環境変数'NODE_ENV'にパラメータファイル名となる環境名を設定してください。\n \
例: export NODE_ENV=Dev"
);
process.exit(1);
}
const app = new cdk.App();
/**
* 標準アーキ1 CDK APPクラス
*
* @remarks
* 標準アーキ1環境をDeployするための最上位となるAPPクラス
* このクラスには、「標準アーキ1 Project tagのvalue」、「標準アーキ1 Environment tagのvalue」のtagが付与される。
*
* **実行時の必要パラメータ**
* - description : 標準アーキ1 CFn Stackのdescription
* - env : Deploy先リージョン、アカウント リージョンの指定はALBからログ出力のため必須
* - terminationProtection : 標準アーキ1 Stackの削除保護 アセットでは無効化
*/
export const GcStdArchiStack = new GcStdArchi1Stack(app, `${envName}-GcStdArchi1Stack`, {
description: "The Main-Stack for the Government-Cloud standard architecture - No.1",
env: {
region: "ap-northeast-1",
account: config.get("common.accountId")
},
// terminationProtection: true,
});
/**
* 標準アーキ1 内リソース共通tagの付与
*/
cdk.Tags.of(app).add("Project", config.get("common.project"));
cdk.Tags.of(app).add("Environment", config.get("common.envPrefix"));
// cdk-nagによるセキュリティ静的解析を有効化
cdk.Aspects.of(app).add(new nag.AwsSolutionsChecks({ verbose: true }));
import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
import { Nw } from "./resources/gc-std-archi1-nw";
import { AppS3Bucket } from "./resources/gc-std-archi1-s3";
import { MainAurora } from "./resources/gc-std-archi1-mainaurora";
import { EcsTourreservation } from "./resources/gc-std-archi1-ecs-tourreservation";
import { EcsHotelmanagement } from "./resources/gc-std-archi1-ecs-hotelmanagement";
import { EcsMastermanagement } from "./resources/gc-std-archi1-ecs-mastermanagement";
import { EcsScheduleLaunch } from "./resources/gc-std-archi1-ecs-schedulelaunch";
import { Logarchive } from "./resources/gc-std-archi1-logarchive";
import { MonitorCommon } from "./resources/gc-std-archi1-monitor";
import { DataInput } from "./resources/gc-std-archi1-datainput";
import * as nag from "cdk-nag"; // cdk-nagモジュールのインポート
import config = require("config"); // node-configモジュールのインポート
/**
* 標準アーキ1 CDK Stackクラス
*
* @remarks
* 標準アーキ1環境をDeployするためのCDKのStackクラス詳細が定義されるResource Constructを生成し、必要に応じてobjectの引き渡しを行う。
* **monitorCommon Constructs構成物**
* - 監視通知用SNSトピック
* - Teams通知Lambda用Log GP
* - Teams通知Lambda用Role
* - Teams通知Lambda
* - SecurityHubのEvent監視Rule
*
* **nw Constructs構成物**
* - サーバアクセスログバケット
* - VPC FlowLog用バケット
* - VPC関連リソース
* - 各種Endpoint
* - Endpoint SG
* - ECRプルスルーキャッシュ
* - ADOTイメージECRリポジトリ情報
* - ECRプルスルーキャッシュ要件のIAMポリシーステートメント
* - ADOTタスク要件のIAMポリシーステートメント
* - 監視Alarm(サーバアクセスログバケット、VPC FlowLog用バケット)
*
* **appS3Bucket Constructs構成物**
* - APP用S3バケット
* - GCログ格納用S3バケット
* - 監視Alarm(APP用S3バケット、GCログ格納用S3バケット)
*
* **main aurora Constructs構成物**
* - Main Aurora用SG,
* - Main Aurora用のパラメターGP
* - Main Aurora用Subnet GP
* - Main Aurora資格情報格納用Secrets Manager
* - Main Aurora資格情報ローテンション
* - Aurora Serverless v2
* - 監視Alarm(Aurora Serverless v2)
*
* **ecsHotelmanagement Constructs構成物**
* - Internal ALB用SG
* - Internal ALB
* - Internal ALB用ログバケット
* - Hotel DynamoDB
* - Hotel Management用SG
* - Hotel Management用Log GP
* - Hotel Management taskdef
* - Hotel Management ALB連携サービス
* - Hotel Management AAS
* - 監視Alarm(Internal ALB、Internal ALB用ログバケット、Hotel DynamoDB、Hotel Management ALB連携サービス)
*
* **ecsMastermanagement Constructs構成物**
* - Master Mnagement SQS(DLQ含む)
* - Master Management用SG
* - Master Management用Log GP
* - Master Management Cluster
* - Master Management taskdef
* - Master Management SQS連携サービス
* - Master Management AAS
* - 監視Alarm(Master Mnagement SQS(DLQ含む)、Master Management SQS連携サービス)
*
* **ecsScheduleLaunch Constructs構成物**
* - スケジュールバッチ用SG
* - スケジュールバッチ用Log GP
* - スケジュールバッチ taskdef
* - スケジュールバッチタスク起動Rule
* - 監視Alarm(スケジュールバッチタスク起動Rule)
*
* **ecsTourreservation Constructs構成物**
* - Redis用SG
* - Redis用Subnet GP
* - Redis用パラメータGP
* - Redis Cluster
* - Global ALB SG
* - Global ALB
* - Global ALB ログ用バケット
* - Global ALB, WAF用ログバケット
* - WAF用Web ACL
* - Tour Reservation用SG
* - Tour Reservation用Log GP
* - Tour Reservation用 taskdef
* - Tour Reservation用ALB連携サービス
* - Tour Reservation用AAS
* - 監視Alarm(Redis Cluster、Global ALB、Global ALB ログ用バケット、Global ALB、WAF用ログバケット、Tour Reservation用ALB連携サービス)
*
* **logarchive Constructs構成物**
* - Log Archive用S3バケット
* - Log Archive用KDF
* - メトリックフィルター設定用Lambda
* - 監視Alarm(Log Archive用S3バケット、メトリックフィルター設定用Lambda)
*
* **dataInput Constructs構成物**
* - 初期データ投入Lambda用SG
* - 初期データ投入Lambda用Log GP
* - 初期データ投入Lambda用Role
* - 初期データ投入Lambda用DynamoDB初期データのLayer
* - 初期データ投入Lambda用Aurora初期データのLayer
* - 初期データ投入Lambda用psycopg2モジュールのLayer
* - 初期データ投入Lambda
* - Stack作成検知Rule
* - 監視Alarm(Lambda、EventBridge Rule)
*
*/
export class GcStdArchi1Stack extends cdk.Stack {
constructor(scope: Construct, id: string, props: cdk.StackProps) {
super(scope, id, props);
/**
* 監視用共通リソースConstructクラス
*/
const monitorCommon = new MonitorCommon(this, "MonitorCommon", {
envName: config.get("common.envPrefix"),
accountId: [ this.account ],
region: [ this.region ],
monitorFailedNotificationEmail: config.get("monitorCommon.monitorFailedNotificationEmail"),
webhookURL: config.get("monitorCommon.webhookURL"),
notificationToTeamsFunctionDurationAlarmThreshold: config.get("monitorCommonAlarm.notificationToTeamsFunctionDurationAlarmThreshold"),
securityHubEventNotificationRuleDeadLetterInvocationAlarmThreshold: config.get("monitorCommonAlarm.securityHubEventNotificationRuleDeadLetterInvocationAlarmThreshold"),
});
/**
* 標準アーキ1NW共通関連リソースContructクラス
*/
const nw = new Nw(this, "Nw", {
envName: config.get("common.envPrefix"),
vpcCider: config.get("nw.vpcCider"),
vpcMaxAZs: config.get("nw.vpcMaxAZs"),
vpcPublicSubnetCidrMask: config.get("nw.vpcPublicSubnetCidrMask"),
vpcPrivateSubnetCidrMask: config.get("nw.vpcPrivateSubnetCidrMask"),
alarmTopic: monitorCommon.alarmTopic,
// アラーム定義の閾値
serverAccessLogBucket4xxErrorsAlarmThreshold: config.get("nwAlarm.serverAccessLogBucket4xxErrorsAlarmThreshold"),
serverAccessLogBucket5xxErrorsAlarmThreshold: config.get("nwAlarm.serverAccessLogBucket5xxErrorsAlarmThreshold"),
serverAccessLogBucketAllRequestsAlarmThreshold: config.get("nwAlarm.serverAccessLogBucketAllRequestsAlarmThreshold"),
flowLogBucket4xxErrorsAlarmThreshold: config.get("nwAlarm.flowLogBucket4xxErrorsAlarmThreshold"),
flowLogBucket5xxErrorsAlarmThreshold: config.get("nwAlarm.flowLogBucket5xxErrorsAlarmThreshold"),
flowLogBucketAllRequestsAlarmThreshold: config.get("nwAlarm.flowLogBucketAllRequestsAlarmThreshold"),
});
/**
* 標準アーキ1共通S3関連リソースContructクラス
*/
const appS3Bucket = new AppS3Bucket(this, "AppS3Bucket", {
envName: config.get("common.envPrefix"),
serverAccessLogBucket: nw.myServerAccessLogBucket,
alarmTopic: monitorCommon.alarmTopic,
// アラーム定義の閾値
appBucket4xxErrorsAlarmThreshold: config.get("appS3BucketAlarm.appBucket4xxErrorsAlarmThreshold"),
appBucket5xxErrorsAlarmThreshold: config.get("appS3BucketAlarm.appBucket5xxErrorsAlarmThreshold"),
appBucketAllRequestsAlarmThreshold: config.get("appS3BucketAlarm.appBucketAllRequestsAlarmThreshold"),
appGCLogBucket4xxErrorsAlarmThreshold: config.get("appS3BucketAlarm.appGCLogBucket4xxErrorsAlarmThreshold"),
appGCLogBucket5xxErrorsAlarmThreshold: config.get("appS3BucketAlarm.appGCLogBucket5xxErrorsAlarmThreshold"),
appGCLogBucketAllRequestsAlarmThreshold: config.get("appS3BucketAlarm.appGCLogBucketAllRequestsAlarmThreshold"),
});
/**
* 標準アーキ1Main Aurora関連リソースContructクラス
*/
const mainaurora = new MainAurora(this, "Aurora", {
envName: config.get("common.envPrefix"),
vpc: nw.myVpc,
clusterParam: config.get("mainAurora.clusterParam"),
maxAurora: config.get("mainAurora.maxAurora"),
minAurora: config.get("mainAurora.minAurora"),
alarmTopic: monitorCommon.alarmTopic,
// アラーム定義の閾値
mainAuroraInstanceAuroraReplicaLagAlarmThreshold: config.get("mainAuroraAlarm.mainAuroraInstanceAuroraReplicaLagAlarmThreshold"),
mainAuroraInstanceCPUUtilizationAlarmThreshold: config.get("mainAuroraAlarm.mainAuroraInstanceCPUUtilizationAlarmThreshold"),
mainAuroraInstanceDatabaseConnectionsAlarmThreshold: config.get("mainAuroraAlarm.mainAuroraInstanceDatabaseConnectionsAlarmThreshold"), // ACU4の場合の最大コネクション数の80%
mainAuroraClusterVolumeBytesUsedAlarmThreshold: config.get("mainAuroraAlarm.mainAuroraClusterVolumeBytesUsedAlarmThreshold"), // 325.6G
});
// Aurora Secrets Rotation Nested Stackエラー抑止
nag.NagSuppressions.addResourceSuppressionsByPath(
this,
// "Dev-GcStdArchi1Stack/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/ServiceRole/Resource",
`${this.stackName}/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/ServiceRole/Resource`,
[
{id: "AwsSolutions-IAM4", reason: "Because of NestedStack"},
]
);
nag.NagSuppressions.addResourceSuppressionsByPath(
this,
// "/Dev-GcStdArchi1Stack/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/ServiceRole/DefaultPolicy/Resource",
`${this.stackName}/LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8a/ServiceRole/DefaultPolicy/Resource`,
[
{id: "AwsSolutions-IAM5", reason: "Because of NestedStack"},
]
);
/**
* 標準アーキ1Hotel Management関連リソースContructクラス
*/
const ecsHotelmanagement = new EcsHotelmanagement(this, "EcsHotelmanagement", {
envName: config.get("common.envPrefix"),
vpc: nw.myVpc,
appBucket: appS3Bucket.myAppBucket,
appGCLogBucket: appS3Bucket.myAppGCLogBucket,
serverAccessLogBucket: nw.myServerAccessLogBucket,
vpcEndpointSg: nw.myVpcEndpointSg,
myAdotEcrRepository: nw.myAdotEcrRepository,
pullThryoughCachePolicyStatement: nw.pullThryoughCachePolicyStatement,
awsOTelTaskRolePolicyStatement: nw.awsOTelTaskRolePolicyStatement,
alarmTopic: monitorCommon.alarmTopic,
hotelTableReadCapacity: config.get("hotelmanagement.hotelTableReadCapacity"),
hotelTableWriteCapacity: config.get("hotelmanagement.hotelTableWriteCapacity"),
hotelTableReadMinCapacity: config.get("hotelmanagement.hotelTableReadMinCapacity"),
hotelTableReadMaxCapacity: config.get("hotelmanagement.hotelTableReadMaxCapacity"),
hotelTableReadTarget: config.get("hotelmanagement.hotelTableReadTarget"),
hotelTableWriteMinCapacity: config.get("hotelmanagement.hotelTableWriteMinCapacity"),
hotelTableWriteMaxCapacity: config.get("hotelmanagement.hotelTableWriteMaxCapacity"),
hotelTableWriteTarget: config.get("hotelmanagement.hotelTableWriteTarget"),
hotelmanagementCPU: config.get("hotelmanagement.hotelmanagementCPU"),
hotelmanagementMEM: config.get("hotelmanagement.hotelmanagementMEM"),
hotelmanagementEcrRepositoryArn: config.get("hotelmanagement.hotelmanagementEcrRepositoryArn"),
// hotelmanagementEnvSpringLifecycleTimeoutPerShutdownPhase: config.get("hotelmanagement.hotelmanagementEnvSpringLifecycleTimeoutPerShutdownPhase"), // チューニングする時のみ使用
hotelmanagementEnvSpringProfilesActive: config.get("hotelmanagement.hotelmanagementEnvSpringProfilesActive"),
hotelmanagementEnvGcUploadIntervalSec: config.get("hotelmanagement.hotelmanagementEnvGcUploadIntervalSec"),
hotelmanagementEnvGcLoglevel: config.get("hotelmanagement.hotelmanagementEnvGcLoglevel"),
hotelmanagementEnvOtelResourceAttributes: config.get("hotelmanagement.hotelmanagementEnvOtelResourceAttributes"),
hotelmanagementDesiredCount: config.get("hotelmanagement.hotelmanagementDesiredCount"),
hotelmanagementFargateAASMin: config.get("hotelmanagement.hotelmanagementFargatAASMin"),
hotelmanagementFargateAASMax: config.get("hotelmanagement.hotelmanagementFargatAASMax"),
hotelmanagementFargateAASTarget: config.get("hotelmanagement.hotelmanagementFargatAASMax"),
// アラーム定義の閾値
hotelmanagementCPUThreshold: config.get("hotelmanagementAlarm.hotelmanagementCPUThreshold"),
hotelmanagementMemThreshold: config.get("hotelmanagementAlarm.hotelmanagementMemThreshold"),
internalAlbCode4XX: config.get("hotelmanagementAlarm.internalAlbCode4XX"),
internalAlbCode5XX: config.get("hotelmanagementAlarm.internalAlbCode5XX"),
internalAlbCode500: config.get("hotelmanagementAlarm.internalAlbCode500"),
internalAlbCode502: config.get("hotelmanagementAlarm.internalAlbCode502"),
internalAlbCode503: config.get("hotelmanagementAlarm.internalAlbCode503"),
internalAlbCode504: config.get("hotelmanagementAlarm.internalAlbCode504"),
internalAlbRejectCount: config.get("hotelmanagementAlarm.internalAlbRejectCount"),
hotelmanagementTGCode2XX: config.get("hotelmanagementAlarm.hotelmanagementTGCode2XX"),
hotelmanagementTGCode3XX: config.get("hotelmanagementAlarm.hotelmanagementTGCode3XX"),
hotelmanagementTGCode4XX: config.get("hotelmanagementAlarm.hotelmanagementTGCode4XX"),
hotelmanagementTGCode5XX: config.get("hotelmanagementAlarm.hotelmanagementTGCode5XX"),
hotelmanagementTGResponseTime: config.get("hotelmanagementAlarm.hotelmanagementTGResponseTime"),
dynamoDBRCUUtilization: config.get("hotelmanagementAlarm.dynamoDBRCUUtilization"),
dynamoDBWCUUtilization: config.get("hotelmanagementAlarm.dynamoDBWCUUtilization"),
hotelTableConsumedWCU: config.get("hotelmanagementAlarm.hotelTableConsumedWCU"),
hotelTableConsumedRCU: config.get("hotelmanagementAlarm.hotelTableConsumedRCU"),
dynamoDBMaxProvisionedTableRCUUtilization: config.get("hotelmanagementAlarm.dynamoDBMaxProvisionedTableRCUUtilization"),
dynamoDBMaxProvisionedTableWCUUtilization: config.get("hotelmanagementAlarm.dynamoDBMaxProvisionedTableWCUUtilization"),
hotelTableSuccessfulRequestLatency: config.get("hotelmanagementAlarm.hotelTableSuccessfulRequestLatency"),
internalAlbLogBucket4xxErrors: config.get("hotelmanagementAlarm.internalAlbLogBucket4xxErrors"),
internalAlbLogBucket5xxErrors: config.get("hotelmanagementAlarm.internalAlbLogBucket4xxErrors"),
internalAlbLogBucketAllRequests: config.get("hotelmanagementAlarm.internalAlbLogBucketAllRequests"),
});
/**
* 標準アーキ1Master Managementn関連リソースContructクラス
*/
const ecsMastermanagement = new EcsMastermanagement(this, "EcsMastermanagement", {
//共通リソース
envName: config.get("common.envPrefix"),
vpc: nw.myVpc,
appBucket: appS3Bucket.myAppBucket,
appGCLogBucket: appS3Bucket.myAppGCLogBucket,
vpcEndpointSg: nw.myVpcEndpointSg,
mainAuroraSecret: mainaurora.myMainAuroraSecret,
internalAlb: ecsHotelmanagement.myInternalAlb,
mainAuroraCluster: mainaurora.myMainAuroraCluster,
myAdotEcrRepository: nw.myAdotEcrRepository,
pullThryoughCachePolicyStatement: nw.pullThryoughCachePolicyStatement,
awsOTelTaskRolePolicyStatement: nw.awsOTelTaskRolePolicyStatement,
alarmTopic: monitorCommon.alarmTopic,
//サービス
mastermanagementDesiredCount: config.get("mastermanagement.mastermanagementDesiredCount"),
mastermanagementAASMax: config.get("mastermanagement.mastermanagementAASMax"),
mastermanagementAASMin: config.get("mastermanagement.mastermanagementAASMin"),
mastermanagementAASTarget: config.get("mastermanagement.mastermanagementAASTarget"),
//タスク定義
masterManagementCpu: config.get("mastermanagement.masterManagementCpu"),
masterManagementMem: config.get("mastermanagement.masterManagementMem"),
//コンテナ定義(Mastermanagement)
mastermanagementEcrRepositoryArn: config.get("mastermanagement.mastermanagementEcrRepositoryArn"),
mastermanagementEnvSpringProfilesActive: config.get("mastermanagement.mastermanagementEnvSpringProfilesActive"),
// mastermanagemnetEnvDatasourceDriverclassname: config.get("mastermanagement.mastermanagemnetEnvDatasourceDriverclassname"), // チューニングする時のみ使用
// mastermanagemnetEnvApiRetryMaxAttempts: config.get("mastermanagement.mastermanagemnetEnvApiRetryMaxAttempts"), // チューニングする時のみ使用v
// mastermanagemnetEnvApiRetryMinBackoff: config.get("mastermanagement.mastermanagemnetEnvApiRetryMinBackoff"), // チューニングする時のみ使用
mastermanagemnetEnvResilience4JTimeout: config.get("mastermanagement.mastermanagemnetEnvResilience4JTimeout"), // チューニングする時のみ使用
// mastermanagementEnvJBA020201_JdbcBatchUpdateSize: config.get("mastermanagement.mastermanagementEnvJBA020201_JdbcBatchUpdateSize"), // チューニングする時のみ使用
// mastermanagementEnvJBA020301_ChunkSize: config.get("mastermanagement.mastermanagementEnvJBA020301_ChunkSize"), // チューニングする時のみ使用
// mastermanagementEnvSqsListenerConcurrency: config.get("mastermanagement.mastermanagementEnvSqsListenerConcurrency"), // チューニングする時のみ使用
// mastermanagementEnvSqsNumberOfMessageStopRefetch: config.get("mastermanagement.mastermanagementEnvSqsNumberOfMessageStopRefetch"), // チューニングする時のみ使用
mastermanagementEnvGcUploadIntervalSec: config.get("mastermanagement.mastermanagementEnvGcUploadIntervalSec"),
mastermanagementEnvGcLogleve: config.get("mastermanagement.mastermanagementEnvGcLogleve"),
mastermanagementEnvOtelResourceAttributes: config.get("mastermanagement.mastermanagementEnvOtelResourceAttributes"),
// アラーム定義の閾値
mastermanagementFargateServiceCPUUtilizationAlarmThreshold: config.get("mastermanagementAlarm.mastermanagementFargateServiceCPUUtilizationAlarmThreshold"),
mastermanagementFargateServiceMemoryUtilizationAlarmThreshold: config.get("mastermanagementAlarm.mastermanagementFargateServiceMemoryUtilizationAlarmThreshold"),
mastermanagementSQSApproximateNumberOfMessagesVisibleAlarmThreshold: config.get("mastermanagementAlarm.mastermanagementSQSApproximateNumberOfMessagesVisibleAlarmThreshold"),
});
/**
* 標準アーキ1スケジュールバッチ関連リソースContructクラス
*/
const ecsScheduleLaunch = new EcsScheduleLaunch(this, "EcsScheduleLaunch", {
// 共通リソースパラメータ
envName: config.get("common.envPrefix"),
vpc: nw.myVpc,
appGCLogBucket: appS3Bucket.myAppGCLogBucket,
vpcEndpointSg: nw.myVpcEndpointSg,
mastermanagementSQS: ecsMastermanagement.myMastermanagementSQS,
mastermanagementFargateCluster: ecsMastermanagement.myMastermanagementFargateCluster,
myAdotEcrRepository: nw.myAdotEcrRepository,
pullThryoughCachePolicyStatement: nw.pullThryoughCachePolicyStatement,
awsOTelTaskRolePolicyStatement: nw.awsOTelTaskRolePolicyStatement,
alarmTopic: monitorCommon.alarmTopic,
// ECSタスク定義
schedulelaunchTaskCpu: config.get("schedulelaunch.schedulelaunchTaskCpu"),
schedulelaunchTaskMemoryLimit: config.get("schedulelaunch.schedulelaunchTaskMemoryLimit"),
// ECSコンテナ定義:Tourreservatisonコンテナ用パラメータ
schedulelaunchEcrRepositoryArn: config.get("schedulelaunch.schedulelaunchEcrRepositoryArn"),
schedulelaunchEnvSpringProfilesActive: config.get("schedulelaunch.schedulelaunchEnvSpringProfilesActive"),
schedulelaunchEnvBatchScheduleTargetId: config.get("schedulelaunch.schedulelaunchEnvBatchScheduleTargetId"),
schedulelaunchEnvOtelResourceAttributes: config.get("schedulelaunch.schedulelaunchEnvOtelResourceAttributes"),
// EventBridge用の定義
schedulelaunchScheduleRate: config.get("schedulelaunch.schedulelaunchScheduleRate"),
// アラーム定義の閾値
schedulelaunchRuleDeadLetterInvocationAlarmThreshold: config.get("schedulelaunchAlarm.schedulelaunchRuleDeadLetterInvocationAlarmThreshold"),
});
/**
* 標準アーキ1Tour Reservation関連リソースContructクラス
*/
const ecsTourreservation = new EcsTourreservation(this, "EcsTourreservation", {
envName: config.get("common.envPrefix"),
vpc: nw.myVpc,
appBucket: appS3Bucket.myAppBucket,
appGCLogBucket: appS3Bucket.myAppGCLogBucket,
serverAccessLogBucket: nw.myServerAccessLogBucket,
vpcEndpointSg: nw.myVpcEndpointSg,
mainAuroraSecret: mainaurora.myMainAuroraSecret,
mastermanagementSQS: ecsMastermanagement.myMastermanagementSQS,
internalAlb: ecsHotelmanagement.myInternalAlb,
mainAuroraCluster: mainaurora.myMainAuroraCluster,
myAdotEcrRepository: nw.myAdotEcrRepository,
pullThryoughCachePolicyStatement: nw.pullThryoughCachePolicyStatement,
awsOTelTaskRolePolicyStatement: nw.awsOTelTaskRolePolicyStatement,
alarmTopic: monitorCommon.alarmTopic,
// ホワイトリストIPアドレス
whitelistAddress: config.get("tourreservation.whitelistAddress"),
// Redis用パラメータ
redisReplicationGroupCacheNodeType: config.get("tourreservation.redisReplicationGroupCacheNodeType"),
redisReplicationGroupCacheClustersNumber: config.get("tourreservation.redisReplicationGroupCacheClustersNumber"),
// ECSサービス定義:Tourreservatison用パラメータ
tourreservationDesiredCount: config.get("tourreservation.tourreservationDesiredCount"),
tourreservationAASMin: config.get("tourreservation.tourreservationAASMin"),
tourreservationAASMax: config.get("tourreservation.tourreservationAASMax"),
tourreservationAASRequestsPerTarget: config.get("tourreservation.tourreservationAASRequestsPerTarget"),
// ECSタスク定義
tourreservationTaskCpu: config.get("tourreservation.tourreservationTaskCpu"),
tourreservationTaskMemoryLimit: config.get("tourreservation.tourreservationTaskMemoryLimit"),
// ECSコンテナ定義:Tourreservatisonコンテナ用パラメータ
tourreservationEcrRepositoryArn: config.get("tourreservation.tourreservationEcrRepositoryArn"),
tourreservationEnvSpringProfilesActive: config.get("tourreservation.tourreservationEnvSpringProfilesActive"),
// tourreservationEnvSpringLifecycleTimeoutPerShutdownPhase: config.get("tourreservation.tourreservationEnvSpringLifecycleTimeoutPerShutdownPhase"), // チューニングする時のみ使用
// tourreservationEnvDatasourceDriverclassname: config.get("tourreservation.tourreservationEnvDatasourceDriverclassname"), // チューニングする時のみ使用
// tourreservationEnvRedisPort: config.get("tourreservation.tourreservationEnvRedisPort"), // チューニングする時のみ使用
// tourreservationEnvApiRetryMaxAttempts: config.get("tourreservation.tourreservationEnvApiRetryMaxAttempts"), // チューニングする時のみ使用
// tourreservationEnvApiRetryMinBackoff: config.get("tourreservation.tourreservationEnvApiRetryMinBackoff"), // チューニングする時のみ使用
tourreservationEnvResilience4JTimeout: config.get("tourreservation.tourreservationEnvResilience4JTimeout"), // チューニングする時のみ使用
tourreservationEnvGcUploadIntervalSec: config.get("tourreservation.tourreservationEnvGcUploadIntervalSec"),
tourreservationEnvGcLogleve: config.get("tourreservation.tourreservationEnvGcLogleve"),
tourreservationEnvOtelResourceAttributes: config.get("tourreservation.tourreservationEnvOtelResourceAttributes"),
// アラーム定義の閾値
publicAlbLogBucketAllRequestsAlarmThreshold: config.get("tourreservationAlarm.publicAlbLogBucketAllRequestsAlarmThreshold"), // 永野さんに実案件での実績確認中
publicAlbLogBucket4xxErrorsAlarmThreshold: config.get("tourreservationAlarm.publicAlbLogBucket4xxErrorsAlarmThreshold"),
publicAlbLogBucket5xxErrorsAlarmThreshold: config.get("tourreservationAlarm.publicAlbLogBucket5xxErrorsAlarmThreshold"),
wafLogBucketAllRequestsAlarmThreshold: config.get("tourreservationAlarm.wafLogBucketAllRequestsAlarmThreshold"), // 永野さんに実案件での実績確認中
wafLogBucket4xxErrorsAlarmThreshold: config.get("tourreservationAlarm.wafLogBucket4xxErrorsAlarmThreshold"),
wafLogBucket5xxErrorsAlarmThreshold: config.get("tourreservationAlarm.wafLogBucket5xxErrorsAlarmThreshold"),
tourreservationFargateServiceCPUUtilizationAlarmThreshold: config.get("tourreservationAlarm.tourreservationFargateServiceCPUUtilizationAlarmThreshold"),
tourreservationFargateServiceMemoryUtilizationAlarmThreshold: config.get("tourreservationAlarm.tourreservationFargateServiceMemoryUtilizationAlarmThreshold"),
publicAlbHTTPCodeELB4XXCountAlarmThreshold: config.get("tourreservationAlarm.publicAlbHTTPCodeELB4XXCountAlarmThreshold"),
publicAlbHTTPCodeELB5XXCountAlarmThreshold: config.get("tourreservationAlarm.publicAlbHTTPCodeELB5XXCountAlarmThreshold"),
publicAlbHTTPCodeELB500CountAlarmThreshold: config.get("tourreservationAlarm.publicAlbHTTPCodeELB500CountAlarmThreshold"),
publicAlbHTTPCodeELB502CountAlarmThreshold: config.get("tourreservationAlarm.publicAlbHTTPCodeELB502CountAlarmThreshold"),
publicAlbHTTPCodeELB503CountAlarmThreshold: config.get("tourreservationAlarm.publicAlbHTTPCodeELB503CountAlarmThreshold"),
publicAlbHTTPCodeELB504CountAlarmThreshold: config.get("tourreservationAlarm.publicAlbHTTPCodeELB504CountAlarmThreshold"),
publicAlbRejectedConnectionCountAlarmThreshold: config.get("tourreservationAlarm.publicAlbRejectedConnectionCountAlarmThreshold"),
tourreservationTargetGroupHealthyHostCountAlarmThreshold: config.get("tourreservationAlarm.tourreservationTargetGroupHealthyHostCountAlarmThreshold"), // オートスケーリングの下限
tourreservationTargetGroupHTTPCodeELB2XXCountAlarmThreshold: config.get("tourreservationAlarm.tourreservationTargetGroupHTTPCodeELB2XXCountAlarmThreshold"),
tourreservationTargetGroupHTTPCodeELB3XXCountAlarmThreshold: config.get("tourreservationAlarm.tourreservationTargetGroupHTTPCodeELB3XXCountAlarmThreshold"),
tourreservationTargetGroupHTTPCodeELB4XXCountAlarmThreshold: config.get("tourreservationAlarm.tourreservationTargetGroupHTTPCodeELB4XXCountAlarmThreshold"),
tourreservationTargetGroupHTTPCodeELB5XXCountAlarmThreshold: config.get("tourreservationAlarm.tourreservationTargetGroupHTTPCodeELB5XXCountAlarmThreshold"),
tourreservationTargetGroupTargetResponseTimeAlarmThreshold: config.get("tourreservationAlarm.tourreservationTargetGroupTargetResponseTimeAlarmThreshold"),
redisNodeCPUUtilizationAlarmThreshold: config.get("tourreservationAlarm.redisNodeCPUUtilizationAlarmThreshold"),
redisNodeFreeableMemoryAlarmThreshold: config.get("tourreservationAlarm.redisNodeFreeableMemoryAlarmThreshold"),
redisNodeSwapUsageAlarmThreshold: config.get("tourreservationAlarm.redisNodeSwapUsageAlarmThreshold"),
redisNodeCurrConnectionsAlarmThreshold: config.get("tourreservationAlarm.redisNodeCurrConnectionsAlarmThreshold"),
redisNodeDatabaseMemoryUsagePercentageAlarmThreshold: config.get("tourreservationAlarm.redisNodeDatabaseMemoryUsagePercentageAlarmThreshold"),
redisNodeMemoryFragmentationRatioAlarmThreshold: config.get("tourreservationAlarm.redisNodeMemoryFragmentationRatioAlarmThreshold"), // 1を超えるとフラグメント発生しているが、標準アーキだとインスタンスタイプが小さいため2.5で設定する。
redisNodeReplicationBytesAlarmThreshold: config.get("tourreservationAlarm.redisNodeReplicationBytesAlarmThreshold"),
redisNodeReplicationLagAlarmThreshold: config.get("tourreservationAlarm.redisNodeReplicationLagAlarmThreshold"),
redisNodeStringBasedCmdsLatencyAlarmThreshold: config.get("tourreservationAlarm.redisNodeStringBasedCmdsLatencyAlarmThreshold"),
});
/**
* 標準アーキ1Log Archive関連リソースContructクラス
*/
const logarchive = new Logarchive(this, "Logarchive", {
envName: config.get("common.envPrefix"),
vpc: nw.myVpc,
serverAccessLogBucket: nw.myServerAccessLogBucket,
alarmTopic: monitorCommon.alarmTopic,
logarchiveMemorySize: config.get("logarchive.logarchiveMemorySize"),
// アラーム定義の閾値
LogarchiveBucket4xxErrorsAlarmThreshold: config.get("logarchiveAlarm.LogarchiveBucket4xxErrorsAlarmThreshold"),
LogarchiveBucket5xxErrorsAlarmThreshold: config.get("logarchiveAlarm.LogarchiveBucket5xxErrorsAlarmThreshold"),
LogarchiveBucketAllRequestsAlarmThreshold: config.get("logarchiveAlarm.LogarchiveBucketAllRequestsAlarmThreshold"),
LogarchiveFunctionDurationAlarmThreshold: config.get("logarchiveAlarm.LogarchiveFunctionDurationAlarmThreshold"),
});
/**
* 標準アーキ1初期データ自動投入関連リソースContructクラス
*/
const dataInput = new DataInput(this, "DataInput", {
envName: config.get("common.envPrefix"),
vpc: nw.myVpc,
vpcEndpointSg: nw.myVpcEndpointSg,
mainAuroraCluster: mainaurora.myMainAuroraCluster,
mainAuroraSecret: mainaurora.myMainAuroraSecret,
myHotelDynamoTable: ecsHotelmanagement.myHotelDynamoTable,
alarmTopic: monitorCommon.alarmTopic,
});
}
}
gc-std-archi1-stack
import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
import * as ssm from "aws-cdk-lib/aws-ssm";
import * as cloudwatch from "aws-cdk-lib/aws-cloudwatch";
export interface GcStdArchi1SsmProps {
instanceId: string;
}
export class GcStdArchi1Ssm extends Construct {
constructor(scope: Construct, id: string, props: GcStdArchi1SsmProps) {
super(scope, id);
// CPU 使用率メトリクスの作成
const cpuMetric = new cloudwatch.Metric({
namespace: "AWS/EC2",
metricName: "CPUUtilization",
dimensionsMap: { InstanceId: props.instanceId },
statistic: "Average",
});
// SSM パラメータにメトリクス情報を保存
new ssm.StringParameter(this, "EC2MetricNamespace", {
parameterName: "/myapp/ec2/namespace",
stringValue: cpuMetric.namespace,
});
new ssm.StringParameter(this, "EC2MetricName", {
parameterName: "/myapp/ec2/metric_name",
stringValue: cpuMetric.metricName,
});
new ssm.StringParameter(this, "EC2MetricDimensions", {
parameterName: "/myapp/ec2/dimensions",
stringValue: JSON.stringify(cpuMetric.dimensionsMap),
});
}
}
lib/resources/GcStdArchi1Ssm.ts
new GcStdArchi1Ssm(this, "GcStdArchi1Ssm", {
instanceId: "i-0123456789", // 必要に応じて実際のインスタンス ID に置き換え
});
btrikra:~/environment/FBS-viz-trial/gc-std-archi1-app (master) $ cdk deploy GcStdArchi1Stack
npm warn exec The following package was not found and will be installed: ts-node@10.9.2
/home/ec2-user/.npm/_npx/1bf7c3c15bf47d04/node_modules/ts-node/src/index.ts:859
return new TSError(diagnosticText, diagnosticCodes, diagnostics);
^
TSError: ⨯ Unable to compile TypeScript:
bin/gc-std-archi1-app.ts:6:25 - error TS2307: Cannot find module 'config' or its corresponding type declarations.
6 import * as config from "config"; // node-configモジュールのインポート
~~~~~~~~
bin/gc-std-archi1-app.ts:12:17 - error TS2580: Cannot find name 'process'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node`.
12 const envName = process.env.NODE_ENV;
~~~~~~~
bin/gc-std-archi1-app.ts:18:3 - error TS2580: Cannot find name 'process'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node`.
18 process.exit(1);
~~~~~~~
at createTSError (/home/ec2-user/.npm/_npx/1bf7c3c15bf47d04/node_modules/ts-node/src/index.ts:859:12)
at reportTSError (/home/ec2-user/.npm/_npx/1bf7c3c15bf47d04/node_modules/ts-node/src/index.ts:863:19)
at getOutput (/home/ec2-user/.npm/_npx/1bf7c3c15bf47d04/node_modules/ts-node/src/index.ts:1077:36)
at Object.compile (/home/ec2-user/.npm/_npx/1bf7c3c15bf47d04/node_modules/ts-node/src/index.ts:1433:41)
at Module.m._compile (/home/ec2-user/.npm/_npx/1bf7c3c15bf47d04/node_modules/ts-node/src/index.ts:1617:30)
at Module._extensions..js (node:internal/modules/cjs/loader:1422:10)
at Object.require.extensions.<computed> [as .ts] (/home/ec2-user/.npm/_npx/1bf7c3c15bf47d04/node_modules/ts-node/src/index.ts:1621:12)
at Module.load (node:internal/modules/cjs/loader:1203:32)
at Function.Module._load (node:internal/modules/cjs/loader:1019:12)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:128:12) {
diagnosticCodes: [ 2307, 2580, 2580 ]
}
****************************************************
*** Newer version of CDK is available [2.166.0] ***
*** Upgrade recommended (npm install -g aws-cdk) ***
****************************************************
Subprocess exited with error 1
btrikra:~/environment/FBS-viz-trial/gc-std-archi1-app (master) $ cdk deploy GcStdArchi1Stack
/home/ec2-user/environment/FBS-viz-trial/gc-std-archi1-app/node_modules/ts-node/src/index.ts:859
return new TSError(diagnosticText, diagnosticCodes, diagnostics);
^
TSError: ⨯ Unable to compile TypeScript:
lib/resources/gc-std-archi1-dashboard.ts:35:45 - error TS2551: Property 'dimensionsMap' does not exist on type 'Metric'. Did you mean 'dimensions'?
35 stringValue: JSON.stringify(cpuMetric.dimensionsMap),
~~~~~~~~~~~~~
node_modules/aws-cdk-lib/aws-cloudwatch/lib/metric.d.ts:227:14
227 readonly dimensions?: DimensionHash;
~~~~~~~~~~
'dimensions' is declared here.
at createTSError (/home/ec2-user/environment/FBS-viz-trial/gc-std-archi1-app/node_modules/ts-node/src/index.ts:859:12)
at reportTSError (/home/ec2-user/environment/FBS-viz-trial/gc-std-archi1-app/node_modules/ts-node/src/index.ts:863:19)
at getOutput (/home/ec2-user/environment/FBS-viz-trial/gc-std-archi1-app/node_modules/ts-node/src/index.ts:1077:36)
at Object.compile (/home/ec2-user/environment/FBS-viz-trial/gc-std-archi1-app/node_modules/ts-node/src/index.ts:1433:41)
at Module.m._compile (/home/ec2-user/environment/FBS-viz-trial/gc-std-archi1-app/node_modules/ts-node/src/index.ts:1617:30)
at Module._extensions..js (node:internal/modules/cjs/loader:1422:10)
at Object.require.extensions.<computed> [as .ts] (/home/ec2-user/environment/FBS-viz-trial/gc-std-archi1-app/node_modules/ts-node/src/index.ts:1621:12)
at Module.load (node:internal/modules/cjs/loader:1203:32)
at Function.Module._load (node:internal/modules/cjs/loader:1019:12)
at Module.require (node:internal/modules/cjs/loader:1231:19) {
diagnosticCodes: [ 2551 ]
}
Subprocess exited with error 1
btrikra:~/environment/FBS-viz-trial/gc-std-archi1-app (master) $ cdk deploy GcStdArchi1Stack
This CDK CLI is not compatible with the CDK library used by your application. Please upgrade the CLI to the latest version. (Cloud assembly schema version mismatch: Maximum schema version supported is 32.0.0, but found 36.0.0) btrikra:~/environment/FBS-viz-trial/gc-std-archi1-app (master) $ cdk --version 2.84.0 (build f7c792f)
btrikra:~/environment/FBS-viz-trial/gc-std-archi1-app (master) $ npm install -g aws-cdk npm error code EACCES npm error syscall rename npm error path /usr/local/lib/node_modules/aws-cdk npm error dest /usr/local/lib/node_modules/.aws-cdk-kzzr8ey1 npm error errno -13 npm error [Error: EACCES: permission denied, rename '/usr/local/lib/node_modules/aws-cdk' -> '/usr/local/lib/node_modules/.aws-cdk-kzzr8ey1'] { npm error errno: -13, npm error code: 'EACCES', npm error syscall: 'rename', npm error path: '/usr/local/lib/node_modules/aws-cdk', npm error dest: '/usr/local/lib/node_modules/.aws-cdk-kzzr8ey1' npm error } npm error npm error The operation was rejected by your operating system. npm error It is likely you do not have the permissions to access this file as the current user npm error npm error If you believe this might be a permissions issue, please double-check the npm error permissions of the file and its containing directories, or try running npm error the command again as root/Administrator. npm error A complete log of this run can be found in: /home/ec2-user/.npm/_logs/2024-11-11T03_10_18_853Z-debug-0.log
// resources/gc-std-archi1-dashboard.ts
import * as cloudwatch from 'aws-cdk-lib/aws-cloudwatch';
import { Construct } from 'constructs';
export interface DashboardProps {
dashboardName: string; // ダッシュボード名を外部から指定可能にする
}
export class GcStdArchi1Dashboard extends Construct {
public readonly dashboard: cloudwatch.Dashboard;
constructor(scope: Construct, id: string, props: DashboardProps) {
super(scope, id);
// ダッシュボードの作成
this.dashboard = new cloudwatch.Dashboard(this, 'Dashboard', {
dashboardName: props.dashboardName
});
// CPU メトリクスの例
const cpuMetric = new cloudwatch.Metric({
namespace: 'AWS/EC2',
metricName: 'CPUUtilization',
dimensionsMap: { InstanceId: 'i-0123456789' }, // 適切なインスタンスIDに置き換え
statistic: 'Average',
});
// グラフウィジェットの追加
this.dashboard.addWidgets(
new cloudwatch.GraphWidget({
title: 'EC2 CPU Utilization',
left: [cpuMetric],
})
);
}
}
// GcStdArchi1Stack ファイル
import * as cdk from "aws-cdk-lib";
import { Construct } from "constructs";
import { GcStdArchi1Dashboard } from "./resources/gc-std-archi1-dashboard"; // 作成したダッシュボードをインポート
export class GcStdArchi1Stack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// CloudWatch ダッシュボードのインスタンスを作成し、スタックに追加
const dashboard = new GcStdArchi1Dashboard(this, 'MyAppDashboard', {
dashboardName: 'GcStdArchi1Dashboard'
});
// 既存のリソース作成コードを保持
// 例: MonitorCommon、Nw、AppS3Bucket などのインスタンス化コード
}
}
import * as cdk from "aws-cdk-lib";
import * as s3 from "aws-cdk-lib/aws-s3";
import { Construct } from "constructs";
import * as lambda from "aws-cdk-lib/aws-lambda";
import * as cloudwatch from "aws-cdk-lib/aws-cloudwatch";
import * as nag from "cdk-nag"; // cdk-nagモジュールのインポート
import * as path from "path";
/**
* Dashboardクラスの初期化に必要なパラメータ定義
*/
export interface DashboardProps {
/**
* 環境名を小文字の英字で指定する。
* リソースの物理名やNameタグに利用される。
*/
envName: string;
}
/**
* ダッシュボードを展開するConstruct。
*
* @remarks
* 以下のリソースを展開する。
* - 表示メトリクス用S3バケット
* - 表示メトリクス用Lambda
* - 各種ウィジェット
* - ダッシュボード
*/
export class Dashboard extends Construct {
/**
* ダッシュボードを展開する。
* 初期化時に引数で与える{@link DashboardProps}の値に応じて環境パラメータが設定される。
*
* @param props -
* AppS3Bucketクラスインスタンス初期化用のプロパティを指定する。詳細は{@link DashboardProps}を参照すること。
*/
constructor(scope: Construct, id: string, props: DashboardProps) {
super(scope, id);
// 表示メトリクス用S3バケット作成
const myVizBucket = new s3.Bucket(this, "VizBucket", {
bucketName: `viz-${props.envName}-vizbucket`,
enforceSSL: true,
removalPolicy: cdk.RemovalPolicy.DESTROY,
autoDeleteObjects: true,
});
cdk.Tags.of(myVizBucket).add(
"Name",
"viz-" + props.envName + "-vizbucket"
);
myVizBucket.addMetric({id: "EntireBucket"});
nag.NagSuppressions.addResourceSuppressions(
myVizBucket,
[
{ id: "AwsSolutions-S1", reason: "Because of test",},
],
true
);
// 表示メトリクス用Lambda作成
const myTestFunction = new lambda.Function(this, "TestFunction", {
functionName: `viz-${props.envName}-test`,
code: lambda.Code.fromAsset(path.join(__dirname, "../../lambda/test/")),
handler: "main.lambda_handler",
runtime: lambda.Runtime.PYTHON_3_8,
});
cdk.Tags.of(myTestFunction).add(
"Name",
"viz-" + props.envName + "-testFnction"
);
nag.NagSuppressions.addResourceSuppressions(
myTestFunction,
[
{ id: "AwsSolutions-IAM4", reason: "Use AWS Managed Policies.", appliesTo: ["Policy::arn:<AWS::Partition>:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"]},
{ id: "AwsSolutions-L1", reason: "Because of test",},
],
true
);
// NumberOfObjectsメトリクスのウィジェット作成
const allRequestsMetric = new cloudwatch.Metric({
namespace: 'AWS/S3',
metricName: 'AllRequests',
dimensionsMap: {
BucketName: myVizBucket.bucketName,
FilterId: "EntireBucket"
},
statistic: 'Average',
period: cdk.Duration.minutes(5),
});
const allRequestsWidget = new cloudwatch.GraphWidget({
title: 'All Requests in S3 Bucket',
left: [allRequestsMetric],
});
// CloudWatchダッシュボードの作成
new cloudwatch.Dashboard(this, 'MyDashboard', {
dashboardName: 'MyDashboard',
widgets: [
[allRequestsWidget]
],
});
};
}
・折れ線と棒グラフを同じウィジェットに表示する方法
・leftとrightの違い
・ウィジェットの配置(addWidgetの仕様?)
AllRequests: バケットへのすべてのリクエスト数。S3 の利用頻度を把握するために使用されます。 GetRequests: GET リクエストの数。オブジェクトの読み取り操作の頻度を把握するために使用します。 PutRequests: PUT リクエストの数。オブジェクトの追加や更新頻度を把握するために使用されます。 4xxErrors: クライアントエラー(4xx)のリクエスト数。ユーザーのアクセスエラーや設定ミスなど、アクセスに関する問題がないか監視します。 5xxErrors: サーバーエラー(5xx)のリクエスト数。S3 サーバー側でのエラーが発生していないか監視するために使用します。 BytesDownloaded: バケットからダウンロードされたデータ量。データ転送量を把握し、トラフィックやコストの管理に役立ちます。 BytesUploaded: バケットにアップロードされたデータ量。アップロードのトラフィック量を確認するために使用します。
// CloudWatch メトリクスの追加
const allRequestsMetric = new cloudwatch.Metric({
namespace: 'AWS/S3',
metricName: 'AllRequests',
dimensionsMap: {
BucketName: myVizBucket.bucketName,
FilterId: "EntireBucket"
},
statistic: 'Sum',
period: cdk.Duration.minutes(5),
});
const getRequestMetric = new cloudwatch.Metric({
namespace: 'AWS/S3',
metricName: 'GetRequests',
dimensionsMap: {
BucketName: myVizBucket.bucketName,
FilterId: "EntireBucket"
},
statistic: 'Sum',
period: cdk.Duration.minutes(5),
});
const putRequestMetric = new cloudwatch.Metric({
namespace: 'AWS/S3',
metricName: 'PutRequests',
dimensionsMap: {
BucketName: myVizBucket.bucketName,
FilterId: "EntireBucket"
},
statistic: 'Sum',
period: cdk.Duration.minutes(5),
});
const clientErrorMetric = new cloudwatch.Metric({
namespace: 'AWS/S3',
metricName: '4xxErrors',
dimensionsMap: {
BucketName: myVizBucket.bucketName,
FilterId: "EntireBucket"
},
statistic: 'Sum',
period: cdk.Duration.minutes(5),
});
const serverErrorMetric = new cloudwatch.Metric({
namespace: 'AWS/S3',
metricName: '5xxErrors',
dimensionsMap: {
BucketName: myVizBucket.bucketName,
FilterId: "EntireBucket"
},
statistic: 'Sum',
period: cdk.Duration.minutes(5),
});
const bytesDownloadedMetric = new cloudwatch.Metric({
namespace: 'AWS/S3',
metricName: 'BytesDownloaded',
dimensionsMap: {
BucketName: myVizBucket.bucketName,
FilterId: "EntireBucket"
},
statistic: 'Sum',
period: cdk.Duration.minutes(5),
});
const bytesUploadedMetric = new cloudwatch.Metric({
namespace: 'AWS/S3',
metricName: 'BytesUploaded',
dimensionsMap: {
BucketName: myVizBucket.bucketName,
FilterId: "EntireBucket"
},
statistic: 'Sum',
period: cdk.Duration.minutes(5),
});
// 折れ線と棒グラフを同じウィジェットに表示
const requestsAndErrorsWidget = new cloudwatch.GraphWidget({
title: 'S3 Requests and Errors',
left: [allRequestsMetric, getRequestMetric, putRequestMetric],
right: [clientErrorMetric, serverErrorMetric], // エラーを右Y軸に表示
view: cloudwatch.GraphWidgetView.BAR, // 棒グラフを指定
});
const bytesWidget = new cloudwatch.GraphWidget({
title: 'S3 Data Transfer',
left: [bytesDownloadedMetric],
right: [bytesUploadedMetric],
view: cloudwatch.GraphWidgetView.TIME_SERIES, // 折れ線グラフを指定
});
// CloudWatch ダッシュボードにウィジェットを配置
new cloudwatch.Dashboard(this, 'MyDashboard', {
dashboardName: 'MyDashboard',
widgets: [
[requestsAndErrorsWidget],
[bytesWidget]
],
});
import * as cdk from "aws-cdk-lib";
import * as s3 from "aws-cdk-lib/aws-s3";
import { Construct } from "constructs";
import * as lambda from "aws-cdk-lib/aws-lambda";
import * as cloudwatch from "aws-cdk-lib/aws-cloudwatch";
import * as nag from "cdk-nag"; // cdk-nagモジュールのインポート
import * as path from "path";
export interface DashboardProps {
envName: string;
}
export class Dashboard extends Construct {
constructor(scope: Construct, id: string, props: DashboardProps) {
super(scope, id);
// 表示メトリクス用S3バケット作成
const myVizBucket = new s3.Bucket(this, "VizBucket", {
bucketName: `viz-${props.envName}-vizbucket`,
enforceSSL: true,
removalPolicy: cdk.RemovalPolicy.DESTROY,
autoDeleteObjects: true,
});
cdk.Tags.of(myVizBucket).add("Name", `viz-${props.envName}-vizbucket`);
myVizBucket.addMetric({ id: "EntireBucket" });
nag.NagSuppressions.addResourceSuppressions(
myVizBucket,
[{ id: "AwsSolutions-S1", reason: "Because of test" }],
true
);
// 表示メトリクス用Lambda作成
const myTestFunction = new lambda.Function(this, "TestFunction", {
functionName: `viz-${props.envName}-test`,
code: lambda.Code.fromAsset(path.join(__dirname, "../../lambda/test/")),
handler: "main.lambda_handler",
runtime: lambda.Runtime.PYTHON_3_8,
});
cdk.Tags.of(myTestFunction).add("Name", `viz-${props.envName}-testFnction`);
nag.NagSuppressions.addResourceSuppressions(
myTestFunction,
[
{
id: "AwsSolutions-IAM4",
reason: "Use AWS Managed Policies.",
appliesTo: [
"Policy::arn:<AWS::Partition>:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",
],
},
{ id: "AwsSolutions-L1", reason: "Because of test" },
],
true
);
// S3の基本メトリクスの設定
const allRequestsMetric = new cloudwatch.Metric({
namespace: "AWS/S3",
metricName: "AllRequests",
dimensionsMap: {
BucketName: myVizBucket.bucketName,
FilterId: "EntireBucket",
},
statistic: "Sum",
period: cdk.Duration.minutes(5),
});
const getRequestMetric = new cloudwatch.Metric({
namespace: "AWS/S3",
metricName: "GetRequests",
dimensionsMap: {
BucketName: myVizBucket.bucketName,
FilterId: "EntireBucket",
},
statistic: "Sum",
period: cdk.Duration.minutes(5),
});
const putRequestMetric = new cloudwatch.Metric({
namespace: "AWS/S3",
metricName: "PutRequests",
dimensionsMap: {
BucketName: myVizBucket.bucketName,
FilterId: "EntireBucket",
},
statistic: "Sum",
period: cdk.Duration.minutes(5),
});
const clientErrorMetric = new cloudwatch.Metric({
namespace: "AWS/S3",
metricName: "4xxErrors",
dimensionsMap: {
BucketName: myVizBucket.bucketName,
FilterId: "EntireBucket",
},
statistic: "Sum",
period: cdk.Duration.minutes(5),
});
const serverErrorMetric = new cloudwatch.Metric({
namespace: "AWS/S3",
metricName: "5xxErrors",
dimensionsMap: {
BucketName: myVizBucket.bucketName,
FilterId: "EntireBucket",
},
statistic: "Sum",
period: cdk.Duration.minutes(5),
});
const bytesDownloadedMetric = new cloudwatch.Metric({
namespace: "AWS/S3",
metricName: "BytesDownloaded",
dimensionsMap: {
BucketName: myVizBucket.bucketName,
FilterId: "EntireBucket",
},
statistic: "Sum",
period: cdk.Duration.minutes(5),
});
const bytesUploadedMetric = new cloudwatch.Metric({
namespace: "AWS/S3",
metricName: "BytesUploaded",
dimensionsMap: {
BucketName: myVizBucket.bucketName,
FilterId: "EntireBucket",
},
statistic: "Sum",
period: cdk.Duration.minutes(5),
});
// リクエスト数とエラー数を同じウィジェットに表示
const requestsAndErrorsWidget = new cloudwatch.GraphWidget({
title: "S3 Requests and Errors",
left: [allRequestsMetric, getRequestMetric, putRequestMetric], // リクエスト数を左Y軸に表示
right: [clientErrorMetric, serverErrorMetric], // エラー数を右Y軸に表示
view: cloudwatch.GraphWidgetView.BAR, // 棒グラフで表示
});
// データ転送量(アップロードとダウンロード)を同じウィジェットに表示
const bytesWidget = new cloudwatch.GraphWidget({
title: "S3 Data Transfer",
left: [bytesDownloadedMetric], // ダウンロードを左Y軸に表示
right: [bytesUploadedMetric], // アップロードを右Y軸に表示
view: cloudwatch.GraphWidgetView.TIME_SERIES, // 折れ線グラフで表示
});
// CloudWatch ダッシュボードの作成とウィジェットの追加
new cloudwatch.Dashboard(this, "MyDashboard", {
dashboardName: "MyDashboard",
widgets: [
[requestsAndErrorsWidget], // 1行目のウィジェット
[bytesWidget], // 2行目のウィジェット
],
});
}
}
// 折れ線と棒グラフを1つのウィジェットにまとめて表示
const combinedWidget = new cloudwatch.GraphWidget({
title: "S3 Metrics: Requests, Errors, and Data Transfer",
left: [allRequestsMetric, getRequestMetric, putRequestMetric], // 左Y軸に棒グラフ形式
right: [clientErrorMetric, serverErrorMetric, bytesDownloadedMetric, bytesUploadedMetric], // 右Y軸に折れ線グラフ形式
leftYAxis: { label: "Requests (Bar)" }, // 左Y軸ラベル
rightYAxis: { label: "Errors & Transfer (Line)" }, // 右Y軸ラベル
view: cloudwatch.GraphWidgetView.BAR, // デフォルトの表示形式をBARに設定
});
// CloudWatch ダッシュボードにウィジェットを追加
new cloudwatch.Dashboard(this, "MyDashboard", {
dashboardName: "MyDashboard",
widgets: [
[combinedWidget],
],
});
}
}
// 左側に表示する棒グラフウィジェット
const leftBarWidget = new cloudwatch.GraphWidget({
title: "S3 Requests (Bar)",
left: [allRequestsMetric, getRequestMetric], // リクエスト系メトリクス
view: cloudwatch.GraphWidgetView.BAR,
});
// 右側に表示する折れ線グラフウィジェット
const rightLineWidget = new cloudwatch.GraphWidget({
title: "S3 Errors and Data Transfer (Line)",
right: [clientErrorMetric, serverErrorMetric], // エラー系メトリクス
view: cloudwatch.GraphWidgetView.TIME_SERIES,
});
// CloudWatch ダッシュボードの作成とウィジェットの追加
new cloudwatch.Dashboard(this, "MyDashboard", {
dashboardName: "MyDashboard",
widgets: [
[leftBarWidget],
[rightLineWidget],
],
});
}
}
現在のCDKのGraphWidgetでは、1つのウィジェットで左側を棒グラフ、右側を折れ線グラフに設定する方法は提供されていません。CDKでのGraphWidgetの表示形式はウィジェット全体に対して適用されるため、左右で異なる表示形式(左が棒グラフ、右が折れ線グラフ)を設定することができないのです。
CloudWatchのウィジェットにおいて、左右のY軸に異なるメトリクスを表示するための設定です
const widget = new cloudwatch.GraphWidget({ title: "S3 Requests and Errors", left: [allRequestsMetric, getRequestMetric], // 左Y軸にリクエスト数を表示 right: [clientErrorMetric, serverErrorMetric], // 右Y軸にエラー数を表示 });
プロパティ
end
height
left
leftAnnotations
leftYAxis
legendPosition
liveData
period
region
right
rightAnnotations
rightYAxis
setPeriodToTimeRange
stacked
start
statistic
title
verticalAnnotations
view
width
メソッド
addLeftMetric(metric)
addRightMetric(metric)
position(x, y)
toJson()
用途 影響箇所 使用例 必須 データ型 デフォルト 備考
GraphWidgetのプロパティ
end
用途: グラフの終了時間を指定します。この設定により、データが表示される時間範囲の終了時刻を制限できます。
影響箇所: グラフの表示範囲
使用例: end: '2023-12-31T23:59:59Z'
必須: いいえ
データ型: string
デフォルト: undefined
備考: startプロパティと組み合わせることで、特定の期間のデータを表示可能です。
height
用途: グラフの縦方向のサイズをピクセル単位で指定します。
影響箇所: グラフの表示サイズ
使用例: height: 300
必須: いいえ
データ型: number
デフォルト: 6
備考: 値が大きいほどグラフが高く表示されます。
left
用途: グラフの左Y軸に表示するメトリクス(指標)を指定します。
影響箇所: 左側Y軸
使用例: left: [metric1, metric2]
必須: いいえ
データ型: IMetric[]
デフォルト: []
備考: addLeftMetricメソッドで動的に追加できます。
leftAnnotations
用途: 左Y軸に表示する水平線(注釈)を設定します。
影響箇所: 左Y軸の注釈
使用例: { value: 70, color: 'red' }
必須: いいえ
データ型: HorizontalAnnotation[]
デフォルト: []
備考: 視覚的な目標値や基準値を示すのに便利です。
leftYAxis
用途: 左Y軸のスケールや表示設定を指定します。
影響箇所: 左Y軸
使用例: { min: 0, max: 100 }
必須: いいえ
データ型: YaxisProps
デフォルト: undefined
備考: Y軸の範囲を固定して表示したい場合に使用します。
legendPosition
用途: 凡例(ラベル)の表示位置を指定します。
影響箇所: 凡例の位置
使用例: legendPosition: 'bottom'
必須: いいえ
データ型: LegendPosition
デフォルト: 'right'
備考: 'bottom'や'right'などが利用可能です。
liveData
用途: グラフをリアルタイムデータに更新するかどうかを設定します。
影響箇所: リアルタイム更新
使用例: liveData: true
必須: いいえ
データ型: boolean
デフォルト: false
備考: trueにすると、最新のデータが自動的に表示されます。
period
用途: データ取得の間隔を秒単位で設定します。
影響箇所: データの間隔
使用例: period: 300(5分間隔)
必須: いいえ
データ型: Duration
デフォルト: undefined
備考: より短い期間で更新する場合に便利です。
region
用途: メトリクスを取得するAWSリージョンを指定します。
影響箇所: データの取得元リージョン
使用例: region: 'us-west-2'
必須: いいえ
データ型: string
デフォルト: undefined
備考: デフォルトリージョン以外のリージョンのメトリクスを使用したい場合に指定します。
right
用途: グラフの右Y軸に表示するメトリクスを指定します。
影響箇所: 右側Y軸
使用例: right: [metric3]
必須: いいえ
データ型: IMetric[]
デフォルト: []
備考: addRightMetricメソッドで動的に追加可能です。
rightAnnotations
用途: 右Y軸に注釈を追加します。
影響箇所: 右Y軸の注釈
使用例: { value: 80, color: 'blue' }
必須: いいえ
データ型: HorizontalAnnotation[]
デフォルト: []
備考: 視覚的な基準値を示す場合に使用されます。
rightYAxis
用途: 右Y軸のスケールや設定を調整します。
影響箇所: 右Y軸
使用例: { min: 0, max: 200 }
必須: いいえ
データ型: YaxisProps
デフォルト: undefined
備考: メトリクスが多い場合の範囲設定に便利です。
setPeriodToTimeRange
用途: 自動で期間を指定した時間範囲に設定します。
影響箇所: データの表示範囲
使用例: setPeriodToTimeRange: true
必須: いいえ
データ型: boolean
デフォルト: false
備考: 時間範囲に応じて動的に期間が変更されます。
stacked
用途: グラフを積み上げ表示するか設定します。
影響箇所: グラフの表示形式
使用例: stacked: true
必須: いいえ
データ型: boolean
デフォルト: false
備考: 積み上げグラフで複数メトリクスの合計値を視覚化可能。
start
用途: グラフの開始時間を指定します。
影響箇所: グラフの表示範囲
使用例: start: '2023-01-01T00:00:00Z'
必須: いいえ
データ型: string
デフォルト: undefined
備考: endと組み合わせて特定の期間を表示します。
statistic
用途: メトリクスの統計タイプを指定します。
影響箇所: データの統計表示
使用例: statistic: 'Average'
必須: いいえ
データ型: string
デフォルト: 'Average'
備考: 'Sum'、'Maximum'なども設定可能です。
title
用途: グラフのタイトルを設定します。
影響箇所: グラフの見出し
使用例: title: 'Monthly Sales Metrics'
必須: いいえ
データ型: string
デフォルト: ''
備考: グラフ上部に表示されます。
verticalAnnotations
用途: グラフ内に縦方向の注釈を追加します。
影響箇所: グラフ内の注釈
使用例: { value: '2023-06-15', label: 'Mid-year' }
必須: いいえ
データ型: VerticalAnnotation[]
デフォルト: []
備考: 特定のイベント日を示す場合に便利です。
view
用途: グラフの表示形式を指定します。
影響箇所: グラフの表示方法
使用例: view: 'timeSeries'
必須: いいえ
データ型: string
デフォルト: 'timeSeries'
備考: 'singleValue'も選択可能です。
width
用途: グラフの横幅をピクセル単位で指定します。
影響箇所: グラフの表示サイズ
使用例: width: 400
必須: いいえ
データ型: number
デフォルト: 6
備考: 値が大きいほどグラフが横に広く表示されます。
GraphWidgetのメソッド
addLeftMetric(metric)
用途: 左Y軸に表示するメトリクスを追加します。
影響箇所: 左側Y軸
使用例: widget.addLeftMetric(metric1)
必須: いいえ
データ型: IMetric
デフォルト: なし
備考: メトリクスを複数追加して視覚的に比較可能です。
addRightMetric(metric)
用途: 右Y軸に表示するメトリクスを追加します。
影響箇所: 右側Y軸
使用例: widget.addRightMetric(metric3)
必須: いいえ
データ型: IMetric
デフォルト: なし
備考: 左右のメトリクスで異なるスケールのデータを表示可能です。
position(x, y)
用途: ダッシュボード上でのグラフの位置を指定します。
影響箇所: ダッシュボードの配置
使用例: widget.position(2, 3)
必須: いいえ
データ型: number, number
デフォルト: なし
備考: 座標指定で柔軟に配置を調整可能です。
toJson()
用途: グラフをJSON形式に変換して出力します。
影響箇所: データ出力
使用例: widget.toJson()
必須: いいえ
データ型: string
デフォルト: なし
備考: ダッシュボードの設定をJSONでエクスポート可能です。
import * as cdk from 'aws-cdk-lib';
import { Duration } from 'aws-cdk-lib';
import * as cloudwatch from 'aws-cdk-lib/aws-cloudwatch';
import { Construct } from 'constructs';
export class MyDashboardStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// S3 Requests and Errors Widget
const requestsAndErrorsWidget = new cloudwatch.GraphWidget({
title: "S3 Requests and Errors",
left: [allRequestsMetric, getRequestMetric, putRequestMetric], // リクエスト数を左Y軸に表示
right: [clientErrorMetric, serverErrorMetric], // エラー数を右Y軸に表示
view: cloudwatch.GraphWidgetView.BAR, // 棒グラフで表示
height: 8, // ウィジェットの高さ
width: 12, // ウィジェットの幅
start: '2023-01-01T00:00:00Z', // 開始時間
end: '2023-12-31T23:59:59Z', // 終了時間
legendPosition: cloudwatch.LegendPosition.BOTTOM, // 凡例の位置
liveData: true, // リアルタイムデータ
setPeriodToTimeRange: true, // 時間範囲に基づいて期間自動設定
stacked: true, // 積み上げグラフ表示
leftYAxis: {
min: 0,
max: 1000,
},
rightYAxis: {
min: 0,
max: 500,
},
leftAnnotations: [
{ value: 800, color: 'red', label: 'High Request Volume' }
],
rightAnnotations: [
{ value: 100, color: 'blue', label: 'Error Threshold' }
],
verticalAnnotations: [
{ value: '2023-06-15T00:00:00Z', label: 'Mid-year' }
],
period: Duration.minutes(5), // データ取得の間隔を指定
region: 'us-west-2', // リージョン
});
// データ転送量(アップロードとダウンロード)ウィジェット
const bytesWidget = new cloudwatch.GraphWidget({
title: "S3 Data Transfer",
left: [bytesDownloadedMetric], // ダウンロードを左Y軸に表示
right: [bytesUploadedMetric], // アップロードを右Y軸に表示
view: cloudwatch.GraphWidgetView.TIME_SERIES, // 折れ線グラフで表示
height: 6,
width: 6,
start: '2023-01-01T00:00:00Z',
end: '2023-12-31T23:59:59Z',
legendPosition: cloudwatch.LegendPosition.RIGHT,
liveData: false,
setPeriodToTimeRange: false,
stacked: false,
leftYAxis: {
min: 0,
max: 1000,
},
rightYAxis: {
min: 0,
max: 2000,
},
leftAnnotations: [
{ value: 500, color: 'green', label: 'Download Target' }
],
rightAnnotations: [
{ value: 1500, color: 'orange', label: 'Upload Warning' }
],
verticalAnnotations: [
{ value: '2023-09-01T00:00:00Z', label: 'Peak Season Start' }
],
period: Duration.minutes(10),
region: 'us-east-1',
});
// addLeftMetric と addRightMetric メソッドの使用例
requestsAndErrorsWidget.addLeftMetric(additionalRequestMetric);
requestsAndErrorsWidget.addRightMetric(additionalErrorMetric);
// CloudWatch ダッシュボードの作成とウィジェットの追加
const dashboard = new cloudwatch.Dashboard(this, "MyDashboard", {
dashboardName: "MyDashboard",
widgets: [
[requestsAndErrorsWidget.position(0, 0)], // 1行目のウィジェット
[bytesWidget.position(1, 0)], // 2行目のウィジェット
],
});
// JSON 表示
console.log(requestsAndErrorsWidget.toJson());
console.log(bytesWidget.toJson());
}
}
Dev-VizStack: deploying... [1/1]
Dev-VizStack: creating CloudFormation changeset...
8:02:40 AM | UPDATE_FAILED | AWS::CloudWatch::Dashboard | DashboardMyDashboardDB214A95
Resource handler returned message: "The dashboard body is invalid, there are 2 validation errors:
[
{
"dataPath": "/widgets/0/properties",
"message": "Should match exactly one schema in oneOf"
},
{
"dataPath": "/widgets/1/properties",
"message": "Should match exactly one schema in oneOf"
}
] (Service: CloudWatch, Status Code: 400, Request ID: c776ca3b-07bc-452b-ab3e-3d3e13e25916)" (RequestToken: bfafd4cd-6599-329f-d9d5-b3a8564cc635, HandlerErrorCode: GeneralServiceException)
❌ Dev-VizStack failed: The stack named Dev-VizStack failed to deploy: UPDATE_ROLLBACK_COMPLETE: Resource handler returned message: "The dashboard body is invalid, there are 2 validation errors:
[
{
"dataPath": "/widgets/0/properties",
"message": "Should match exactly one schema in oneOf"
},
{
"dataPath": "/widgets/1/properties",
"message": "Should match exactly one schema in oneOf"
}
] (Service: CloudWatch, Status Code: 400, Request ID: c776ca3b-07bc-452b-ab3e-3d3e13e25916)" (RequestToken: bfafd4cd-6599-329f-d9d5-b3a8564cc635, HandlerErrorCode: GeneralServiceException)
import * as cdk from "aws-cdk-lib";
import * as s3 from "aws-cdk-lib/aws-s3";
import { Construct } from "constructs";
import * as lambda from "aws-cdk-lib/aws-lambda";
import * as cloudwatch from "aws-cdk-lib/aws-cloudwatch";
import * as nag from "cdk-nag"; // cdk-nagモジュールのインポート
import * as path from "path";
import { Duration } from "aws-cdk-lib";
/**
* Dashboardクラスの初期化に必要なパラメータ定義
*/
export interface DashboardProps {
/**
* 環境名を小文字の英字で指定する。
* リソースの物理名やNameタグに利用される。
*/
envName: string;
}
/**
* ダッシュボードを展開するConstruct。
*
* @remarks
* 以下のリソースを展開する。
* - 表示メトリクス用S3バケット
* - 表示メトリクス用Lambda
* - 各種ウィジェット
* - ダッシュボード
*/
export class Dashboard extends Construct {
/**
* ダッシュボードを展開する。
* 初期化時に引数で与える{@link DashboardProps}の値に応じて環境パラメータが設定される。
*
* @param props -
* AppS3Bucketクラスインスタンス初期化用のプロパティを指定する。詳細は{@link DashboardProps}を参照すること。
*/
constructor(scope: Construct, id: string, props: DashboardProps) {
super(scope, id);
// 表示メトリクス用S3バケット作成
const myVizBucket = new s3.Bucket(this, "VizBucket", {
bucketName: `viz-${props.envName}-vizbucket`,
enforceSSL: true,
removalPolicy: cdk.RemovalPolicy.DESTROY,
autoDeleteObjects: true,
});
cdk.Tags.of(myVizBucket).add(
"Name",
"viz-" + props.envName + "-vizbucket"
);
myVizBucket.addMetric({id: "EntireBucket"});
nag.NagSuppressions.addResourceSuppressions(
myVizBucket,
[
{ id: "AwsSolutions-S1", reason: "Because of test",},
],
true
);
// 表示メトリクス用Lambda作成
const myTestFunction = new lambda.Function(this, "TestFunction", {
functionName: `viz-${props.envName}-test`,
code: lambda.Code.fromAsset(path.join(__dirname, "../../lambda/test/")),
handler: "main.lambda_handler",
runtime: lambda.Runtime.PYTHON_3_8,
});
cdk.Tags.of(myTestFunction).add(
"Name",
"viz-" + props.envName + "-testFnction"
);
nag.NagSuppressions.addResourceSuppressions(
myTestFunction,
[
{ id: "AwsSolutions-IAM4", reason: "Use AWS Managed Policies.", appliesTo: ["Policy::arn:<AWS::Partition>:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"]},
{ id: "AwsSolutions-L1", reason: "Because of test",},
],
true
);
// メトリクスのウィジェット作成
const allRequestsMetric = new cloudwatch.Metric({
namespace: 'AWS/S3',
metricName: 'AllRequests',
dimensionsMap: {
BucketName: myVizBucket.bucketName,
FilterId: "EntireBucket"
},
statistic: 'Average',
period: cdk.Duration.minutes(5),
});
const getRequestMetric = new cloudwatch.Metric({
namespace: "AWS/S3",
metricName: "GetRequests",
dimensionsMap: {
BucketName: myVizBucket.bucketName,
FilterId: "EntireBucket",
},
statistic: "Sum",
period: cdk.Duration.minutes(5),
});
const putRequestMetric = new cloudwatch.Metric({
namespace: "AWS/S3",
metricName: "PutRequests",
dimensionsMap: {
BucketName: myVizBucket.bucketName,
FilterId: "EntireBucket",
},
statistic: "Sum",
period: cdk.Duration.minutes(5),
});
const clientErrorMetric = new cloudwatch.Metric({
namespace: "AWS/S3",
metricName: "4xxErrors",
dimensionsMap: {
BucketName: myVizBucket.bucketName,
FilterId: "EntireBucket",
},
statistic: "Sum",
period: cdk.Duration.minutes(5),
});
const serverErrorMetric = new cloudwatch.Metric({
namespace: "AWS/S3",
metricName: "5xxErrors",
dimensionsMap: {
BucketName: myVizBucket.bucketName,
FilterId: "EntireBucket",
},
statistic: "Sum",
period: cdk.Duration.minutes(5),
});
const bytesDownloadedMetric = new cloudwatch.Metric({
namespace: "AWS/S3",
metricName: "BytesDownloaded",
dimensionsMap: {
BucketName: myVizBucket.bucketName,
FilterId: "EntireBucket",
},
statistic: "Sum",
period: cdk.Duration.minutes(5),
});
const bytesUploadedMetric = new cloudwatch.Metric({
namespace: "AWS/S3",
metricName: "BytesUploaded",
dimensionsMap: {
BucketName: myVizBucket.bucketName,
FilterId: "EntireBucket",
},
statistic: "Sum",
period: cdk.Duration.minutes(5),
});
// const RequestsWidget = new cloudwatch.GraphWidget({
// title: "S3 Requests",
// left: [allRequestsMetric, getRequestMetric, putRequestMetric], // リクエスト系メトリクス
// view: cloudwatch.GraphWidgetView.BAR,
// });
// const ErrorsWidget = new cloudwatch.GraphWidget({
// title: "S3 Errors",
// left: [clientErrorMetric, serverErrorMetric], // エラート系メトリクス
// view: cloudwatch.GraphWidgetView.BAR,
// });
// const BytesWidget = new cloudwatch.GraphWidget({
// title: "Data Transfer",
// right: [bytesDownloadedMetric, bytesUploadedMetric], // データ量系メトリクス
// view: cloudwatch.GraphWidgetView.TIME_SERIES,
// });
// // CloudWatch ダッシュボードの作成とウィジェットの追加
// new cloudwatch.Dashboard(this, "MyDashboard", {
// dashboardName: "MyDashboard",
// widgets: [
// [RequestsWidget,ErrorsWidget], //一行目
// [BytesWidget], //二行目
// ],
// });
// S3 Requests and Errors Widget
const requestsAndErrorsWidget = new cloudwatch.GraphWidget({
title: "S3 Requests and Errors",
left: [allRequestsMetric, getRequestMetric, putRequestMetric], // リクエスト数を左Y軸に表示
view: cloudwatch.GraphWidgetView.BAR, // 棒グラフで表示
height: 8, // ウィジェットの高さ
width: 12, // ウィジェットの幅
start: '2023-01-01T00:00:00Z', // 開始時間
end: '2023-12-31T23:59:59Z', // 終了時間
legendPosition: cloudwatch.LegendPosition.BOTTOM, // 凡例の位置
liveData: true, // リアルタイムデータ
setPeriodToTimeRange: true, // 時間範囲に基づいて期間自動設定
stacked: true, // 積み上げグラフ表示
leftYAxis: {
min: 0,
max: 1000,
},
rightYAxis: {
min: 0,
max: 500,
},
leftAnnotations: [
{ value: 800, color: 'red', label: 'High Request Volume' }
],
rightAnnotations: [
{ value: 100, color: 'blue', label: 'Error Threshold' }
],
verticalAnnotations: [
{ date: '2023-06-15T00:00:00Z', label: 'Mid-year' }
],
period: Duration.minutes(5), // データ取得の間隔を指定
region: 'us-west-2', // リージョン
});
// データ転送量(アップロードとダウンロード)ウィジェット
const bytesWidget = new cloudwatch.GraphWidget({
title: "S3 Data Transfer",
left: [bytesDownloadedMetric], // ダウンロードを左Y軸に表示
right: [bytesUploadedMetric], // アップロードを右Y軸に表示
view: cloudwatch.GraphWidgetView.TIME_SERIES, // 折れ線グラフで表示
height: 6,
width: 6,
start: '2023-01-01T00:00:00Z',
end: '2023-12-31T23:59:59Z',
legendPosition: cloudwatch.LegendPosition.RIGHT,
liveData: false,
setPeriodToTimeRange: false,
stacked: false,
leftYAxis: {
min: 0,
max: 1000,
},
rightYAxis: {
min: 0,
max: 2000,
},
leftAnnotations: [
{ value: 500, color: 'green', label: 'Download Target' }
],
rightAnnotations: [
{ value: 1500, color: 'orange', label: 'Upload Warning' }
],
verticalAnnotations: [
{ date: '2023-09-01T00:00:00Z', label: 'Peak Season Start' }
],
period: Duration.minutes(10),
region: 'us-east-1',
});
// addLeftMetric と addRightMetric メソッドの使用例
requestsAndErrorsWidget.addLeftMetric(clientErrorMetric);
requestsAndErrorsWidget.addRightMetric(serverErrorMetric);
new cloudwatch.Dashboard(this, "MyDashboard", {
dashboardName: "MyDashboard",
widgets: [
[requestsAndErrorsWidget], // 1行目のウィジェット
[bytesWidget], // 2行目のウィジェット
],
});
// JSON 表示
console.log(requestsAndErrorsWidget.toJson());
console.log(bytesWidget.toJson());
}
}
const requestsAndErrorsWidget = new cloudwatch.GraphWidget({
title: "S3 Requests and Errors",
left: [allRequestsMetric, getRequestMetric],
view: cloudwatch.GraphWidgetView.BAR,
height: 8,
width: 12,
start: "-24h", // 过去24小时
legendPosition: cloudwatch.LegendPosition.BOTTOM,
liveData: true,
setPeriodToTimeRange: true,
stacked: true,
leftYAxis: { min: 0, max: 1000 },
rightYAxis: { min: 0, max: 500 },
leftAnnotations: [{ value: 800, color: "red", label: "High Request Volume" }],
rightAnnotations: [{ value: 100, color: "blue", label: "Error Threshold" }],
verticalAnnotations: [
{ date: Date.now() / 1000 - 30 * 24 * 60 * 60, label: "1 Month Ago" }, // 1个月前
],
period: Duration.minutes(5),
});
const bytesWidget = new cloudwatch.GraphWidget({
title: "S3 Data Transfer",
left: [clientErrorMetric],
view: cloudwatch.GraphWidgetView.TIME_SERIES,
height: 6,
width: 6,
start: "-7d", // 过去7天
legendPosition: cloudwatch.LegendPosition.RIGHT,
liveData: false,
setPeriodToTimeRange: false,
stacked: false,
leftYAxis: { min: 0, max: 1000 },
period: Duration.minutes(10),
});
btrikra:~/environment/FBS-viz-trial (template) $ cdk deploy Dev-VizStack
[
{
type: 'metric',
width: 12,
height: 8,
x: undefined,
y: undefined,
properties: {
view: 'bar',
title: 'S3 Requests and Errors',
region: '${Token[AWS.Region.12]}',
stacked: true,
metrics: [Array],
annotations: [Object],
yAxis: [Object],
legend: [Object],
liveData: true,
setPeriodToTimeRange: true,
period: 300,
stat: undefined,
start: '-24h',
end: undefined
}
}
]
[
{
type: 'metric',
width: 6,
height: 6,
x: undefined,
y: undefined,
properties: {
view: 'timeSeries',
title: 'S3 Data Transfer',
region: '${Token[AWS.Region.12]}',
stacked: false,
metrics: [Array],
annotations: undefined,
yAxis: [Object],
legend: [Object],
liveData: false,
setPeriodToTimeRange: false,
period: 600,
stat: undefined,
start: '-7d',
end: undefined
}
}
]
✨ Synthesis time: 20.26s
Dev-VizStack: start: Building 3c3ab79ea898ed38cf6ba93bfa8c89a1bc5372b141b0cf34b746c3fb556018db:656100244460-ap-northeast-1
Dev-VizStack: success: Built 3c3ab79ea898ed38cf6ba93bfa8c89a1bc5372b141b0cf34b746c3fb556018db:656100244460-ap-northeast-1
Dev-VizStack: start: Publishing 3c3ab79ea898ed38cf6ba93bfa8c89a1bc5372b141b0cf34b746c3fb556018db:656100244460-ap-northeast-1
Dev-VizStack: success: Published 3c3ab79ea898ed38cf6ba93bfa8c89a1bc5372b141b0cf34b746c3fb556018db:656100244460-ap-northeast-1
Dev-VizStack: deploying... [1/1]
Dev-VizStack: creating CloudFormation changeset...
8:13:34 AM | UPDATE_FAILED | AWS::CloudWatch::Dashboard | DashboardMyDashboardDB214A95
Resource handler returned message: "The dashboard body is invalid, there are 1 validation errors:
[
{
"dataPath": "/widgets/0/properties",
"message": "Should match exactly one schema in oneOf"
}
] (Service: CloudWatch, Status Code: 400, Request ID: 296bbaa3-7c18-407d-962f-ec5ec805d597)" (RequestToken: 4a80c488-4055-7e13-6f55-b24e31b10890, HandlerErrorCode: GeneralServiceException)
❌ Dev-VizStack failed: The stack named Dev-VizStack failed to deploy: UPDATE_ROLLBACK_COMPLETE: Resource handler returned message: "The dashboard body is invalid, there are 1 validation errors:
[
{
"dataPath": "/widgets/0/properties",
"message": "Should match exactly one schema in oneOf"
}
] (Service: CloudWatch, Status Code: 400, Request ID: 296bbaa3-7c18-407d-962f-ec5ec805d597)" (RequestToken: 4a80c488-4055-7e13-6f55-b24e31b10890, HandlerErrorCode: GeneralServiceException)
import * as cdk from "aws-cdk-lib";
import * as cloudwatch from "aws-cdk-lib/aws-cloudwatch";
import { Duration } from "aws-cdk-lib";
// 示例度量和 `GraphWidget`
const exampleMetric = new cloudwatch.Metric({
namespace: "AWS/S3",
metricName: "AllRequests",
statistic: "Sum",
period: Duration.minutes(5),
});
const myWidget = new cloudwatch.GraphWidget({
title: "S3 Requests and Errors",
view: cloudwatch.GraphWidgetView.BAR,
left: [exampleMetric],
stacked: true,
height: 8,
width: 12,
start: "-24h",
legendPosition: cloudwatch.LegendPosition.BOTTOM,
liveData: true,
setPeriodToTimeRange: true,
verticalAnnotations: [
{
label: "1 Month Ago",
value: Math.floor(new Date("2023-06-15T00:00:00Z").getTime() / 1000), // 使用 UNIX 时间戳
},
],
});
new cloudwatch.Dashboard(this, "MyDashboard", {
dashboardName: "MyDashboard",
widgets: [
[myWidget],
],
});