UNPKG

@cloud-carbon-footprint/aws

Version:

The core logic to get cloud usage data and estimate energy and carbon emissions from Amazon Web Services.

118 lines (106 loc) 3.06 kB
/* * © 2021 Thoughtworks, Inc. */ import { GetMetricDataCommandInput, MetricDataResult, } from '@aws-sdk/client-cloudwatch' import { GetCostAndUsageCommandInput } from '@aws-sdk/client-cost-explorer' import { Cost, ComputeUsage, buildComputeUsages, extractRawComputeUsages, RawComputeUsage, ServiceWithCPUUtilization, CloudConstants, } from '@cloud-carbon-footprint/core' import { getCostFromCostExplorer } from './CostMapper' import { ServiceWrapper } from './ServiceWrapper' import { AWS_CLOUD_CONSTANTS } from '../domain' export default class EC2 extends ServiceWithCPUUtilization { serviceName = 'EC2' constructor(private serviceWrapper: ServiceWrapper) { super() } async getUsage(start: Date, end: Date): Promise<ComputeUsage[]> { const response = await this.serviceWrapper.getQueryByInterval( 30, this.runQuery, start, end, ) return response.flat() } private runQuery = async ( start: Date, end: Date, ): Promise<ComputeUsage[]> => { const params: GetMetricDataCommandInput = { StartTime: start, EndTime: end, MetricDataQueries: [ { Id: 'cpuUtilizationWithEmptyValues', Expression: "SEARCH('{AWS/EC2,InstanceId} MetricName=\"CPUUtilization\"', 'Average', 3600)", ReturnData: false, }, { Id: 'cpuUtilization', Expression: 'REMOVE_EMPTY(cpuUtilizationWithEmptyValues)', }, { Id: 'vCPUs', Expression: 'SEARCH(\'{AWS/Usage,Resource,Type,Service,Class } Resource="vCPU" MetricName="ResourceCount"\', \'Average\', 3600)', }, ], ScanBy: 'TimestampAscending', } const responses = await this.serviceWrapper.getMetricDataResponses(params) const metricDataResults: MetricDataResult[] = responses.flatMap( (response) => response.MetricDataResults, ) const rawComputeUsages: RawComputeUsage[] = metricDataResults.flatMap( extractRawComputeUsages, ) const cloudConstants: CloudConstants = { avgCpuUtilization: AWS_CLOUD_CONSTANTS.AVG_CPU_UTILIZATION_2020, } return buildComputeUsages(rawComputeUsages, cloudConstants) } async getCosts(start: Date, end: Date, region: string): Promise<Cost[]> { const params: GetCostAndUsageCommandInput = { TimePeriod: { Start: start.toISOString().substr(0, 10), End: end.toISOString().substr(0, 10), }, Filter: { And: [ { Dimensions: { Key: 'REGION', Values: [region], }, }, { Dimensions: { Key: 'USAGE_TYPE_GROUP', Values: ['EC2: Running Hours'], }, }, ], }, Granularity: 'DAILY', GroupBy: [ { Key: 'USAGE_TYPE', Type: 'DIMENSION', }, ], Metrics: ['AmortizedCost'], } return getCostFromCostExplorer(params, this.serviceWrapper) } }