CloudWatchのメトリクスをBoto3を使ってLambdaで取得してみた

夏の夜に Lambdaに取らす メトリクス
2021.08.01

夕方の涼しい時間になるまで液体と化してしまう季節になりました。

▲ 麦茶が美味しい季節でもありますね

こんにちは。Shirotaです。
今日は、LambdaでBoto3を使ってCloudWatchのメトリクスを取得したので、やりたかったことや実際に動かしたものをまとめてみました。

今回やりたかったこと

CloudWatchのメトリクスをLambdaで取得したかったので、Boto3を使ってLambdaを作成してみました。
具体的には、MediaConvertのメトリクスの1つである「StandbyTime」の5分前の値を取得するコードをBoto3を使って書きました。

今回作成したもの

ここからは、今回作成したものの簡単な解説とコードを紹介していこうと思います。

作成したLambdaにアタッチしたIAM Roleの権限

今回はLambda関数作成の際に新規で作成できるIAMRoleに、CloudWatchのメトリクスを取得するためのポリシーを追加でアタッチしました。

▲ 今回Lambdaで用いたGetMetricDataを許可するポリシーです

書いたコード

実際に書いたコードはこちらです。

import boto3
import datetime
import pprint
pp = pprint.PrettyPrinter(indent=4)

client = boto3.client('cloudwatch')
def lambda_handler(event, context): 
    response = client.get_metric_data(
        MetricDataQueries=[
            {
                'Id': 'm1',
                'MetricStat': {
                    'Metric': {
                        'Namespace': 'AWS/MediaConvert',
                        'MetricName': 'StandbyTime',
                        'Dimensions': [
                            {
                                'Name': 'Queue',
                                'Value': 'arn:aws:mediaconvert:ap-northeast-1:XXXXXXXXXXXX:queues/reserved-queue'
                            },
                        ]
                    },
                    'Period': 300,
                    'Stat': 'Average',
                    'Unit': 'Milliseconds'
                },
            },
        ],
        StartTime=datetime.datetime.now() - datetime.timedelta(minutes=5),
        EndTime=datetime.datetime.now()
    )
    pp.pprint(response)
    metric = response['MetricDataResults'][0]['Values'][0]
    return metric

client.get_metric_dataの中身についてはBoto3の公式ドキュメンテーションのRequest Syntaxを参考にして、必要なパラメータを中心に記述しました。

この中のパラメータで、特に自分が悩んだものをピックアップして以下にまとめます。

MetricDataQueriesの中身のパラメータについて

CloudWatchで対象のメトリクスを見ながら、以下の項目を埋めました。

▲ すんなり分からなかった自分への備忘録として書き残しておきます

  • Id

GetMetricDataは Metric Math をサポートしています。
Metric Mathは、数式を用いてメトリクスを計算したものを表示できるようにすることが出来、その際に各メトリクスに振られたIDを用いるようになっています。

デフォルトでは、CloudWatchコンソール上でIDが確認できないため、「Graphe metrics」タブの「Math expression」をクリックして、「All Functions」から任意の数式を追加してコンソール上にIDを表示させます。

▲ 多分デフォルトでIDはm〜になっているのではないかと思います

今回、取得したいメトリクスである「StandbyTime」は「m1」だったので、これを利用しました。

  • Namespace

上記の画像には載っていないのですが、こちらも少々悩んだので記載しておきます。
CloudWatchには、Namespaceという概念があります。
これは、通常AWS/サービス名という命名規則があります。
今回は、MediaConvertのメトリクスを取得するためにAWS/MediaConvertを利用しました。

  • MetricName

これは、今回取得したいメトリクスの名前なので上記画像の「Label」の部分に入っているメトリクス名を利用しました。

  • Dimensionsの「Name」と「Value」

DimensionsのNameとValueは、上記画像の「Details」の中に記載されています。
今回の場合だと、Nameは「Queue」でValueは「ARN名」となっていました。

今回、PeriodやStatistic、Unitは元々コンソール上に表示する際に用いられているデフォルトの数値や設定を利用しました。

  • StartTimeとEndTime

こちらも必須のパラメータとなっています。
今回リクエストをするデータの開始時間と終了時間のタイムスタンプを設定する必要があります。
今回は、Pythonの標準ライブラリであるdatatimeを使って、Lambda関数を呼び出した時刻から5分前までの期間のメトリクスを取得するように記述しました。

client.get_metric_dataを実行した際のレスポンス

client.get_metric_dataを実行して得られるレスポンスは、以下のようになっています。こちらは、辞書型でレスポンスが返ってきます。

START RequestId: XXXXXXXXXXXXXXXX Version: $LATEST
{   'Messages': [],
    'MetricDataResults': [   {   'Id': 'm1',
                                 'Label': 'StandbyTime',
                                 'StatusCode': 'Complete',
                                 'Timestamps': [   datetime.datetime(2021, 8, 1, 8, 48, tzinfo=tzlocal())],
                                 'Values': [523833.02]}],
    'ResponseMetadata': {   'HTTPHeaders': {   'content-length': '617',
                                               'content-type': 'text/xml',
                                               'date': 'Sun, 01 Aug 2021 '
                                                       '08:53:13 GMT',
                                               'x-amzn-requestid': 'XXXXXXXXXXXXXXXXXXXXXXXX'},
                            'HTTPStatusCode': 200,
                            'RequestId': 'XXXXXXXXXXXXXXXXXX',
                            'RetryAttempts': 0}}
END RequestId: XXXXXXXXXXXXXXXXXX
REPORT RequestId: XXXXXXXXXXXXXXXXXXX	Duration: 170.87 ms	Billed Duration: 171 ms	Memory Size: 128 MB	Max Memory Used: 76 MB

今回は、この中の「MetricDataResults」の「Values」の値が欲しかったので、以下のようにして「metric」に格納して返しています。

    metric = response['MetricDataResults'][0]['Values'][0]
    return metric

Lambdaでテストを実施して、欲しかったStandbyTimeの値が返ってきているかを確認しました。

▲ 欲しかった値が返ってきていました!

今後やりたいこと

今回取得できたメトリクスをStep Functionsに渡して分岐条件として利用することを考えているのですが、今回はそれの前準備としてLambdaを作成してみました。
自分が不慣れなので、今回Lambda関数を書くに当たって悩んだ部分をブログとしてまとめさせて頂きました。

この記事が、同じようにLambda関数でCloudWatchのメトリクスを取得したい人の助けになれば幸いです。