@cloud-carbon-footprint/core
Version:
The core logic to get cloud usage data and estimate energy and carbon emissions.
168 lines • 7.83 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.estimateKwh = exports.estimateCo2 = exports.getAverage = exports.getWattsByAverageOrMedian = exports.appendOrAccumulateEstimatesByDay = exports.accumulateKilowattHours = exports.aggregateEstimatesByDay = exports.AccumulateKilowattHoursBy = void 0;
const ramda_1 = require("ramda");
const compute_1 = require("./compute");
const common_1 = require("@cloud-carbon-footprint/common");
var AccumulateKilowattHoursBy;
(function (AccumulateKilowattHoursBy) {
AccumulateKilowattHoursBy["COST"] = "cost";
AccumulateKilowattHoursBy["USAGE_AMOUNT"] = "usageAmount";
})(AccumulateKilowattHoursBy = exports.AccumulateKilowattHoursBy || (exports.AccumulateKilowattHoursBy = {}));
const aggregateEstimatesByDay = (estimates) => {
const getDayOfEstimate = (estimate) => estimate.timestamp.toISOString().substr(0, 10);
const accumulatingFn = (acc, value) => {
if (acc.timestamp.getTime() === new Date(0).getTime()) {
acc.timestamp = new Date(getDayOfEstimate(value));
}
acc.kilowattHours += value.kilowattHours;
acc.co2e += value.co2e;
if (value.usesAverageCPUConstant) {
acc.usesAverageCPUConstant =
acc.usesAverageCPUConstant || value.usesAverageCPUConstant;
}
return acc;
};
return (0, ramda_1.reduceBy)(accumulatingFn, {
kilowattHours: 0,
co2e: 0,
timestamp: new Date(0),
usesAverageCPUConstant: false,
}, getDayOfEstimate, estimates);
};
exports.aggregateEstimatesByDay = aggregateEstimatesByDay;
const accumulateKilowattHours = (kilowattHoursByServiceAndUsageUnit, billingDataRow, kilowattHours, accumulateBy) => {
setOrAccumulateByServiceAndUsageUnit(kilowattHoursByServiceAndUsageUnit, billingDataRow, kilowattHours, accumulateBy);
setOrAccumulateUsageUnitTotals(kilowattHoursByServiceAndUsageUnit, billingDataRow, kilowattHours, accumulateBy);
};
exports.accumulateKilowattHours = accumulateKilowattHours;
const setOrAccumulateByServiceAndUsageUnit = (kilowattHoursByServiceAndUsageUnit, billingDataRow, kilowattHours, accumulateBy) => {
const { serviceName, usageUnit, [accumulateBy]: accumValue } = billingDataRow;
if (!kilowattHoursByServiceAndUsageUnit[serviceName]) {
kilowattHoursByServiceAndUsageUnit[serviceName] = {
[usageUnit]: {
[accumulateBy]: accumValue,
kilowattHours: kilowattHours,
},
};
return;
}
if (kilowattHoursByServiceAndUsageUnit[serviceName] &&
!kilowattHoursByServiceAndUsageUnit[serviceName][usageUnit]) {
kilowattHoursByServiceAndUsageUnit[serviceName][usageUnit] = {
[accumulateBy]: accumValue,
kilowattHours: kilowattHours,
};
return;
}
if (kilowattHoursByServiceAndUsageUnit[serviceName][usageUnit]) {
kilowattHoursByServiceAndUsageUnit[serviceName][usageUnit][accumulateBy] =
(kilowattHoursByServiceAndUsageUnit[serviceName][usageUnit][accumulateBy] || 0) + accumValue;
kilowattHoursByServiceAndUsageUnit[serviceName][usageUnit].kilowattHours +=
kilowattHours;
}
};
const setOrAccumulateUsageUnitTotals = (kilowattHoursByServiceAndUsageUnit, billingDataRow, kilowattHours, accumulateBy) => {
const { usageUnit, [accumulateBy]: accumValue } = billingDataRow;
if (kilowattHoursByServiceAndUsageUnit.total[usageUnit]) {
kilowattHoursByServiceAndUsageUnit.total[usageUnit][accumulateBy] =
(kilowattHoursByServiceAndUsageUnit.total[usageUnit][accumulateBy] || 0) +
accumValue;
kilowattHoursByServiceAndUsageUnit.total[usageUnit].kilowattHours +=
kilowattHours;
}
else {
kilowattHoursByServiceAndUsageUnit.total[usageUnit] = {
[accumulateBy]: accumValue,
kilowattHours: kilowattHours,
};
}
};
const appendOrAccumulateEstimatesByDay = (results, rowData, footprintEstimate, grouping, tagNames) => {
const serviceEstimate = {
cloudProvider: rowData.cloudProvider,
kilowattHours: footprintEstimate.kilowattHours,
co2e: footprintEstimate.co2e,
usesAverageCPUConstant: !!footprintEstimate?.usesAverageCPUConstant,
serviceName: rowData.serviceName,
accountId: rowData.accountId,
accountName: rowData.accountName,
region: rowData.region,
cost: rowData.cost,
tags: rowData.tags,
};
const dayFoundInEstimate = results.find((estimate) => estimate.timestamp.getTime() === rowData.timestamp.getTime());
if (dayFoundInEstimate) {
const estimateFoundWithSameRegionAndServiceAccountAndTags = dayFoundInEstimate.serviceEstimates.find((estimateForDay) => {
return hasSameRegionAndServiceAndAccountAndTags(estimateForDay, serviceEstimate, tagNames);
});
if (estimateFoundWithSameRegionAndServiceAccountAndTags) {
estimateFoundWithSameRegionAndServiceAccountAndTags.kilowattHours +=
serviceEstimate.kilowattHours;
estimateFoundWithSameRegionAndServiceAccountAndTags.co2e +=
serviceEstimate.co2e;
estimateFoundWithSameRegionAndServiceAccountAndTags.cost +=
serviceEstimate.cost;
if (serviceEstimate.usesAverageCPUConstant) {
estimateFoundWithSameRegionAndServiceAccountAndTags.usesAverageCPUConstant =
estimateFoundWithSameRegionAndServiceAccountAndTags.usesAverageCPUConstant ||
serviceEstimate.usesAverageCPUConstant;
}
}
else {
dayFoundInEstimate.serviceEstimates.push(serviceEstimate);
}
}
else {
results.push({
timestamp: rowData.timestamp,
periodStartDate: rowData.timestamp,
periodEndDate: (0, common_1.getPeriodEndDate)(rowData.timestamp, grouping),
groupBy: grouping,
serviceEstimates: [serviceEstimate],
});
}
};
exports.appendOrAccumulateEstimatesByDay = appendOrAccumulateEstimatesByDay;
function hasSameRegionAndServiceAndAccountAndTags(estimateOne, estimateTwo, tagNames) {
if (estimateOne.region != estimateTwo.region ||
estimateOne.serviceName != estimateTwo.serviceName ||
estimateOne.accountId != estimateTwo.accountId) {
return false;
}
for (const tagIndex in tagNames) {
const tagName = tagNames[tagIndex];
if (estimateOne.tags[tagName] != estimateTwo.tags[tagName]) {
return false;
}
}
return true;
}
function getWattsByAverageOrMedian(computeProcessors, wattsForProcessors) {
if (computeProcessors.includes(compute_1.COMPUTE_PROCESSOR_TYPES.SANDY_BRIDGE) ||
computeProcessors.includes(compute_1.COMPUTE_PROCESSOR_TYPES.IVY_BRIDGE)) {
return (0, ramda_1.median)(wattsForProcessors);
}
return getAverage(wattsForProcessors);
}
exports.getWattsByAverageOrMedian = getWattsByAverageOrMedian;
function getAverage(nums) {
if (!nums.length)
return 0;
if (nums.length === 1)
return nums[0];
return nums.reduce((a, b) => a + b) / nums.length;
}
exports.getAverage = getAverage;
function estimateCo2(estimatedKilowattHours, region, emissionsFactors) {
return (estimatedKilowattHours *
(emissionsFactors[region] || emissionsFactors['Unknown']));
}
exports.estimateCo2 = estimateCo2;
function estimateKwh(estimatedCo2e, region, emissionsFactors, replicationFactor = 1) {
return ((estimatedCo2e /
(emissionsFactors[region] || emissionsFactors['Unknown'])) *
replicationFactor);
}
exports.estimateKwh = estimateKwh;
//# sourceMappingURL=FootprintEstimate.js.map