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);
}
// 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<const MOSDOp*>(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<const MOSDOp*>(op.get_req());
- c->first += (now - m->get_recv_stamp()).to_nsec();
- c->second++;
- }
- return;
+#include <ostream>
+
+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<int>(d.type) << ")";
}
+ return os << "~/" << d.regex_str << "/";
}
void PerformanceCounterDescriptor::pack_counter(const PerformanceCounter &c,
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<const MOSDOp*>(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<int>(d.type) << ")";
}
}
}
std::ostream& operator<<(std::ostream& os, const OSDPerfMetricQuery &query) {
- return os << "simple";
+ return os << "{key=" << query.key_descriptor << ", counters="
+ << query.performance_counter_descriptors << "}";
}
#include "include/denc.h"
#include "include/stringify.h"
-#include <ostream>
+#include <regex>
-class OpRequest;
-class utime_t;
+typedef std::vector<std::string> OSDPerfMetricSubKey; // array of regex match
+typedef std::vector<OSDPerfMetricSubKey> OSDPerfMetricKey;
+
+enum class OSDPerfMetricSubKeyType : uint8_t {
+ CLIENT_ID = 0,
+ POOL_ID = 1,
+ OBJECT_NAME = 2,
+};
+
+struct OSDPerfMetricSubKeyDescriptor {
+ OSDPerfMetricSubKeyType type = static_cast<OSDPerfMetricSubKeyType>(-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<OSDPerfMetricSubKeyDescriptor> OSDPerfMetricKeyDescriptor;
+
+template<>
+struct denc_traits<OSDPerfMetricKeyDescriptor> {
+ 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<uint64_t,uint64_t> PerformanceCounter;
typedef std::vector<PerformanceCounter> PerformanceCounters;
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;
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 <typename L>
+ 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);
}
*descriptors = performance_counter_descriptors;
}
- void filter_out_unknown_performance_counter_descriptors();
+ template <typename L>
+ 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)
struct OSDPerfMetricReport {
PerformanceCounterDescriptors performance_counter_descriptors;
- std::map<std::string, bufferlist> group_packed_performance_counters;
+ std::map<OSDPerfMetricKey, bufferlist> group_packed_performance_counters;
DENC(OSDPerfMetricReport, v, p) {
DENC_START(1, 1, p);
#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:
void set_queries(const std::list<OSDPerfMetricQuery> &queries) {
std::map<OSDPerfMetricQuery,
- std::map<std::string, PerformanceCounters>> new_data;
+ std::map<OSDPerfMetricKey, PerformanceCounters>> new_data;
for (auto &query : queries) {
std::swap(new_data[query], data[query]);
}
}
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<const MOSDOp*>(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]);
}
}
}
}
private:
- std::map<OSDPerfMetricQuery, std::map<std::string, PerformanceCounters>> data;
+ std::map<OSDPerfMetricQuery,
+ std::map<OSDPerfMetricKey, PerformanceCounters>> data;
};
#endif // DYNAMIC_PERF_STATS_H
void OSD::set_perf_queries(const std::list<OSDPerfMetricQuery> &queries) {
dout(10) << "setting " << queries.size() << " queries" << dendl;
+ std::list<OSDPerfMetricQuery> 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<PGRef> pgs;
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();
}
}