Created
February 13, 2020 19:11
-
-
Save phillippelevidad/4943b54fb3139f77538621b635e8c40e to your computer and use it in GitHub Desktop.
A quick-start class to pull sumarized costs from your AWS account.
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
namespace NameIt | |
{ | |
public static class AwsCostExplorer | |
{ | |
private const string metricType = "BlendedCost"; | |
private static readonly RegionEndpoint regionEndpoint = RegionEndpoint.USEast1; | |
public static AwsCostStructure GetCostForAccount(string accessKey, string secretKey, Period period) | |
{ | |
var client = new AmazonCostExplorerClient( | |
new BasicAWSCredentials(accessKey, secretKey), | |
regionEndpoint); | |
var request = new GetCostAndUsageRequest | |
{ | |
Granularity = Granularity.MONTHLY, | |
Metrics = new List<string> { metricType }, | |
GroupBy = new List<GroupDefinition> { new GroupDefinition { Type = "DIMENSION", Key = "SERVICE" } }, | |
TimePeriod = GetTimePeriod(period) | |
}; | |
var response = client.GetCostAndUsageAsync(request).GetAwaiter().GetResult(); | |
return CostAndUsageConverter.Convert(response); | |
} | |
private static DateInterval GetTimePeriod(Period period) | |
{ | |
var today = DateTime.Today; | |
var start = period switch | |
{ | |
Period.MonthToDate => new DateTime(today.Year, today.Month, 1), | |
Period.Last7Days => today.AddDays(-7d), | |
Period.Last30Days => today.AddDays(-30d), | |
_ => throw new IndexOutOfRangeException($"Enum value Period.{period} is not known."), | |
}; | |
return new DateInterval { Start = start.ToString("yyyy-MM-dd"), End = today.ToString("yyyy-MM-dd") }; | |
} | |
private static class CostAndUsageConverter | |
{ | |
public static AwsCostStructure Convert(GetCostAndUsageResponse costAndUsage) | |
{ | |
var resources = new Dictionary<string, decimal>(); | |
foreach (var group in costAndUsage.ResultsByTime.SelectMany(r => r.Groups)) | |
{ | |
var key = GetGroupKey(group); | |
var amount = decimal.Parse(group.Metrics[metricType].Amount, CultureInfo.InvariantCulture); | |
if (resources.ContainsKey(key)) | |
resources[key] += amount; | |
else resources.Add(key, amount); | |
} | |
return new AwsCostStructure(resources); | |
} | |
private static string GetGroupKey(Group group) | |
{ | |
var rawKey = group.Keys.First(); | |
switch (rawKey) | |
{ | |
case "Amazon CloudFront": | |
return "CloudFront"; | |
case "EC2 - Other": | |
case "Amazon Elastic Compute Cloud - Compute": | |
return "EC2"; | |
case "Amazon Relational Database Service": | |
return "RDS"; | |
case "Amazon Simple Storage Service": | |
return "S3"; | |
case "AmazonCloudWatch": | |
return "CloudWatch"; | |
case "AWS Elemental MediaStore": | |
case "AWS Key Management Service": | |
return "Other"; | |
default: return rawKey; | |
} | |
} | |
} | |
public enum Period | |
{ | |
MonthToDate, | |
Last7Days, | |
Last30Days | |
} | |
} | |
public class AwsCostStructure | |
{ | |
public AwsCostStructure(IDictionary<string, decimal> costByResources) | |
{ | |
CostByResources = new ReadOnlyDictionary<string, decimal>(costByResources); | |
Total = costByResources.Values.Sum(); | |
} | |
public ReadOnlyDictionary<string, decimal> CostByResources { get; } | |
public decimal Total { get; } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage
As simple as this one-liner:
Modify the source to change the AWS Region of resources (defaults to us-east-1, Virginia), and Metric Type (defaults to Blended Costs).
Prints results like this:
Important
You should first enable the Cost Explorer feature for your account. Log in to the AWS Console, navigate to Account and click the button to enable it under the "Cost Explorer" menu.