LoginSignup
4
3

More than 5 years have passed since last update.

DynamoDBのCloudWatchメトリクス(キャパシティユニット)を盛大に誤解していた話

Posted at

DynamoDBの監視をしたくて、CloudWatchメトリクスのキャパシティユニットを扱おうとしていたけど、公式ページを読んでもあまり理解できなく。。。

わかった気になって実装をしていたら、後から盛大に勘違いしていたことに気づいた話。

DynamoDB CloudWatchメトリクス(キャパシティユニット)

スクリーンショット 2018-06-08 8.51.35.png

これは読みに関する記述ですが、なんとなーくわかった気になれる書き方。

やりたかったこと

  • DynamoDBのキャパシティユニット使用量を確認し、プロビジョンドキャパシティユニットとして設定した値の閾値(例:80%)を超えたら通知を出す
  • 上述のために、キャパシティユニットの使用量を割合で出せるようにする。

実装のフロー

  1. 対象テーブルの読み/書きにおけるプロビジョンドキャパシティユニットをCloudWatchメトリクスから取得する。(ProvisionedWriteCapacityUnits, ProvisionedReadCapacityUnits)
  2. 実際のキャパシティユニットの使用量をCloudWatchメトリクスから取得する。(ConsumedWriteCapacityUnits, ConsumedReadCapacityUnits)
  3. No.1,2で取得した値を用いて、Metric Mathを利用してキャパシティユニットの使用量を算出する。

boto3を利用した実装方法

こんな感じで実装しようとしました。(仕様を誤解していたため、誤った実装です)
指定していた条件は以下。(書き込みキャパシティユニットの計算を想定)GetMetricData関数を使います。

  1. 1時間分のCloudWatchメトリクスを取得する
  2. 期間を5分で指定する
  3. 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時間の開きを指定
4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3