UNPKG

@cloud-carbon-footprint/core

Version:

The core logic to get cloud usage data and estimate energy and carbon emissions.

168 lines 7.83 kB
"use strict"; 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