Back to all patterns

About

Development Tool

cloudformation

Type

pattern

Deploy a CloudWatch dashboard for an Amazon ECS service

Create your own custom CloudWatch dashboard for an ECS service

Nathan Peck
Nathan Peck
Senior Developer Advocate at AWS

About

Amazon ECS collects telemetry and generates loggable events for your service. This information is displayed in the default Amazon ECS web console views. However, you may wish to generate your own custom CloudWatch dashboard that has the specific metrics you are interested in.

This pattern shows how you can use CloudFormation to define and create a custom dashboard for observing the performance and events of your ECS deployments.

Container Insights

This pattern assumes that you have already enabled Container Insights on your ECS cluster.

💡 Tip: There is no charge for using Amazon ECS, however the Container Insights feature does come with an additional cost based on the amount of data stored in CloudWatch, and an additional cost for querying that data using CloudWatch Log Insights. A task with one container generates about 1 MB of telemetry data per day. If there is more than one container per task, or you have frequent task turnover you may generate even more telemetry data. Queries will also cost more based on the amount of telemetry data processed by the query. See Amazon CloudWatch pricing for more info.

In order to activate Container Insights for a cluster, you can use the command line:

aws ecs update-cluster-settings \
  --cluster cluster_name_or_arn \
  --settings name=containerInsights,value=enabled \
  --region us-east-1

Or you can enable Container Insights when creating an ECS cluster with CloudFormation:

MyCluster:
  Type: AWS::ECS::Cluster
  Properties:
    ClusterName: production
    Configuration:
      containerInsights: enabled

Once Container Insights has been enabled you will start to get high cardinality telemetry data about your tasks, streamed into CloudWatch Logs and CloudWatch Metrics.

Dashboard Template

The following template demonstrates how to setup a custom CloudWatch dashboard for a single ECS service.

File: cloudwatch-dashboard-ecs.yml Language: yml
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
AWSTemplateFormatVersion: '2010-09-09'
Description: This template deploys an automatically generated CloudWatch
             dashboard for the referenced ECS service.
Transform:
  - AWS::LanguageExtensions

Parameters:
  ServiceArn:
    Type: String
    Description: The ARN of the service that we want to generate the dashboard from.

Resources:
  # A CloudWatch log group for persisting the deployment events
  ServiceEventLog:
    Type: AWS::Logs::LogGroup

  # Create the EventBridge rule that captures deployment events into the CloudWatch log group
  CaptureServiceDeploymentEvents:
    Type: AWS::Events::Rule
    Properties:
      Description:
        Fn::Sub:
          - 'Capture service deployment events from the ECS service ${ServiceName}'
          # Scary but working way to get service's human name from it's ARN
          - ServiceName: !Select [2, !Split ['/', !Select [5, !Split [':', !Ref ServiceArn]]]]
      EventPattern:
        source:
          - aws.ecs
        detail-type:
          - "ECS Deployment State Change"
          - "ECS Service Action"
        resources:
          - !Ref ServiceArn
      # Where to send the events
      Targets:
        - Arn: !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:${ServiceEventLog}
          Id: 'CloudWatchLogGroup'

  # Create a log group resource policy that allows EventBridge to put logs into
  # the log group
  LogGroupForEventsPolicy:
    Type: AWS::Logs::ResourcePolicy
    Properties:
      PolicyName: EventBridgeToCWLogsPolicy
      PolicyDocument: !Sub
      - >
        {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Sid": "EventBridgetoCWLogsPolicy",
              "Effect": "Allow",
              "Principal": {
                "Service": [
                  "delivery.logs.amazonaws.com",
                  "events.amazonaws.com"
                ]
              },
              "Action": [
                "logs:CreateLogStream",
                "logs:PutLogEvents"
              ],
              "Resource": [
                "${LogArn}"
              ]
            }
          ]
        }
      - { LogArn: !GetAtt ServiceEventLog.Arn, RuleArn: !GetAtt CaptureServiceDeploymentEvents.Arn}

  # This resource creates the widgets that will live in the CloudWatch
  # dashboard, by pulling stats from Container Insights
  ServiceDashboard:
    Type: AWS::CloudWatch::Dashboard
    Properties:
      DashboardName:
        Fn::Sub:
          - "${ServiceName}-dashboard"
          - ServiceName: !Select [2, !Split ['/', !Select [5, !Split [':', !Ref ServiceArn]]]]
      DashboardBody:
        Fn::ToJsonString:
          widgets:
            # A table that shows recent deployment events
            - type: log
              x: 0
              y: 0
              width: 24
              height: 4
              properties:
                region: !Ref AWS::Region
                title: Service Deployments
                query: !Sub "SOURCE '${ServiceEventLog}' | fields @timestamp, detail.eventName, detail.deploymentId | sort @timestamp desc | limit 500"
                view: table

            # A graph showing the running task count over time
            - type: metric
              x: 0
              y: 13
              width: 24
              height: 6
              properties:
                metrics:
                - - "ECS/ContainerInsights"
                  - "RunningTaskCount"
                  - "ServiceName"
                  # Extract service name from service ARN
                  - !Select [2, !Split ['/', !Select [5, !Split [':', !Ref ServiceArn]]]]
                  - "ClusterName"
                  # Extract cluster name from service ARN
                  - !Select [1, !Split ['/', !Select [5, !Split [':', !Ref ServiceArn]]]]
                - [ ".", "DesiredTaskCount", ".", ".", ".", "." ]
                view: timeSeries
                stacked: false
                region: !Ref AWS::Region
                stat: Sum
                period: 60
                yAxis:
                  left:
                    min: 0
                title: "DesiredTaskCount, RunningTaskCount"

            # A graph showing CPU and Memory utilization over time
            - type: metric
              x: 0
              y: 13
              width: 24
              height: 6
              properties:
                metrics:
                - - "ECS/ContainerInsights"
                  - "CpuUtilized"
                  - "ServiceName"
                  # Extract service name from service ARN
                  - !Select [2, !Split ['/', !Select [5, !Split [':', !Ref ServiceArn]]]]
                  - "ClusterName"
                  # Extract cluster name from service ARN
                  - !Select [1, !Split ['/', !Select [5, !Split [':', !Ref ServiceArn]]]]
                - [ ".", "MemoryUtilized", ".", ".", ".", "." ]
                view: timeSeries
                stacked: false
                region: !Ref AWS::Region
                stat: Sum
                period: 60
                yAxis:
                  left:
                    min: 0
                title: "CPU Utilization, Memory Utilization"

This template only requires a single input variable:

  • ServiceArn - The ECS service’s ARN (Amazon Resource Name) to track in the dashboard. It should look something like this: arn:aws:ecs:us-west-2:123456789012:service/sample-webapp

You can deploy this template using the AWS CloudFormation console, or using the AWS CLI:

aws cloudformation deploy \
  --template-file cloudwatch-dashboard-ecs.yml \
  --stack-name cloudwatch-dashboard-ecs \
  --capabilities CAPABILITY_IAM \
  --parameter-overrides \
     ServiceArn=arn:aws:ecs:us-east-2:209640446841:service/capacity-provider-environment-BaseStack-18PANC6K9E7D8-ECSCluster-NNBNpIh5AkZO/nginx-on-fargate
capacity-provider-environment-BaseStack-18PANC6K9E7D8-ECSCluster-NNBNpIh5AkZO

See Also