@cloud-carbon-footprint/aws
Version:
The core logic to get cloud usage data and estimate energy and carbon emissions from Amazon Web Services.
146 lines • 6.73 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const core_1 = require("@cloud-carbon-footprint/core");
const common_1 = require("@cloud-carbon-footprint/common");
const AWSInstanceTypes_1 = require("./AWSInstanceTypes");
const domain_1 = require("../domain");
const ramda_1 = require("ramda");
const ReplicationFactors_1 = require("./ReplicationFactors");
const CostAndUsageTypes_1 = require("./CostAndUsageTypes");
const GLUE_VCPUS_PER_USAGE = 4;
const SIMPLE_DB_VCPUS_PER_USAGE = 1;
class CostAndUsageReportsRow extends core_1.BillingDataRow {
constructor(timestamp, accountId, accountName, region, serviceName, usageType, usageUnit, vCpus, usageAmount, cost, tags) {
super({
timestamp,
accountId,
accountName,
region,
serviceName,
usageType,
usageUnit: cleanUsageUnit(usageUnit, serviceName, usageType),
vCpus,
usageAmount: cleanUsageAmount(usageAmount, usageUnit, serviceName),
cost,
tags,
});
this.vCpuHours = this.getVCpuHours(this.vCpus);
this.gpuHours = this.getGpuHours();
this.cloudProvider = 'AWS';
this.instanceType = this.parseInstanceTypeFromUsageType();
this.replicationFactor = this.getReplicationFactor();
}
getVCpuHours(vCpuFromReport) {
const instanceType = this.extractInstanceTypeFromUsageType();
if (this.serviceName === 'AWSGlue')
return GLUE_VCPUS_PER_USAGE * this.usageAmount;
if (this.serviceName === 'AmazonSimpleDB')
return SIMPLE_DB_VCPUS_PER_USAGE * this.usageAmount;
if (this.usageType.includes('Aurora:ServerlessUsage') ||
this.usageType.includes('Aurora:ServerlessV2Usage') ||
this.usageType.includes('Aurora:ServerlessV2IOOptimizedUsage') ||
this.usageType.includes('Neptune:ServerlessUsage'))
return this.usageAmount / 4;
if ((0, common_1.containsAny)([
'Fargate-vCPU-Hours',
'Fargate-ARM-vCPU-Hours',
'Fargate-Windows-vCPU-Hours',
'CPUCredits',
'Consumption-based:vCPU',
'FARGATE-vCPUHours',
'AppRunner-vCPU-hours',
'SERVERLESS-vCPUHours',
'DatabaseInsights-vCPU-Hours',
], this.usageType))
return this.usageAmount;
if ((0, common_1.containsAny)(Object.keys(AWSInstanceTypes_1.BURSTABLE_INSTANCE_BASELINE_UTILIZATION), this.usageType)) {
return (this.getBurstableInstanceVCPu(instanceType.split('.', 2).join('.')) *
this.usageAmount);
}
if (!vCpuFromReport)
return this.extractVCpuFromInstanceType(instanceType) * this.usageAmount;
return vCpuFromReport * this.usageAmount;
}
getGpuHours() {
const instanceType = this.extractInstanceTypeFromUsageType();
return AWSInstanceTypes_1.GPU_INSTANCES_TYPES[instanceType] * this.usageAmount || 0;
}
extractInstanceTypeFromUsageType() {
return this.usageType
.split(':')
.pop()
.replace(/^((db|cache|dax|dms|ml|mq|KernelGateway-ml|CodeEditor-ml|JupyterLab-ml|Notebook-sc|.+Kafka)\.)/, '');
}
getBurstableInstanceVCPu(instanceType) {
return (this.extractVCpuFromInstanceType(instanceType) *
(AWSInstanceTypes_1.BURSTABLE_INSTANCE_BASELINE_UTILIZATION[instanceType] /
domain_1.AWS_CLOUD_CONSTANTS.AVG_CPU_UTILIZATION_2020));
}
extractVCpuFromInstanceType(instanceType) {
const [instanceFamily, instanceSize] = instanceType.split('.');
if (this.usageType.includes('Kafka'))
return AWSInstanceTypes_1.MSK_INSTANCE_TYPES[`Kafka${this.usageType.split('Kafka').pop()}`];
if (this.usageType.includes('Express'))
return AWSInstanceTypes_1.MSK_INSTANCE_TYPES[`express${this.usageType.split('Express').pop()}`];
if (this.serviceName === 'AmazonRedshift')
return AWSInstanceTypes_1.REDSHIFT_INSTANCE_TYPES[instanceFamily]?.[instanceSize]?.[0] / 3600;
return AWSInstanceTypes_1.EC2_INSTANCE_TYPES[instanceFamily]?.[instanceSize]?.[0];
}
parseInstanceTypeFromUsageType() {
if (this.usageType.endsWith('xl'))
this.usageType = this.usageType.concat('arge');
const prefixes = ['db', 'cache', 'Kafka'];
const includesPrefix = prefixes.find((prefix) => this.usageType.includes(prefix));
return includesPrefix
? this.usageType.split((0, ramda_1.concat)(includesPrefix, '.')).pop()
: this.usageType.split(':').pop();
}
getReplicationFactor() {
return ((ReplicationFactors_1.AWS_REPLICATION_FACTORS_FOR_SERVICES[this.serviceName] &&
ReplicationFactors_1.AWS_REPLICATION_FACTORS_FOR_SERVICES[this.serviceName](this.usageType, this.region)) ||
ReplicationFactors_1.AWS_REPLICATION_FACTORS_FOR_SERVICES.DEFAULT());
}
getComputeProcessors() {
if (this.serviceName === 'AWSLambda') {
if (this.usageType.endsWith('-ARM')) {
return [core_1.COMPUTE_PROCESSOR_TYPES.AWS_GRAVITON_2];
}
else {
return [core_1.COMPUTE_PROCESSOR_TYPES.UNKNOWN];
}
}
return (AWSInstanceTypes_1.INSTANCE_TYPE_COMPUTE_PROCESSOR_MAPPING[this.instanceType] || [
core_1.COMPUTE_PROCESSOR_TYPES.UNKNOWN,
]);
}
getGPUComputeProcessors() {
if (this.serviceName === 'AWSLambda') {
return [core_1.COMPUTE_PROCESSOR_TYPES.UNKNOWN];
}
return (AWSInstanceTypes_1.INSTANCE_TYPE_GPU_PROCESSOR_MAPPING[this.instanceType] || [
core_1.COMPUTE_PROCESSOR_TYPES.UNKNOWN,
]);
}
}
exports.default = CostAndUsageReportsRow;
const cleanUsageUnit = (rawUsageUnit, serviceName, usageType) => {
if (usageType.includes('Fargate-GB-Hours') ||
usageType.includes('Fargate-ARM-GB-Hours')) {
return CostAndUsageTypes_1.KNOWN_USAGE_UNITS.GB_HOURS;
}
if (isRedshiftComputeUsage(serviceName, rawUsageUnit)) {
return CostAndUsageTypes_1.KNOWN_USAGE_UNITS.HOURS_1;
}
return rawUsageUnit;
};
const isRedshiftComputeUsage = (serviceName, usageUnit) => {
return (serviceName === 'AmazonRedshift' &&
usageUnit === CostAndUsageTypes_1.KNOWN_USAGE_UNITS.SECONDS_1);
};
const cleanUsageAmount = (rawUsageAmount, rawUsageUnit, serviceName) => {
if (isRedshiftComputeUsage(serviceName, rawUsageUnit)) {
return rawUsageAmount / 3600;
}
return rawUsageAmount;
};
//# sourceMappingURL=CostAndUsageReportsRow.js.map