@cloud-carbon-footprint/aws
Version:
The core logic to get cloud usage data and estimate energy and carbon emissions from Amazon Web Services.
148 lines (131 loc) • 5.18 kB
text/typescript
/*
* © 2021 Thoughtworks, Inc.
*/
import {
CloudConstants,
COMPUTE_PROCESSOR_TYPES,
MemoryEstimator,
MemoryUsage,
FootprintEstimate,
FootprintEstimatesDataBuilder,
calculateGigabyteHours,
getPhysicalChips,
CloudConstantsEmissionsFactors,
} from '@cloud-carbon-footprint/core'
import { AWS_CLOUD_CONSTANTS } from '../domain'
import {
BURSTABLE_INSTANCE_BASELINE_UTILIZATION,
EC2_INSTANCE_TYPES,
INSTANCE_TYPE_COMPUTE_PROCESSOR_MAPPING,
REDSHIFT_INSTANCE_TYPES,
} from './AWSInstanceTypes'
import RightsizingRecommendation from './Recommendations/Rightsizing/RightsizingRecommendation'
import CostAndUsageReportsRow from './CostAndUsageReportsRow'
import { EC2CurrentComputeOptimizerRecommendation } from './Recommendations/ComputeOptimizer'
export default class AWSMemoryEstimatesBuilder extends FootprintEstimatesDataBuilder {
constructor(
rowData:
| RightsizingRecommendation
| CostAndUsageReportsRow
| EC2CurrentComputeOptimizerRecommendation,
memoryEstimator: MemoryEstimator,
emissionsFactors: CloudConstantsEmissionsFactors,
) {
super(rowData)
this.vCpuHours = rowData.vCpuHours
this.instanceType = rowData.instanceType
this.usageAmount = rowData.usageAmount
this.region = rowData.region
this.powerUsageEffectiveness = AWS_CLOUD_CONSTANTS.getPUE(this.region)
this.computeProcessors = rowData.getComputeProcessors()
this.memoryUsage = this.getMemoryUsage()
this.memoryConstants = this.getMemoryConstants()
this.memoryFootprint = this.getMemoryFootprint(
memoryEstimator,
this.memoryUsage,
this.memoryConstants,
this.region,
emissionsFactors,
)
}
private getGigabytesFromInstanceTypeAndProcessors(): number {
if (!this.instanceType) return 0
const [instanceFamily, instanceSize] = this.instanceType.split('.')
// check to see if the instance type is contained in the AWSInstanceTypes lists
// or if the instance type is not a burstable instance, otherwise return void
const { isValidInstanceType, isBurstableInstance } =
this.checkInstanceTypes(instanceFamily)
if (!isValidInstanceType || isBurstableInstance) return 0
// grab the list of processors per instance type
// and then the aws specific memory constant for the processors
const processors = INSTANCE_TYPE_COMPUTE_PROCESSOR_MAPPING[
this.instanceType
] || [COMPUTE_PROCESSOR_TYPES.UNKNOWN]
const processorMemoryGigabytesPerPhysicalChip =
AWS_CLOUD_CONSTANTS.getMemory(processors)
// grab the instance type vcpu from the AWSInstanceTypes lists
const instanceTypeMemory =
EC2_INSTANCE_TYPES[instanceFamily]?.[instanceSize]?.[1] ||
REDSHIFT_INSTANCE_TYPES[instanceFamily]?.[instanceSize]?.[1]
// grab the entire instance family that the instance type is classified within
const familyInstanceTypes: number[][] = Object.values(
EC2_INSTANCE_TYPES[instanceFamily] ||
REDSHIFT_INSTANCE_TYPES[instanceFamily],
)
// grab the vcpu and memory (gb) from the largest instance type in the family
const [largestInstanceTypevCpus, largestInstanceTypeMemory] =
familyInstanceTypes[familyInstanceTypes.length - 1]
// there are special cases for instance families m5zn and z1d where they are always 2
const physicalChips = ['m5zn', 'z1d'].includes(instanceFamily)
? 2
: getPhysicalChips(largestInstanceTypevCpus)
return calculateGigabyteHours(
physicalChips,
largestInstanceTypeMemory,
processorMemoryGigabytesPerPhysicalChip,
instanceTypeMemory,
this.usageAmount,
)
}
public checkInstanceTypes(instanceFamily: string): {
[key: string]: boolean
} {
// a valid instance type is one that is mapped in the AWSInstanceTypes lists
const isValidInstanceType =
Object.keys(EC2_INSTANCE_TYPES).includes(instanceFamily) ||
Object.keys(REDSHIFT_INSTANCE_TYPES).includes(instanceFamily)
// we are not able to calculate memory usage for burstable (t family) instances
// unlike other instance families, the largest t instance is not equal to a full machine
const isBurstableInstance = Object.keys(
BURSTABLE_INSTANCE_BASELINE_UTILIZATION,
).includes(this.instanceType)
return { isValidInstanceType, isBurstableInstance }
}
private getMemoryUsage(): MemoryUsage {
return {
gigabyteHours: this.getGigabytesFromInstanceTypeAndProcessors(),
}
}
private getMemoryConstants(): CloudConstants {
return {
minWatts: AWS_CLOUD_CONSTANTS.getMinWatts(this.computeProcessors),
maxWatts: AWS_CLOUD_CONSTANTS.getMaxWatts(this.computeProcessors),
powerUsageEffectiveness: this.powerUsageEffectiveness,
replicationFactor: this.replicationFactor,
}
}
private getMemoryFootprint(
memoryEstimator: MemoryEstimator,
memoryUsage: MemoryUsage,
memoryConstants: CloudConstants,
region: string,
emissionsFactors: CloudConstantsEmissionsFactors,
): FootprintEstimate {
return memoryEstimator.estimate(
[memoryUsage],
region,
emissionsFactors,
memoryConstants,
)[0]
}
}