Help us understand the problem. What is going on with this article?

(Python)AWSの請求金額を取得する

はじめに

AWS アカウントを取得したので、請求を管理したいと思う。
予定外の出費はできる事なら避けたい。
そこで、Python を使用して AWS の Cost Explorer から請求情報を取得する。

環境

実行環境は以下

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.15.1
BuildVersion:   19B88

$ python --version
Python 3.7.4

API 仕様

  • 合計請求額を表示する。
  • 各サービスごとの詳細請求額を表示する。
  • 請求金額取得対象期間は以下とする。
    • START : API 実行日を含む月の1日
    • END : API 実行日の前日
  • API 実行日が1日だった場合、前月の請求額を表示する。

API 実行日と実行月の1日を取得する

datetimeパッケージを使用して以下のように実行日と実行月の1日を取得するメソッドを作成する。

from datetime import datetime, timedelta, date

# 実行月の1日を取得
def get_begin_of_month() -> str:
    return date.today().replace(day=1).isoformat()


# 実行日を取得
def get_today() -> str:
    return date.today().isoformat()

請求金額取得対象期間を取得する

前述したメソッドを用いて請求金額取得対象期間を返却するメソッドを作成する。
ただし、取得対象期間の START と END が同じ場合、 Cost Explorer の SDK に引数として設定できない。
そのため、取得対象期間の START と END が同じ場合は前月の1日から月末を返却するようにする。

# 請求金額取得対象期間を取得
def get_total_cost_date_range() -> (str, str):
    start_date = get_begin_of_month()
    end_date = get_today()

    # get_cost_and_usage()のstartとendに同じ日付は指定不可のため、
    # 「今日が1日」なら、「先月1日から今月1日(今日)」までの範囲にする
    if start_date == end_date:
        end_of_month = datetime.strptime(start_date, '%Y-%m-%d') + timedelta(days=-1)
        begin_of_month = end_of_month.replace(day=1)
        return begin_of_month.date().isoformat(), end_date
    return start_date, end_date

合計請求額取得を取得する

SDK を用いて取得対象期間の合計請求額取得する。

import boto3
client = boto3.client('ce', region_name='us-east-1')

# 合計請求額取得を取得
def get_total_billing(client) -> dict:
    (start_date, end_date) = get_total_cost_date_range()
    response = client.get_cost_and_usage(
        TimePeriod={
            'Start': start_date,
            'End': end_date
        },
        Granularity='MONTHLY',
        Metrics=[
            'AmortizedCost'
        ]
    )

    return {
        'start': response['ResultsByTime'][0]['TimePeriod']['Start'],
        'end': response['ResultsByTime'][0]['TimePeriod']['End'],
        'billing': response['ResultsByTime'][0]['Total']['AmortizedCost']['Amount'],
    }

各サービスの詳細請求金額を取得する

合計請求額と同様に各サービスの詳細請求金額を取得する。

import boto3
client = boto3.client('ce', region_name='us-east-1')

# 各サービスの詳細請求金額を取得
def get_service_billings(client) -> list:
    (start_date, end_date) = get_total_cost_date_range()

#CostExplorer.Client.get_cost_and_usage
    response = client.get_cost_and_usage(
        TimePeriod={
            'Start': start_date,
            'End': end_date
        },
        Granularity='MONTHLY',
        Metrics=[
            'AmortizedCost'
        ],
        GroupBy=[
            {
                'Type': 'DIMENSION',
                'Key': 'SERVICE'
            }
        ]
    )

    billings = []

    for item in response['ResultsByTime'][0]['Groups']:
        billings.append({
            'service_name': item['Keys'][0],
            'billing': item['Metrics']['AmortizedCost']['Amount']
        })
    return billings

作成した API を実行する。

以下、実行結果。

{'start': '2020-01-01', 'end': '2020-01-12', 'billing': '0.44'}
[
  {'service_name': 'AWS Cost Explorer', 'billing': '0.4'}, 
  {'service_name': 'AWS Key Management Service', 'billing': '0'}, 
  {'service_name': 'AWS Lambda', 'billing': '0'}, 
  {'service_name': 'Amazon API Gateway', 'billing': '0'}, 
  {'service_name': 'Amazon DynamoDB', 'billing': '0'}, 
  {'service_name': 'Amazon Simple Notification Service', 'billing': '0'}, 
  {'service_name': 'Amazon Simple Storage Service', 'billing': '0'}, 
  {'service_name': 'AmazonCloudWatch', 'billing': '0'}, 
  {'service_name': 'Tax', 'billing': '0.04'}
]

おわりに

この結果を Slack などに表示したいメッセージに加工し、こちらで作成したbotAPIに組み込む。
こんな感じに表示されるようになる。
スクリーンショット 2020-01-12 16.46.57.png

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
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  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
ユーザーは見つかりませんでした