From: John Spray Date: Tue, 27 Jan 2015 11:13:59 +0000 (+0000) Subject: common: filtering in `perf dump` X-Git-Tag: v0.93~170^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=a8e257975abcb76e3db9f3d38c25faf372942f57;p=ceph.git common: filtering in `perf dump` So that we can get out a particular subsystem or particular counter without dumping everything. Should make tests that watch perf counters much less spammy! `logger` and `counter` params are used with an exact comparison here but the interface should be amenable to extending to e.g. globbing if we wanted to in the future. Also tidy up some iterator while()s into for()s. Signed-off-by: John Spray --- diff --git a/src/common/ceph_context.cc b/src/common/ceph_context.cc index bec006bfdf548..7f1adb091f4d5 100644 --- a/src/common/ceph_context.cc +++ b/src/common/ceph_context.cc @@ -236,7 +236,11 @@ void CephContext::do_command(std::string command, cmdmap_t& cmdmap, << ss.str() << dendl; if (command == "perfcounters_dump" || command == "1" || command == "perf dump") { - _perf_counters_collection->dump_formatted(f, false); + std::string logger; + std::string counter; + cmd_getval(this, cmdmap, "logger", logger); + cmd_getval(this, cmdmap, "counter", counter); + _perf_counters_collection->dump_formatted(f, false, logger, counter); } else if (command == "perfcounters_schema" || command == "2" || command == "perf schema") { @@ -379,7 +383,7 @@ CephContext::CephContext(uint32_t module_type_) _admin_hook = new CephContextHook(this); _admin_socket->register_command("perfcounters_dump", "perfcounters_dump", _admin_hook, ""); _admin_socket->register_command("1", "1", _admin_hook, ""); - _admin_socket->register_command("perf dump", "perf dump", _admin_hook, "dump perfcounters value"); + _admin_socket->register_command("perf dump", "perf dump name=logger,type=CephString,req=false name=counter,type=CephString,req=false", _admin_hook, "dump perfcounters value"); _admin_socket->register_command("perfcounters_schema", "perfcounters_schema", _admin_hook, ""); _admin_socket->register_command("2", "2", _admin_hook, ""); _admin_socket->register_command("perf schema", "perf schema", _admin_hook, "dump perfcounters schema"); diff --git a/src/common/perf_counters.cc b/src/common/perf_counters.cc index 3824bea95ff38..61242727f3bc9 100644 --- a/src/common/perf_counters.cc +++ b/src/common/perf_counters.cc @@ -102,17 +102,30 @@ bool PerfCountersCollection::reset(const std::string &name) } -void PerfCountersCollection::dump_formatted(Formatter *f, bool schema) +/** + * Serialize current values of performance counters. Optionally + * output the schema instead, or filter output to a particular + * PerfCounters or particular named counter. + * + * @param logger name of subsystem logger, e.g. "mds_cache", may be empty + * @param counter name of counter within subsystem, e.g. "num_strays", + * may be empty. + * @param schema if true, output schema instead of current data. + */ +void PerfCountersCollection::dump_formatted( + Formatter *f, + bool schema, + const std::string &logger, + const std::string &counter) { Mutex::Locker lck(m_lock); f->open_object_section("perfcounter_collection"); - perf_counters_set_t::iterator l = m_loggers.begin(); - perf_counters_set_t::iterator l_end = m_loggers.end(); - if (l != l_end) { - while (true) { - (*l)->dump_formatted(f, schema); - if (++l == l_end) - break; + + for (perf_counters_set_t::iterator l = m_loggers.begin(); + l != m_loggers.end(); ++l) { + // Optionally filter on logger name, pass through counter filter + if (logger.empty() || (*l)->get_name() == logger) { + (*l)->dump_formatted(f, schema, counter); } } f->close_section(); @@ -264,16 +277,18 @@ void PerfCounters::reset() } } -void PerfCounters::dump_formatted(Formatter *f, bool schema) +void PerfCounters::dump_formatted(Formatter *f, bool schema, + const std::string &counter) { f->open_object_section(m_name.c_str()); - perf_counter_data_vec_t::const_iterator d = m_data.begin(); - perf_counter_data_vec_t::const_iterator d_end = m_data.end(); - if (d == d_end) { - f->close_section(); - return; - } - while (true) { + + for (perf_counter_data_vec_t::const_iterator d = m_data.begin(); + d != m_data.end(); ++d) { + if (!counter.empty() && counter != d->name) { + // Optionally filter on counter name + continue; + } + if (schema) { f->open_object_section(d->name); f->dump_int("type", d->type); @@ -307,9 +322,6 @@ void PerfCounters::dump_formatted(Formatter *f, bool schema) } } } - - if (++d == d_end) - break; } f->close_section(); } diff --git a/src/common/perf_counters.h b/src/common/perf_counters.h index 24b505dc3a273..8850138a23fa9 100644 --- a/src/common/perf_counters.h +++ b/src/common/perf_counters.h @@ -95,7 +95,8 @@ public: utime_t tget(int idx) const; void reset(); - void dump_formatted(ceph::Formatter *f, bool schema); + void dump_formatted(ceph::Formatter *f, bool schema, + const std::string &counter = ""); pair get_tavg_ms(int idx) const; const std::string& get_name() const; @@ -203,7 +204,11 @@ public: void remove(class PerfCounters *l); void clear(); bool reset(const std::string &name); - void dump_formatted(ceph::Formatter *f, bool schema); + void dump_formatted( + ceph::Formatter *f, + bool schema, + const std::string &logger = "", + const std::string &counter = ""); private: CephContext *m_cct;