]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr: add limit param to osd perf query
authorMykola Golub <mgolub@suse.com>
Fri, 23 Nov 2018 13:25:22 +0000 (15:25 +0200)
committerMykola Golub <mgolub@suse.com>
Tue, 4 Dec 2018 15:36:14 +0000 (17:36 +0200)
Signed-off-by: Mykola Golub <mgolub@suse.com>
14 files changed:
src/messages/MMgrConfigure.h
src/mgr/ActivePyModules.cc
src/mgr/ActivePyModules.h
src/mgr/BaseMgrModule.cc
src/mgr/DaemonServer.cc
src/mgr/DaemonServer.h
src/mgr/MgrClient.h
src/mgr/OSDPerfMetricCollector.cc
src/mgr/OSDPerfMetricCollector.h
src/mgr/OSDPerfMetricTypes.cc
src/mgr/OSDPerfMetricTypes.h
src/osd/OSD.cc
src/osd/OSD.h
src/pybind/mgr/mgr_module.py

index e53a357ff2b23326b703b9750fe70f81a648d8f7..05d21578b8b3587eb0c321eb89b39fcd89d2de36 100644 (file)
@@ -32,11 +32,11 @@ private:
 
 public:
   uint32_t stats_period = 0;
-  
+
   // Default 0 means if unspecified will include all stats
   uint32_t stats_threshold = 0;
 
-  std::list<OSDPerfMetricQuery> osd_perf_metric_queries;
+  std::map<OSDPerfMetricQuery, OSDPerfMetricLimits> osd_perf_metric_queries;
 
   void decode_payload() override
   {
index 595ac7d7e977e08a636726d1ce56aa89486450ac..b5391b2566bfbb0b0f07486bd64feb29b2626856 100644 (file)
@@ -902,9 +902,10 @@ void ActivePyModules::set_uri(const std::string& module_name,
 }
 
 OSDPerfMetricQueryID ActivePyModules::add_osd_perf_query(
-  const OSDPerfMetricQuery &query)
+    const OSDPerfMetricQuery &query,
+    const std::optional<OSDPerfMetricLimit> &limit)
 {
-  return server.add_osd_perf_query(query);
+  return server.add_osd_perf_query(query, limit);
 }
 
 void ActivePyModules::remove_osd_perf_query(OSDPerfMetricQueryID query_id)
index 03f0ee2d5fd0124bb6e7f76d1eee6969493917a3..b0d0eade8e115d9e85dfdc2503b371d8e469b022 100644 (file)
@@ -92,7 +92,9 @@ public:
       const std::string &svc_id,
       const std::string &path) const;
 
-  OSDPerfMetricQueryID add_osd_perf_query(const OSDPerfMetricQuery &query);
+  OSDPerfMetricQueryID add_osd_perf_query(
+      const OSDPerfMetricQuery &query,
+      const std::optional<OSDPerfMetricLimit> &limit);
   void remove_osd_perf_query(OSDPerfMetricQueryID query_id);
   PyObject *get_osd_perf_counters(OSDPerfMetricQueryID query_id);
 
index 5c08bb88abc95b6ebaea8a00a7dc21514d502e40..8f209a8f30e30561180bf619775696a6621d695a 100644 (file)
@@ -29,6 +29,8 @@
 #include "BaseMgrModule.h"
 #include "Gil.h"
 
+#include <algorithm>
+
 #define dout_context g_ceph_context
 #define dout_subsys ceph_subsys_mgr
 
@@ -681,8 +683,11 @@ ceph_add_osd_perf_query(BaseMgrModule *self, PyObject *args)
   static const std::string NAME_KEY_DESCRIPTOR = "key_descriptor";
   static const std::string NAME_COUNTERS_DESCRIPTORS =
       "performance_counter_descriptors";
+  static const std::string NAME_LIMIT = "limit";
   static const std::string NAME_SUB_KEY_TYPE = "type";
   static const std::string NAME_SUB_KEY_REGEX = "regex";
