DynamoDBの監視をしたくて、CloudWatchメトリクスのキャパシティユニットを扱おうとしていたけど、公式ページを読んでもあまり理解できなく。。。
わかった気になって実装をしていたら、後から盛大に勘違いしていたことに気づいた話。
DynamoDB CloudWatchメトリクス(キャパシティユニット)
これは読みに関する記述ですが、なんとなーくわかった気になれる書き方。
やりたかったこと
- DynamoDBのキャパシティユニット使用量を確認し、プロビジョンドキャパシティユニットとして設定した値の閾値(例:80%)を超えたら通知を出す
- 上述のために、キャパシティユニットの使用量を割合で出せるようにする。
実装のフロー
- 対象テーブルの読み/書きにおけるプロビジョンドキャパシティユニットをCloudWatchメトリクスから取得する。(ProvisionedWriteCapacityUnits, ProvisionedReadCapacityUnits)
- 実際のキャパシティユニットの使用量をCloudWatchメトリクスから取得する。(ConsumedWriteCapacityUnits, ConsumedReadCapacityUnits)
- No.1,2で取得した値を用いて、Metric Mathを利用してキャパシティユニットの使用量を算出する。
boto3を利用した実装方法
こんな感じで実装しようとしました。(仕様を誤解していたため、誤った実装です)
指定していた条件は以下。(書き込みキャパシティユニットの計算を想定)GetMetricData関数を使います。
- 1時間分のCloudWatchメトリクスを取得する
- 期間を5分で指定する
- 5分間の平均キャパシティユニットを取得する
(なんども書きますが、この実装は間違ってます)
response = cloudwatch_client.get_metric_data(
MetricDataQueries=[
{
'Id': 'm1',
'MetricStat': {
'Metric': {
'Namespace': 'AWS/DynamoDB',
'MetricName': 'ProvisionedWriteCapacityUnits',
'Dimensions': [
{
'Name': 'TableName',
'Value': TABLE_NAME
},
]
},
'Period': 300,
'Stat': 'Average',
'Unit': 'Count'
},
'Label': 'ProvisionedWriteCapacityUnits'
},
{
'Id': 'm2',
'MetricStat': {
'Metric': {
'Namespace': 'AWS/DynamoDB',
'MetricName': 'ConsumedWriteCapacityUnits',
'Dimensions': [
{
'Name': 'TableName',
'Value': TABLE_NAME
},
]
},
'Period': 300,
'Stat': 'Average',
'Unit': 'Count'
},
'Label': 'ConsumedWriteCapacityUnits'
},
{
'Id': 'calculationResult',
'Expression': 'm2/m1'
'Label': 'CalculationResult',
'ReturnData': True
}
],
StartTime=start_time,
EndTime=end_time
# StartTimeとEndTimeには1時間の開きを指定
間違いポイント
CloudWatchメトリクスのページに以下の記述があるのですが、この点を誤って理解していました。
- Average – 消費されたリクエストごとの平均読み込みキャパシティー。
Averageは「消費されたリクエストごとの平均」を出すので、あくまでリクエスト毎の平均値を出すだけでした。
→5分間の間に10回のアクセスがあり、それぞれの使用ユニット量が「1, 2, 2, 3, 2, 2, 1, 1, 4, 3」ならAverageで取得した値は「2.1」になります(21 / 10)。この平均の計算に「期間」が利用されない、ということを理解していませんでした。
正しい算出方法
よくよく見れば「注記」に書かれていることをやればいいのですが、
(期間分のユニット使用量の合計値)/(期間[秒])
という計算をしてあげる必要があります。クエリで表すとこんな感じです。
response = cloudwatch_client.get_metric_data(
MetricDataQueries=[
{
'Id': 'm1_tmp', # 変更点
'MetricStat': {
'Metric': {
'Namespace': 'AWS/DynamoDB',
'MetricName': 'ProvisionedWriteCapacityUnits',
'Dimensions': [
{
'Name': 'TableName',
'Value': TABLE_NAME
},
]
},
'Period': 300,
'Stat': 'Sum', # 変更点
'Unit': 'Count'
},
'Label': 'ProvisionedWriteCapacityUnits'
},
{
'Id': 'm2',
'MetricStat': {
'Metric': {
'Namespace': 'AWS/DynamoDB',
'MetricName': 'ConsumedWriteCapacityUnits',
'Dimensions': [
{
'Name': 'TableName',
'Value': TABLE_NAME
},
]
},
'Period': 300,
'Stat': 'Sum', # 変更点
'Unit': 'Count'
},
'Label': 'ConsumedWriteCapacityUnits'
},
# 下記のブロックを追加。
{
'Id': 'm1',
'Expression': 'm1_tmp/300',
'Label': 'm1_tmp',
},
{
'Id': 'calculationResult',
'Expression': 'm2/m1'
'Label': 'CalculationResult',
'ReturnData': True
}
],
StartTime=start_time,
EndTime=end_time
# StartTimeとEndTimeには1時間の開きを指定