40
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

CloudWatchメトリクス AWS CLI サンプル集

この記事はCloudWatchメトリクスをAWS CLIで扱うサンプルをまとめた記事です。

CloudWatchとは

CloudWatchはAWSが提供するモニタリングのためのマネージドサービスです。
この記事で主に取り扱うメトリクスのほかに様々なサービスがあります。
- CloudWatch Metrics: メトリクス
- CloudWatch Alarms: アラーム(通知)
- CloudWatch Logs: ログ
- CloudWatch Events (現在は Amazon EventBridge): イベント契機の通知や処理
- CloudWatch Dashboards: ダッシュボード、コンソール画面
- CloudWatch Synthetics: 外形監視
- CloudWatch ServiceLens: X-Rayと連携したアプリケーション監視・分散トレーシング
- CloudWatch Contributor Insights: パフォーマンスに最も影響を及ぼしている要因の分析
- CloudWatch Container Insights: ECSとEKSのメトリクス・ログ収集
- CloudWatch Application Insights for .NET and SQL Server
- CloudWatch (unified) agent: 任意のサーバーで実行できるメトリクス・ログ収集エージェント
- CloudWatch SDK metrics for Enterprise Support: AWS APIをクライアントからコールした回数等の状況をSDKレベルでメトリクス化

基本操作

メトリクスストレージとしての(狭義の)CloudWatchメトリクスはPut/List/Getの3つの機能(だけ)をもちます。
EC2やRDS、Lambdaなどの各種AWSサービスはそれぞれメトリクスを収集して、CloudWatchに送信しています。
CloudWatchメトリクスはそのメトリクスを保管・参照する機能を提供しているわけです。

CloudWatchはメトリクスを特定するために、Namespace(文字列)、Metric Name(文字列)、そしてDimensions(Key/Valueの配列)の3つの情報をユニーク識別子として使用します。
Put/Getのときにはこの識別子を指定してメトリクスを操作することになります。

まずは基本のPut/List/GetからAWS CLIで実行してみましょう。

Put

CloudWatchではメトリクスのPutにPutMetricDataというAPIを使用します。
- PutMetricData API https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_PutMetricData.html

put-metric-data

以下のput-metric-dataコマンドでは、Namespace=JawsCLIMetric Name=TestMetricsDimensions=[TestKey=TestValue]という識別値に対して、100という値をPutしています。

$ aws cloudwatch put-metric-data --namespace JawsCLI --metric-name TestMetric --dimensions TestKey=TestValue --value 100

ちなみに、ここではtimestampunitを指定していません。
CloudWatchはこの場合、timestamp=(現在日時)unit=Noneを自動で使用します。

List

CloudWatchではメトリクスのListにListMetricsというAPIを使用します。
- ListMetrics API https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_ListMetrics.html

list-metrics

以下のlist-metricsコマンドでは、Namespace=JawsCLI配下のメトリクスをすべて表示しています。

$ aws cloudwatch list-metrics --namespace JawsCLI
{
    "Metrics": [
        {
            "Namespace": "JawsCLI",
            "MetricName": "TestMetric",
            "Dimensions": [
                {
                    "Name": "TestKey",
                    "Value": "TestValue"
                }
            ]
        }
    ]
}

さきほどPutしたTestMetricsが確認できます。

なお、新しいメトリクスをPutしてからListできるようになるまでには、最大15分かかることがAPIドキュメントでも説明されています。ただ、ほとんどの場合、数十秒程度でListできますし、Getできるようになるまではもっと短い時間ですみます。

After you create a metric, allow up to fifteen minutes before the metric appears. Statistics about the metric, however, are available sooner using GetMetricData or GetMetricStatistics.

Get

CloudWatchではメトリクスのGetにGetMetricStatisticsGetMetricDataというAPIを使用します。
- GetMetricStatistics API https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_GetMetricStatistics.html
- GetMetricData API https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_GetMetricData.html

get-metric-statistics

