From acf015dfe4c6b4270259dc862040e569c8f2399a Mon Sep 17 00:00:00 2001 From: Jonathan Goldwasser Date: Tue, 11 Jun 2019 14:34:47 +0200 Subject: [PATCH] feat(ecs): add metrics for Fargate services (#2798) The `BaseService` class had a `metric()` implementation missing the `clusterName` dimension (it was overriden in `Ec2Service` with a correct implementation). Moved correct `metric()`, `metricCpuUtilization()` and `metricMemoryUtilization()` methods to `BaseService`. Both `Ec2Service` and `FargateService` now have correct `metricXxx()` methods. Added tests for `metricXxx()` methods. --- .../@aws-cdk/aws-ecs/lib/base/base-service.ts | 20 +++++++++++- .../@aws-cdk/aws-ecs/lib/ec2/ec2-service.ts | 31 ------------------ .../aws-ecs/test/ec2/test.ec2-service.ts | 32 +++++++++++++++++++ .../test/fargate/test.fargate-service.ts | 31 ++++++++++++++++++ 4 files changed, 82 insertions(+), 32 deletions(-) diff --git a/packages/@aws-cdk/aws-ecs/lib/base/base-service.ts b/packages/@aws-cdk/aws-ecs/lib/base/base-service.ts index 33f30feebec03..ff2c41da4eaa8 100644 --- a/packages/@aws-cdk/aws-ecs/lib/base/base-service.ts +++ b/packages/@aws-cdk/aws-ecs/lib/base/base-service.ts @@ -227,11 +227,29 @@ export abstract class BaseService extends Resource return new cloudwatch.Metric({ namespace: 'AWS/ECS', metricName, - dimensions: { ServiceName: this.serviceName }, + dimensions: { ClusterName: this.clusterName, ServiceName: this.serviceName }, ...props }); } + /** + * Metric for cluster Memory utilization + * + * @default average over 5 minutes + */ + public metricMemoryUtilization(props?: cloudwatch.MetricOptions): cloudwatch.Metric { + return this.metric('MemoryUtilization', props); + } + + /** + * Metric for cluster CPU utilization + * + * @default average over 5 minutes + */ + public metricCpuUtilization(props?: cloudwatch.MetricOptions): cloudwatch.Metric { + return this.metric('CPUUtilization', props); + } + /** * Set up AWSVPC networking for this construct */ diff --git a/packages/@aws-cdk/aws-ecs/lib/ec2/ec2-service.ts b/packages/@aws-cdk/aws-ecs/lib/ec2/ec2-service.ts index f9ae74eb5f4e8..dccf0cd573e4a 100644 --- a/packages/@aws-cdk/aws-ecs/lib/ec2/ec2-service.ts +++ b/packages/@aws-cdk/aws-ecs/lib/ec2/ec2-service.ts @@ -1,4 +1,3 @@ -import cloudwatch = require ('@aws-cdk/aws-cloudwatch'); import ec2 = require('@aws-cdk/aws-ec2'); import elb = require('@aws-cdk/aws-elasticloadbalancing'); import { Construct, Lazy, Resource } from '@aws-cdk/cdk'; @@ -242,36 +241,6 @@ export class Ec2Service extends BaseService implements IEc2Service, elb.ILoadBal }); } - /** - * Return the given named metric for this Service - */ - public metric(metricName: string, props?: cloudwatch.MetricOptions): cloudwatch.Metric { - return new cloudwatch.Metric({ - namespace: 'AWS/ECS', - metricName, - dimensions: { ClusterName: this.clusterName, ServiceName: this.serviceName }, - ...props - }); - } - - /** - * Metric for cluster Memory utilization - * - * @default average over 5 minutes - */ - public metricMemoryUtilization(props?: cloudwatch.MetricOptions): cloudwatch.Metric { - return this.metric('MemoryUtilization', props ); - } - - /** - * Metric for cluster CPU utilization - * - * @default average over 5 minutes - */ - public metricCpuUtilization(props?: cloudwatch.MetricOptions): cloudwatch.Metric { - return this.metric('CPUUtilization', props); - } - /** * Validate this Ec2Service */ diff --git a/packages/@aws-cdk/aws-ecs/test/ec2/test.ec2-service.ts b/packages/@aws-cdk/aws-ecs/test/ec2/test.ec2-service.ts index 57566c5cc95c1..891d3592325bc 100644 --- a/packages/@aws-cdk/aws-ecs/test/ec2/test.ec2-service.ts +++ b/packages/@aws-cdk/aws-ecs/test/ec2/test.ec2-service.ts @@ -1007,5 +1007,37 @@ export = { test.done(); }, + }, + + 'Metric'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'MyVpc', {}); + const cluster = new ecs.Cluster(stack, 'EcsCluster', { vpc }); + cluster.addCapacity('DefaultAutoScalingGroup', { instanceType: new ec2.InstanceType('t2.micro') }); + const taskDefinition = new ecs.Ec2TaskDefinition(stack, 'FargateTaskDef'); + taskDefinition.addContainer('Container', { + image: ecs.ContainerImage.fromRegistry('hello') + }); + + // WHEN + const service = new ecs.Ec2Service(stack, 'Service', { + cluster, + taskDefinition, + }); + + // THEN + test.deepEqual(stack.resolve(service.metricMemoryUtilization()), { + dimensions: { + ClusterName: { Ref: 'EcsCluster97242B84' }, + ServiceName: { 'Fn::GetAtt': ['ServiceD69D759B', 'Name'] } + }, + namespace: 'AWS/ECS', + metricName: 'MemoryUtilization', + periodSec: 300, + statistic: 'Average' + }); + + test.done(); } }; diff --git a/packages/@aws-cdk/aws-ecs/test/fargate/test.fargate-service.ts b/packages/@aws-cdk/aws-ecs/test/fargate/test.fargate-service.ts index 0345d199ab196..16950b85d80ef 100644 --- a/packages/@aws-cdk/aws-ecs/test/fargate/test.fargate-service.ts +++ b/packages/@aws-cdk/aws-ecs/test/fargate/test.fargate-service.ts @@ -467,5 +467,36 @@ export = { test.done(); }, + }, + + 'Metric'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'MyVpc', {}); + const cluster = new ecs.Cluster(stack, 'EcsCluster', { vpc }); + const taskDefinition = new ecs.FargateTaskDefinition(stack, 'FargateTaskDef'); + taskDefinition.addContainer('Container', { + image: ecs.ContainerImage.fromRegistry('hello') + }); + + // WHEN + const service = new ecs.FargateService(stack, 'Service', { + cluster, + taskDefinition, + }); + + // THEN + test.deepEqual(stack.resolve(service.metricCpuUtilization()), { + dimensions: { + ClusterName: { Ref: 'EcsCluster97242B84' }, + ServiceName: { 'Fn::GetAtt': ['ServiceD69D759B', 'Name'] } + }, + namespace: 'AWS/ECS', + metricName: 'CPUUtilization', + periodSec: 300, + statistic: 'Average' + }); + + test.done(); } };