-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathcloudwatch_metrics_to_sumo_v2.py
executable file
·188 lines (141 loc) · 7.79 KB
/
cloudwatch_metrics_to_sumo_v2.py
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
"""
Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file
distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you
under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.
"""
#!/usr/bin/env python
# This script uses the boto, the Python interface to Amazon Web Services - http://boto.readthedocs.org/
#
# Requirements:
# Install onto EC2 instance that has the AWS cli installed - http://aws.amazon.com/cli/
# AWS IAM user with permission to read from CloudWatch including access key ID and secret access key
# Write privileges if pushing Linux metrics to CloudWatch
# Sumo Logic installed collector on instance running the script, or a hosted collector
#
# Both the default EC2 metrics and custom Linux metrics are pulled by this script.
# The default metrics are automatically pushed every 5 minutes
# The Linux metrics can be pushed to CloudWatch using the Linux Monitoring Scripts - http://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/mon-scripts-perl.html
#
# Cloudwatch results can be pushed to Sumo using either an installed collector or a hosted collector.
# For an installed collector use the write_to_file function
# For a hosted collector use the push_to_collector function
import boto, datetime, json, urllib2, time
from boto import ec2
from pytz import timezone
import boto.ec2.cloudwatch
from time import gmtime, strftime
# Set our AWS access keys. Must have Cloudwatch permissions in AWS IAM
AWS_ACCESS_KEY_ID = 'YOUR KEY ID HERE'
AWS_SECRET_ACCESS_KEY = 'YOUR ACCESS KEY HERE'
### Set Global Variables ###
# The Sumo Logic collector where we are sending logs
url = 'https://collectors.sumologic.com/receiver/v1/http/SUMO_HTTP_TOKEN
# The file where we are writing our logs
boto_log = '/home/ubuntu/log/boto.log'
### Set AWS EC2 Variables ###
# The AWS regions from which we are collecting log data
regions = ["us-east-1", "us-west-1", "us-west-2", "ap-northeast-1", "ap-southeast-1", "ap-southeast-2", "eu-west-1", "sa-east-1"]
### Set AWS CloudWatch Variables ###
# Start and end times for the Cloudwatch query
query_end_time = datetime.datetime.utcnow()
query_start_time = query_end_time - datetime.timedelta(minutes=9)
# Set the default EC2 metrics we want to pull
# These are sent by default to CloudWatch
ec2_metrics = [ 'CPUCreditUsage', 'CPUCreditBalance', 'CPUUtilization', 'NetworkIn', 'NetworkOut', 'DiskReadBytes', 'DiskReadOps', 'DiskWriteBytes', 'DiskWriteOps', 'StatusCheckFailed', 'StatusCheckFailed_Instance', 'StatusCheckFailed_System' ]
# Set the Linux EC2 metrics we want to pull
# Requires that Linux metrics be pushed to Cloudwatch using the Linux Monitoring scripts
# http://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/mon-scripts-perl.html
linux_metrics = [ 'DiskSpaceUtilization', 'MemoryUtilization', 'SwapUtilization' ]
### CONSTANTS ###
# Generate UTC timestamps - create a timestamp for local logging
timeStamp = strftime("%Y-%m-%d %H:%M:%S", gmtime())
timeStamp += "Z"
# Create the dictionary where we will store our results
d = {}
### Functions ###
## Writes a given log message to file with timestamp.
def write_to_file(log_data):
my_file = open(boto_log, "a")
my_file.write(timeStamp + ': ' + log_data + '\n')
my_file.close()
## Pushes a given log message with timestamp to a hosted collector.
def push_to_collector(log_data):
log_data = timeStamp + ': ' + log_data + '\n'
print urllib2.urlopen(url, log_data).read()
## Convert the timestamp returned from CloudWatch to a human readable format.
def cloudwatch_timestamp_to_utc(timestamp):
l = timestamp.split(' ')
ts = l[0] + 'T' + l[1] + 'Z'
return ts
## Pull instance metrics from CloudWatch.
def get_cloudwatch_metrics(namespace, metric, unit):
#data_points = c.get_metric_statistics(300, query_start_time, query_end_time, metric,'AWS/EC2', 'Average', dimensions={'InstanceId' : d["InstanceId"]}, unit=unit)
data_points = c.get_metric_statistics(300, query_start_time, query_end_time, metric, namespace, 'Average', dimensions={'InstanceId' : d["InstanceId"]}, unit=unit)
# Check to see if any metrics are returned
if data_points:
# Data is returned from CloudWatch in a list of dictionaries. Based on our query (look back 9 minutes for a 5 minute interval)
# the assumption is being made that only one result is being returned.
data_point = data_points[0]
# Extract Timestamp, pass it to cloudwatch_timestamp_to_utc for processing.
# Timestamp is returned as a tuple, we need to make it pretty for human consumption
timestamp = cloudwatch_timestamp_to_utc(str(data_point['Timestamp']))
# Update the computer friendly timestamp with a human friendly one
data_point['Timestamp'] = timestamp
# Write our results back into a list
l = [data_point]
else:
# If there are no results for this metric, the list is empty
l = []
# Add the metric to our log message
d[metric] = l
# Iterate through each of the regions
for region in regions:
ec2_conn = ec2.connect_to_region(region, aws_access_key_id=AWS_ACCESS_KEY_ID, aws_secret_access_key=AWS_SECRET_ACCESS_KEY)
reservations = ec2_conn.get_all_instances()
instances = [i for r in reservations for i in r.instances]
for i in instances:
# Set the region
d['region'] = region
# Extract attributes
d['availability_zone'] = i.placement
d['InstanceId'] = i.id
d['state'] = i.state
d['state_code'] = i.state_code
# Extract customer name or other unique tag
# Mostly applicable in a multi-tenant environment
#if 'customerName' in i.tags:
# d['customerName'] = i.tags['customerName']
if i.state == 'running':
d['state_reason'] = i.state_reason
d['public_dns_name'] = i.public_dns_name
else:
d["state_reason"] = i.state_reason['code']
d["state_reason_msg"] = i.state_reason['message']
# Create a connection to CloudWatch
c = boto.ec2.cloudwatch.connect_to_region(region, aws_access_key_id=AWS_ACCESS_KEY_ID, aws_secret_access_key=AWS_SECRET_ACCESS_KEY)
# Iterate through each of the metrics in ec2_metrics
for metric in ec2_metrics:
namespace = 'AWS/EC2'
if metric == 'CPUUtilization':
get_cloudwatch_metrics(namespace, metric, 'Percent')
elif ( metric == 'NetworkIn' or metric == 'NetworkOut' or metric == 'DiskReadBytes' or metric == 'DiskWriteBytes'):
get_cloudwatch_metrics(namespace, metric, 'Bytes/Second')
elif (metric == 'DiskReadOps' or metric == 'DiskWriteOps'):
get_cloudwatch_metrics(namespace, metric, 'Count/Second')
else:
get_cloudwatch_metrics(namespace, metric, 'Count')
# Iterate through each of the metrics in linux_metrics
for metric in linux_metrics:
namespace = 'System/Linux'
get_cloudwatch_metrics(namespace, metric, 'Count')
jsonResults = json.dumps(d)
# Uncomment to display results to the screen
print jsonResults
# Uncomment the appropriate function for your environment.
# write_to_file(jsonResults)
# push_to_collector(jsonResults)