以下のget-metric-statisticsコマンドでは、Namespace=JawsCLIMetric Name=TestMetricsDimensions=[TestKey=TestValue]という識別値にひもづくメトリクスの平均値を60秒粒度で、15分前から現在の分まで取得しています。

$ aws cloudwatch get-metric-statistics --namespace JawsCLI --metric-name TestMetric --dimensions Name=TestKey,Value=TestValue --period 60 --statistics Average --start-time $(date -u +"%Y-%m-%dT%H:%M:%SZ" -d "15 min ago") --end-time $(date -u +"%Y-%m-%dT%H:%M:%SZ")
{
    "Label": "TestMetric",
    "Datapoints": [
        {
            "Timestamp": "2020-03-02T07:27:00Z",
            "Average": 100.0,
            "Unit": "None"
        }
    ]
}

get-metric-data

以下のget-metric-dataコマンドでは、Namespace=JawsCLIMetric Name=TestMetricsDimensions=[TestKey=TestValue]という識別値にひもづくメトリクスの平均値を60秒粒度で、15分前から現在の分まで取得しています。

なお、今回はCLIの引数にJSON文字列を含めていますが、file://プレフィックスによりJSONファイルから読み取らせることもできます。

$ aws cloudwatch get-metric-data --metric-data-queries '{"Id":"q1","MetricStat":{"Metric":{"Namespace":"JawsCLI","MetricName":"TestMetric","Dimensions":[{"Name":"TestKey","Value":"TestValue"}]},"Period":60,"Stat":"Average"}}' --start-time $(date -u +"%Y-%m-%dT%H:%M:%SZ" -d "15 min ago") --end-time $(date -u +"%Y-%m-%dT%H:%M:%SZ")
{
    "MetricDataResults": [
        {
            "Id": "q1",
            "Label": "TestMetric",
            "Timestamps": [
                "2020-03-02T07:56:00Z"
            ],
            "Values": [
                100.0
            ],
            "StatusCode": "Complete"
        }
    ],
    "Messages": []
}

上記のように、GetMetricStatisticsGetMetricDataはいずれもメトリクスの取得に使用できます。
違いについては以下のドキュメントに記述があります。
基本的には何も考えずにGetMetricDataを使えばOKです。

参考: CloudWatch メトリクスでは、GetMetricData または GetMetricStatistics を使用する必要がありますか?
https://aws.amazon.com/jp/premiumsupport/knowledge-center/cloudwatch-getmetricdata-api/

複数メトリクス同時処理

CloudWatchはAPIごとに秒間実行数の上限値をもちます。また、CloudWatchはAPIコールに課金するサービスです。
このため、APIコール数を減らすことが、上限値の影響の回避、さらにコスト削減につながります。

CloudWatchメトリクスはPut時もGet時も、いずれも複数のメトリクスをまとめて処理できます。

Put

put-metric-data--metric-nameなどの代わりに--metric-dataを指定するのがポイントです。

$ cat metrics.json
[
  {
    "MetricName": "TestMetric1",
    "Dimensions": [
      {
        "Name": "TestKey",
        "Value": "TestValue"
      }
    ],
    "Value": 100
  },
  {
    "MetricName": "TestMetric2",
    "Dimensions": [
      {
        "Name": "TestKey1",
        "Value": "TestValue1"
      },
      {
        "Name": "TestKey2",
        "Value": "TestValue2"
      }
    ],
    "Value": 200
  }
]

$ aws cloudwatch put-metric-data --namespace JawsCLI --metric-data file://./metrics.json

なお、複数のメトリクスを同時にPutする場合、Metric NameDimensionsは全く異なるものを同時に扱うことができますが、Namespaceは同一である必要があります。

List

