From 91982f895283e2b87acd618ddb12cced75a64849 Mon Sep 17 00:00:00 2001 From: Amin Fazl Date: Tue, 4 Oct 2022 15:36:06 +1100 Subject: [PATCH 1/2] feat(ECS): Added support for fargate service --- src/aspect.ts | 10 ++ src/ecs/index.ts | 92 ++++++++++++++++++ src/ecs/service.ts | 98 +++++++++++++++++++ src/{ecs.ts => ecs/target-group.ts} | 140 ++++++---------------------- src/watchful.ts | 14 ++- 5 files changed, 239 insertions(+), 115 deletions(-) create mode 100644 src/ecs/index.ts create mode 100644 src/ecs/service.ts rename src/{ecs.ts => ecs/target-group.ts} (54%) diff --git a/src/aspect.ts b/src/aspect.ts index 2f05ae3f..18880937 100644 --- a/src/aspect.ts +++ b/src/aspect.ts @@ -1,7 +1,9 @@ import { IAspect } from 'aws-cdk-lib'; import * as apigw from 'aws-cdk-lib/aws-apigateway'; import * as dynamodb from 'aws-cdk-lib/aws-dynamodb'; +import * as ecs from 'aws-cdk-lib/aws-ecs'; import * as ecs_patterns from 'aws-cdk-lib/aws-ecs-patterns'; +import * as elasticLoadBalancing from 'aws-cdk-lib/aws-elasticloadbalancingv2'; import * as lambda from 'aws-cdk-lib/aws-lambda'; import * as rds from 'aws-cdk-lib/aws-rds'; import * as stepfunctions from 'aws-cdk-lib/aws-stepfunctions'; @@ -99,9 +101,17 @@ export class WatchfulAspect implements IAspect { this.watchful.watchFargateEcs(node.node.path, node.service, node.targetGroup); } + if (watchFargateEcs && node instanceof ecs.FargateService) { + this.watchful.watchFargateService(node.node.path, node); + } + if (watchEc2Ecs && node instanceof ecs_patterns.ApplicationLoadBalancedEc2Service) { this.watchful.watchEc2Ecs(node.node.path, node.service, node.targetGroup); } + + if (watchEc2Ecs && node instanceof elasticLoadBalancing.ApplicationTargetGroup) { + this.watchful.watchApplicationTargetGroup(node.node.path, node); + } } } diff --git a/src/ecs/index.ts b/src/ecs/index.ts new file mode 100644 index 00000000..d7567cef --- /dev/null +++ b/src/ecs/index.ts @@ -0,0 +1,92 @@ +import { Names } from 'aws-cdk-lib'; +import * as ecs from 'aws-cdk-lib/aws-ecs'; +import { ApplicationTargetGroup } from 'aws-cdk-lib/aws-elasticloadbalancingv2'; +import { Construct } from 'constructs'; +import { IWatchful } from '../api'; +import { linkForEcsService, WatchService } from './service'; +import { WatchTargetGroup } from './target-group'; + +export * from './target-group'; +export * from './service'; + + +export interface WatchEcsServiceOptions { + /** + * Threshold for the Cpu Maximum utilization + * + * @default 80 + */ + readonly cpuMaximumThresholdPercent?: number; + + /** + * Threshold for the Memory Maximum utilization. + * + * @default - 0. + */ + readonly memoryMaximumThresholdPercent?: number; + + /** + * Threshold for the Target Response Time. + * + * @default - 0. + */ + readonly targetResponseTimeThreshold?: number; + + /** + * Threshold for the Number of Requests. + * + * @default - 0. + */ + readonly requestsThreshold?: number; + + /** + * Threshold for the Number of Request Errors. + * + * @default - 0. + */ + readonly requestsErrorRateThreshold?: number; +} + +export interface WatchEcsServiceProps extends WatchEcsServiceOptions { + readonly title: string; + readonly watchful: IWatchful; + readonly fargateService?: ecs.FargateService; + readonly ec2Service?: ecs.Ec2Service; + readonly targetGroup: ApplicationTargetGroup; +} + +export class WatchEcsService extends Construct { + + private readonly watchful: IWatchful; + private readonly ecsService: ecs.BaseService; + + constructor(scope: Construct, id: string, props: WatchEcsServiceProps) { + super(scope, id); + + this.watchful = props.watchful; + + if (!props.ec2Service || !props.fargateService) { + throw new Error('No service provided to monitor.'); + }; + + this.ecsService = props.ec2Service ?? props.fargateService; + + this.watchful.addSection(props.title, { + links: [ + { title: 'ECS Service', url: linkForEcsService(this.ecsService) }, + ], + }); + + new WatchService(this, Names.uniqueId(this.ecsService), { + ...props, + service: this.ecsService, + skipLinkSection: true, + }); + + new WatchTargetGroup(this, Names.uniqueId(props.targetGroup), { + ...props, + skipLinkSection: true, + }); + } + +} diff --git a/src/ecs/service.ts b/src/ecs/service.ts new file mode 100644 index 00000000..66bdb72e --- /dev/null +++ b/src/ecs/service.ts @@ -0,0 +1,98 @@ +import * as cloudwatch from 'aws-cdk-lib/aws-cloudwatch'; +import * as ecs from 'aws-cdk-lib/aws-ecs'; +import { Construct } from 'constructs'; +import { IWatchful } from '../api'; +import { WatchEcsServiceOptions } from '../ecs'; +import { EcsMetricFactory } from '../monitoring/aws/ecs/metrics'; + + +export interface WatchServiceProps extends WatchEcsServiceOptions { + readonly title: string; + readonly watchful: IWatchful; + readonly service: ecs.BaseService; + /** + * Whether to add link section at the start of widget + * @default - false + */ + readonly skipLinkSection?: boolean; +} + +export class WatchService extends Construct { + + private readonly watchful: IWatchful; + private readonly ecsService: any; + private readonly serviceName: string; + private readonly clusterName: string; + private readonly metrics: EcsMetricFactory; + + constructor(scope: Construct, id: string, props: WatchServiceProps) { + super(scope, id); + + this.watchful = props.watchful; + + this.ecsService = props.service; + this.serviceName = props.service.serviceName; + this.clusterName = props.service.cluster.clusterName; + + + this.metrics = new EcsMetricFactory(); + + const skipLinkSection = props.skipLinkSection ?? false; + + if (!skipLinkSection) { + this.watchful.addSection(props.title, { + links: [ + { title: 'ECS Service', url: linkForEcsService(this.ecsService) }, + ], + }); + } + + const { cpuUtilizationMetric, cpuUtilizationAlarm } = this.createCpuUtilizationMonitor(props.cpuMaximumThresholdPercent); + const { memoryUtilizationMetric, memoryUtilizationAlarm } = this.createMemoryUtilizationMonitor(props.memoryMaximumThresholdPercent); + + + this.watchful.addWidgets( + new cloudwatch.GraphWidget({ + title: `CPUUtilization/${cpuUtilizationMetric.period.toMinutes()}min`, + width: 12, + left: [cpuUtilizationMetric], + leftAnnotations: [cpuUtilizationAlarm.toAnnotation()], + }), + new cloudwatch.GraphWidget({ + title: `MemoryUtilization/${memoryUtilizationMetric.period.toMinutes()}min`, + width: 12, + left: [memoryUtilizationMetric], + leftAnnotations: [memoryUtilizationAlarm.toAnnotation()], + }), + ); + } + + private createCpuUtilizationMonitor(cpuMaximumThresholdPercent = 0) { + const cpuUtilizationMetric = this.metrics.metricCpuUtilizationAverage(this.clusterName, this.serviceName); + const cpuUtilizationAlarm = cpuUtilizationMetric.createAlarm(this, 'cpuUtilizationAlarm', { + alarmDescription: 'cpuUtilizationAlarm', + threshold: cpuMaximumThresholdPercent, + comparisonOperator: cloudwatch.ComparisonOperator.GREATER_THAN_THRESHOLD, + evaluationPeriods: 3, + }); + this.watchful.addAlarm(cpuUtilizationAlarm); + return { cpuUtilizationMetric, cpuUtilizationAlarm }; + } + + private createMemoryUtilizationMonitor(memoryMaximumThresholdPercent = 0) { + const memoryUtilizationMetric = this.metrics.metricMemoryUtilizationAverage(this.clusterName, this.serviceName); + const memoryUtilizationAlarm = memoryUtilizationMetric.createAlarm(this, 'memoryUtilizationAlarm', { + alarmDescription: 'memoryUtilizationAlarm', + threshold: memoryMaximumThresholdPercent, + comparisonOperator: cloudwatch.ComparisonOperator.GREATER_THAN_THRESHOLD, + evaluationPeriods: 3, + }); + this.watchful.addAlarm(memoryUtilizationAlarm); + return { memoryUtilizationMetric, memoryUtilizationAlarm }; + } + +} + +export function linkForEcsService(ecsService: any) { + return `https://console.aws.amazon.com/ecs/home?region=${ecsService.stack.region}#/clusters/${ecsService.cluster.clusterName}/services/${ecsService.serviceName}/details`; +} diff --git a/src/ecs.ts b/src/ecs/target-group.ts similarity index 54% rename from src/ecs.ts rename to src/ecs/target-group.ts index d59647b4..31f5c627 100644 --- a/src/ecs.ts +++ b/src/ecs/target-group.ts @@ -1,96 +1,50 @@ import * as cloudwatch from 'aws-cdk-lib/aws-cloudwatch'; -import * as ecs from 'aws-cdk-lib/aws-ecs'; -import { ApplicationTargetGroup } from 'aws-cdk-lib/aws-elasticloadbalancingv2'; +import { TargetGroupBase } from 'aws-cdk-lib/aws-elasticloadbalancingv2'; import { Construct } from 'constructs'; -import { IWatchful } from './api'; -import { EcsMetricFactory } from './monitoring/aws/ecs/metrics'; +import { IWatchful } from '../api'; +import { WatchEcsServiceOptions } from '../ecs'; +import { EcsMetricFactory } from '../monitoring/aws/ecs/metrics'; - -export interface WatchEcsServiceOptions { - /** - * Threshold for the Cpu Maximum utilization - * - * @default 80 - */ - readonly cpuMaximumThresholdPercent?: number; - - /** - * Threshold for the Memory Maximum utilization. - * - * @default - 0. - */ - readonly memoryMaximumThresholdPercent?: number; - - /** - * Threshold for the Target Response Time. - * - * @default - 0. - */ - readonly targetResponseTimeThreshold?: number; - - /** - * Threshold for the Number of Requests. - * - * @default - 0. - */ - readonly requestsThreshold?: number; - - /** - * Threshold for the Number of Request Errors. - * - * @default - 0. - */ - readonly requestsErrorRateThreshold?: number; -} - -export interface WatchEcsServiceProps extends WatchEcsServiceOptions { +export interface WatchTargetGroupProps extends WatchEcsServiceOptions { readonly title: string; readonly watchful: IWatchful; - readonly fargateService?: ecs.FargateService; - readonly ec2Service?: ecs.Ec2Service; - readonly targetGroup: ApplicationTargetGroup; + readonly targetGroup: TargetGroupBase; + /** + * Whether to add link section at the start of widget + * @default - false + */ + readonly skipLinkSection?: boolean; } -export class WatchEcsService extends Construct { +export class WatchTargetGroup extends Construct { private readonly watchful: IWatchful; - private readonly ecsService: any; - private readonly targetGroup: ApplicationTargetGroup; - private readonly serviceName: string; - private readonly clusterName: string; + private readonly targetGroup: TargetGroupBase; private readonly targetGroupName: string; private readonly loadBalancerName: string; private readonly metrics: EcsMetricFactory; - constructor(scope: Construct, id: string, props: WatchEcsServiceProps) { + constructor(scope: Construct, id: string, props: WatchTargetGroupProps) { super(scope, id); this.watchful = props.watchful; - if (props.ec2Service) { - this.ecsService = props.ec2Service; - this.serviceName = props.ec2Service.serviceName; - this.clusterName = props.ec2Service.cluster.clusterName; - } else if (props.fargateService) { - this.ecsService = props.fargateService; - this.serviceName = props.fargateService.serviceName; - this.clusterName = props.fargateService.cluster.clusterName; - } else { - throw new Error('No service provided to monitor.'); - } this.targetGroup = props.targetGroup; this.targetGroupName = this.targetGroup.targetGroupFullName; this.loadBalancerName = this.targetGroup.firstLoadBalancerFullName; this.metrics = new EcsMetricFactory(); - this.watchful.addSection(props.title, { - links: [ - { title: 'ECS Service', url: linkForEcsService(this.ecsService) }, - ], - }); + const skipLinkSection = props.skipLinkSection ?? false; + console.log('###DEBUG-skipLinkSection:', skipLinkSection); - const { cpuUtilizationMetric, cpuUtilizationAlarm } = this.createCpuUtilizationMonitor(props.cpuMaximumThresholdPercent); - const { memoryUtilizationMetric, memoryUtilizationAlarm } = this.createMemoryUtilizationMonitor(props.memoryMaximumThresholdPercent); + console.log('###DEBUG-linkForTargetGroup(this.targetGroup):', linkForTargetGroup(this.targetGroup)); + if (!skipLinkSection) { + this.watchful.addSection(props.title, { + links: [ + { title: 'ECS Target Group', url: linkForTargetGroup(this.targetGroup) }, + ], + }); + } const { targetResponseTimeMetric, targetResponseTimeAlarm } = this.createTargetResponseTimeMonitor(props.targetResponseTimeThreshold); const { healthyHostsMetric, unhealthyHostsMetric } = this.createHostCountMetrics(); @@ -99,21 +53,6 @@ export class WatchEcsService extends Construct { const { http2xxMetric, http3xxMetric, http4xxMetric, http5xxMetric } = this.createHttpRequestsMetrics(); const { requestsErrorRateMetric, requestsErrorRateAlarm } = this.requestsErrorRate(props.requestsErrorRateThreshold); - - this.watchful.addWidgets( - new cloudwatch.GraphWidget({ - title: `CPUUtilization/${cpuUtilizationMetric.period.toMinutes()}min`, - width: 12, - left: [cpuUtilizationMetric], - leftAnnotations: [cpuUtilizationAlarm.toAnnotation()], - }), - new cloudwatch.GraphWidget({ - title: `MemoryUtilization/${memoryUtilizationMetric.period.toMinutes()}min`, - width: 12, - left: [memoryUtilizationMetric], - leftAnnotations: [memoryUtilizationAlarm.toAnnotation()], - }), - ); this.watchful.addWidgets( new cloudwatch.SingleValueWidget({ title: 'Healthy Hosts', @@ -155,30 +94,6 @@ export class WatchEcsService extends Construct { ); } - private createCpuUtilizationMonitor(cpuMaximumThresholdPercent = 0) { - const cpuUtilizationMetric = this.metrics.metricCpuUtilizationAverage(this.clusterName, this.serviceName); - const cpuUtilizationAlarm = cpuUtilizationMetric.createAlarm(this, 'cpuUtilizationAlarm', { - alarmDescription: 'cpuUtilizationAlarm', - threshold: cpuMaximumThresholdPercent, - comparisonOperator: cloudwatch.ComparisonOperator.GREATER_THAN_THRESHOLD, - evaluationPeriods: 3, - }); - this.watchful.addAlarm(cpuUtilizationAlarm); - return { cpuUtilizationMetric, cpuUtilizationAlarm }; - } - - private createMemoryUtilizationMonitor(memoryMaximumThresholdPercent = 0) { - const memoryUtilizationMetric = this.metrics.metricMemoryUtilizationAverage(this.clusterName, this.serviceName); - const memoryUtilizationAlarm = memoryUtilizationMetric.createAlarm(this, 'memoryUtilizationAlarm', { - alarmDescription: 'memoryUtilizationAlarm', - threshold: memoryMaximumThresholdPercent, - comparisonOperator: cloudwatch.ComparisonOperator.GREATER_THAN_THRESHOLD, - evaluationPeriods: 3, - }); - this.watchful.addAlarm(memoryUtilizationAlarm); - return { memoryUtilizationMetric, memoryUtilizationAlarm }; - } - private createTargetResponseTimeMonitor(targetResponseTimeThreshold = 0) { const targetResponseTimeMetric = this.metrics.metricTargetResponseTime(this.targetGroupName, this.loadBalancerName).avg; const targetResponseTimeAlarm = targetResponseTimeMetric.createAlarm(this, 'targetResponseTimeAlarm', { @@ -233,9 +148,6 @@ export class WatchEcsService extends Construct { } - -function linkForEcsService(ecsService: any) { - return `https://console.aws.amazon.com/ecs/home?region=${ecsService.stack.region}#/clusters/${ecsService.cluster.clusterName}/services/${ecsService.serviceName}/details`; +export function linkForTargetGroup(targetGroup: any) { + return `https://console.aws.amazon.com/ecs/home?region=${targetGroup.node.scope?.region}#TargetGroup:targetGroupArn=${targetGroup.targetGroupArn}`; } - - diff --git a/src/watchful.ts b/src/watchful.ts index 1a7c50f5..978e03c8 100644 --- a/src/watchful.ts +++ b/src/watchful.ts @@ -4,7 +4,7 @@ import * as cloudwatch from 'aws-cdk-lib/aws-cloudwatch'; import * as cloudwatch_actions from 'aws-cdk-lib/aws-cloudwatch-actions'; import * as dynamodb from 'aws-cdk-lib/aws-dynamodb'; import * as ecs from 'aws-cdk-lib/aws-ecs'; -import { ApplicationTargetGroup } from 'aws-cdk-lib/aws-elasticloadbalancingv2'; +import { ApplicationTargetGroup, TargetGroupBase } from 'aws-cdk-lib/aws-elasticloadbalancingv2'; import * as lambda from 'aws-cdk-lib/aws-lambda'; import * as rds from 'aws-cdk-lib/aws-rds'; import * as sns from 'aws-cdk-lib/aws-sns'; @@ -17,6 +17,8 @@ import { WatchApiGatewayOptions, WatchApiGateway } from './api-gateway'; import { WatchfulAspect, WatchfulAspectProps } from './aspect'; import { WatchDynamoTableOptions, WatchDynamoTable } from './dynamodb'; import { WatchEcsServiceOptions, WatchEcsService } from './ecs'; +import { WatchService } from './ecs/service'; +import { WatchTargetGroup } from './ecs/target-group'; import { WatchLambdaFunctionOptions, WatchLambdaFunction } from './lambda'; import { WatchRdsAuroraOptions, WatchRdsAurora } from './rds-aurora'; import { WatchStateMachineOptions, WatchStateMachine } from './state-machine'; @@ -192,6 +194,16 @@ export class Watchful extends Construct implements IWatchful { title, watchful: this, ec2Service, targetGroup, ...options, }); } + public watchFargateService(title: string, service: ecs.FargateService, options: WatchEcsServiceOptions = {}) { + return new WatchService(this, Names.uniqueId(service), { + title, watchful: this, service, ...options, + }); + } + public watchApplicationTargetGroup(title: string, targetGroup: TargetGroupBase, options: WatchEcsServiceOptions = {}) { + return new WatchTargetGroup(this, Names.uniqueId(targetGroup), { + title, watchful: this, targetGroup, ...options, + }); + } } function linkForDashboard(dashboard: cloudwatch.Dashboard) { From 960999a772ec421e2f19a124f38abe454075f08c Mon Sep 17 00:00:00 2001 From: Amin Fazl Date: Tue, 4 Oct 2022 15:43:22 +1100 Subject: [PATCH 2/2] Updated Documentation --- API.md | 150 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) diff --git a/API.md b/API.md index fa10af18..3c98aee0 100644 --- a/API.md +++ b/API.md @@ -9,7 +9,9 @@ Name|Description [WatchEcsService](#cdk-watchful-watchecsservice)|*No description* [WatchLambdaFunction](#cdk-watchful-watchlambdafunction)|*No description* [WatchRdsAurora](#cdk-watchful-watchrdsaurora)|*No description* +[WatchService](#cdk-watchful-watchservice)|*No description* [WatchStateMachine](#cdk-watchful-watchstatemachine)|*No description* +[WatchTargetGroup](#cdk-watchful-watchtargetgroup)|*No description* [Watchful](#cdk-watchful-watchful)|*No description* [WatchfulAspect](#cdk-watchful-watchfulaspect)|A CDK aspect that can automatically watch all resources within a scope. @@ -30,8 +32,10 @@ Name|Description [WatchLambdaFunctionProps](#cdk-watchful-watchlambdafunctionprops)|*No description* [WatchRdsAuroraOptions](#cdk-watchful-watchrdsauroraoptions)|*No description* [WatchRdsAuroraProps](#cdk-watchful-watchrdsauroraprops)|*No description* +[WatchServiceProps](#cdk-watchful-watchserviceprops)|*No description* [WatchStateMachineOptions](#cdk-watchful-watchstatemachineoptions)|*No description* [WatchStateMachineProps](#cdk-watchful-watchstatemachineprops)|*No description* +[WatchTargetGroupProps](#cdk-watchful-watchtargetgroupprops)|*No description* [WatchedOperation](#cdk-watchful-watchedoperation)|An operation (path and method) worth monitoring. [WatchfulAspectProps](#cdk-watchful-watchfulaspectprops)|*No description* [WatchfulProps](#cdk-watchful-watchfulprops)|*No description* @@ -195,6 +199,38 @@ new WatchRdsAurora(scope: Construct, id: string, props: WatchRdsAuroraProps) +## class WatchService + + + +__Implements__: [IConstruct](#constructs-iconstruct), [IDependable](#constructs-idependable) +__Extends__: [Construct](#constructs-construct) + +### Initializer + + + + +```ts +new WatchService(scope: Construct, id: string, props: WatchServiceProps) +``` + +* **scope** ([Construct](#constructs-construct)) *No description* +* **id** (string) *No description* +* **props** ([WatchServiceProps](#cdk-watchful-watchserviceprops)) *No description* + * **cpuMaximumThresholdPercent** (number) Threshold for the Cpu Maximum utilization. __*Default*__: 80 + * **memoryMaximumThresholdPercent** (number) Threshold for the Memory Maximum utilization. __*Default*__: 0. + * **requestsErrorRateThreshold** (number) Threshold for the Number of Request Errors. __*Default*__: 0. + * **requestsThreshold** (number) Threshold for the Number of Requests. __*Default*__: 0. + * **targetResponseTimeThreshold** (number) Threshold for the Target Response Time. __*Default*__: 0. + * **service** ([aws_ecs.BaseService](#aws-cdk-lib-aws-ecs-baseservice)) *No description* + * **title** (string) *No description* + * **watchful** ([IWatchful](#cdk-watchful-iwatchful)) *No description* + * **skipLinkSection** (boolean) Whether to add link section at the start of widget. __*Default*__: false + + + + ## class WatchStateMachine @@ -222,6 +258,38 @@ new WatchStateMachine(scope: Construct, id: string, props: WatchStateMachineProp +## class WatchTargetGroup + + + +__Implements__: [IConstruct](#constructs-iconstruct), [IDependable](#constructs-idependable) +__Extends__: [Construct](#constructs-construct) + +### Initializer + + + + +```ts +new WatchTargetGroup(scope: Construct, id: string, props: WatchTargetGroupProps) +``` + +* **scope** ([Construct](#constructs-construct)) *No description* +* **id** (string) *No description* +* **props** ([WatchTargetGroupProps](#cdk-watchful-watchtargetgroupprops)) *No description* + * **cpuMaximumThresholdPercent** (number) Threshold for the Cpu Maximum utilization. __*Default*__: 80 + * **memoryMaximumThresholdPercent** (number) Threshold for the Memory Maximum utilization. __*Default*__: 0. + * **requestsErrorRateThreshold** (number) Threshold for the Number of Request Errors. __*Default*__: 0. + * **requestsThreshold** (number) Threshold for the Number of Requests. __*Default*__: 0. + * **targetResponseTimeThreshold** (number) Threshold for the Target Response Time. __*Default*__: 0. + * **targetGroup** ([aws_elasticloadbalancingv2.TargetGroupBase](#aws-cdk-lib-aws-elasticloadbalancingv2-targetgroupbase)) *No description* + * **title** (string) *No description* + * **watchful** ([IWatchful](#cdk-watchful-iwatchful)) *No description* + * **skipLinkSection** (boolean) Whether to add link section at the start of widget. __*Default*__: false + + + + ## class Watchful @@ -312,6 +380,26 @@ watchApiGateway(title: string, restApi: RestApi, options?: WatchApiGatewayOption __Returns__: * [WatchApiGateway](#cdk-watchful-watchapigateway) +#### watchApplicationTargetGroup(title, targetGroup, options?) + + + +```ts +watchApplicationTargetGroup(title: string, targetGroup: TargetGroupBase, options?: WatchEcsServiceOptions): WatchTargetGroup +``` + +* **title** (string) *No description* +* **targetGroup** ([aws_elasticloadbalancingv2.TargetGroupBase](#aws-cdk-lib-aws-elasticloadbalancingv2-targetgroupbase)) *No description* +* **options** ([WatchEcsServiceOptions](#cdk-watchful-watchecsserviceoptions)) *No description* + * **cpuMaximumThresholdPercent** (number) Threshold for the Cpu Maximum utilization. __*Default*__: 80 + * **memoryMaximumThresholdPercent** (number) Threshold for the Memory Maximum utilization. __*Default*__: 0. + * **requestsErrorRateThreshold** (number) Threshold for the Number of Request Errors. __*Default*__: 0. + * **requestsThreshold** (number) Threshold for the Number of Requests. __*Default*__: 0. + * **targetResponseTimeThreshold** (number) Threshold for the Target Response Time. __*Default*__: 0. + +__Returns__: +* [WatchTargetGroup](#cdk-watchful-watchtargetgroup) + #### watchDynamoTable(title, table, options?) @@ -371,6 +459,26 @@ watchFargateEcs(title: string, fargateService: FargateService, targetGroup: Appl __Returns__: * [WatchEcsService](#cdk-watchful-watchecsservice) +#### watchFargateService(title, service, options?) + + + +```ts +watchFargateService(title: string, service: FargateService, options?: WatchEcsServiceOptions): WatchService +``` + +* **title** (string) *No description* +* **service** ([aws_ecs.FargateService](#aws-cdk-lib-aws-ecs-fargateservice)) *No description* +* **options** ([WatchEcsServiceOptions](#cdk-watchful-watchecsserviceoptions)) *No description* + * **cpuMaximumThresholdPercent** (number) Threshold for the Cpu Maximum utilization. __*Default*__: 80 + * **memoryMaximumThresholdPercent** (number) Threshold for the Memory Maximum utilization. __*Default*__: 0. + * **requestsErrorRateThreshold** (number) Threshold for the Number of Request Errors. __*Default*__: 0. + * **requestsThreshold** (number) Threshold for the Number of Requests. __*Default*__: 0. + * **targetResponseTimeThreshold** (number) Threshold for the Target Response Time. __*Default*__: 0. + +__Returns__: +* [WatchService](#cdk-watchful-watchservice) + #### watchLambdaFunction(title, fn, options?) @@ -743,6 +851,27 @@ Name | Type | Description +## struct WatchServiceProps + + + + + + +Name | Type | Description +-----|------|------------- +**service** | [aws_ecs.BaseService](#aws-cdk-lib-aws-ecs-baseservice) | +**title** | string | +**watchful** | [IWatchful](#cdk-watchful-iwatchful) | +**cpuMaximumThresholdPercent**? | number | Threshold for the Cpu Maximum utilization.
__*Default*__: 80 +**memoryMaximumThresholdPercent**? | number | Threshold for the Memory Maximum utilization.
__*Default*__: 0. +**requestsErrorRateThreshold**? | number | Threshold for the Number of Request Errors.
__*Default*__: 0. +**requestsThreshold**? | number | Threshold for the Number of Requests.
__*Default*__: 0. +**skipLinkSection**? | boolean | Whether to add link section at the start of widget.
__*Default*__: false +**targetResponseTimeThreshold**? | number | Threshold for the Target Response Time.
__*Default*__: 0. + + + ## struct WatchStateMachineOptions @@ -772,6 +901,27 @@ Name | Type | Description +## struct WatchTargetGroupProps + + + + + + +Name | Type | Description +-----|------|------------- +**targetGroup** | [aws_elasticloadbalancingv2.TargetGroupBase](#aws-cdk-lib-aws-elasticloadbalancingv2-targetgroupbase) | +**title** | string | +**watchful** | [IWatchful](#cdk-watchful-iwatchful) | +**cpuMaximumThresholdPercent**? | number | Threshold for the Cpu Maximum utilization.
__*Default*__: 80 +**memoryMaximumThresholdPercent**? | number | Threshold for the Memory Maximum utilization.
__*Default*__: 0. +**requestsErrorRateThreshold**? | number | Threshold for the Number of Request Errors.
__*Default*__: 0. +**requestsThreshold**? | number | Threshold for the Number of Requests.
__*Default*__: 0. +**skipLinkSection**? | boolean | Whether to add link section at the start of widget.
__*Default*__: false +**targetResponseTimeThreshold**? | number | Threshold for the Target Response Time.
__*Default*__: 0. + + + ## struct WatchedOperation