Now that I have an AWS account, I want to manage my billing. I want to avoid unplanned expenses if possible. So I use Python to get the billing information from AWS Cost Explorer.
The execution environment is as follows
$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.15.1
BuildVersion: 19B88
$ python --version
Python 3.7.4
--Display the total billed amount. --Display the detailed billing amount for each service. --The period for obtaining the billed amount is as follows. --START: The first day of the month including the API execution date --END: The day before the API execution date --If the API execution date is one day, the billing amount of the previous month is displayed.
Create a method to get the execution date and the first day of the execution month as follows using the datetime
package.
from datetime import datetime, timedelta, date
#Get the first day of the execution month
def get_begin_of_month() -> str:
return date.today().replace(day=1).isoformat()
#Get execution date
def get_today() -> str:
return date.today().isoformat()
Create a method to return the billing amount acquisition target period using the above method. However, if the START and END of the acquisition target period are the same, it cannot be set as an argument in the SDK of Cost Explorer. Therefore, if the START and END of the acquisition target period are the same, the end of the month should be returned from the 1st of the previous month.
#Acquire the billing amount acquisition period
def get_total_cost_date_range() -> (str, str):
start_date = get_begin_of_month()
end_date = get_today()
# get_cost_and_usage()Because the same date cannot be specified for start and end of
#If "Today is 1st", make it in the range from "Last month 1st to this month 1st (today)"
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
Acquire the total billing amount for the acquisition target period using the SDK.
import boto3
client = boto3.client('ce', region_name='us-east-1')
#Get total billing amount acquisition
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'],
}
Get the detailed billing amount for each service as well as the total billing amount.
import boto3
client = boto3.client('ce', region_name='us-east-1')
#Get detailed billing amount for each service
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
Below is the execution result.
{'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'}
]
Process this result into a message you want to display on Slack etc. and incorporate it into the bot API created by here. It will be displayed like this.
Recommended Posts