+  static const std::string NAME_LIMIT_ORDER_BY = "order_by";
+  static const std::string NAME_LIMIT_MAX_COUNT = "max_count";
   static const std::map<std::string, OSDPerfMetricSubKeyType> sub_key_types = {
     {"client_id", OSDPerfMetricSubKeyType::CLIENT_ID},
     {"pool_id", OSDPerfMetricSubKeyType::POOL_ID},
@@ -712,6 +717,7 @@ ceph_add_osd_perf_query(BaseMgrModule *self, PyObject *args)
 
   PyObject *query_params = PyDict_Items(py_query);
   OSDPerfMetricQuery query;
+  std::optional<OSDPerfMetricLimit> limit;
 
   // {
   //   'key_descriptor': [
@@ -721,6 +727,7 @@ ceph_add_osd_perf_query(BaseMgrModule *self, PyObject *args)
   //   'performance_counter_descriptors': [
   //     list, of, descriptor, types
   //   ],
+  //   'limit': {'order_by': performance_counter_type, 'max_count': n},
   // }
 
   for (int i = 0; i < PyList_Size(query_params); ++i) {
@@ -822,19 +829,80 @@ ceph_add_osd_perf_query(BaseMgrModule *self, PyObject *args)
         }
         query.performance_counter_descriptors.push_back(it->second);
       }
+    } else if (query_param_name == NAME_LIMIT) {
+      if (!PyDict_Check(query_param_val)) {
+        derr << __func__ << " query " << query_param_name << " not a dict"
+             << dendl;
+        Py_RETURN_NONE;
+      }
+
+      limit = OSDPerfMetricLimit();
+      PyObject *limit_params = PyDict_Items(query_param_val);
+
+      for (int j = 0; j < PyList_Size(limit_params); ++j) {
+        PyObject *kv = PyList_GET_ITEM(limit_params, j);
+        char *limit_param_name = nullptr;
+        PyObject *limit_param_val = nullptr;
+        if (!PyArg_ParseTuple(kv, "sO:pair", &limit_param_name,
+                              &limit_param_val)) {
+          derr << __func__ << " limit item " << j << " not a size 2 tuple"
+               << dendl;
+          Py_RETURN_NONE;
+        }
+
+        if (limit_param_name == NAME_LIMIT_ORDER_BY) {
+          if (!PyString_Check(limit_param_val)) {
+            derr << __func__ << " " << limit_param_name << " not a string"
+                 << dendl;
+            Py_RETURN_NONE;
+          }
+          auto order_by = PyString_AsString(limit_param_val);
+          auto it = counter_types.find(order_by);
+          if (it == counter_types.end()) {
+            derr << __func__ << " limit " << limit_param_name
+                 << " not a valid counter type" << dendl;
+            Py_RETURN_NONE;
+          }
+          limit->order_by = it->second;
+        } else if (limit_param_name == NAME_LIMIT_MAX_COUNT) {
+#if PY_MAJOR_VERSION <= 2
+          if (!PyInt_Check(limit_param_val) && !PyLong_Check(limit_param_val)) {
+#else
+          if (!PyLong_Check(limit_param_val)) {
+#endif
+            derr << __func__ << " " << limit_param_name << " not an int"
+                 << dendl;
+            Py_RETURN_NONE;
+          }
+          limit->max_count = PyLong_AsLong(limit_param_val);
+        } else {
+          derr << __func__ << " unknown limit param: " << limit_param_name
+               << dendl;
+          Py_RETURN_NONE;
+        }
+      }
     } else {
-      derr << "unknown query param: " << query_param_name << dendl;
+      derr << __func__ << " unknown query param: " << query_param_name << dendl;
       Py_RETURN_NONE;
     }
   }
 
   if (query.key_descriptor.empty() ||
       query.performance_counter_descriptors.empty()) {
-    derr << "invalid query" << dendl;
+    derr << __func__ << " invalid query" << dendl;
     Py_RETURN_NONE;
   }
 
-  auto query_id = self->py_modules->add_osd_perf_query(query);
+  if (limit) {
+    auto &ds = query.performance_counter_descriptors;
+    if (std::find(ds.begin(), ds.end(), limit->order_by) == ds.end()) {
+      derr << __func__ << " limit order_by " << limit->order_by
+           << " not in performance_counter_descriptors" << dendl;
+      Py_RETURN_NONE;
+    }
+  }
+
+  auto query_id = self->py_modules->add_osd_perf_query(query, limit);
   return PyLong_FromLong(query_id);
 }
 
index 716ae6dde75ec3ac995c1c6cb587b5e4e55dd45e..a1d5f87208e6afb2618013ba039205957905ce4e 100644 (file)
@@ -2684,9 +2684,10 @@ void DaemonServer::_send_configure(ConnectionRef c)
 }
 
 OSDPerfMetricQueryID DaemonServer::add_osd_perf_query(
-  const OSDPerfMetricQuery &query)
+    const OSDPerfMetricQuery &query,
+    const std::optional<OSDPerfMetricLimit> &limit)
 {
-  return osd_perf_metric_collector.add_query(query);
+  return osd_perf_metric_collector.add_query(query, limit);
 }
 
 int DaemonServer::remove_osd_perf_query(OSDPerfMetricQueryID query_id)
