mirror of
https://github.com/ceph/ceph
synced 2025-01-01 16:42:29 +00:00
cephfs-top: add read/write io speed support
Calculate the speeds in cephfs-top. Fixes: https://tracker.ceph.com/issues/49811 Signed-off-by: Xiubo Li <xiubli@redhat.com>
This commit is contained in:
parent
17f0cbb688
commit
ec22208364
@ -79,6 +79,14 @@ Descriptions of fields
|
||||
|
||||
total size of write IOs
|
||||
|
||||
.. describe:: rsp
|
||||
|
||||
speed of read IOs compared with the last refresh
|
||||
|
||||
.. describe:: wsp
|
||||
|
||||
speed of write IOs compared with the last refresh
|
||||
|
||||
|
||||
Availability
|
||||
============
|
||||
|
@ -6,6 +6,7 @@ import curses
|
||||
import errno
|
||||
import json
|
||||
import signal
|
||||
import time
|
||||
|
||||
from collections import OrderedDict
|
||||
from datetime import datetime
|
||||
@ -82,6 +83,10 @@ CLIENT_METADATA_VALID_METRICS_KEY = "valid_metrics"
|
||||
GLOBAL_METRICS_KEY = "global_metrics"
|
||||
GLOBAL_COUNTERS_KEY = "global_counters"
|
||||
|
||||
last_time = time.time()
|
||||
last_read_size = {}
|
||||
last_write_size = {}
|
||||
|
||||
|
||||
def calc_perc(c):
|
||||
if c[0] == 0 and c[1] == 0:
|
||||
@ -98,6 +103,13 @@ def calc_size(c):
|
||||
return round(c[1] / (1024 * 1024), 2)
|
||||
|
||||
|
||||
# in MB/s
|
||||
def calc_speed(size, duration):
|
||||
if duration == 0:
|
||||
return 0.0
|
||||
return round(size / (duration * 1024 * 1024), 2)
|
||||
|
||||
|
||||
def wrap(s, sl):
|
||||
"""return a '+' suffixed wrapped string"""
|
||||
if len(s) < sl:
|
||||
@ -224,6 +236,22 @@ class FSTop(object):
|
||||
# return empty string for none type
|
||||
return ''
|
||||
|
||||
def speed_items(self, item):
|
||||
if item == "READ_IO_SIZES":
|
||||
return "rsp"
|
||||
if item == "WRITE_IO_SIZES":
|
||||
return "wsp"
|
||||
else:
|
||||
# return empty string for none type
|
||||
return ''
|
||||
|
||||
def speed_mtype(self, typ):
|
||||
if typ == MetricType.METRIC_TYPE_SIZE:
|
||||
return "(MB/s)"
|
||||
else:
|
||||
# return empty string for none type
|
||||
return ''
|
||||
|
||||
def refresh_top_line_and_build_coord(self):
|
||||
if self.topl is None:
|
||||
return
|
||||
@ -245,6 +273,16 @@ class FSTop(object):
|
||||
x_coord_map[item] = (xp, nlen)
|
||||
xp += nlen
|
||||
|
||||
if item == "READ_IO_SIZES" or item == "WRITE_IO_SIZES":
|
||||
it = f'{self.speed_items(item)}{self.speed_mtype(typ)}'
|
||||
heading.append(it)
|
||||
nlen = len(it) + len(ITEMS_PAD)
|
||||
if item == "READ_IO_SIZES":
|
||||
x_coord_map["READ_IO_SPEED"] = (xp, nlen)
|
||||
if item == "WRITE_IO_SIZES":
|
||||
x_coord_map["WRITE_IO_SPEED"] = (xp, nlen)
|
||||
xp += nlen
|
||||
|
||||
for item in MAIN_WINDOW_TOP_LINE_ITEMS_END:
|
||||
heading.append(item)
|
||||
nlen = len(item) + len(ITEMS_PAD)
|
||||
@ -268,6 +306,10 @@ class FSTop(object):
|
||||
return True
|
||||
|
||||
def refresh_client(self, client_id, metrics, counters, client_meta, x_coord_map, y_coord):
|
||||
global last_time
|
||||
cur_time = time.time()
|
||||
duration = cur_time - last_time
|
||||
last_time = cur_time
|
||||
remaining_hlen = self.width - 1
|
||||
for item in MAIN_WINDOW_TOP_LINE_ITEMS_START:
|
||||
coord = x_coord_map[item]
|
||||
@ -293,6 +335,7 @@ class FSTop(object):
|
||||
return
|
||||
|
||||
cidx = 0
|
||||
client_id = x_coord_map[FS_TOP_MAIN_WINDOW_COL_CLIENT_ID]
|
||||
for item in counters:
|
||||
coord = x_coord_map[item]
|
||||
hlen = coord[1] - len(ITEMS_PAD)
|
||||
@ -302,7 +345,8 @@ class FSTop(object):
|
||||
else:
|
||||
remaining_hlen -= coord[1]
|
||||
m = metrics[cidx]
|
||||
typ = MAIN_WINDOW_TOP_LINE_METRICS[MGR_STATS_COUNTERS[cidx]]
|
||||
key = MGR_STATS_COUNTERS[cidx]
|
||||
typ = MAIN_WINDOW_TOP_LINE_METRICS[key]
|
||||
if item.lower() in client_meta.get(CLIENT_METADATA_VALID_METRICS_KEY, []):
|
||||
if typ == MetricType.METRIC_TYPE_PERCENTAGE:
|
||||
self.mainw.addnstr(y_coord, coord[0], f'{calc_perc(m)}', hlen)
|
||||
@ -310,6 +354,31 @@ class FSTop(object):
|
||||
self.mainw.addnstr(y_coord, coord[0], f'{calc_lat(m)}', hlen)
|
||||
elif typ == MetricType.METRIC_TYPE_SIZE:
|
||||
self.mainw.addnstr(y_coord, coord[0], f'{calc_size(m)}', hlen)
|
||||
if remaining_hlen == 0:
|
||||
return
|
||||
if key == "READ_IO_SIZES":
|
||||
coord = x_coord_map["READ_IO_SPEED"]
|
||||
elif key == "WRITE_IO_SIZES":
|
||||
coord = x_coord_map["WRITE_IO_SPEED"]
|
||||
hlen = coord[1] - len(ITEMS_PAD)
|
||||
hlen = min(hlen, remaining_hlen)
|
||||
if remaining_hlen < coord[1]:
|
||||
remaining_hlen = 0
|
||||
else:
|
||||
remaining_hlen -= coord[1]
|
||||
if key == "READ_IO_SIZES":
|
||||
global last_read_size
|
||||
last_size = last_read_size.get(client_id, 0)
|
||||
size = m[1] - last_size
|
||||
last_read_size[client_id] = m[1]
|
||||
if key == "WRITE_IO_SIZES":
|
||||
global last_write_size
|
||||
last_size = last_write_size.get(client_id, 0)
|
||||
size = m[1] - last_size
|
||||
last_write_size[client_id] = m[1]
|
||||
self.mainw.addnstr(y_coord, coord[0],
|
||||
f'{calc_speed(size, duration)}',
|
||||
hlen)
|
||||
else:
|
||||
# display 0th element from metric tuple
|
||||
self.mainw.addnstr(y_coord, coord[0], f'{m[0]}', hlen)
|
||||
|
Loading…
Reference in New Issue
Block a user