Classify costs
This commit is contained in:
parent
7125ce9606
commit
b38a041f1e
|
@ -7,4 +7,5 @@ build
|
||||||
node_modules
|
node_modules
|
||||||
out
|
out
|
||||||
sentinel.h
|
sentinel.h
|
||||||
financials/????-??
|
financials/????-??/*
|
||||||
|
!financials/????-??/breakdown.txt
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
Riju :: $175.43
|
||||||
|
CloudWatch :: $34.80
|
||||||
|
EC2 :: $112.98
|
||||||
|
Data Transfer :: $0.68
|
||||||
|
EBS Snapshot :: $11.42
|
||||||
|
EBS Volume :: $46.40
|
||||||
|
EBS Volume :: $46.40
|
||||||
|
gp2 :: $11.61
|
||||||
|
gp3 :: $34.78
|
||||||
|
Instance :: $54.48
|
||||||
|
t2.small :: $0.04
|
||||||
|
t3 :: $0.08
|
||||||
|
t3.2xlarge :: $29.80
|
||||||
|
t3.medium :: $14.77
|
||||||
|
t3.small :: $9.78
|
||||||
|
ECR :: $7.31
|
||||||
|
Data Transfer :: $3.29
|
||||||
|
Storage :: $4.02
|
||||||
|
ELB :: $20.05
|
||||||
|
Data Transfer :: $0.31
|
||||||
|
LCUs :: $0.06
|
||||||
|
Load Balancer :: $19.68
|
||||||
|
S3 :: $0.29
|
|
@ -0,0 +1,18 @@
|
||||||
|
Riju :: $52.21
|
||||||
|
EC2 :: $27.85
|
||||||
|
Data Transfer :: $0.03
|
||||||
|
EBS Snapshot :: $1.51
|
||||||
|
EBS Volume :: $15.87
|
||||||
|
EBS Volume :: $15.87
|
||||||
|
gp2 :: $0.60
|
||||||
|
gp3 :: $15.27
|
||||||
|
Instance :: $10.44
|
||||||
|
t3.small :: $10.44
|
||||||
|
ECR :: $6.00
|
||||||
|
Data Transfer :: $1.38
|
||||||
|
Storage :: $4.62
|
||||||
|
ELB :: $18.25
|
||||||
|
Data Transfer :: $0.17
|
||||||
|
LCUs :: $0.06
|
||||||
|
Load Balancer :: $18.02
|
||||||
|
S3 :: $0.12
|
|
@ -184,6 +184,12 @@ def classify_line_item(item, billing_month=None, full=False):
|
||||||
category = ["EC2"]
|
category = ["EC2"]
|
||||||
if "ElasticIP:IdleAddress" in usage_type:
|
if "ElasticIP:IdleAddress" in usage_type:
|
||||||
category.append("EIP")
|
category.append("EIP")
|
||||||
|
# Apparently tags on EIPs are ignored for billing
|
||||||
|
# purposes, so we just have to know what we were using
|
||||||
|
# them for. (Leaving them uncategorized for 2021-07
|
||||||
|
# though.)
|
||||||
|
if billing_month != "2021-07":
|
||||||
|
project = "Corona"
|
||||||
elif "EBS:VolumeUsage" in usage_type:
|
elif "EBS:VolumeUsage" in usage_type:
|
||||||
category.append("EBS Volume")
|
category.append("EBS Volume")
|
||||||
category.extend(["EBS Volume", re.sub(r"^.+\.", "", usage_type)])
|
category.extend(["EBS Volume", re.sub(r"^.+\.", "", usage_type)])
|
||||||
|
@ -252,28 +258,29 @@ def uncategorized_last(key):
|
||||||
return (key == "Uncategorized", key)
|
return (key == "Uncategorized", key)
|
||||||
|
|
||||||
|
|
||||||
def print_taxonomy(taxonomy, indent=""):
|
def print_taxonomy(taxonomy, indent="", file=sys.stdout):
|
||||||
cost = taxonomy["cost"]
|
cost = taxonomy["cost"]
|
||||||
if not indent:
|
|
||||||
print(f"(total) :: ${cost:.2f}")
|
|
||||||
categories = taxonomy.get("categories", {})
|
categories = taxonomy.get("categories", {})
|
||||||
for category in sorted(categories, key=uncategorized_last):
|
for category in sorted(categories, key=uncategorized_last):
|
||||||
subtaxonomy = categories[category]
|
subtaxonomy = categories[category]
|
||||||
cost = subtaxonomy["cost"]
|
cost = subtaxonomy["cost"]
|
||||||
if cost < 0.01:
|
if cost < 0.01:
|
||||||
continue
|
continue
|
||||||
print(f"{indent}{category} :: ${cost:.2f}")
|
print(f"{indent}{category} :: ${cost:.2f}", file=file)
|
||||||
print_taxonomy(subtaxonomy, indent=indent + " ")
|
print_taxonomy(subtaxonomy, indent=indent + " ", file=file)
|
||||||
|
|
||||||
|
|
||||||
def classify_costs(csv_path, **kwargs):
|
def classify_costs(csv_path, **kwargs):
|
||||||
items = [item for item in read_csv(csv_path) if item["lineItem/UnblendedCost"]]
|
all_items = [item for item in read_csv(csv_path)]
|
||||||
for item in items:
|
items = []
|
||||||
item["lineItem/UnblendedCost"] = float(item["lineItem/UnblendedCost"])
|
for item in all_items:
|
||||||
|
cost = item["lineItem/UnblendedCost"]
|
||||||
|
if cost and float(cost):
|
||||||
|
items.append({**item, "lineItem/UnblendedCost": float(cost)})
|
||||||
taxonomy = {}
|
taxonomy = {}
|
||||||
for item in embed_taxes(items):
|
for item in embed_taxes(items):
|
||||||
add_to_taxonomy(taxonomy, classify_line_item(item, **kwargs), item)
|
add_to_taxonomy(taxonomy, ["AWS", *classify_line_item(item, **kwargs)], item)
|
||||||
print_taxonomy(taxonomy)
|
return taxonomy
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -284,7 +291,13 @@ def main():
|
||||||
year, month = map(int, args.date.split("-"))
|
year, month = map(int, args.date.split("-"))
|
||||||
billing_month = f"{year}-{month:02d}"
|
billing_month = f"{year}-{month:02d}"
|
||||||
csv_path = get_csv(year, month, force_download=args.force_download)
|
csv_path = get_csv(year, month, force_download=args.force_download)
|
||||||
classify_costs(csv_path, billing_month=billing_month)
|
taxonomy = classify_costs(csv_path, billing_month=billing_month)
|
||||||
|
print_taxonomy(taxonomy)
|
||||||
|
riju_taxonomy = taxonomy["categories"]["AWS"]
|
||||||
|
riju_taxonomy["categories"] = {"Riju": riju_taxonomy["categories"]["Riju"]}
|
||||||
|
target_dir = ROOT / f"{year}-{month:02d}"
|
||||||
|
with open(target_dir / "breakdown.txt", "w") as f:
|
||||||
|
print_taxonomy(riju_taxonomy, file=f)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
Loading…
Reference in New Issue