$ aws cloudwatch list-metrics --namespace JawsCLI
{
    "Metrics": [
        {
            "Namespace": "JawsCLI",
            "MetricName": "TestMetric",
            "Dimensions": [
                {
                    "Name": "TestKey",
                    "Value": "TestValue"
                }
            ]
        },
        {
            "Namespace": "JawsCLI",
            "MetricName": "TestMetric1",
            "Dimensions": [
                {
                    "Name": "TestKey",
                    "Value": "TestValue"
                }
            ]
        },
        {
            "Namespace": "JawsCLI",
            "MetricName": "TestMetric2",
            "Dimensions": [
                {
                    "Name": "TestKey2",
                    "Value": "TestValue2"
                },
                {
                    "Name": "TestKey1",
                    "Value": "TestValue1"
                }
            ]
        }
    ]
}

Get

先述の通り、GetにはGetMetricStatisticsGetMetricDataのふたつのAPIがありますが、複数のメトリクスを同時に扱うには、GetMetricDataを使う必要があります。

$ aws cloudwatch get-metric-data --metric-data-queries '[{"Id":"q1","MetricStat":{"Metric":{"Namespace":"JawsCLI","MetricName":"TestMetric1","Dimensions":[{"Name":"TestKey","Value":"TestValue"}]},"Period":60,"Stat":"Average"}},{"Id":"q2","MetricStat":{"Metric":{"Namespace":"JawsCLI","MetricName":"TestMetric2","Dimensions":[{"Name":"TestKey1","Value":"TestValue1"},{"Name":"TestKey2","Value":"TestValue2"}]},"Period":60,"Stat":"Average"}}]' --start-time $(date -u +"%Y-%m-%dT%H:%M:%SZ" -d "15 min ago") --end-time $(date -u +"%Y-%m-%dT%H:%M:%SZ")
{
    "MetricDataResults": [
        {
            "Id": "q1",
            "Label": "TestValue TestMetric1",
            "Timestamps": [
                "2020-03-02T08:19:00Z"
            ],
            "Values": [
                100.0
            ],
            "StatusCode": "Complete"
        },
        {
            "Id": "q2",
            "Label": "TestValue1 TestValue2 TestMetric2",
            "Timestamps": [
                "2020-03-02T08:19:00Z"
            ],
            "Values": [
                200.0
            ],
            "StatusCode": "Complete"
        }
    ],
    "Messages": []
}

Put時とは異なり、GetMetricDataでメトリクスを複数同時に扱う場合は、NamespaceMetric NameDimensionsのいずれも全く異なるものを同時に扱うことができます。

メトリック計算

CloudWatchメトリクスには、複数のメトリクスをもとに算出した値を取得する機能があります。

Put

ここでは、サンプルとしてInvocationsErrorsという2種類のメトリクスを用意して、(Lambda関数のような)エラーレートを算出してみましょう。

先述の他のサンプルのように、put-metric-dataでまとめてメトリクスをPutしますが、今回は数が多いのでJSONファイルに外出しします。

