]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
proflogger: test multiple profloggers
authorColin Patrick McCabe <cmccabe@alumni.cmu.edu>
Tue, 19 Jul 2011 00:18:52 +0000 (17:18 -0700)
committerColin Patrick McCabe <cmccabe@alumni.cmu.edu>
Tue, 19 Jul 2011 00:18:52 +0000 (17:18 -0700)
Test multiple profloggers, and removing profloggers.

Add a clear function which removes all profloggers.

Make the order in which profloggers are output to JSON determininstic.

Const cleanup on get() methods.

Signed-off-by: Colin McCabe <colin.mccabe@dreamhost.com>
src/common/ProfLogger.cc
src/common/ProfLogger.h
src/test/proflogger.cc

index 4d3fde5abf429f007374936875d5c4a8600246ae..6cf012fffcf4505fb2d0ae003b1b16fdff22ec67 100644 (file)
@@ -259,7 +259,7 @@ private:
     {
       Mutex::Locker lck(m_parent->m_lock); // Take lock to access m_loggers
       buffer.push_back('{');
-      for (std::set <ProfLogger*>::iterator l = m_parent->m_loggers.begin();
+      for (prof_logger_set_t::iterator l = m_parent->m_loggers.begin();
           l != m_parent->m_loggers.end(); ++l)
       {
        (*l)->write_json_to_buf(buffer);
@@ -311,7 +311,7 @@ ProfLoggerCollection::
 {
   Mutex::Locker lck(m_lock);
   shutdown();
-  for (std::set <ProfLogger*>::iterator l = m_loggers.begin();
+  for (prof_logger_set_t::iterator l = m_loggers.begin();
        l != m_loggers.end(); ++l) {
     delete *l;
   }
@@ -345,7 +345,7 @@ void ProfLoggerCollection::
 logger_add(class ProfLogger *l)
 {
   Mutex::Locker lck(m_lock);
-  std::set<ProfLogger*>::iterator i = m_loggers.find(l);
+  prof_logger_set_t::iterator i = m_loggers.find(l);
   assert(i == m_loggers.end());
   m_loggers.insert(l);
 }
@@ -354,11 +354,24 @@ void ProfLoggerCollection::
 logger_remove(class ProfLogger *l)
 {
   Mutex::Locker lck(m_lock);
-  std::set<ProfLogger*>::iterator i = m_loggers.find(l);
+  prof_logger_set_t::iterator i = m_loggers.find(l);
   assert(i != m_loggers.end());
+  delete *i;
   m_loggers.erase(i);
 }
 
+void ProfLoggerCollection::
+logger_clear()
+{
+  Mutex::Locker lck(m_lock);
+  prof_logger_set_t::iterator i = m_loggers.begin();
+  prof_logger_set_t::iterator i_end = m_loggers.end();
+  for (; i != i_end; ) {
+    delete *i;
+    m_loggers.erase(i++);
+  }
+}
+
 bool ProfLoggerCollection::
 init(const std::string &uri)
 {
@@ -456,12 +469,12 @@ set(int idx, uint64_t amt)
 }
 
 uint64_t ProfLogger::
-get(int idx)
+get(int idx) const
 {
   Mutex::Locker lck(m_lock);
   assert(idx > m_lower_bound);
   assert(idx < m_upper_bound);
-  prof_log_data_any_d& data(m_data[idx - m_lower_bound - 1]);
+  const prof_log_data_any_d& data(m_data[idx - m_lower_bound - 1]);
   if (data.type != PROF_LOG_DATA_ANY_DOUBLE)
     return 0;
   return data.u.u64;
@@ -496,12 +509,12 @@ fset(int idx, double amt)
 }
 
 double ProfLogger::
-fget(int idx)
+fget(int idx) const
 {
   Mutex::Locker lck(m_lock);
   assert(idx > m_lower_bound);
   assert(idx < m_upper_bound);
-  prof_log_data_any_d& data(m_data[idx - m_lower_bound - 1]);
+  const prof_log_data_any_d& data(m_data[idx - m_lower_bound - 1]);
   if (data.type != PROF_LOG_DATA_ANY_DOUBLE)
     return 0.0;
   return data.u.dbl;
@@ -556,6 +569,12 @@ write_json_to_buf(std::vector <char> &buffer)
   }
 }
 
+const std::string &ProfLogger::
+get_name() const
+{
+  return m_name;
+}
+
 ProfLogger::
 ProfLogger(CephContext *cct, const std::string &name,
           int lower_bound, int upper_bound)
index 8015db5d465ba64ca6f10428ff51bfa68a07b2f7..d7db2aa8510d14608f0f485a920b7b65f8419657 100644 (file)
 #include <string>
 #include <vector>
 
+class CephContext;
 class ProfLoggerBuilder;
 class ProfLoggerCollectionTest;
-class CephContext;
 class Thread;
 
 /*
- * ProfLog manages the profiler logging for a Ceph process.
+ * A ProfLogger is usually associated with a single subsystem.
+ * It contains counters which we modify to track performance and throughput
+ * over time. 
+ *
+ * ProfLogger is thread-safe. However, it is better to avoid sharing
+ * ProfLoggers between multiple threads to avoid cacheline ping-pong.
  */
-class ProfLoggerCollection : public md_config_obs_t
-{
-public:
-  ProfLoggerCollection(CephContext *cct);
-  ~ProfLoggerCollection();
-  virtual const char** get_tracked_conf_keys() const;
-  virtual void handle_conf_change(const md_config_t *conf,
-                         const std::set <std::string> &changed);
-  void logger_add(class ProfLogger *l);
-  void logger_remove(class ProfLogger *l);
-private:
-  bool init(const std::string &uri);
-  void shutdown();
-
-  CephContext *m_cct;
-  Thread* m_thread;
-
-  /** Protects m_loggers */
-  Mutex m_lock;
-
-  int m_shutdown_fd;
-  std::set <ProfLogger*> m_loggers;
-  std::string m_uri;
-
-  friend class ProfLogThread;
-  friend class ProfLoggerCollectionTest;
-};
-
 class ProfLogger
 {
 public:
@@ -66,14 +43,16 @@ public:
 
   void inc(int idx, uint64_t v = 1);
   void set(int idx, uint64_t v);
-  uint64_t get(int idx);
+  uint64_t get(int idx) const;
 
   void fset(int idx, double v);
   void finc(int idx, double v);
-  double fget(int idx);
+  double fget(int idx) const;
 
   void write_json_to_buf(std::vector <char> &buffer);
 
+  const std::string& get_name() const;
+
 private:
   ProfLogger(CephContext *cct, const std::string &name,
             int lower_bound, int upper_bound);
@@ -99,13 +78,54 @@ private:
   const std::string m_name;
 
   /** Protects m_data */
-  Mutex m_lock;
+  mutable Mutex m_lock;
 
   prof_log_data_vec_t m_data;
 
   friend class ProfLoggerBuilder;
 };
 
+class SortProfLoggersByName {
+public:
+  bool operator()(const ProfLogger* lhs, const ProfLogger* rhs) const {
+    return (lhs->get_name() < rhs->get_name());
+  }
+};
+
+typedef std::set <ProfLogger*, SortProfLoggersByName> prof_logger_set_t;
+
+/*
+ * ProfLoggerCollection manages the set of ProfLoggers for a Ceph process.
+ */
+class ProfLoggerCollection : public md_config_obs_t
+{
+public:
+  ProfLoggerCollection(CephContext *cct);
+  ~ProfLoggerCollection();
+  virtual const char** get_tracked_conf_keys() const;
+  virtual void handle_conf_change(const md_config_t *conf,
+                         const std::set <std::string> &changed);
+  void logger_add(class ProfLogger *l);
+  void logger_remove(class ProfLogger *l);
+  void logger_clear();
+private:
+  bool init(const std::string &uri);
+  void shutdown();
+
+  CephContext *m_cct;
+  Thread* m_thread;
+
+  /** Protects m_loggers */
+  mutable Mutex m_lock;
+
+  int m_shutdown_fd;
+  prof_logger_set_t m_loggers;
+  std::string m_uri;
+
+  friend class ProfLogThread;
+  friend class ProfLoggerCollectionTest;
+};
+
 /* Class for constructing ProfLoggers.
  *
  * This class peforms some validation that the parameters we have supplied are
index 68f0067cfb1f17eedb827d88af1b98606e9885e8..f2c897d6f29286d6611db1382c24222a83973bd2 100644 (file)
@@ -191,7 +191,7 @@ static ProfLogger* setup_fake_proflogger1(CephContext *cct)
   return bld.create_proflogger();
 }
 
-TEST(ProfLogger, FakeProflogger1) {
+TEST(ProfLogger, SingleProfLogger) {
   ProfLoggerCollection *coll = g_ceph_context->GetProfLoggerCollection();
   ProfLogger* fake_pf = setup_fake_proflogger1(g_ceph_context);
   coll->logger_add(fake_pf);
@@ -212,3 +212,49 @@ TEST(ProfLogger, FakeProflogger1) {
   ASSERT_EQ("", test_client.get_message(&msg));
   ASSERT_EQ("{'element1':1,'element2':0.5,'element3':{'count':3,'sum':125},}", msg);
 }
+
+enum {
+  FAKE_PROFLOGGER2_ELEMENT_FIRST = 400,
+  FAKE_PROFLOGGER2_ELEMENT_FOO,
+  FAKE_PROFLOGGER2_ELEMENT_BAR,
+  FAKE_PROFLOGGER2_ELEMENT_LAST,
+};
+
+static ProfLogger* setup_fake_proflogger2(CephContext *cct)
+{
+  ProfLoggerBuilder bld(cct, "fake_proflogger_2",
+         FAKE_PROFLOGGER2_ELEMENT_FIRST, FAKE_PROFLOGGER2_ELEMENT_LAST);
+  bld.add_u64(FAKE_PROFLOGGER2_ELEMENT_FOO, "foo");
+  bld.add_fl(FAKE_PROFLOGGER2_ELEMENT_BAR, "bar");
+  return bld.create_proflogger();
+}
+
+TEST(ProfLogger, MultipleProfloggers) {
+  ProfLoggerCollection *coll = g_ceph_context->GetProfLoggerCollection();
+  coll->logger_clear();
+  ProfLogger* fake_pf1 = setup_fake_proflogger1(g_ceph_context);
+  ProfLogger* fake_pf2 = setup_fake_proflogger2(g_ceph_context);
+  coll->logger_add(fake_pf1);
+  coll->logger_add(fake_pf2);
+  ProfLoggerCollectionTest plct(coll);
+  ASSERT_EQ(true, plct.shutdown());
+  ASSERT_EQ(true, plct.init(get_socket_path()));
+  ProfLoggerTestClient test_client(get_socket_path());
+  std::string msg;
+
+  ASSERT_EQ("", test_client.get_message(&msg));
+  ASSERT_EQ("{'element1':0,'element2':0,'element3':{'count':0,'sum':0},'foo':0,'bar':0,}", msg);
+
+  fake_pf1->inc(FAKE_PROFLOGGER1_ELEMENT_1);
+  fake_pf1->inc(FAKE_PROFLOGGER1_ELEMENT_1, 5);
+  ASSERT_EQ("", test_client.get_message(&msg));
+  ASSERT_EQ("{'element1':6,'element2':0,'element3':{'count':0,'sum':0},'foo':0,'bar':0,}", msg);
+
+  coll->logger_remove(fake_pf2);
+  ASSERT_EQ("", test_client.get_message(&msg));
+  ASSERT_EQ("{'element1':6,'element2':0,'element3':{'count':0,'sum':0},}", msg);
+
+  coll->logger_clear();
+  ASSERT_EQ("", test_client.get_message(&msg));
+  ASSERT_EQ("{}", msg);
+}