number of opened inodes
+.. describe:: rtio
+
+ total size of read IOs
+
+.. describe:: wtio
+
+ total size of write IOs
+
Availability
============
}
message.push_back(metric);
+ // read io sizes
+ metric = ClientMetricMessage(ReadIoSizesPayload(total_read_ops,
+ total_read_size));
+ message.push_back(metric);
+
+ // write io sizes
+ metric = ClientMetricMessage(WriteIoSizesPayload(total_write_ops,
+ total_write_size));
+ message.push_back(metric);
+
session->con->send_message2(make_message<MClientMetrics>(std::move(message)));
}
success:
ceph_assert(rc >= 0);
+ update_read_io_size(bl->length());
if (movepos) {
// adjust fd pos
f->pos = start_pos + rc;
void Client::C_Readahead::finish(int r) {
lgeneric_subdout(client->cct, client, 20) << "client." << client->get_nodeid() << " " << "C_Readahead on " << f->inode << dendl;
client->put_cap_ref(f->inode.get(), CEPH_CAP_FILE_RD | CEPH_CAP_FILE_CACHE);
+ if (r > 0) {
+ client->update_read_io_size(r);
+ }
}
int Client::_read_async(Fh *f, uint64_t off, uint64_t len, bufferlist *bl)
r = onfinish.wait();
client_lock.lock();
put_cap_ref(in, CEPH_CAP_FILE_CACHE);
+ update_read_io_size(bl->length());
}
if(f->readahead.get_min_readahead_size() > 0) {
// if we get here, write was successful, update client metadata
success:
+ update_write_io_size(size);
// time
lat = ceph_clock_now();
lat -= start;
void tick();
void start_tick_thread();
+ void update_read_io_size(size_t size) {
+ total_read_ops++;
+ total_read_size += size;
+ }
+
+ void update_write_io_size(size_t size) {
+ total_write_ops++;
+ total_write_size += size;
+ }
+
void inc_dentry_nr() {
++dentry_nr;
}
uint64_t pinned_icaps = 0;
uint64_t opened_inodes = 0;
+ uint64_t total_read_ops = 0;
+ uint64_t total_read_size = 0;
+
+ uint64_t total_write_ops = 0;
+ uint64_t total_write_size = 0;
+
ceph::spinlock delay_i_lock;
std::map<Inode*,int> delay_i_release;
};
CLIENT_METRIC_TYPE_OPENED_FILES,
CLIENT_METRIC_TYPE_PINNED_ICAPS,
CLIENT_METRIC_TYPE_OPENED_INODES,
+ CLIENT_METRIC_TYPE_READ_IO_SIZES,
+ CLIENT_METRIC_TYPE_WRITE_IO_SIZES,
};
inline std::ostream &operator<<(std::ostream &os, const ClientMetricType &type) {
switch(type) {
case ClientMetricType::CLIENT_METRIC_TYPE_OPENED_INODES:
os << "OPENED_INODES";
break;
+ case ClientMetricType::CLIENT_METRIC_TYPE_READ_IO_SIZES:
+ os << "READ_IO_SIZES";
+ break;
+ case ClientMetricType::CLIENT_METRIC_TYPE_WRITE_IO_SIZES:
+ os << "WRITE_IO_SIZES";
+ break;
default:
os << "(UNKNOWN:" << static_cast<std::underlying_type<ClientMetricType>::type>(type) << ")";
break;
}
};
+struct ReadIoSizesPayload : public ClientMetricPayloadBase {
+ uint64_t total_ops = 0;
+ uint64_t total_size = 0;
+
+ ReadIoSizesPayload()
+ : ClientMetricPayloadBase(ClientMetricType::CLIENT_METRIC_TYPE_READ_IO_SIZES) { }
+ ReadIoSizesPayload(uint64_t total_ops, uint64_t total_size)
+ : ClientMetricPayloadBase(ClientMetricType::CLIENT_METRIC_TYPE_READ_IO_SIZES),
+ total_ops(total_ops), total_size(total_size) { }
+
+ void encode(bufferlist &bl) const {
+ using ceph::encode;
+ ENCODE_START(1, 1, bl);
+ encode(total_ops, bl);
+ encode(total_size, bl);
+ ENCODE_FINISH(bl);
+ }
+
+ void decode(bufferlist::const_iterator &iter) {
+ using ceph::decode;
+ DECODE_START(1, iter);
+ decode(total_ops, iter);
+ decode(total_size, iter);
+ DECODE_FINISH(iter);
+ }
+
+ void dump(Formatter *f) const {
+ f->dump_int("total_ops", total_ops);
+ f->dump_int("total_size", total_size);
+ }
+
+ void print(std::ostream *out) const {
+ *out << "total_ops: " << total_ops << " total_size: " << total_size;
+ }
+};
+
+struct WriteIoSizesPayload : public ClientMetricPayloadBase {
+ uint64_t total_ops = 0;
+ uint64_t total_size = 0;
+
+ WriteIoSizesPayload()
+ : ClientMetricPayloadBase(ClientMetricType::CLIENT_METRIC_TYPE_WRITE_IO_SIZES) { }
+ WriteIoSizesPayload(uint64_t total_ops, uint64_t total_size)
+ : ClientMetricPayloadBase(ClientMetricType::CLIENT_METRIC_TYPE_WRITE_IO_SIZES),
+ total_ops(total_ops), total_size(total_size) {
+ }
+
+ void encode(bufferlist &bl) const {
+ using ceph::encode;
+ ENCODE_START(1, 1, bl);
+ encode(total_ops, bl);
+ encode(total_size, bl);
+ ENCODE_FINISH(bl);
+ }
+
+ void decode(bufferlist::const_iterator &iter) {
+ using ceph::decode;
+ DECODE_START(1, iter);
+ decode(total_ops, iter);
+ decode(total_size, iter);
+ DECODE_FINISH(iter);
+ }
+
+ void dump(Formatter *f) const {
+ f->dump_int("total_ops", total_ops);
+ f->dump_int("total_size", total_size);
+ }
+
+ void print(std::ostream *out) const {
+ *out << "total_ops: " << total_ops << " total_size: " << total_size;
+ }
+};
+
struct UnknownPayload : public ClientMetricPayloadBase {
UnknownPayload()
: ClientMetricPayloadBase(static_cast<ClientMetricType>(-1)) { }
ReadLatencyPayload,
WriteLatencyPayload,
MetadataLatencyPayload,
- DentryLeasePayload,
- OpenedFilesPayload,
- PinnedIcapsPayload,
- OpenedInodesPayload,
+ DentryLeasePayload,
+ OpenedFilesPayload,
+ PinnedIcapsPayload,
+ OpenedInodesPayload,
+ ReadIoSizesPayload,
+ WriteIoSizesPayload,
UnknownPayload> ClientMetricPayload;
// metric update message sent by clients
case ClientMetricType::CLIENT_METRIC_TYPE_OPENED_INODES:
payload = OpenedInodesPayload();
break;
+ case ClientMetricType::CLIENT_METRIC_TYPE_READ_IO_SIZES:
+ payload = ReadIoSizesPayload();
+ break;
+ case ClientMetricType::CLIENT_METRIC_TYPE_WRITE_IO_SIZES:
+ payload = WriteIoSizesPayload();
+ break;
default:
payload = UnknownPayload(static_cast<ClientMetricType>(metric_type));
break;
}
};
+struct ReadIoSizesMetric {
+ uint64_t total_ops = 0;
+ uint64_t total_size = 0;
+ bool updated = false;
+
+ DENC(ReadIoSizesMetric, v, p) {
+ DENC_START(1, 1, p);
+ denc(v.total_ops, p);
+ denc(v.total_size, p);
+ denc(v.updated, p);
+ DENC_FINISH(p);
+ }
+
+ void dump(Formatter *f) const {
+ f->dump_unsigned("total_ops", total_ops);
+ f->dump_unsigned("total_size", total_size);
+ }
+
+ friend std::ostream& operator<<(std::ostream& os, const ReadIoSizesMetric &metric) {
+ os << "{total_ops=" << metric.total_ops << ", total_size=" << metric.total_size <<"}";
+ return os;
+ }
+};
+
+struct WriteIoSizesMetric {
+ uint64_t total_ops = 0;
+ uint64_t total_size = 0;
+ bool updated = false;
+
+ DENC(WriteIoSizesMetric, v, p) {
+ DENC_START(1, 1, p);
+ denc(v.total_ops, p);
+ denc(v.total_size, p);
+ denc(v.updated, p);
+ DENC_FINISH(p);
+ }
+
+ void dump(Formatter *f) const {
+ f->dump_unsigned("total_ops", total_ops);
+ f->dump_unsigned("total_size", total_size);
+ }
+
+ friend std::ostream& operator<<(std::ostream& os, const WriteIoSizesMetric &metric) {
+ os << "{total_ops=" << metric.total_ops << ", total_size=" << metric.total_size <<"}";
+ return os;
+ }
+};
+
WRITE_CLASS_DENC(CapHitMetric)
WRITE_CLASS_DENC(ReadLatencyMetric)
WRITE_CLASS_DENC(WriteLatencyMetric)
WRITE_CLASS_DENC(OpenedFilesMetric)
WRITE_CLASS_DENC(PinnedIcapsMetric)
WRITE_CLASS_DENC(OpenedInodesMetric)
+WRITE_CLASS_DENC(ReadIoSizesMetric)
+WRITE_CLASS_DENC(WriteIoSizesMetric)
// metrics that are forwarded to the MDS by client(s).
struct Metrics {
OpenedFilesMetric opened_files_metric;
PinnedIcapsMetric pinned_icaps_metric;
OpenedInodesMetric opened_inodes_metric;
+ ReadIoSizesMetric read_io_sizes_metric;
+ WriteIoSizesMetric write_io_sizes_metric;
// metric update type
uint32_t update_type = UpdateType::UPDATE_TYPE_REFRESH;
DENC(Metrics, v, p) {
- DENC_START(3, 1, p);
+ DENC_START(4, 1, p);
denc(v.update_type, p);
denc(v.cap_hit_metric, p);
denc(v.read_latency_metric, p);
denc(v.pinned_icaps_metric, p);
denc(v.opened_inodes_metric, p);
}
+ if (struct_v >= 4) {
+ denc(v.read_io_sizes_metric, p);
+ denc(v.write_io_sizes_metric, p);
+ }
DENC_FINISH(p);
}
f->dump_object("opened_files_metric", opened_files_metric);
f->dump_object("pinned_icaps_metric", pinned_icaps_metric);
f->dump_object("opened_inodes_metric", opened_inodes_metric);
+ f->dump_object("read_io_sizes_metric", read_io_sizes_metric);
+ f->dump_object("write_io_sizes_metric", write_io_sizes_metric);
}
friend std::ostream& operator<<(std::ostream& os, const Metrics& metrics) {
<< ", read_latency=" << metrics.read_latency_metric
<< ", write_latency=" << metrics.write_latency_metric
<< ", metadata_latency=" << metrics.metadata_latency_metric
- << ", dentry_lease =" << metrics.dentry_lease_metric
- << ", opened_files_metric =" << metrics.opened_files_metric
- << ", pinned_icaps_metric =" << metrics.pinned_icaps_metric
- << ", opened_inodes_metric =" << metrics.opened_inodes_metric
+ << ", dentry_lease=" << metrics.dentry_lease_metric
+ << ", opened_files_metric=" << metrics.opened_files_metric
+ << ", pinned_icaps_metric=" << metrics.pinned_icaps_metric
+ << ", opened_inodes_metric=" << metrics.opened_inodes_metric
+ << ", read_io_sizes_metric=" << metrics.read_io_sizes_metric
+ << ", write_io_sizes_metric=" << metrics.write_io_sizes_metric
<< "}]";
return os;
}
c->second = metrics.opened_inodes_metric.total_inodes;
}
break;
+ case MDSPerformanceCounterType::READ_IO_SIZES_METRIC:
+ if (metrics.read_io_sizes_metric.updated) {
+ c->first = metrics.read_io_sizes_metric.total_ops;
+ c->second = metrics.read_io_sizes_metric.total_size;
+ }
+ break;
+ case MDSPerformanceCounterType::WRITE_IO_SIZES_METRIC:
+ if (metrics.write_io_sizes_metric.updated) {
+ c->first = metrics.write_io_sizes_metric.total_ops;
+ c->second = metrics.write_io_sizes_metric.total_size;
+ }
+ break;
default:
ceph_abort_msg("unknown counter type");
}
metrics.opened_files_metric = { };
metrics.pinned_icaps_metric = { };
metrics.opened_inodes_metric = { };
+ metrics.read_io_sizes_metric = { };
+ metrics.write_io_sizes_metric = { };
metrics.update_type = UPDATE_TYPE_REMOVE;
}
metrics.opened_inodes_metric.updated = true;
}
+void MetricsHandler::handle_payload(Session *session, const ReadIoSizesPayload &payload) {
+ dout(20) << ": type=" << payload.get_type()
+ << ", session=" << session << ", total_ops=" << payload.total_ops
+ << ", total_size=" << payload.total_size << dendl;
+
+ auto it = client_metrics_map.find(session->info.inst);
+ if (it == client_metrics_map.end()) {
+ return;
+ }
+
+ auto &metrics = it->second.second;
+ metrics.update_type = UPDATE_TYPE_REFRESH;
+ metrics.read_io_sizes_metric.total_ops = payload.total_ops;
+ metrics.read_io_sizes_metric.total_size = payload.total_size;
+ metrics.read_io_sizes_metric.updated = true;
+}
+
+void MetricsHandler::handle_payload(Session *session, const WriteIoSizesPayload &payload) {
+ dout(20) << ": type=" << payload.get_type()
+ << ", session=" << session << ", total_ops=" << payload.total_ops
+ << ", total_size=" << payload.total_size << dendl;
+
+ auto it = client_metrics_map.find(session->info.inst);
+ if (it == client_metrics_map.end()) {
+ return;
+ }
+
+ auto &metrics = it->second.second;
+ metrics.update_type = UPDATE_TYPE_REFRESH;
+ metrics.write_io_sizes_metric.total_ops = payload.total_ops;
+ metrics.write_io_sizes_metric.total_size = payload.total_size;
+ metrics.write_io_sizes_metric.updated = true;
+}
+
void MetricsHandler::handle_payload(Session *session, const UnknownPayload &payload) {
dout(5) << ": type=Unknown, session=" << session << ", ignoring unknown payload" << dendl;
}
void handle_payload(Session *session, const OpenedFilesPayload &payload);
void handle_payload(Session *session, const PinnedIcapsPayload &payload);
void handle_payload(Session *session, const OpenedInodesPayload &payload);
+ void handle_payload(Session *session, const ReadIoSizesPayload &payload);
+ void handle_payload(Session *session, const WriteIoSizesPayload &payload);
void handle_payload(Session *session, const UnknownPayload &payload);
void set_next_seq(version_t seq);
CLIENT_METRIC_TYPE_OPENED_FILES, \
CLIENT_METRIC_TYPE_PINNED_ICAPS, \
CLIENT_METRIC_TYPE_OPENED_INODES, \
+ CLIENT_METRIC_TYPE_READ_IO_SIZES, \
+ CLIENT_METRIC_TYPE_WRITE_IO_SIZES, \
}
#define CEPHFS_FEATURES_MDS_SUPPORTED CEPHFS_FEATURES_ALL
{"opened_files", MDSPerformanceCounterType::OPENED_FILES_METRIC},
{"pinned_icaps", MDSPerformanceCounterType::PINNED_ICAPS_METRIC},
{"opened_inodes", MDSPerformanceCounterType::OPENED_INODES_METRIC},
+ {"read_io_sizes", MDSPerformanceCounterType::READ_IO_SIZES_METRIC},
+ {"write_io_sizes", MDSPerformanceCounterType::WRITE_IO_SIZES_METRIC},
};
PyObject *py_query = nullptr;
case MDSPerformanceCounterType::OPENED_FILES_METRIC:
case MDSPerformanceCounterType::PINNED_ICAPS_METRIC:
case MDSPerformanceCounterType::OPENED_INODES_METRIC:
+ case MDSPerformanceCounterType::READ_IO_SIZES_METRIC:
+ case MDSPerformanceCounterType::WRITE_IO_SIZES_METRIC:
break;
default:
ceph_abort_msg("unknown counter type");
case MDSPerformanceCounterType::OPENED_FILES_METRIC:
case MDSPerformanceCounterType::PINNED_ICAPS_METRIC:
case MDSPerformanceCounterType::OPENED_INODES_METRIC:
+ case MDSPerformanceCounterType::READ_IO_SIZES_METRIC:
+ case MDSPerformanceCounterType::WRITE_IO_SIZES_METRIC:
break;
default:
ceph_abort_msg("unknown counter type");
case MDSPerformanceCounterType::OPENED_INODES_METRIC:
os << "opened_inodes_metric";
break;
+ case MDSPerformanceCounterType::READ_IO_SIZES_METRIC:
+ os << "read_io_sizes_metric";
+ break;
+ case MDSPerformanceCounterType::WRITE_IO_SIZES_METRIC:
+ os << "write_io_sizes_metric";
+ break;
}
return os;
OPENED_FILES_METRIC = 5,
PINNED_ICAPS_METRIC = 6,
OPENED_INODES_METRIC = 7,
+ READ_IO_SIZES_METRIC = 8,
+ WRITE_IO_SIZES_METRIC = 9,
};
struct MDSPerformanceCounterDescriptor {
case MDSPerformanceCounterType::OPENED_FILES_METRIC:
case MDSPerformanceCounterType::PINNED_ICAPS_METRIC:
case MDSPerformanceCounterType::OPENED_INODES_METRIC:
+ case MDSPerformanceCounterType::READ_IO_SIZES_METRIC:
+ case MDSPerformanceCounterType::WRITE_IO_SIZES_METRIC:
return true;
default:
return false;
'dentry_lease': 4,
'opened_files': 5,
'pinned_icaps': 6,
- 'opened_inodes': 7})
+ 'opened_inodes': 7,
+ 'read_io_sizes': 8,
+ 'write_io_sizes': 9})
MDS_PERF_QUERY_COUNTERS = [] # type: List[str]
-MDS_GLOBAL_PERF_QUERY_COUNTERS = ['cap_hit', 'read_latency', 'write_latency', 'metadata_latency', 'dentry_lease', 'opened_files', 'pinned_icaps', 'opened_inodes'] # type: List[str]
+MDS_GLOBAL_PERF_QUERY_COUNTERS = ['cap_hit', 'read_latency', 'write_latency', 'metadata_latency', 'dentry_lease', 'opened_files', 'pinned_icaps', 'opened_inodes', 'read_io_sizes', 'write_io_sizes'] # type: List[str]
QUERY_EXPIRE_INTERVAL = timedelta(minutes=1)
METRIC_TYPE_NONE = 0
METRIC_TYPE_PERCENTAGE = 1
METRIC_TYPE_LATENCY = 2
+ METRIC_TYPE_SIZE = 3
FS_TOP_PROG_STR = 'cephfs-top'
("OPENED_FILES", MetricType.METRIC_TYPE_NONE),
("PINNED_ICAPS", MetricType.METRIC_TYPE_NONE),
("OPENED_INODES", MetricType.METRIC_TYPE_NONE),
+ ("READ_IO_SIZES", MetricType.METRIC_TYPE_SIZE),
+ ("WRITE_IO_SIZES", MetricType.METRIC_TYPE_SIZE),
])
MGR_STATS_COUNTERS = list(MAIN_WINDOW_TOP_LINE_METRICS.keys())
return round(c[0] + c[1] / 1000000000, 2)
+# in MB
+def calc_size(c):
+ return round(c[1] / (1024 * 1024), 2)
+
+
def wrap(s, sl):
"""return a '+' suffixed wrapped string"""
if len(s) < sl:
return "oicaps"
if item == "OPENED_INODES":
return "oinodes"
+ if item == "READ_IO_SIZES":
+ return "rtio"
+ if item == "WRITE_IO_SIZES":
+ return "wtio"
else:
# return empty string for none type
return ''
return "(%)"
elif typ == MetricType.METRIC_TYPE_LATENCY:
return "(s)"
+ elif typ == MetricType.METRIC_TYPE_SIZE:
+ return "(MB)"
else:
# return empty string for none type
return ''
self.mainw.addnstr(y_coord, coord[0], f'{calc_perc(m)}', hlen)
elif typ == MetricType.METRIC_TYPE_LATENCY:
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)
else:
# display 0th element from metric tuple
self.mainw.addnstr(y_coord, coord[0], f'{m[0]}', hlen)