$ cat metric-data.json 
[
  {
    "MetricName": "Invocations",
    "Dimensions": [
      {
        "Name": "FunctionName",
        "Value": "MyFunc"
      }
    ],
    "Timestamp": "2020-03-02T08:00:00Z",
    "Value": 10
  },
  { 
    "MetricName": "Invocations",
    "Dimensions": [
      { 
        "Name": "FunctionName",
        "Value": "MyFunc"
      }
    ],
    "Timestamp": "2020-03-02T08:05:00Z",
    "Value": 10
  },
  { 
    "MetricName": "Invocations",
    "Dimensions": [
      { 
        "Name": "FunctionName",
        "Value": "MyFunc"
      }
    ],
    "Timestamp": "2020-03-02T08:10:00Z",
    "Value": 10
  },
  { 
    "MetricName": "Invocations",
    "Dimensions": [
      { 
        "Name": "FunctionName",
        "Value": "MyFunc"
      }
    ],
    "Timestamp": "2020-03-02T08:15:00Z",
    "Value": 10
  },
  { 
    "MetricName": "Invocations",
    "Dimensions": [
      { 
        "Name": "FunctionName",
        "Value": "MyFunc"
      }
    ],
    "Timestamp": "2020-03-02T08:20:00Z",
    "Value": 10
  },
  { 
    "MetricName": "Errors",
    "Dimensions": [
      { 
        "Name": "FunctionName",
        "Value": "MyFunc"
      }
    ],
    "Timestamp": "2020-03-02T08:00:00Z",
    "Value": 3
  },
  { 
    "MetricName": "Errors",
    "Dimensions": [
      { 
        "Name": "FunctionName",
        "Value": "MyFunc"
      }
    ],
    "Timestamp": "2020-03-02T08:05:00Z",
    "Value": 6
  },
  { 
    "MetricName": "Errors",
    "Dimensions": [
      { 
        "Name": "FunctionName",
        "Value": "MyFunc"
      }
    ],
    "Timestamp": "2020-03-02T08:10:00Z",
    "Value": 2
  },
  { 
    "MetricName": "Errors",
    "Dimensions": [
      { 
        "Name": "FunctionName",
        "Value": "MyFunc"
      }
    ],
    "Timestamp": "2020-03-02T08:15:00Z",
    "Value": 9
  },
  { 
    "MetricName": "Errors",
    "Dimensions": [
      { 
        "Name": "FunctionName",
        "Value": "MyFunc"
      }
    ],
    "Timestamp": "2020-03-02T08:20:00Z",
    "Value": 1
  }
]

$ aws cloudwatch put-metric-data --namespace MyApplication --metric-data file://./metric-data.json

Get

では、メトリクス計算により算出された値を取得してみましょう。

まず、あらかじめ算出用のクエリを用意します。
ここでは、m1m2に定義したメトリクスにe1m1/m2という式を適用しています。

$ cat metric-data-queries.json 
[
    {
        "Id": "e1",
        "Expression": "m1 / m2",
        "Label": "ErrorRate"
    },
    {
        "Id": "m1",
        "MetricStat": {
            "Metric": {
                "Namespace": "MyApplication",
                "MetricName": "Errors",
                "Dimensions": [
                    {
                        "Name": "FunctionName",
                        "Value": "MyFunc"
                    }
                ]
            },
            "Period": 300,
            "Stat": "Sum"
        },
        "ReturnData": true
    },
    {
        "Id": "m2",
        "MetricStat": {
            "Metric": {
                "Namespace": "MyApplication",
                "MetricName": "Invocations",
                "Dimensions": [
                    {
                        "Name": "FunctionName",
                        "Value": "MyFunc"
                    }
                ]
            },
            "Period": 300,
            "Stat": "Sum"
        },
        "ReturnData": true
    }
]

メトリクス計算にはGetMetricDataを使用します。

$ aws cloudwatch get-metric-data --metric-data-queries file://./metric-data-queries.json --start-time 2020-03-02T08:00:00Z --end-time 2020-03-02T08:30:00Z
{
    "MetricDataResults": [
        {
            "Id": "m1",
            "Label": "Errors",
            "Timestamps": [
                "2020-03-02T08:20:00Z",
                "2020-03-02T08:15:00Z",
                "2020-03-02T08:10:00Z",
                "2020-03-02T08:05:00Z",
                "2020-03-02T08:00:00Z"
            ],
            "Values": [
                2.0,
                18.0,
                4.0,
                12.0,
                6.0
            ],
            "StatusCode": "Complete"
        },
        {
            "Id": "m2",
            "Label": "Invocations",
            "Timestamps": [
                "2020-03-02T08:20:00Z",
                "2020-03-02T08:15:00Z",
                "2020-03-02T08:10:00Z",
                "2020-03-02T08:05:00Z",
                "2020-03-02T08:00:00Z"
            ],
            "Values": [
                20.0,
                20.0,
                20.0,
                20.0,
                20.0
            ],
            "StatusCode": "Complete"
        },
        {
            "Id": "e1",
            "Label": "ErrorRate",
            "Timestamps": [
                "2020-03-02T08:20:00Z",
                "2020-03-02T08:15:00Z",
                "2020-03-02T08:10:00Z",
                "2020-03-02T08:05:00Z",
                "2020-03-02T08:00:00Z"
            ],
            "Values": [
                0.1,
                0.9,
                0.2,
                0.6,
                0.3
            ],
            "StatusCode": "Complete"
        }
    ],
    "Messages": []
}

