From: Colin Patrick McCabe Date: Tue, 19 Jul 2011 00:18:52 +0000 (-0700) Subject: proflogger: test multiple profloggers X-Git-Tag: v0.32~53^2~13 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=64d3314237e7ad6a7cb6788d37ef9ae6bfa23e46;p=ceph.git proflogger: test multiple profloggers 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 --- diff --git a/src/common/ProfLogger.cc b/src/common/ProfLogger.cc index 4d3fde5abf42..6cf012fffcf4 100644 --- a/src/common/ProfLogger.cc +++ b/src/common/ProfLogger.cc @@ -259,7 +259,7 @@ private: { Mutex::Locker lck(m_parent->m_lock); // Take lock to access m_loggers buffer.push_back('{'); - for (std::set ::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 ::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::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::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 &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) diff --git a/src/common/ProfLogger.h b/src/common/ProfLogger.h index 8015db5d465b..d7db2aa8510d 100644 --- a/src/common/ProfLogger.h +++ b/src/common/ProfLogger.h @@ -23,42 +23,19 @@ #include #include +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 &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 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 &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 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 &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 diff --git a/src/test/proflogger.cc b/src/test/proflogger.cc index 68f0067cfb1f..f2c897d6f292 100644 --- a/src/test/proflogger.cc +++ b/src/test/proflogger.cc @@ -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); +}