index 47020a884b4b8aff301195492474242f2d2cd8b1..d6a5aafbd6b97b1202602b1c081acc9bace69c28 100644 (file)
@@ -165,7 +165,9 @@ public:
 
   void _send_configure(ConnectionRef c);
 
-  OSDPerfMetricQueryID add_osd_perf_query(const OSDPerfMetricQuery &query);
+  OSDPerfMetricQueryID add_osd_perf_query(
+      const OSDPerfMetricQuery &query,
+      const std::optional<OSDPerfMetricLimit> &limit);
   int remove_osd_perf_query(OSDPerfMetricQueryID query_id);
   int get_osd_perf_counters(OSDPerfMetricQueryID query_id,
                             std::map<OSDPerfMetricKey, PerformanceCounters> *c);
index 72348ab23c53a48665559f7382847ede13dc0903..09764afaf8cce679bda05f67751e6cf0b61ebb3a 100644 (file)
@@ -79,7 +79,8 @@ protected:
   // If provided, use this to compose an MPGStats to send with
   // our reports (hook for use by OSD)
   std::function<MPGStats*()> pgstats_cb;
-  std::function<void(const std::list<OSDPerfMetricQuery> &)> set_perf_queries_cb;
+  std::function<void(const std::map<OSDPerfMetricQuery,
+                                    OSDPerfMetricLimits> &)> set_perf_queries_cb;
   std::function<void(std::map<OSDPerfMetricQuery,
                               OSDPerfMetricReport> *)> get_perf_report_cb;
 