e1で返却されたJSONに、算出されたエラーレートが0.1, 0.9等のように確認できます。

統計とパーセンタイル

CloudWatchメトリクスは、Putされたデータを生データのままもつわけではなく、すべて統計値として保管します。

これは、CloudWatchメトリクスがポーリング型のメトリクス収集サービスではなく、メトリクスの登録を待ち受けるかたちのサービスであるためです。

例えば、同じ時間帯(2020-03-02T09:00:00Z)に異なる値(3,6,9)をそれぞれ登録したとき、どうすべきでしょうか?後勝ちにして9で上書きしちゃう?上書き禁止にして3を採用しちゃう?

CloudWatchではこのような問題は実は起こりません。
なぜなら、すべてのデータを統計値として扱うためです。
この例では、3,6,9をすべて登録して統計値を計算し、サンプル数=3, 平均=6, 最大=9, 最小=6, 合計=12というデータとして扱う、ということになります。

標準の統計であるSampleCount, Maximum, Minimum, Average, Sumで統計値が変わるのか、さらに異なるパーセンタイル値を指定するとどのような結果が得られるのかを見ていきましょう。

Put

aws cloudwatch put-metric-data --namespace JawsCLI --metric-name Test --value 20
aws cloudwatch put-metric-data --namespace JawsCLI --metric-name Test --value 20
aws cloudwatch put-metric-data --namespace JawsCLI --metric-name Test --value 20
aws cloudwatch put-metric-data --namespace JawsCLI --metric-name Test --value 90
aws cloudwatch put-metric-data --namespace JawsCLI --metric-name Test --value 20

Get

統計(標準)

ここではget-metric-statisticsコマンドの--statisticsに異なる統計をそれぞれ指定した結果をみていきます。

$ aws cloudwatch get-metric-statistics --namespace JawsCLI --metric-name Test --start-time $(date -u +"%Y-%m-%dT%H:%M:%SZ" -d "15 min ago") --end-time $(date -u +"%Y-%m-%dT%H:%M:%SZ") --period 300 --statistics SampleCount
{
    "Label": "Test",
    "Datapoints": [
        {
            "Timestamp": "2020-03-02T08:55:00Z",
            "SampleCount": 5.0,
            "Unit": "None"
        }
    ]
}
$ aws cloudwatch get-metric-statistics --namespace JawsCLI --metric-name Test --start-time $(date -u +"%Y-%m-%dT%H:%M:%SZ" -d "15 min ago") --end-time $(date -u +"%Y-%m-%dT%H:%M:%SZ") --period 300 --statistics Maximum
{
    "Label": "Test",
    "Datapoints": [
        {
            "Timestamp": "2020-03-02T08:55:00Z",
            "Maximum": 90.0,
            "Unit": "None"
        }
    ]
}
$ aws cloudwatch get-metric-statistics --namespace JawsCLI --metric-name Test --start-time $(date -u +"%Y-%m-%dT%H:%M:%SZ" -d "15 min ago") --end-time $(date -u +"%Y-%m-%dT%H:%M:%SZ") --period 300 --statistics Minimum
{
    "Label": "Test",
    "Datapoints": [
        {
            "Timestamp": "2020-03-02T08:55:00Z",
            "Minimum": 20.0,
            "Unit": "None"
        }
    ]
}
$ aws cloudwatch get-metric-statistics --namespace JawsCLI --metric-name Test --start-time $(date -u +"%Y-%m-%dT%H:%M:%SZ" -d "15 min ago") --end-time $(date -u +"%Y-%m-%dT%H:%M:%SZ") --period 300 --statistics Average
{
    "Label": "Test",
    "Datapoints": [
        {
            "Timestamp": "2020-03-02T08:55:00Z",
            "Average": 34.0,
            "Unit": "None"
        }
    ]
}
$ aws cloudwatch get-metric-statistics --namespace JawsCLI --metric-name Test --start-time $(date -u +"%Y-%m-%dT%H:%M:%SZ" -d "15 min ago") --end-time $(date -u +"%Y-%m-%dT%H:%M:%SZ") --period 300 --statistics Sum
{
    "Label": "Test",
    "Datapoints": [
        {
            "Timestamp": "2020-03-02T08:55:00Z",
            "Sum": 170.0,
            "Unit": "None"
        }
    ]
}

