-
Notifications
You must be signed in to change notification settings - Fork 433
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Fix Cost Calculation for AWS CloudFront Distributions & Functions #1131
feat: Fix Cost Calculation for AWS CloudFront Distributions & Functions #1131
Conversation
Signed-off-by: bishal7679 <[email protected]>
@AvineshTripathi @Azanul |
|
||
// calculate region data transfer out to origin | ||
dataTransferToOrigin := (bytesDownloaded / 1000000000) * 0.02 | ||
dataTransferToOriginCost := awsUtils.GetCost(priceMap["AWS-CloudFront-DataTransfer-Out-Bytes"], (float64(bytesDownloaded) / 1099511627776)*1024) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a thought it would be better to declare a var for static values for better readability for others who might take ref of your work
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The priceMap keys are incorrect, please fix those. Log the pricing output to find the correct keys.
Cloudfront distribution cost is Data transfer out cost
+ request cost
Check out the pricing examples in https://aws.amazon.com/cloudfront/pricing/
But I didn't change anything on this. It was included cost = upload + download + request |
|
||
lambdaEdgeDurationCost := awsUtils.GetCost(priceMap["AWS-Lambda-Edge-Duration"], lambdaEdgeDuration) | ||
|
||
lambdaEdgeRequestsCost := awsUtils.GetCost(priceMap["AWS-Lambda-Edge-Requests"], lambdaEdgeRequests/10000000) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you should declare a constant for 10000000
this should be descriptive so other developers would have an idea of what this calculation achieves.
Try without the region code filter since for cloudfront from which region the data is fetched is also considered. Here's the full pricing output w/o region code filter. |
Signed-off-by: bishal7679 <[email protected]>
4b1ba27
to
ad9362d
Compare
@Azanul @AvineshTripathi PTAL now! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cloufroint functions looks good to go from me.
Calculation for distributions requires much more calculation as the implementation here would simply take the last value that parser gets in the list of prices. In short, the location needs to be taken into consideration.
Could you pls elaborate more |
If you see the pricing output or the cloudfront pricing page, you'll notice that price is location wise. The location is (probably) from location, the location/region of the origin from the data is fetched. To get this I think we'll probably have to map the aws regions to the listed cloudfront regions and calculate accordingly. Someone with more AWS expertise might be able to confirm. |
StartTime: aws.Time(utils.BeginningOfMonth(time.Now())), | ||
EndTime: aws.Time(time.Now()), | ||
MetricName: aws.String("Duration"), | ||
Namespace: aws.String("AWS/LambdaEdge"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is that not aws.String("AWS/Cloudfront")
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Azanul WDYT??
AWS/Cloudfront
or AWS/Lambda
would be correct??
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
capital F
StartTime: aws.Time(utils.BeginningOfMonth(time.Now())), | ||
EndTime: aws.Time(time.Now()), | ||
MetricName: aws.String("Requests"), | ||
Namespace: aws.String("AWS/LambdaEdge"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't it AWS/Cloudfront
?
metricsLambdaEdgeDurationOutput, err := cloudwatchClient.GetMetricStatistics(ctx, &cloudwatch.GetMetricStatisticsInput{ | ||
StartTime: aws.Time(utils.BeginningOfMonth(time.Now())), | ||
EndTime: aws.Time(time.Now()), | ||
MetricName: aws.String("Duration"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does that work? If yes, that would be great 👍
resources = append(resources, Resource{ | ||
Provider: "AWS", | ||
Account: client.Name, | ||
Service: "CloudFront", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't it be Cloudfront Functions
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cloudfront functions isn't a service, it's a resource/sub-resource of Cloudfront service
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right.
@bishal7679 I recently uncovered an oversight here. Cloudfront functions and Lambda edge functions are different, the current PR mixes them both. I'm looking for the Lambda edge metrics API, when found, we could use those metrics instead of cloudfront function invocations, change the file name and it'll work out. |
Found Lambda@Edge is similar to cloudfront means the functions running on cloudfront edge regionally. Thats might be the reason pricing output is giving Lambda edge results for CloudFront |
Lambda edge is a feature of cloudfront only but is different from cloudfront functions |
I agree, Lambda@Edge is just a Lambda function that's triggered on a CloudFront edge |
So meaning my PR #1127 is not completely useless? :D |
How it'd be useless?? |
The location loop is the anti-pattern here. Regions are not handled in every service's file, they're handled in provider's file i.e., aws in this case. |
since all corresponding edge location of every region of |
try to increase max results for the pricing output |
Could you try once either? I've removed all the attribute only using serviceCode. |
When setting MaxResults to 100 |
I've taken all the results from your given op.json previously 😃 |
OK! It is giving 2 extra region. suggest modification in my full distribution code and in the location code as well. Would be happy to apply |
#1131 (comment) |
Well moving out the entire code out of the two loop (region, location) and Will I be able to get for which region currently fetching distributions by using |
Signed-off-by: bishal7679 <[email protected]>
8f151f1
to
8fcfcc7
Compare
@Azanul Now everything is working nicely!
pricingOutput, err := pricingClient.GetProducts(ctx, &pricing.GetProductsInput{
ServiceCode: aws.String("AmazonCloudFront"),
}) will only by ServiceCode work or need to add another attributes? |
PTAL! |
|
||
// calculate region data transfer out to origin | ||
dataTransferToOrigin := (bytesDownloaded / 1000000000) * 0.02 | ||
dataTransferToOriginCost := awsUtils.GetCost(priceMapForDataTransfer[EdgeLocation], (float64(bytesDownloaded)/1099511627776)*1024) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be better to use the freeTierUpload
variable so anyone can tell by the name what this calculation should do You might also create a variable for 1024
as well.
|
||
} | ||
|
||
func getRegionMapping() map[string]string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it will be better to have this region mapping in an AWS util file so it can be reused by any AWS service needing to map regions.
Also, we should cross-verify if this does not exist (or in a different format) in the codebase as of now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeap you are right but this mapping is cloudfront specific
I'm not sure same edge location will be needed for any other service and same edge locations might not be present in their pricingoutput
WDYT??
@bishal7679 good work you have done with the CloudFront cost calculation |
The result is paginated anyway, so I looped through all the pages (used NextToken) and merged the results into one. |
Yeah! I see |
Let's use upcoming Komiser weekly to have an exhaustive discussion on AWS Cloudfront and our approach for calculating it's cost. |
@Azanul what's the update on it |
Will soon give an update on this, we might pivot from our current cost approach for AWS support |
@bishal7679 We're going to go with cost explorer API integration. It's safe to close this PR |
Its been three times closing same PR after a lot of consuming time |
Another day in a software developer's life |
Problem #877
Currently, cost for AWS CloudFront is full static and showing wrong.
Solution
This PR is fixing that issue by adding more metrics for
lambda-edge-duration
,lambda-edge-requests
,origin-shield-request
with pricemap fetching.Changes Made
AmazonCloudFront
service code and appropriate filters.lambda-edge-duration
,lambda-edge-requests
,origin-shield-request
metrics using CloudWatchChecklist
Pricingoutput :-
pricing.json
REF :- #1083