[AWS]LambdaでCloudwatchを触ろう

Lambda

有識者からしたら、何言ってんだってタイトルになりそうだけど、多めに見てください…
※[追記] pprintをインポートしなくても標準出力でも行けそう・・・。

boto3 というモジュールを使うらしい

どうやってデータを引っ張るか調べると、boto3ってのを使うらしい
Boto3 documentation — Boto3 Docs 1.26.49 documentation (amazonaws.com)

ってことは、レイヤー使うのかもなー・・・。(。´・ω・)
でも、AWSサービスとして盛り込まれてるって線も・・・試してみようず!

lambdaでデフォで作成される関数に、boto3をインポートしてみた
※ブログじゃなくて、ドキュメント見てると、漁る時間がかかる

import json
import pprint
import boto3

def lambda_handler(event, context):
    pprint.pprint(boto3.__version__)
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

実行してみたら、バージョンがちゃんと出てきた。

ってことは、レイヤー使わなくても大丈夫そうじゃん!!

コードでCloudwatchを利用しよう v0.1(本番はここから)

ドキュメントもちょろっと、サンプルコードあるし、インテリセンス使えはサクっといけそう!!
 ※この気持ちがダメ

cw = boto3.resource('cloudwatch')
cw.      ### ん?出なくない?

ってことで素直に行こうぜ。(VSCodeで環境でコード作成してから実装しようと強く誓った)

この部分参照しながら、地味にやってみた
CloudWatch — Boto3 Docs 1.26.49 documentation (amazonaws.com)

それでも、[Namespace][MetricName][Dimensions:Name][Dimensions:Value]ってのは
何入れるか読み取れず不明だったのだが、たまたま別項目の設定をしてるときに、これじゃん?と。

おや?なんか必要そうな項目がありそうな?

ってことで書いてみたコード v0.1 で実行

import json
import boto3
import datetime
import pprint

def lambda_handler(event, context):

    client = boto3.client('cloudwatch', region_name='us-east-1')
    
    response = client.get_metric_statistics(
        Namespace='AWS/Billing',
        MetricName='EstimatedCharges',
        Dimensions=[
            {
                'Name':'Currency',
                'Value': 'USD'
            },
        ],
        Period=60,

        # 日付は月末の課金が多かった時
        StartTime = datetime.datetime(2022, 12, 29),
        EndTime =   datetime.datetime(2022, 12, 30),
        Statistics=['Maximum']
    )
    pprint.pprint(response)
    
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

どん! エラーが発生!!

ちょっと細かすぎるのでエラー分だけ抽出したのが、これ↓

“An error occurred (AccessDenied) when calling the GetMetricStatistics operation: User: arn:aws:sts::<AWSID>:assumed-role/<role名>/<関数名> is not authorized to perform: cloudwatch:GetMetricStatistics because no identity-based policy allows the cloudwatch:GetMetricStatistics action”,

んー、、、権限ないらしい。なのでロールに権限を付与します。

ロールに権限を付与

lambda関数作成時に自動でIAMロール作成してもらったので、今回は勉強かねて
ポリシー作成 > ロールにアタッチをしました。

作成したポリシーのアクセス権限はこんな感じ。とりあえずエラー箇所だけ追加しようかね。

作成したポリシーをロールにアタッチして完成!!
※アタッチするHCは修正めんどくさかったので省きます。

再度実行+コード修正しよう v0.5

日付のところを、ちょっとだけ修正

実行したら・・・。

いやいや、情報多すぎるて( ;∀;) ww
これは、配列なんですかね?って try&err しまくってて、コード修正しました。

import json
import boto3
import datetime
import pprint

def lambda_handler(event, context):

    client = boto3.client('cloudwatch', region_name='us-east-1')
    
    response = client.get_metric_statistics(
        Namespace='AWS/Billing',
        MetricName='EstimatedCharges',
        Dimensions=[
            {
                'Name':'Currency',
                'Value': 'USD'
            },
        ],
    # Periodの理解が不安だけど、これが今一番ちょうどいい
        Period=86400,
        StartTime = datetime.datetime.now() - datetime.timedelta(days=1) ,
        EndTime = datetime.datetime.now(),
        
        Statistics=['Maximum']
    )

    pprint.pprint(response['Datapoints'][0]['Maximum'])
    
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

そしたら、こんな感じになったさ!!

出たけども、使ってないから面白みのない数字・・・

自分コード最終版 v1.0

最終的には実行したときに、数字が何を表してるか分からなくなるので、表示文字列を修正しました。

import json
import boto3
import datetime
import pprint

def lambda_handler(event, context):

    client = boto3.client('cloudwatch', region_name='us-east-1')
    
    response = client.get_metric_statistics(
        Namespace='AWS/Billing',
        MetricName='EstimatedCharges',
        Dimensions=[
            {
                'Name':'Currency',
                'Value': 'USD'
            },
        ],
        Period=86400,
        StartTime = datetime.datetime.now() - datetime.timedelta(days=1) ,
        EndTime = datetime.datetime.now(),
        
        Statistics=['Maximum']
    )

    today = datetime.datetime.now()
    str_today = (today.strftime('%Y/%m/%d'))

    pprint.pprint(str_today + " AWS Billing :  " + str(response['Datapoints'][0]['Maximum']))

    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda!')
    }

なんかそれっぽくなったじゃん! ※自己満足

料金部分はfloat型だったらしく、そのまま文字列結合したら怒られたので注意しようね

まとめ

公式ドキュメントが読みづらいのと、Pythonを知らんから、関係ないとこで引っかかってる感じ。
だけど、なんとなく分かると、使い道が広がるなこれも。

あとはプログラムの整理というか、メイン関数になんでも書きすぎなので修正したい。

おわり

コメント

タイトルとURLをコピーしました