統計(パーセンタイル)

ここではget-metric-statisticsコマンドの--extended-statisticsに異なるパーセンタイル値をそれぞれ指定した結果をみていきます。

$ aws cloudwatch get-metric-statistics --namespace JawsCLI --metric-name Test --start-time $(date -u +"%Y-%m-%dT%H:%M:%SZ" -d "15 min ago") --end-time $(date -u +"%Y-%m-%dT%H:%M:%SZ") --period 300 --extended-statistics p95
{
    "Label": "Test",
    "Datapoints": [
        {
            "Timestamp": "2020-03-02T08:56:00Z",
            "Unit": "None",
            "ExtendedStatistics": {
                "p95": 89.54594678486895
            }
        }
    ]
}
$ aws cloudwatch get-metric-statistics --namespace JawsCLI --metric-name Test --start-time $(date -u +"%Y-%m-%dT%H:%M:%SZ" -d "15 min ago") --end-time $(date -u +"%Y-%m-%dT%H:%M:%SZ") --period 300 --extended-statistics p90
{
    "Label": "Test",
    "Datapoints": [
        {
            "Timestamp": "2020-03-02T08:57:00Z",
            "Unit": "None",
            "ExtendedStatistics": {
                "p90": 89.09418428442875
            }
        }
    ]
}
$ aws cloudwatch get-metric-statistics --namespace JawsCLI --metric-name Test --start-time $(date -u +"%Y-%m-%dT%H:%M:%SZ" -d "15 min ago") --end-time $(date -u +"%Y-%m-%dT%H:%M:%SZ") --period 300 --extended-statistics p50
{
    "Label": "Test",
    "Datapoints": [
        {
            "Timestamp": "2020-03-02T08:57:00Z",
            "Unit": "None",
            "ExtendedStatistics": {
                "p50": 20.689021529142646
            }
        }
    ]
}
$ aws cloudwatch get-metric-statistics --namespace JawsCLI --metric-name Test --start-time $(date -u +"%Y-%m-%dT%H:%M:%SZ" -d "15 min ago") --end-time $(date -u +"%Y-%m-%dT%H:%M:%SZ") --period 300 --extended-statistics p10
{
    "Label": "Test",
    "Datapoints": [
        {
            "Timestamp": "2020-03-02T08:57:00Z",
            "Unit": "None",
            "ExtendedStatistics": {
                "p10": 20.135943634260624
            }
        }
    ]
}

ここで、10パーセンタイル値として返却された20.135943634260624みたいな値は実際にPutしたデータではなく、算出されたパーセンタイル値であることが見て取れるかと思います。

おわりに

今回は、JAWS-UG CLI専門支部への参加のお土産(?)として、CloudWatchの各機能をAWS CLIで扱うサンプルを書いてみました。
CloudWatchはもちろんサービスとしても便利ですが、数値をもつ時系列データベースのような使い方もできちゃう柔軟性の高いサービスですので、AWS CLIとの相性がとてもよいかと思います。
ぜひAWS CLIでCloudWatchメトリクスを使い倒してみていただけたら幸いです。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
40
Help us understand the problem. What are the problem?