]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr: generalize OSDPerfMetricQuery to support different queries
authorMykola Golub <mgolub@suse.com>
Mon, 12 Nov 2018 18:39:33 +0000 (20:39 +0200)
committerMykola Golub <mgolub@suse.com>
Tue, 20 Nov 2018 11:18:30 +0000 (13:18 +0200)
Signed-off-by: Mykola Golub <mgolub@suse.com>
src/mgr/BaseMgrModule.cc
src/mgr/OSDPerfMetricTypes.cc
src/mgr/OSDPerfMetricTypes.h
src/osd/DynamicPerfStats.h
src/osd/OSD.cc

index 038490dedadf2b46d7889ab645a7357e2308381d..0aee22318b4d92171c48467c5b40305626abc7b5 100644 (file)
@@ -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);
 }
index 2177bed37a0a24b275bb1a2dd20866f6448546f2..266fc403cc5edc5b643e7f9f6a856776534bf6e8 100644 (file)
@@ -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<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,
@@ -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<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) << ")";
   }
 }
 
@@ -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 << "}";
 }
index 8367b96d5e6f2daf47fc130bd66421caeb114fc9..38bbd2c69d14424ba4178d5880c48b3039776afc 100644 (file)
 #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;
@@ -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 <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);
   }
@@ -124,20 +254,25 @@ struct OSDPerfMetricQuery {
     *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)
 
@@ -145,7 +280,7 @@ std::ostream& operator<<(std::ostream& os, const OSDPerfMetricQuery &query);
 
 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);
index dd19a858a0883405400032ee7dce1e35fb16309c..45259083736b40b34dc02909f927160f7c686f6e 100644 (file)
@@ -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<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]);
     }
@@ -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<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]);
       }
     }
   }
@@ -58,7 +137,8 @@ public:
   }
 
 private:
-  std::map<OSDPerfMetricQuery, std::map<std::string, PerformanceCounters>> data;
+  std::map<OSDPerfMetricQuery,
+           std::map<OSDPerfMetricKey, PerformanceCounters>> data;
 };
 
 #endif // DYNAMIC_PERF_STATS_H
index 8f3bd8e6afc80faf168ef6db023f609f1ea93a33..88b84fe5a26a7f0f295af4fa3cfdaf85908ac233 100644 (file)
@@ -9782,9 +9782,20 @@ int OSD::init_op_flags(OpRequestRef& op)
 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;
@@ -9792,7 +9803,7 @@ void OSD::set_perf_queries(const std::list<OSDPerfMetricQuery> &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();
     }
   }