UNPKG

@cloud-carbon-footprint/core

Version:

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

98 lines (85 loc) 2.72 kB
/* * © 2021 Thoughtworks, Inc. */ import { MetricDataResult } from 'aws-sdk/clients/cloudwatch' import { IUsageData, CloudConstants } from '../.' export default interface ComputeUsage extends IUsageData { cpuUtilizationAverage: number vCpuHours: number usesAverageCPUConstant: boolean } export class ComputeUsageBuilder { private timestamp: string private cpuUtilizations: number[] private vCpuHours: number private constants: CloudConstants constructor(timestamp: string, constants: CloudConstants) { this.timestamp = timestamp this.cpuUtilizations = [] this.vCpuHours = 0 this.constants = constants } addCpuUtilization(cpuUtilization: number): ComputeUsageBuilder { if (cpuUtilization) { this.cpuUtilizations.push(cpuUtilization) } return this } setVCpuHours(vCpuHours: number): ComputeUsageBuilder { this.vCpuHours = vCpuHours return this } build(): ComputeUsage { const hasMeasurements = this.cpuUtilizations.length > 0 const cpuUtilizationAverage = hasMeasurements ? this.cpuUtilizations.reduce((sum, x) => sum + x) / this.cpuUtilizations.length : this.constants.avgCpuUtilization return { timestamp: new Date(this.timestamp), cpuUtilizationAverage, vCpuHours: this.vCpuHours, usesAverageCPUConstant: !hasMeasurements, } } } export interface RawComputeUsage { id: string timestamp: string value: number } type GroupedComputeUsages = { [timestamp: string]: ComputeUsageBuilder } export const extractRawComputeUsages: ( mdr: MetricDataResult, ) => RawComputeUsage[] = (metricData: MetricDataResult) => metricData.Timestamps.map((timestamp, i) => ({ timestamp: new Date(timestamp).toISOString(), id: metricData.Id, value: metricData.Values[i], })) const mergeUsageByTimestamp = ( acc: GroupedComputeUsages, data: RawComputeUsage, constants: CloudConstants, ) => { const usageToUpdate = acc[data.timestamp] || new ComputeUsageBuilder(data.timestamp, constants) if (data.id === 'cpuUtilization') { acc[data.timestamp] = usageToUpdate.addCpuUtilization(data.value) } else if (data.id === 'vCPUs') { acc[data.timestamp] = usageToUpdate.setVCpuHours(data.value) } return acc } export function buildComputeUsages( rawComputeUsages: RawComputeUsage[], constants: CloudConstants, ): ComputeUsage[] { const groupedComputeUsages: GroupedComputeUsages = rawComputeUsages.reduce( (acc, data) => mergeUsageByTimestamp(acc, data, constants), {}, ) return Object.values(groupedComputeUsages) .map((builder: ComputeUsageBuilder) => builder.build()) .filter((usage: ComputeUsage) => usage.vCpuHours > 0) }