1#!/usr/bin/env python 2# Author: Chris Moyer <cmoyer@newstex.com> 3# Description: CloudWatch Utility 4# For listing stats, creating alarms, and managing 5# other CloudWatch aspects 6 7import boto 8cw = boto.connect_cloudwatch() 9 10from datetime import datetime, timedelta 11 12def _parse_time(time_string): 13 """Internal function to parse a time string""" 14 15def _parse_dict(d_string): 16 result = {} 17 if d_string: 18 for d in d_string.split(","): 19 d = d.split(":") 20 result[d[0]] = d[1] 21 return result 22 23def ls(namespace=None): 24 """ 25 List metrics, optionally filtering by a specific namespace 26 namespace: Optional Namespace to filter on 27 """ 28 print "%-10s %-50s %s" % ("Namespace", "Metric Name", "Dimensions") 29 print "-"*80 30 for m in cw.list_metrics(): 31 if namespace is None or namespace.upper() in m.namespace: 32 print "%-10s %-50s %s" % (m.namespace, m.name, m.dimensions) 33 34def stats(namespace, metric_name, dimensions=None, statistics="Average", start_time=None, end_time=None, period=60, unit=None): 35 """ 36 Lists the statistics for a specific metric 37 namespace: The namespace to use, usually "AWS/EC2", "AWS/SQS", etc. 38 metric_name: The name of the metric to track, pulled from `ls` 39 dimensions: The dimensions to use, formatted as Name:Value (such as QueueName:myQueue) 40 statistics: The statistics to measure, defaults to "Average" 41 'Minimum', 'Maximum', 'Sum', 'Average', 'SampleCount' 42 start_time: Start time, default to now - 1 day 43 end_time: End time, default to now 44 period: Period/interval for counts, default to 60 minutes 45 unit: Unit to track, default depends on what metric is being tracked 46 """ 47 48 # Parse the dimensions 49 dimensions = _parse_dict(dimensions) 50 51 # Parse the times 52 if end_time: 53 end_time = _parse_time(end_time) 54 else: 55 end_time = datetime.utcnow() 56 if start_time: 57 start_time = _parse_time(start_time) 58 else: 59 start_time = datetime.utcnow() - timedelta(days=1) 60 61 print "%-30s %s" % ('Timestamp', statistics) 62 print "-"*50 63 data = {} 64 for m in cw.get_metric_statistics(int(period), start_time, end_time, metric_name, namespace, statistics, dimensions, unit): 65 data[m['Timestamp']] = m[statistics] 66 keys = data.keys() 67 keys.sort() 68 for k in keys: 69 print "%-30s %s" % (k, data[k]) 70 71def put(namespace, metric_name, dimensions=None, value=None, unit=None, statistics=None, timestamp=None): 72 """ 73 Publish custom metrics 74 namespace: The namespace to use; values starting with "AWS/" are reserved 75 metric_name: The name of the metric to update 76 dimensions: The dimensions to use, formatted as Name:Value (such as QueueName:myQueue) 77 value: The value to store, mutually exclusive with `statistics` 78 statistics: The statistics to store, mutually exclusive with `value` 79 (must specify all of "Minimum", "Maximum", "Sum", "SampleCount") 80 timestamp: The timestamp of this measurement, default is current server time 81 unit: Unit to track, default depends on what metric is being tracked 82 """ 83 84 def simplify(lst): 85 return lst[0] if len(lst) == 1 else lst 86 87 print cw.put_metric_data(namespace, simplify(metric_name.split(';')), 88 dimensions = simplify(map(_parse_dict, dimensions.split(';'))) if dimensions else None, 89 value = simplify(value.split(';')) if value else None, 90 statistics = simplify(map(_parse_dict, statistics.split(';'))) if statistics else None, 91 timestamp = simplify(timestamp.split(';')) if timestamp else None, 92 unit = simplify(unit.split(';')) if unit else None) 93 94def help(fnc=None): 95 """ 96 Print help message, optionally about a specific function 97 """ 98 import inspect 99 self = sys.modules['__main__'] 100 if fnc: 101 try: 102 cmd = getattr(self, fnc) 103 except: 104 cmd = None 105 if not inspect.isfunction(cmd): 106 print "No function named: %s found" % fnc 107 sys.exit(2) 108 (args, varargs, varkw, defaults) = inspect.getargspec(cmd) 109 print cmd.__doc__ 110 print "Usage: %s %s" % (fnc, " ".join([ "[%s]" % a for a in args])) 111 else: 112 print "Usage: cwutil [command]" 113 for cname in dir(self): 114 if not cname.startswith("_") and not cname == "cmd": 115 cmd = getattr(self, cname) 116 if inspect.isfunction(cmd): 117 doc = cmd.__doc__ 118 print "\t%s - %s" % (cname, doc) 119 sys.exit(1) 120 121 122if __name__ == "__main__": 123 import sys 124 self = sys.modules['__main__'] 125 if len(sys.argv) >= 2: 126 try: 127 cmd = getattr(self, sys.argv[1]) 128 except: 129 cmd = None 130 args = sys.argv[2:] 131 else: 132 cmd = help 133 args = [] 134 if not cmd: 135 cmd = help 136 try: 137 cmd(*args) 138 except TypeError, e: 139 print e 140 help(cmd.__name__) 141