Last active
April 12, 2024 14:07
-
-
Save Alex-Just/cea96961c37577298e8982c895d4f687 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
This script retrieves and displays the top five AWS service costs for each of the past six months. | |
It uses the AWS Cost Explorer API through the AWS CLI to fetch cost data, then processes and | |
sorts this data to find the most significant service costs. The costs are displayed in USD format, | |
showing the service name and the incurred cost over each month's period. | |
Note: AWS CLI must be configured with the appropriate permissions for this script to run successfully. | |
Sample output: | |
Period from 2024-02-01 to 2024-02-29: | |
Amazon Relational Database Service: $1,000.08 | |
Amazon Elastic Compute Cloud - Compute: $400.63 | |
Amazon ElastiCache: $200.23 | |
AWS Transfer Family: $100.60 | |
EC2 - Other: $300.39 | |
Period from 2024-03-01 to 2024-03-31: | |
... | |
""" | |
import json | |
import subprocess | |
from datetime import datetime, timedelta | |
PAST_MONTHS = 6 # including current month | |
TOP_SERVICES = 5 | |
def get_top_services(start_date, end_date): | |
result = subprocess.run([ | |
'aws', 'ce', 'get-cost-and-usage', | |
'--time-period', f'Start={start_date},End={end_date}', | |
'--granularity', 'MONTHLY', | |
'--metrics', 'BlendedCost', | |
'--group-by', 'Type=DIMENSION,Key=SERVICE' | |
], capture_output=True, text=True) | |
if result.returncode != 0: | |
print(f"Error for {start_date} to {end_date}: {result.stderr}") | |
return [] | |
output = json.loads(result.stdout) | |
costs = output['ResultsByTime'][0]['Groups'] | |
top_costs = sorted(costs, key=lambda x: float(x['Metrics']['BlendedCost']['Amount']), reverse=True)[:TOP_SERVICES] | |
return top_costs | |
def get_month_boundaries(date): | |
first_day = date.replace(day=1) | |
next_month = first_day + timedelta(days=31) | |
last_day = next_month.replace(day=1) - timedelta(days=1) | |
return first_day, last_day | |
def to_usd_str(decimal_price): | |
amount = float(decimal_price or 0) | |
return f'{"-" if amount < 0 else ""}${abs(amount):,.2f}'.replace('.00', '') | |
def main(): | |
current_date = datetime.utcnow().date() | |
for i in range(PAST_MONTHS - 1, -1, -1): | |
month_to_query = current_date - timedelta(days=current_date.day - 1) - timedelta(days=i * 30) | |
start_date, end_of_month = get_month_boundaries(month_to_query) | |
if start_date.month == current_date.month and start_date.year == current_date.year: | |
end_of_month = current_date | |
top_services = get_top_services(start_date.strftime("%Y-%m-%d"), end_of_month.strftime("%Y-%m-%d")) | |
print(f"Period from {start_date} to {end_of_month}:") | |
for service in top_services: | |
service_name = service['Keys'][0] | |
amount = to_usd_str(service['Metrics']['BlendedCost']['Amount']) | |
print(f" {service_name}: {amount}") | |
print() | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment