├── media ├── LineType.png └── NumberType.png ├── .github └── PULL_REQUEST_TEMPLATE.md ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── CONTRIBUTING.md └── amazon-ec2-global-dashboard.yaml /media/LineType.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/amazon-ec2-global-dashboard/HEAD/media/LineType.png -------------------------------------------------------------------------------- /media/NumberType.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/amazon-ec2-global-dashboard/HEAD/media/NumberType.png -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | *Issue #, if available:* 2 | 3 | *Description of changes:* 4 | 5 | 6 | By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. 7 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 10 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 11 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 12 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 13 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 14 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Amazon EC2 Global Dashboard 2 | 3 | Monitor how many EC2 instances are running across all regions with a simple dashboard. 4 | 5 | ### Details 6 | 7 | Amazon EC2 Global Dashboard is created with a CloudFormation template. All elements of the dashboard are handled by the CloudFormation stack. 8 | 9 | The goal of the dashboard is to give insight over all regions for how many instances are currently in a running state and monitor usage. With the overall goal of keeping costs down and helping monitor your account. 10 | 11 | The dashboard is populated by a Lambda function counting instances in a running state in each region and pushing them to CloudWatch as custom metrics. The stack can be created in any region. 12 | 13 | Resources created by CloudFormation: 14 | - AWS::CloudWatch::Dashboard 15 | - AWS::IAM::Role 16 | - AWS::Lambda::Permission 17 | - AWS::Lambda::Function 18 | - AWS::Events::Rule 19 | 20 | ### Setup 21 | 22 | 1. Save the file called 'amazon-ec2-global-dashboard.yaml' locally 23 | 2. Go to CloudFormation in your AWS management console 24 | 3. Select 'Create Stack' -> 'Template is ready' -> 'Upload a template file' 25 | 4. Upload 'amazon-ec2-global-dashboard.yaml' -> 'Next' 26 | 5. Give it a name (amazon-ec2-global-dashboard) -> 'Next' 27 | 6. No requirements on the *Configure stack options* page -> 'Next' 28 | 7. On the *Review* page you must accept the acknowledgment to allow the stack to create an IAM Role -> 'Create stack' 29 | 30 | The stack will begin to create the resources. Give it about 15 minutes to gather and push the initial metrics. 31 | View your dashboard in CloudWatch management console -> Dashboards. 32 | 33 | ### New Feature 34 | 35 | Tags are an essential part of infrastructure management. You can now choose to monitor all or tagged running EC2 instances. 36 | This option is configured using Parameters when launching the Stack. 37 | If you wish to use tag-based monitoring, you can use the default `(Key=tag:amazon-ec2-global-dashboard,Value=enabled)` or provide your own. 38 | 39 | ### Widgets 40 | 41 | The Dashboard contains two widgets: 42 | - **Running Instances** - Dynamic widget showing the number of running instances and historical data. 43 | - **Region mapping** – Maps the region name with the region code and hyperlinks to the instances in each region. 44 | 45 | The ‘Number’ widget type will show the current number of running EC2 instances, this is the default view: 46 | ![NumberType](media/NumberType.png) 47 | 48 | The ‘Line’ widget type will show historical data: 49 | ![LineType](media/LineType.png) 50 | 51 | ## License Summary 52 | 53 | This sample code is made available under the MIT-0 license. See the LICENSE file. 54 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check [existing open](https://github.com/aws-samples/amazon-ec2-global-dashboard/issues), or [recently closed](https://github.com/aws-samples/amazon-ec2-global-dashboard/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aclosed%20), issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *master* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 3. Ensure local tests pass. 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | 43 | ## Finding contributions to work on 44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/aws-samples/amazon-ec2-global-dashboard/labels/help%20wanted) issues is a great place to start. 45 | 46 | 47 | ## Code of Conduct 48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 50 | opensource-codeofconduct@amazon.com with any additional questions or comments. 51 | 52 | 53 | ## Security issue notifications 54 | If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. 55 | 56 | 57 | ## Licensing 58 | 59 | See the [LICENSE](https://github.com/aws-samples/amazon-ec2-global-dashboard/blob/master/LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 60 | 61 | We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes. 62 | -------------------------------------------------------------------------------- /amazon-ec2-global-dashboard.yaml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: 2010-09-09 2 | Description: >- 3 | Amazon EC2 Global Dashboard. Monitor how many EC2 Instances are running across 4 | all regions with a CloudWatch dashboard. 5 | Outputs: 6 | Region: 7 | Description: Region the stack was launched in. 8 | Value: !Ref 'AWS::Region' 9 | TagBasedCounting: 10 | Description: Monitor all running EC2 Instances = 'all'. Monitor by tag = 'tag'. 11 | Value: !Ref TagBasedParameter 12 | Parameters: 13 | TagBasedParameter: 14 | Type: String 15 | Default: all 16 | Description: Monitor all running EC2 Instances = 'all'. Monitor by tag = 'tag'. 17 | TagKeyParameter: 18 | Type: String 19 | Default: tag:amazon-ec2-global-dashboard 20 | Description: The Tag Key which you would like to use. Must be formated like 'tag:YOUR_KEY_HERE'. 21 | TagValueParameter: 22 | Type: String 23 | Default: enabled 24 | Description: The Tag Value which you would like to use. 25 | Resources: 26 | AmazonEC2GlobalDashboardFunction: 27 | Type: 'AWS::Lambda::Function' 28 | Properties: 29 | FunctionName: amazon-ec2-global-dashboard 30 | Environment: 31 | Variables: 32 | TagEnabled: !Ref TagBasedParameter 33 | VarKey: !Ref TagKeyParameter 34 | VarValue: !Ref TagValueParameter 35 | Code: 36 | ZipFile: | 37 | import boto3 38 | import os 39 | cloudwatch = boto3.client('cloudwatch') 40 | client = boto3.client('ec2') 41 | TagEnabled = os.environ['TagEnabled'] 42 | VarKey = os.environ['VarKey'] 43 | VarValue = os.environ['VarValue'] 44 | def lambda_handler(event, context): 45 | regions = [region['RegionName'] for region in client.describe_regions()['Regions']] 46 | for region in regions: 47 | x = region 48 | ec2 = boto3.resource('ec2', region_name=x) 49 | if TagEnabled == 'all': 50 | instances = ec2.instances.filter( 51 | Filters=[{'Name': 'instance-state-name', 'Values': ['running']}]) 52 | instlist = list(instances) 53 | y = (len(instlist)) 54 | cloudwatch.put_metric_data( 55 | MetricData=[ 56 | { 57 | 'MetricName': 'running-state', 58 | 'Dimensions': [ 59 | { 60 | 'Name': 'region', 61 | 'Value': x 62 | }, 63 | ], 64 | 'Unit': 'Count', 65 | 'Value': y 66 | }, 67 | ], 68 | Namespace='Running-instances' 69 | ) 70 | else: 71 | instances = ec2.instances.filter( 72 | Filters=[{'Name': 'instance-state-name', 'Values': ['running']},{'Name': VarKey, 'Values': [VarValue]}]) 73 | instlist = list(instances) 74 | y = (len(instlist)) 75 | cloudwatch.put_metric_data( 76 | MetricData=[ 77 | { 78 | 'MetricName': 'running-state', 79 | 'Dimensions': [ 80 | { 81 | 'Name': 'region', 82 | 'Value': x 83 | }, 84 | ], 85 | 'Unit': 'Count', 86 | 'Value': y 87 | }, 88 | ], 89 | Namespace='Running-instances' 90 | ) 91 | 92 | Handler: index.lambda_handler 93 | Runtime: python3.6 94 | Timeout: '30' 95 | Role: !GetAtt 96 | - LambdaExecutionRole 97 | - Arn 98 | LambdaExecutionRole: 99 | Type: 'AWS::IAM::Role' 100 | Properties: 101 | AssumeRolePolicyDocument: 102 | Version: 2012-10-17 103 | Statement: 104 | - Effect: Allow 105 | Principal: 106 | Service: 107 | - lambda.amazonaws.com 108 | Action: 109 | - 'sts:AssumeRole' 110 | Path: / 111 | Policies: 112 | - PolicyName: root 113 | PolicyDocument: 114 | Version: 2012-10-17 115 | Statement: 116 | - Effect: Allow 117 | Action: 118 | - 'ec2:DescribeRegions' 119 | - 'ec2:DescribeInstances' 120 | - 'cloudwatch:PutMetricData' 121 | - 'cloudwatch:PutDashboard' 122 | - 'logs:CreateLogGroup' 123 | - 'logs:CreateLogStream' 124 | - 'logs:PutLogEvents' 125 | Resource: '*' 126 | ScheduledRule: 127 | Type: 'AWS::Events::Rule' 128 | Properties: 129 | Description: Amazon EC2 Global Dashboard rule. 130 | ScheduleExpression: rate(15 minutes) 131 | State: ENABLED 132 | Targets: 133 | - Arn: !GetAtt 134 | - AmazonEC2GlobalDashboardFunction 135 | - Arn 136 | Id: AmazonEC2GlobalDashboardFunction 137 | PermissionForEventsToInvokeLambda: 138 | Type: 'AWS::Lambda::Permission' 139 | Properties: 140 | FunctionName: !Ref AmazonEC2GlobalDashboardFunction 141 | Action: 'lambda:InvokeFunction' 142 | Principal: events.amazonaws.com 143 | SourceArn: !GetAtt 144 | - ScheduledRule 145 | - Arn 146 | Dashboard: 147 | Type: 'AWS::CloudWatch::Dashboard' 148 | Properties: 149 | DashboardName: Amazon_EC2_Global_Dashboard 150 | DashboardBody: !Join 151 | - '' 152 | - - >- 153 | {"widgets":[{"type":"metric","x":0,"y":0,"width":12,"height":16,"properties":{"metrics":[["Running-instances","running-state","region","us-east-1"],[".",".",".","us-east-2"],[".",".",".","us-west-1"],[".",".",".","us-west-2"],[".",".",".","ca-central-1"],[".",".",".","eu-central-1"],[".",".",".","eu-west-1"],[".",".",".","eu-west-2"],[".",".",".","eu-west-3"],[".",".",".","eu-north-1"],[".",".",".","ap-northeast-1"],[".",".",".","ap-northeast-2"],[".",".",".","ap-northeast-3"],[".",".",".","ap-southeast-1"],[".",".",".","ap-southeast-2"],[".",".",".","ap-south-1"],[".",".",".","sa-east-1"]],"region":" 154 | - !Ref 'AWS::Region' 155 | - >- 156 | ","view":"singleValue","period":900,"stat":"Maximum","title":"Running 157 | Instances"}}, 158 | {"type":"text","x":12,"y":0,"width":6,"height":16,"properties":{"markdown":"# 159 | Region 160 | mapping\nCode|Name\n----|----\n[us-east-1](https://us-east-1.console.aws.amazon.com/ec2/v2/home?region=us-east-1#Instances:sort=instanceId)|US 161 | East (N. 162 | Virginia)\n[us-east-2](https://us-east-2.console.aws.amazon.com/ec2/v2/home?region=us-east-2#Instances:sort=instanceId)|US 163 | East 164 | (Ohio)\n[us-west-1](https://us-west-1.console.aws.amazon.com/ec2/v2/home?region=us-west-1#Instances:sort=instanceId)|US 165 | West (N. 166 | California)\n[us-west-2](https://us-west-2.console.aws.amazon.com/ec2/v2/home?region=us-west-2#Instances:sort=instanceId)|US 167 | West 168 | (Oregon)\n[ca-central-1](https://ca-central-1.console.aws.amazon.com/ec2/v2/home?region=ca-central-1#Instances:sort=instanceId)|Canada 169 | (Central)\n[eu-central-1](https://eu-central-1.console.aws.amazon.com/ec2/v2/home?region=eu-central-1#Instances:sort=instanceId)|EU 170 | (Frankfurt)\n[eu-west-1](https://eu-west-1.console.aws.amazon.com/ec2/v2/home?region=eu-west-1#Instances:sort=instanceId)|EU 171 | (Ireland)\n[eu-west-2](https://eu-west-2.console.aws.amazon.com/ec2/v2/home?region=eu-west-2#Instances:sort=instanceId)|EU 172 | (London)\n[eu-west-3](https://eu-west-3.console.aws.amazon.com/ec2/v2/home?region=eu-west-3#Instances:sort=instanceId)|EU 173 | (Paris)\n[eu-north-1](https://eu-north-1.console.aws.amazon.com/ec2/v2/home?region=eu-north-1#Instances:sort=instanceId)|EU 174 | (Stockholm)\n[ap-northeast-1](https://ap-northeast-1.console.aws.amazon.com/ec2/v2/home?region=ap-northeast-1#Instances:sort=instanceId)|Asia 175 | Pacific 176 | (Tokyo)\n[ap-northeast-2](https://ap-northeast-2.console.aws.amazon.com/ec2/v2/home?region=ap-northeast-2#Instances:sort=instanceId)|Asia 177 | Pacific 178 | (Seoul)\n[ap-northeast-3](https://ap-northeast-3.console.aws.amazon.com/ec2/v2/home?region=ap-northeast-3#Instances:sort=instanceId)|Asia 179 | Pacific 180 | (Osaka-Local)\n[ap-southeast-1](https://ap-southeast-1.console.aws.amazon.com/ec2/v2/home?region=ap-southeast-1#Instances:sort=instanceId)|Asia 181 | Pacific 182 | (Singapore)\n[ap-southeast-2](https://ap-southeast-2.console.aws.amazon.com/ec2/v2/home?region=ap-southeast-2#Instances:sort=instanceId)|Asia 183 | Pacific 184 | (Sydney)\n[ap-south-1](https://ap-south-1.console.aws.amazon.com/ec2/v2/home?region=ap-south-1#Instances:sort=instanceId)|Asia 185 | Pacific 186 | (Mumbai)\n[sa-east-1](https://sa-east-1.console.aws.amazon.com/ec2/v2/home?region=sa-east-1#Instances:sort=instanceId)|South 187 | America (São Paulo)\n"}}]} 188 | --------------------------------------------------------------------------------