forked from koder-ua/ceph-monitoring
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathceph_info.py
158 lines (124 loc) · 4.6 KB
/
ceph_info.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
import sys
import copy
import os.path
import collections
import texttable
from ceph_report_templ import templ
class DevLoad(object):
def __init__(self, name):
self.name = name
self.values = collections.defaultdict(lambda: [])
self.is_partition = name[-1].isdigit()
def get_dev(self):
name = self.name
while name[-1].isdigit():
name = name[:-1]
return name
def get_avg_sz(self):
return self.sum_data() / self.sum_iops()
def sum_data(self):
return sum(map(float, self.values['wkB/s']))
def sum_iops(self):
return sum(map(float, self.values['w/s']))
def load_io_usage(fname):
fc = [i.strip()
for i in open(fname).read().split("\n")
if i.strip() != ""]
devs = fc[0].split()
num_devs = len(fc[1].split())
fc = fc[2:]
pairs = zip(devs[::2], devs[1::2])
per_dev = {}
names = ('rrqm/s wrqm/s r/s w/s' +
' rkB/s wkB/s avgrq-sz avgqu-sz' +
' await r_await w_awaits vctm util').split()
for offset in range(len(fc) / num_devs):
data = fc[offset * num_devs:(offset + 1) * num_devs]
for line in data:
items = line.split()
if items[0] not in per_dev:
obj = DevLoad(items[0])
per_dev[items[0]] = obj
else:
obj = per_dev[items[0]]
for metr_name, val in zip(names, map(float, items[1:])):
obj.values[metr_name].append(val)
return pairs, per_dev
class Host(object):
def __init__(self, name, files):
self.name = name
self.files = files
self.io_usage = None
self.devs_pairs = None
self.pure_dev_names = None
def __str__(self):
return "Host({0.name}, {0.files})".format(self)
def __repr__(self):
return str(self)
def agg_partitions(self):
self.pure_dev_names = set()
devs = collections.defaultdict(lambda: [])
for part_name, part_obj in self.io_usage.items():
if not part_obj.is_partition:
self.pure_dev_names.add(part_name)
else:
devs[part_obj.get_dev()].append(part_name)
for dev, parts in devs.items():
if len(parts) == 1:
dev_obj = copy.deepcopy(self.io_usage[parts[0]])
dev_obj.name = dev
else:
dev_obj = DevLoad(dev)
part_objs = map(self.io_usage.get, parts)
utils = [part_obj.values['util']
for part_obj in part_objs]
# this is actually wrong
dev_obj.values['util'] = [min(i, 100)
for i in map(sum, zip(*utils))]
for name in ('w/s', 'r/s', 'rkB/s', 'wkB/s'):
vals = [part_obj.values[name]
for part_obj in part_objs]
dev_obj.values[name] = map(sum, zip(*vals))
self.io_usage[dev] = dev_obj
self.pure_dev_names.add(dev)
hosts = {}
for fname in sys.argv[1:]:
base_fname = os.path.basename(fname)
assert base_fname.startswith('osd_mon')
pref, tp = base_fname.rsplit('.', 1)
_, name = pref.split('.', 1)
if name in hosts:
hosts[name].files[tp] = fname
else:
hosts[name] = Host(name, {tp: fname})
all_devs = []
data_param = []
for host in hosts.values():
host.devs_pairs, host.io_usage = load_io_usage(host.files['io'])
host.agg_partitions()
tab = texttable.Texttable(max_width=120)
tab.set_deco(tab.HEADER | tab.VLINES | tab.BORDER)
tab.set_cols_align(['r', 'r', 'r', 'r', 'r'])
tab.header(['host::dev', 'avg_sz', 'wr Mb', 'wr kIO', 'avg util %'])
hosts_list = sorted(hosts.values(), key=lambda x: x.name)
for host in hosts_list:
for dev_name in sorted(host.pure_dev_names):
dev = host.io_usage[dev_name]
tab.add_row([
host.name + "::" + dev_name,
int(dev.get_avg_sz()),
int(dev.sum_data() / 1024),
int(dev.sum_iops() / 1000),
int(sum(dev.values['util']) / len(dev.values['util']))])
if host != hosts_list[-1]:
tab.add_row(['----'] * 5)
print tab.draw()
exit(1)
for host in hosts_list:
for dev_name in sorted(host.pure_dev_names):
dev = host.io_usage[dev_name]
dname = "'{0}.{1}'".format(host.name, dev_name)
all_devs.append(dname)
vals = ','.join(map(str, dev.values['util']))
data_param.append('{0}: [{1}]'.format(dname, vals))
print templ.replace('{{devs}}', ", ".join(all_devs)).replace('{{data}}', ",".join(data_param))