/
exastat.py
executable file
·123 lines (98 loc) · 4.25 KB
/
exastat.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
#!/usr/bin/env python
################################################################################
##
## File name: exastat.py (v1.0)
## Purpose: Show cumulative exadata metrics from CELLCLI and their deltas
## in multicolumn format
##
## Author: Tanel Poder ( tanel@tanelpoder.com | @tanelpoder | blog.tanelpoder.com )
## Copyright: Tanel Poder. All Rights Reserved.
##
## Usage: Save LIST METRICHISTORY into a file or pipe directly to exastat
##
## Example: cellcli -e "LIST METRICHISTORY WHERE name LIKE 'FL_.*' AND collectionTime > '"`date --date \
## '1 day ago' "+%Y-%m-%dT%H:%M:%S%:z"`"'" | ./exastat FL_DISK_FIRST FL_FLASH_FIRST
##
## The above example lists you two metrics FL_DISK_FIRST and FL_FLASH_FIRST in columnar format
## You can list any number of metrics (you're not restricted to only two)
##
##
################################################################################
import fileinput, re, datetime, time, sys
DEBUG=False
rawmetrics = {} # main metric array
errors = [] # unparsable lines
timestamps = []
cell_pattern = re.compile(r"^\s*(?P<name>\w+)\s+(?P<obj>\w+)\s+(?P<value>[\w,]+)\s(?P<unit>.*)\s+(?P<timestamp>.{25})$")
def extract_metric_value(s, pattern):
match = pattern.match(s)
if match:
name = match.group("name").strip()
obj = match.group("obj").strip()
value = int(match.group("value").strip().replace(',',''))
unit = match.group("unit").strip()
timestamp = datetime.datetime.fromtimestamp(time.mktime(time.strptime(match.group("timestamp").strip()[:-6], "%Y-%m-%dT%H:%M:%S")))
return {"METRIC_NAME":name, "METRIC_OBJECT":obj, "METRIC_VALUE":value, "METRIC_UNIT":unit, "TIMESTAMP":timestamp}
def get_timestamps(m):
t = []
for i in (key for key in sorted(m.keys(), key=lambda x: x[1])):
if not t.__contains__(i[1]):
t.append( i[1] )
return t
def get_ordered_metric_values(m, metric_name):
r = []
for i in (key for key in sorted(m.keys(), key=lambda x: x[1]) if key[0]==metric_name):
if DEBUG: print "key = %s value = %s" % (i, m[i])
r.append({ "METRIC_NAME":i[0], "TIMESTAMP":i[1], "METRIC_OBJECT":i[2], "METRIC_VALUE":m[i]["METRIC_VALUE"], "METRIC_UNIT":m[i]["METRIC_UNIT"] })
return r
def get_delta_metric_values(m, metric_name):
r = {}
prev_metric_value = None
# requires ordered input
for i in (key for key in (get_ordered_metric_values(m, metric_name))):
if prev_metric_value:
if DEBUG: print "%s delta %s = %s (%s - %s)" % ( i["TIMESTAMP"], i["METRIC_NAME"], i["METRIC_VALUE"] - prev_metric_value, i["METRIC_VALUE"], prev_metric_value )
r[i["TIMESTAMP"]] = ( i["TIMESTAMP"], i["METRIC_NAME"], i["METRIC_VALUE"] - prev_metric_value, i["METRIC_VALUE"], prev_metric_value )
prev_metric_value = i["METRIC_VALUE"]
else:
prev_metric_value = i["METRIC_VALUE"]
return r
# main()
metric_list = sys.argv[1:]
for line in sys.stdin.readlines():
e = extract_metric_value(line, cell_pattern)
if e:
if e["METRIC_NAME"] in metric_list:
rawmetrics[e["METRIC_NAME"], e["TIMESTAMP"], e["METRIC_OBJECT"]] = { "METRIC_VALUE":e["METRIC_VALUE"], "METRIC_UNIT":e["METRIC_UNIT"] }
else:
errors.append(line)
if DEBUG: print "len(rawmetrics) = %s len(errors) = %s" % (len(rawmetrics), len(errors))
m = {}
for mn in metric_list:
m[mn] = get_delta_metric_values(rawmetrics, mn)
timestamps = get_timestamps(rawmetrics)
if DEBUG: print timestamps.pop(0) # 0-th sample doesn't have delta
output_header = ("%-26s %10s" % ("TIMESTAMP", "SECONDS"))
output_separator = "%-26s %10s" % ("-" * 26, "-" * 10)
for x in metric_list:
output_header += ("%" + str(len(x)+1) +"s") % x
output_separator += ' ' + '-' * len(x)
print ""
print output_header
print output_separator
prev_ts = None
for ts in iter(timestamps):
if prev_ts:
out = "%-26s %10s" % (ts, (ts - prev_ts).seconds)
prev_ts = ts
else:
out = "%-26s %10s" % (ts, "")
prev_ts = ts
for mn in metric_list:
if ts in m[mn]:
v = m[mn][ts][2]
else:
v = 0
out += (" %"+str(len(mn)) +"d") % v
print out
print ""