@cloud-carbon-footprint/aws
Version:
The core logic to get cloud usage data and estimate energy and carbon emissions from Amazon Web Services.
111 lines • 6.77 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const common_1 = require("@cloud-carbon-footprint/common");
const AWSComputeEstimatesBuilder_1 = __importDefault(require("../AWSComputeEstimatesBuilder"));
const AWSMemoryEstimatesBuilder_1 = __importDefault(require("../AWSMemoryEstimatesBuilder"));
const Rightsizing_1 = require("./Rightsizing");
const domain_1 = require("../../domain");
const AWSRegions_1 = require("../AWSRegions");
class RightsizingRecommendations {
constructor(computeEstimator, memoryEstimator, serviceWrapper) {
this.computeEstimator = computeEstimator;
this.memoryEstimator = memoryEstimator;
this.serviceWrapper = serviceWrapper;
this.rightsizingRecommendationsService = 'AmazonEC2';
this.recommendationsLogger = new common_1.Logger('AWSRecommendations');
}
async getRecommendations(recommendationTarget) {
const params = {
Service: this.rightsizingRecommendationsService,
Configuration: {
BenefitsConsidered: false,
RecommendationTarget: recommendationTarget,
},
};
try {
const results = await this.serviceWrapper.getRightsizingRecommendationsResponses(params);
const rightsizingRecommendations = results.flatMap(({ RightsizingRecommendations }) => RightsizingRecommendations);
const recommendationsResult = [];
for (let i = 0; i < rightsizingRecommendations.length; i++) {
const recommendation = rightsizingRecommendations[i];
const rightsizingCurrentRecommendation = new Rightsizing_1.RightsizingCurrentRecommendation(recommendation);
const [currentComputeFootprint, currentMemoryFootprint] = await this.getFootprintEstimates(rightsizingCurrentRecommendation);
let kilowattHourSavings = currentComputeFootprint.kilowattHours;
let co2eSavings = currentComputeFootprint.co2e;
let costSavings = rightsizingCurrentRecommendation.costSavings;
let recommendationDetail = this.getRecommendationDetail(rightsizingCurrentRecommendation);
if (currentMemoryFootprint.co2e) {
kilowattHourSavings += currentMemoryFootprint.kilowattHours;
co2eSavings += currentMemoryFootprint.co2e;
}
if (recommendation.RightsizingType === 'Modify') {
this.getTargetInstance(recommendation);
const rightsizingTargetRecommendation = new Rightsizing_1.RightsizingTargetRecommendation(recommendation);
const [targetComputeFootprint, targetMemoryFootprint] = await this.getFootprintEstimates(rightsizingTargetRecommendation);
kilowattHourSavings -= targetComputeFootprint.kilowattHours;
co2eSavings -= targetComputeFootprint.co2e;
costSavings = rightsizingTargetRecommendation.costSavings;
recommendationDetail = this.getRecommendationDetail(rightsizingCurrentRecommendation, rightsizingTargetRecommendation);
if (targetMemoryFootprint.co2e) {
kilowattHourSavings -= targetMemoryFootprint.kilowattHours;
co2eSavings -= targetMemoryFootprint.co2e;
}
}
recommendationsResult.push({
cloudProvider: 'AWS',
accountId: rightsizingCurrentRecommendation.accountId,
accountName: rightsizingCurrentRecommendation.accountId,
region: rightsizingCurrentRecommendation.region,
recommendationType: rightsizingCurrentRecommendation.type,
recommendationDetail,
kilowattHourSavings,
resourceId: rightsizingCurrentRecommendation.resourceId,
instanceName: rightsizingCurrentRecommendation.instanceName,
co2eSavings,
costSavings,
});
}
return recommendationsResult;
}
catch (e) {
throw new Error(`Failed to grab AWS Rightsizing recommendations. Reason: ${e.message}`);
}
}
getRecommendationDetail(rightsizingCurrentRecommendation, rightsizingTargetRecommendation) {
const modifyDetail = `Update instance type ${rightsizingCurrentRecommendation.instanceType} to ${rightsizingTargetRecommendation?.instanceType}`;
let defaultDetail = `${rightsizingCurrentRecommendation.type} instance: ${rightsizingCurrentRecommendation.instanceName}.`;
if (!rightsizingCurrentRecommendation.instanceName) {
defaultDetail = `${rightsizingCurrentRecommendation.type} instance with Resource ID: ${rightsizingCurrentRecommendation.resourceId}.`;
}
const recommendationTypes = {
Terminate: defaultDetail,
Modify: `${defaultDetail} ${modifyDetail}`,
};
return recommendationTypes[rightsizingCurrentRecommendation.type];
}
async getFootprintEstimates(rightsizingRecommendation) {
const dateTime = new Date().toISOString();
const emissionsFactors = await (0, common_1.getEmissionsFactors)(rightsizingRecommendation.region, dateTime, domain_1.AWS_EMISSIONS_FACTORS_METRIC_TON_PER_KWH, AWSRegions_1.AWS_MAPPED_REGIONS_TO_ELECTRICITY_MAPS_ZONES, this.recommendationsLogger);
const computeFootprint = new AWSComputeEstimatesBuilder_1.default(rightsizingRecommendation, this.computeEstimator, emissionsFactors).computeFootprint;
const memoryFootprint = new AWSMemoryEstimatesBuilder_1.default(rightsizingRecommendation, this.memoryEstimator, emissionsFactors).memoryFootprint;
return [computeFootprint, memoryFootprint];
}
getTargetInstance(rightsizingRecommendationData) {
let targetInstance = rightsizingRecommendationData.ModifyRecommendationDetail.TargetInstances.pop();
let savings = 0;
rightsizingRecommendationData.ModifyRecommendationDetail.TargetInstances.map((instance) => {
if (parseFloat(instance.EstimatedMonthlySavings) >= savings) {
savings = parseFloat(instance.EstimatedMonthlySavings);
targetInstance = instance;
}
});
rightsizingRecommendationData.ModifyRecommendationDetail.TargetInstances = [
targetInstance,
];
}
}
exports.default = RightsizingRecommendations;
//# sourceMappingURL=RightsizingRecommendations.js.map