@@ -119,7 +120,8 @@ public:
   bool handle_command_reply(MCommandReply *m);
 
   void set_perf_metric_query_cb(
-          std::function<void(const std::list<OSDPerfMetricQuery> &)> cb_set,
+    std::function<void(const std::map<OSDPerfMetricQuery,
+                                      OSDPerfMetricLimits> &)> cb_set,
           std::function<void(std::map<OSDPerfMetricQuery,
                                       OSDPerfMetricReport> *)> cb_get)
   {
index e8669bb163b0d1a5c6a0cd30d7f74a748fc7f290..5cd8e27326a851dad35739a418f9c94c667383ae 100644 (file)
 #undef dout_prefix
 #define dout_prefix *_dout << "mgr.osd_perf_metric_collector " << __func__ << " "
 
+namespace {
+
+bool is_limited(const std::map<OSDPerfMetricQueryID,
+                                std::optional<OSDPerfMetricLimit>> &limits) {
+  for (auto &it : limits) {
+    if (!it.second) {
+      return false;
+    }
+  }
+  return true;
+}
+
+} // anonymous namespace
+
 OSDPerfMetricCollector::OSDPerfMetricCollector(Listener &listener)
   : listener(listener), lock("OSDPerfMetricCollector::lock") {
 }
 
-std::list<OSDPerfMetricQuery> OSDPerfMetricCollector::get_queries() {
+std::map<OSDPerfMetricQuery, OSDPerfMetricLimits>
+OSDPerfMetricCollector::get_queries() const {
   std::lock_guard locker(lock);
 
-  std::list<OSDPerfMetricQuery> query_list;
+  std::map<OSDPerfMetricQuery, OSDPerfMetricLimits> result;
   for (auto &it : queries) {
-    query_list.push_back(it.first);
+    auto &query = it.first;
+    auto &limits = it.second;
+    auto result_it = result.insert({query, {}}).first;
+    if (is_limited(limits)) {
+      for (auto &iter : limits) {
+        result_it->second.insert(*iter.second);
+      }
+    }
   }
 
-  return query_list;
+  return result;
 }
 
-int OSDPerfMetricCollector::add_query(const OSDPerfMetricQuery& query) {
+OSDPerfMetricQueryID OSDPerfMetricCollector::add_query(
+    const OSDPerfMetricQuery& query,
+    const std::optional<OSDPerfMetricLimit> &limit) {
   uint64_t query_id;
   bool notify = false;
 
@@ -38,12 +62,15 @@ int OSDPerfMetricCollector::add_query(const OSDPerfMetricQuery& query) {
     if (it == queries.end()) {
       it = queries.insert({query, {}}).first;
       notify = true;
+    } else if (is_limited(it->second)) {
+      notify = true;
     }
-    it->second.insert(query_id);
+    it->second.insert({query_id, limit});
     counters[query_id];
   }
 
-  dout(10) << query << " query_id=" << query_id << dendl;
+  dout(10) << query << " " << (limit ? stringify(*limit) : "unlimited")
+           << " query_id=" << query_id << dendl;
 
   if (notify) {
     listener.handle_query_updated();
@@ -60,16 +87,20 @@ int OSDPerfMetricCollector::remove_query(int query_id) {
     std::lock_guard locker(lock);
 
     for (auto it = queries.begin() ; it != queries.end(); it++) {
-      auto &ids = it->second;
+      auto iter = it->second.find(query_id);
+      if (iter == it->second.end()) {
+        continue;
+      }
 
-      if (ids.erase(query_id) > 0) {
-        if (ids.empty()) {
-          queries.erase(it);
-          notify = true;
-        }
-        found = true;
-        break;
+      it->second.erase(iter);
+      if (it->second.empty()) {
+        queries.erase(it);
+        notify = true;
+      } else if (is_limited(it->second)) {
+        notify = true;
       }
+      found = true;
+      break;
     }
     counters.erase(query_id);
   }
@@ -142,7 +173,8 @@ void OSDPerfMetricCollector::process_reports(
       auto &key = it.first;
       auto bl_it = it.second.cbegin();
 
-      for (auto query_id : queries[query]) {
+      for (auto &queries_it : queries[query]) {
+        auto query_id = queries_it.first;
         auto &key_counters = counters[query_id][key];
         if (key_counters.empty()) {
           key_counters.resize(query.performance_counter_descriptors.size(),
@@ -155,14 +187,15 @@ void OSDPerfMetricCollector::process_reports(
         if (desc_it == report.performance_counter_descriptors.end()) {
           break;
         }
-        if (desc_it->type != query.performance_counter_descriptors[i].type) {
+        if (*desc_it != query.performance_counter_descriptors[i]) {
           continue;
         }
         PerformanceCounter c;
         desc_it->unpack_counter(bl_it, &c);
         dout(20) << "counter " << key << " " << *desc_it << ": " << c << dendl;
 
-        for (auto query_id : queries[query]) {
+        for (auto &queries_it : queries[query]) {
+          auto query_id = queries_it.first;
           auto &key_counters = counters[query_id][key];
           key_counters[i].first += c.first;
           key_counters[i].second += c.second;
index 5b9b8dc10ba95504ee0ddacf14515b50785fd33e..89e330915749f39497ba60180f953b42f5cbb297 100644 (file)
@@ -8,8 +8,7 @@
 
 #include "mgr/OSDPerfMetricTypes.h"
 
-#include <list>
-#include <set>
+#include <map>
 
 /**
  * OSD performance query class.
@@ -25,9 +24,11 @@ public:
 
   OSDPerfMetricCollector(Listener &listener);
 
-  std::list<OSDPerfMetricQuery> get_queries();
+  std::map<OSDPerfMetricQuery, OSDPerfMetricLimits> get_queries() const;
 
-  OSDPerfMetricQueryID add_query(const OSDPerfMetricQuery& query);
+  OSDPerfMetricQueryID add_query(
+      const OSDPerfMetricQuery& query,
+      const std::optional<OSDPerfMetricLimit> &limit);
   int remove_query(OSDPerfMetricQueryID query_id);
   void remove_all_queries();
 
@@ -38,7 +39,9 @@ public:
       const std::map<OSDPerfMetricQuery, OSDPerfMetricReport> &reports);
 
 private:
-  typedef std::map<OSDPerfMetricQuery, std::set<OSDPerfMetricQueryID>> Queries;
+  typedef std::optional<OSDPerfMetricLimit> OptionalLimit;
+  typedef std::map<OSDPerfMetricQuery,
+                   std::map<OSDPerfMetricQueryID, OptionalLimit>> Queries;
   typedef std::map<OSDPerfMetricQueryID,
                    std::map<OSDPerfMetricKey, PerformanceCounters>> Counters;
 
index 181a1f38c7c596619c5c82f9d6bd058a93f0ba70..9cf733c3d2382e6c563d96eb5230f3e8a6230303 100644 (file)
@@ -93,6 +93,11 @@ std::ostream& operator<<(std::ostream& os,
   }
 }
 
+std::ostream& operator<<(std::ostream& os, const OSDPerfMetricLimit &limit) {
+  return os << "{order_by=" << limit.order_by << ", max_count="
+            << limit.max_count << "}";
+}
+
 void OSDPerfMetricQuery::pack_counters(const PerformanceCounters &counters,
                                        bufferlist *bl) const {
   auto it = counters.begin();
index c1777af0fa4c4d93435876577e1ceea84343b24d..f68740c38fff169115a3750fca37e746dfe2c5f6 100644 (file)
@@ -157,6 +157,14 @@ struct PerformanceCounterDescriptor {
     return type < other.type;
   }
 
+  bool operator==(const PerformanceCounterDescriptor &other) const {
+    return type == other.type;
+  }
+
+  bool operator!=(const PerformanceCounterDescriptor &other) const {
+    return type != other.type;
+  }
+
   DENC(PerformanceCounterDescriptor, v, p) {
     DENC_START(1, 1, p);
     denc(v.type, p);
@@ -212,6 +220,38 @@ struct denc_traits<PerformanceCounterDescriptors> {
   }
 };
 
+struct OSDPerfMetricLimit {
+  PerformanceCounterDescriptor order_by;
+  uint64_t max_count = 0;
+
+  OSDPerfMetricLimit() {
+  }
+
+  OSDPerfMetricLimit(const PerformanceCounterDescriptor &order_by,
+                     uint64_t max_count)
+    : order_by(order_by), max_count(max_count) {
+  }
+
+  bool operator<(const OSDPerfMetricLimit &other) const {
+    if (order_by != other.order_by) {
+      return order_by < other.order_by;
+    }
+    return max_count < other.max_count;
+  }
+
+  DENC(OSDPerfMetricLimit, v, p) {
+    DENC_START(1, 1, p);
+    denc(v.order_by, p);
+    denc(v.max_count, p);
+    DENC_FINISH(p);
+  }
+};
+WRITE_CLASS_DENC(OSDPerfMetricLimit)
+
+std::ostream& operator<<(std::ostream& os, const OSDPerfMetricLimit &limit);
+
+typedef std::set<OSDPerfMetricLimit> OSDPerfMetricLimits;
+
 typedef int OSDPerfMetricQueryID;
 
 struct OSDPerfMetricQuery {
index 06f945ecbe51d988fca26b3f542123c990ce5fe7..0eeab719b4d0f4b86a9c3287239ed7ff88357e0a 100644 (file)
@@ -2807,7 +2807,7 @@ int OSD::init()
 
   mgrc.set_pgstats_cb([this](){ return collect_pg_stats(); });
   mgrc.set_perf_metric_query_cb(
-      [this](const std::list<OSDPerfMetricQuery> &queries) {
+    [this](const std::map<OSDPerfMetricQuery, OSDPerfMetricLimits> &queries) {
         set_perf_queries(queries);
       },
       [this](std::map<OSDPerfMetricQuery, OSDPerfMetricReport> *reports) {
@@ -9800,15 +9800,17 @@ int OSD::init_op_flags(OpRequestRef& op)
   return 0;
 }
 
-void OSD::set_perf_queries(const std::list<OSDPerfMetricQuery> &queries) {
+void OSD::set_perf_queries(
+    const std::map<OSDPerfMetricQuery, OSDPerfMetricLimits> &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();
-               });
+  for (auto &it : queries) {
+    auto &query = it.first;
+    if (!query.key_descriptor.empty()) {
+      supported_queries.push_back(query);
+    }
+  }
   if (supported_queries.size() < queries.size()) {
     dout(1) << queries.size() - supported_queries.size()
             << " unsupported queries" << dendl;
index 7253e9aa14a7cc60b7e15c38a365400bd4e9a01f..49d689b588c4698b7f0ff577b8348ff5d7b5e837 100644 (file)
@@ -2310,7 +2310,8 @@ public:
   friend class OSDService;
 
 private:
-  void set_perf_queries(const std::list<OSDPerfMetricQuery> &queries);
+  void set_perf_queries(
+      const std::map<OSDPerfMetricQuery, OSDPerfMetricLimits> &queries);
   void get_perf_reports(
       std::map<OSDPerfMetricQuery, OSDPerfMetricReport> *reports);
 
index ccf763c776ed1259ffbfb700c87a66ab22b9e28a..f66ba6183469516b5236408fc543f4994e6443b3 100644 (file)
@@ -967,6 +967,7 @@ class MgrModule(ceph_module.BaseMgrModule):
              'performance_counter_descriptors': [
                list, of, descriptor, types
              ],
+             'limit': {'order_by': performance_counter_type, 'max_count': n},
            }
 
         Valid subkey types: 'client_id', 'pool_id', 'object_name'