]>
git.proxmox.com Git - ceph.git/blob - ceph/src/pybind/mgr/osd_perf_query/module.py
6 from itertools
import groupby
11 from mgr_module
import MgrModule
13 def get_human_readable(bytes
, precision
=2):
14 suffixes
= ['', 'Ki', 'Mi', 'Gi', 'Ti']
16 while bytes
> 1024 and suffix_index
< 4:
17 # increment the index of the suffix
20 bytes
= bytes
/ 1024.0
21 return '%.*f%s' % (precision
, bytes
, suffixes
[suffix_index
])
23 class OSDPerfQuery(MgrModule
):
26 "cmd": "osd perf query add "
27 "name=query,type=CephChoices,"
28 "strings=client_id|rbd_image_id|all_subkeys",
29 "desc": "add osd perf query",
33 "cmd": "osd perf query remove "
34 "name=query_id,type=CephInt,req=true",
35 "desc": "remove osd perf query",
39 "cmd": "osd perf counters get "
40 "name=query_id,type=CephInt,req=true",
41 "desc": "fetch osd perf counters",
48 {'type': 'client_id', 'regex': '^(.+)$'},
50 'performance_counter_descriptors': [
51 'bytes', 'write_ops', 'read_ops', 'write_bytes', 'read_bytes',
52 'write_latency', 'read_latency',
54 'limit': {'order_by': 'bytes', 'max_count': 10},
57 RBD_IMAGE_ID_QUERY
= {
59 {'type': 'pool_id', 'regex': '^(.+)$'},
60 {'type': 'object_name',
61 'regex': '^(?:rbd|journal)_data\.(?:([0-9]+)\.)?([^.]+)\.'},
63 'performance_counter_descriptors': [
64 'bytes', 'write_ops', 'read_ops', 'write_bytes', 'read_bytes',
65 'write_latency', 'read_latency',
67 'limit': {'order_by': 'bytes', 'max_count': 10},
72 {'type': 'client_id', 'regex': '^(.*)$'},
73 {'type': 'client_address', 'regex': '^(.*)$'},
74 {'type': 'pool_id', 'regex': '^(.*)$'},
75 {'type': 'namespace', 'regex': '^(.*)$'},
76 {'type': 'osd_id', 'regex': '^(.*)$'},
77 {'type': 'pg_id', 'regex': '^(.*)$'},
78 {'type': 'object_name', 'regex': '^(.*)$'},
79 {'type': 'snap_id', 'regex': '^(.*)$'},
81 'performance_counter_descriptors': [
82 'write_ops', 'read_ops',
88 def handle_command(self
, inbuf
, cmd
):
89 if cmd
['prefix'] == "osd perf query add":
90 if cmd
['query'] == 'rbd_image_id':
91 query
= self
.RBD_IMAGE_ID_QUERY
92 elif cmd
['query'] == 'client_id':
93 query
= self
.CLIENT_ID_QUERY
95 query
= self
.ALL_SUBKEYS_QUERY
96 query_id
= self
.add_osd_perf_query(query
)
98 return -errno
.EINVAL
, "", "Invalid query"
99 self
.queries
[query_id
] = [query
, time()]
100 return 0, str(query_id
), "added query " + cmd
['query'] + " with id " + str(query_id
)
101 elif cmd
['prefix'] == "osd perf query remove":
102 if cmd
['query_id'] not in self
.queries
:
103 return -errno
.ENOENT
, "", "unknown query id " + str(cmd
['query_id'])
104 self
.remove_osd_perf_query(cmd
['query_id'])
105 del self
.queries
[cmd
['query_id']]
106 return 0, "", "removed query with id " + str(cmd
['query_id'])
107 elif cmd
['prefix'] == "osd perf counters get":
108 if cmd
['query_id'] not in self
.queries
:
109 return -errno
.ENOENT
, "", "unknown query id " + str(cmd
['query_id'])
111 query
= self
.queries
[cmd
['query_id']][0]
112 res
= self
.get_osd_perf_counters(cmd
['query_id'])
114 last_update
= self
.queries
[cmd
['query_id']][1]
115 descriptors
= query
['performance_counter_descriptors']
117 if query
== self
.RBD_IMAGE_ID_QUERY
:
118 column_names
= ["pool_id", "rbd image_id"]
120 column_names
= [sk
['type'] for sk
in query
['key_descriptor']]
121 for d
in descriptors
:
125 elif d
in ['write_bytes', 'read_bytes']:
127 elif d
in ['write_latency', 'read_latency']:
129 column_names
.append(desc
)
131 table
= prettytable
.PrettyTable(tuple(column_names
),
132 hrules
=prettytable
.FRAME
)
134 if query
== self
.RBD_IMAGE_ID_QUERY
:
136 # {'k': [['3'], ['', '16fe5b5a8435e']],
137 # 'c': [[1024, 0], [1, 0], ...]}
138 # pool id fixup: if the object_name regex has matched pool id
139 # use it as the image pool id
140 for c
in res
['counters']:
142 c
['k'][0][0] = c
['k'][1][0]
143 # group by (pool_id, image_id)
145 res
['counters'].sort(key
=lambda c
: [c
['k'][0][0], c
['k'][1][1]])
146 for key
, group
in groupby(res
['counters'],
147 lambda c
: [c
['k'][0][0], c
['k'][1][1]]):
148 counters
= [[0, 0] for x
in descriptors
]
150 for i
in range(len(counters
)):
151 counters
[i
][0] += c
['c'][i
][0]
152 counters
[i
][1] += c
['c'][i
][1]
153 processed
.append({'k' : key
, 'c' : counters
})
156 # {'k': [['client.94348']], 'c': [[1024, 0], [1, 0], ...]}
157 processed
= res
['counters']
159 max_count
= len(processed
)
161 if 'max_count' in query
['limit']:
162 max_count
= query
['limit']['max_count']
163 if 'order_by' in query
['limit']:
164 i
= descriptors
.index(query
['limit']['order_by'])
165 processed
.sort(key
=lambda x
: x
['c'][i
][0], reverse
=True)
166 for c
in processed
[:max_count
]:
167 if query
== self
.RBD_IMAGE_ID_QUERY
:
170 row
= [sk
[0] for sk
in c
['k']]
172 for i
in range(len(descriptors
)):
173 if descriptors
[i
] in ['bytes']:
175 elif descriptors
[i
] in ['write_bytes', 'read_bytes']:
176 bps
= counters
[i
][0] / (now
- last_update
)
177 row
.append(get_human_readable(bps
))
178 elif descriptors
[i
] in ['write_latency', 'read_latency']:
180 if counters
[i
][1] > 0:
181 lat
= 1.0 * counters
[i
][0] / counters
[i
][1] / 1000000
182 row
.append("%.2f" % lat
)
184 row
.append("%d" % counters
[i
][0])
187 msg
= "counters for the query id %d for the last %d sec" % \
188 (cmd
['query_id'], now
- last_update
)
189 self
.queries
[cmd
['query_id']][1] = now
191 return 0, table
.get_string() + "\n", msg
193 raise NotImplementedError(cmd
['prefix'])