From: Mykola Golub Date: Mon, 12 Nov 2018 18:39:33 +0000 (+0200) Subject: mgr: generalize OSDPerfMetricQuery to support different queries X-Git-Tag: v14.1.0~843^2~6 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=073555e30f3d1224425edd7763becf5f1bc4d654;p=ceph.git mgr: generalize OSDPerfMetricQuery to support different queries Signed-off-by: Mykola Golub --- diff --git a/src/mgr/BaseMgrModule.cc b/src/mgr/BaseMgrModule.cc index 038490dedadf..0aee22318b4d 100644 --- a/src/mgr/BaseMgrModule.cc +++ b/src/mgr/BaseMgrModule.cc @@ -670,7 +670,14 @@ ceph_add_osd_perf_query(BaseMgrModule *self, PyObject *args) return nullptr; } - OSDPerfMetricQuery query; + OSDPerfMetricQuery query = {{{OSDPerfMetricSubKeyType::CLIENT_ID, "^.*$"}}, + {{PerformanceCounterType::WRITE_OPS}, + {PerformanceCounterType::READ_OPS}, + {PerformanceCounterType::WRITE_BYTES}, + {PerformanceCounterType::READ_BYTES}, + {PerformanceCounterType::WRITE_LATENCY}, + {PerformanceCounterType::READ_LATENCY}}}; + auto query_id = self->py_modules->add_osd_perf_query(query); return PyLong_FromLong(query_id); } diff --git a/src/mgr/OSDPerfMetricTypes.cc b/src/mgr/OSDPerfMetricTypes.cc index 2177bed37a0a..266fc403cc5e 100644 --- a/src/mgr/OSDPerfMetricTypes.cc +++ b/src/mgr/OSDPerfMetricTypes.cc @@ -2,52 +2,25 @@ // vim: ts=8 sw=2 smarttab #include "mgr/OSDPerfMetricTypes.h" -#include "messages/MOSDOp.h" -#include "osd/OpRequest.h" -void PerformanceCounterDescriptor::update_counter( - const OpRequest& op, uint64_t inb, uint64_t outb, const utime_t &now, - PerformanceCounter *c) const { - switch(type) { - case PerformanceCounterType::WRITE_OPS: - if (op.may_write() || op.may_cache()) { - c->first++; - } - return; - case PerformanceCounterType::READ_OPS: - if (op.may_read()) { - c->first++; - } - return; - case PerformanceCounterType::WRITE_BYTES: - if (op.may_write() || op.may_cache()) { - c->first += inb; - c->second++; - } - return; - case PerformanceCounterType::READ_BYTES: - if (op.may_read()) { - c->first += outb; - c->second++; - } - return; - case PerformanceCounterType::WRITE_LATENCY: - if (op.may_write() || op.may_cache()) { - const MOSDOp* const m = static_cast(op.get_req()); - c->first += (now - m->get_recv_stamp()).to_nsec(); - c->second++; - } - return; - case PerformanceCounterType::READ_LATENCY: - if (op.may_read()) { - const MOSDOp* const m = static_cast(op.get_req()); - c->first += (now - m->get_recv_stamp()).to_nsec(); - c->second++; - } - return; +#include + +std::ostream& operator<<(std::ostream& os, + const OSDPerfMetricSubKeyDescriptor &d) { + switch(d.type) { + case OSDPerfMetricSubKeyType::CLIENT_ID: + os << "client_id"; + break; + case OSDPerfMetricSubKeyType::POOL_ID: + os << "pool_id"; + break; + case OSDPerfMetricSubKeyType::OBJECT_NAME: + os << "object_name"; + break; default: - ceph_abort_msg("unknown counter type"); + os << "unknown (" << static_cast(d.type) << ")"; } + return os << "~/" << d.regex_str << "/"; } void PerformanceCounterDescriptor::pack_counter(const PerformanceCounter &c, @@ -104,29 +77,7 @@ std::ostream& operator<<(std::ostream& os, case PerformanceCounterType::READ_LATENCY: return os << "read latency"; default: - return os << "unknown (" << d.type << ")"; - } -} - -bool OSDPerfMetricQuery::get_key(const OpRequest& op, std::string *key) const { - const MOSDOp* const m = static_cast(op.get_req()); - - *key = stringify(m->get_reqid().name); - return true; -} - -void OSDPerfMetricQuery::update_counters(const OpRequest& op, uint64_t inb, - uint64_t outb, const utime_t &now, - PerformanceCounters *counters) const { - auto it = counters->begin(); - for (auto &descriptor : performance_counter_descriptors) { - // TODO: optimize - if (it == counters->end()) { - counters->push_back(PerformanceCounter()); - it = std::prev(counters->end()); - } - descriptor.update_counter(op, inb, outb, now, &(*it)); - it++; + return os << "unknown (" << static_cast(d.type) << ")"; } } @@ -144,5 +95,6 @@ void OSDPerfMetricQuery::pack_counters(const PerformanceCounters &counters, } std::ostream& operator<<(std::ostream& os, const OSDPerfMetricQuery &query) { - return os << "simple"; + return os << "{key=" << query.key_descriptor << ", counters=" + << query.performance_counter_descriptors << "}"; } diff --git a/src/mgr/OSDPerfMetricTypes.h b/src/mgr/OSDPerfMetricTypes.h index 8367b96d5e6f..38bbd2c69d14 100644 --- a/src/mgr/OSDPerfMetricTypes.h +++ b/src/mgr/OSDPerfMetricTypes.h @@ -7,10 +7,110 @@ #include "include/denc.h" #include "include/stringify.h" -#include +#include -class OpRequest; -class utime_t; +typedef std::vector OSDPerfMetricSubKey; // array of regex match +typedef std::vector OSDPerfMetricKey; + +enum class OSDPerfMetricSubKeyType : uint8_t { + CLIENT_ID = 0, + POOL_ID = 1, + OBJECT_NAME = 2, +}; + +struct OSDPerfMetricSubKeyDescriptor { + OSDPerfMetricSubKeyType type = static_cast(-1); + std::string regex_str; + std::regex regex; + + bool is_supported() const { + switch (type) { + case OSDPerfMetricSubKeyType::CLIENT_ID: + case OSDPerfMetricSubKeyType::POOL_ID: + case OSDPerfMetricSubKeyType::OBJECT_NAME: + return true; + default: + return false; + } + } + + OSDPerfMetricSubKeyDescriptor() { + } + + OSDPerfMetricSubKeyDescriptor(OSDPerfMetricSubKeyType type, + const std::string regex) + : type(type), regex_str(regex) { + } + + bool operator<(const OSDPerfMetricSubKeyDescriptor &other) const { + if (type < other.type) { + return true; + } + if (type > other.type) { + return false; + } + return regex_str < other.regex_str; + } + + DENC(OSDPerfMetricSubKeyDescriptor, v, p) { + DENC_START(1, 1, p); + denc(v.type, p); + denc(v.regex_str, p); + DENC_FINISH(p); + } +}; +WRITE_CLASS_DENC(OSDPerfMetricSubKeyDescriptor) + +std::ostream& operator<<(std::ostream& os, + const OSDPerfMetricSubKeyDescriptor &d); + +typedef std::vector OSDPerfMetricKeyDescriptor; + +template<> +struct denc_traits { + static constexpr bool supported = true; + static constexpr bool bounded = false; + static constexpr bool featured = false; + static constexpr bool need_contiguous = true; + static void bound_encode(const OSDPerfMetricKeyDescriptor& v, size_t& p) { + p += sizeof(uint32_t); + const auto size = v.size(); + if (size) { + size_t per = 0; + denc(v.front(), per); + p += per * size; + } + } + static void encode(const OSDPerfMetricKeyDescriptor& v, + bufferlist::contiguous_appender& p) { + denc_varint(v.size(), p); + for (auto& i : v) { + denc(i, p); + } + } + static void decode(OSDPerfMetricKeyDescriptor& v, + bufferptr::const_iterator& p) { + unsigned num; + denc_varint(num, p); + v.clear(); + v.reserve(num); + for (unsigned i=0; i < num; ++i) { + OSDPerfMetricSubKeyDescriptor d; + denc(d, p); + if (!d.is_supported()) { + v.clear(); + return; + } + try { + d.regex = {d.regex_str.c_str()}; + } catch (const std::regex_error& e) { + v.clear(); + return; + } + v.push_back(std::move(d)); + } + } +}; typedef std::pair PerformanceCounter; typedef std::vector PerformanceCounters; @@ -47,14 +147,16 @@ struct PerformanceCounterDescriptor { PerformanceCounterDescriptor(PerformanceCounterType type) : type(type) { } + bool operator<(const PerformanceCounterDescriptor &other) const { + return type < other.type; + } + DENC(PerformanceCounterDescriptor, v, p) { DENC_START(1, 1, p); denc(v.type, p); DENC_FINISH(p); } - void update_counter(const OpRequest& op, uint64_t inb, uint64_t outb, - const utime_t &now, PerformanceCounter *c) const; void pack_counter(const PerformanceCounter &c, bufferlist *bl) const; void unpack_counter(bufferlist::const_iterator& bl, PerformanceCounter *c) const; @@ -108,13 +210,41 @@ typedef int OSDPerfMetricQueryID; struct OSDPerfMetricQuery { bool operator<(const OSDPerfMetricQuery &other) const { - return false; + if (key_descriptor < other.key_descriptor) { + return true; + } + if (key_descriptor > other.key_descriptor) { + return false; + } + return (performance_counter_descriptors < + other.performance_counter_descriptors); } - bool get_key(const OpRequest& op, std::string *key) const; + OSDPerfMetricQuery() { + } + + OSDPerfMetricQuery( + const OSDPerfMetricKeyDescriptor &key_descriptor, + const PerformanceCounterDescriptors &performance_counter_descriptors) + : key_descriptor(key_descriptor), + performance_counter_descriptors(performance_counter_descriptors) { + } + + template + bool get_key(L&& get_sub_key, OSDPerfMetricKey *key) const { + for (auto &sub_key_descriptor : key_descriptor) { + OSDPerfMetricSubKey sub_key; + if (!get_sub_key(sub_key_descriptor, &sub_key)) { + return false; + } + key->push_back(sub_key); + } + return true; + } DENC(OSDPerfMetricQuery, v, p) { DENC_START(1, 1, p); + denc(v.key_descriptor, p); denc(v.performance_counter_descriptors, p); DENC_FINISH(p); } @@ -124,20 +254,25 @@ struct OSDPerfMetricQuery { *descriptors = performance_counter_descriptors; } - void filter_out_unknown_performance_counter_descriptors(); + template + void update_counters(L &&update_counter, + PerformanceCounters *counters) const { + auto it = counters->begin(); + for (auto &descriptor : performance_counter_descriptors) { + // TODO: optimize + if (it == counters->end()) { + counters->push_back(PerformanceCounter()); + it = std::prev(counters->end()); + } + update_counter(descriptor, &(*it)); + it++; + } + } - void update_counters(const OpRequest& op, uint64_t inb, uint64_t outb, - const utime_t &now, PerformanceCounters *counters) const; void pack_counters(const PerformanceCounters &counters, bufferlist *bl) const; - PerformanceCounterDescriptors performance_counter_descriptors = { - {PerformanceCounterType::WRITE_OPS}, - {PerformanceCounterType::READ_OPS}, - {PerformanceCounterType::WRITE_BYTES}, - {PerformanceCounterType::READ_BYTES}, - {PerformanceCounterType::WRITE_LATENCY}, - {PerformanceCounterType::READ_LATENCY}, - }; + OSDPerfMetricKeyDescriptor key_descriptor; + PerformanceCounterDescriptors performance_counter_descriptors; }; WRITE_CLASS_DENC(OSDPerfMetricQuery) @@ -145,7 +280,7 @@ std::ostream& operator<<(std::ostream& os, const OSDPerfMetricQuery &query); struct OSDPerfMetricReport { PerformanceCounterDescriptors performance_counter_descriptors; - std::map group_packed_performance_counters; + std::map group_packed_performance_counters; DENC(OSDPerfMetricReport, v, p) { DENC_START(1, 1, p); diff --git a/src/osd/DynamicPerfStats.h b/src/osd/DynamicPerfStats.h index dd19a858a088..45259083736b 100644 --- a/src/osd/DynamicPerfStats.h +++ b/src/osd/DynamicPerfStats.h @@ -4,7 +4,9 @@ #ifndef DYNAMIC_PERF_STATS_H #define DYNAMIC_PERF_STATS_H +#include "messages/MOSDOp.h" #include "mgr/OSDPerfMetricTypes.h" +#include "osd/OpRequest.h" class DynamicPerfStats { public: @@ -19,7 +21,7 @@ public: void set_queries(const std::list &queries) { std::map> new_data; + std::map> new_data; for (auto &query : queries) { std::swap(new_data[query], data[query]); } @@ -31,12 +33,89 @@ public: } void add(const OpRequest& op, uint64_t inb, uint64_t outb, - const utime_t &now) { + const utime_t &latency) { + + auto update_counter_fnc = + [&op, inb, outb, &latency](const PerformanceCounterDescriptor &d, + PerformanceCounter *c) { + ceph_assert(d.is_supported()); + + switch(d.type) { + case PerformanceCounterType::WRITE_OPS: + if (op.may_write() || op.may_cache()) { + c->first++; + } + return; + case PerformanceCounterType::READ_OPS: + if (op.may_read()) { + c->first++; + } + return; + case PerformanceCounterType::WRITE_BYTES: + if (op.may_write() || op.may_cache()) { + c->first += inb; + c->second++; + } + return; + case PerformanceCounterType::READ_BYTES: + if (op.may_read()) { + c->first += outb; + c->second++; + } + return; + case PerformanceCounterType::WRITE_LATENCY: + if (op.may_write() || op.may_cache()) { + c->first += latency.to_nsec(); + c->second++; + } + return; + case PerformanceCounterType::READ_LATENCY: + if (op.may_read()) { + c->first += latency.to_nsec(); + c->second++; + } + return; + default: + ceph_abort_msg("unknown counter type"); + } + }; + + auto get_subkey_fnc = + [&op](const OSDPerfMetricSubKeyDescriptor &d, + OSDPerfMetricSubKey *sub_key) { + ceph_assert(d.is_supported()); + + auto m = static_cast(op.get_req()); + std::string match_string; + switch(d.type) { + case OSDPerfMetricSubKeyType::CLIENT_ID: + match_string = stringify(m->get_reqid().name); + break; + case OSDPerfMetricSubKeyType::POOL_ID: + match_string = stringify(m->get_spg().pool()); + break; + case OSDPerfMetricSubKeyType::OBJECT_NAME: + match_string = m->get_oid().name; + break; + default: + ceph_abort_msg("unknown counter type"); + } + + std::smatch match; + if (!std::regex_search(match_string, match, d.regex)) { + return false; + } + for (auto &sub_match : match) { + sub_key->push_back(sub_match.str()); + } + return true; + }; + for (auto &it : data) { auto &query = it.first; - std::string key; - if (query.get_key(op, &key)) { - query.update_counters(op, inb, outb, now, &it.second[key]); + OSDPerfMetricKey key; + if (query.get_key(get_subkey_fnc, &key)) { + query.update_counters(update_counter_fnc, &it.second[key]); } } } @@ -58,7 +137,8 @@ public: } private: - std::map> data; + std::map> data; }; #endif // DYNAMIC_PERF_STATS_H diff --git a/src/osd/OSD.cc b/src/osd/OSD.cc index 8f3bd8e6afc8..88b84fe5a26a 100644 --- a/src/osd/OSD.cc +++ b/src/osd/OSD.cc @@ -9782,9 +9782,20 @@ int OSD::init_op_flags(OpRequestRef& op) void OSD::set_perf_queries(const std::list &queries) { dout(10) << "setting " << queries.size() << " queries" << dendl; + std::list supported_queries; + std::copy_if(queries.begin(), queries.end(), + std::back_inserter(supported_queries), + [](const OSDPerfMetricQuery &query) { + return !query.key_descriptor.empty(); + }); + if (supported_queries.size() < queries.size()) { + dout(1) << queries.size() - supported_queries.size() + << " unsupported queries" << dendl; + } + { Mutex::Locker locker(m_perf_queries_lock); - m_perf_queries = queries; + m_perf_queries = supported_queries; } std::vector pgs; @@ -9792,7 +9803,7 @@ void OSD::set_perf_queries(const std::list &queries) { for (auto& pg : pgs) { if (pg->is_primary()) { pg->lock(); - pg->set_dynamic_perf_stats_queries(queries); + pg->set_dynamic_perf_stats_queries(supported_queries); pg->unlock(); } }