diff --git a/ceph.spec.in b/ceph.spec.in index 0b2f1a7192723..fb129345264f6 100644 --- a/ceph.spec.in +++ b/ceph.spec.in @@ -121,6 +121,7 @@ BuildRequires: pkgconfig BuildRequires: python BuildRequires: python-devel BuildRequires: python-nose +BuildRequires: python-prettytable BuildRequires: python-requests BuildRequires: python-sphinx BuildRequires: python-virtualenv @@ -256,6 +257,7 @@ Requires: python-rados = %{epoch}:%{version}-%{release} Requires: python-rbd = %{epoch}:%{version}-%{release} Requires: python-cephfs = %{epoch}:%{version}-%{release} Requires: python-rgw = %{epoch}:%{version}-%{release} +Requires: python-prettytable Requires: python-requests %{?systemd_requires} %if 0%{?suse_version} diff --git a/debian/control b/debian/control index 1ae3a8a7662c1..c0fdad67aaaf3 100644 --- a/debian/control +++ b/debian/control @@ -50,6 +50,7 @@ Build-Depends: bc, python (>= 2.7), python-all-dev, python-nose, + python-prettytable, python-setuptools, python-sphinx, python3-all-dev, @@ -363,7 +364,8 @@ Depends: librbd1 (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends}, python-rbd (= ${binary:Version}), python-rgw (= ${binary:Version}), ${python:Depends}, - python-requests + python-requests, + python-prettytable Conflicts: ceph-client-tools Replaces: ceph-client-tools, ceph (<< 10), diff --git a/src/ceph.in b/src/ceph.in index 3ab1c222a3c8d..89b52cecc5bcb 100755 --- a/src/ceph.in +++ b/src/ceph.in @@ -38,6 +38,15 @@ FLAG_NOFORWARD = (1 << 0) FLAG_OBSOLETE = (1 << 1) FLAG_DEPRECATED = (1 << 2) +# priorities from src/common/perf_counters.h +PRIO_CRITICAL = 10 +PRIO_INTERESTING = 8 +PRIO_USEFUL = 5 +PRIO_UNINTERESTING = 2 +PRIO_DEBUGONLY = 0 + +PRIO_DEFAULT = PRIO_USEFUL + # Make life easier on developers: # If in src/, and .libs and pybind exist here, assume we're running # from a Ceph source dir and tweak PYTHONPATH and LD_LIBRARY_PATH @@ -266,10 +275,15 @@ ping Send simple presence/life test to a mon may be 'mon.*' for all mons daemon {type.id|path} Same as --admin-daemon, but auto-find admin socket -daemonperf {type.id | path} [] [] +daemonperf {type.id | path} [stat-pats] [priority] [] [] +daemonperf {type.id | path} list|ls [stat-pats] [priority] Get selected perf stats from daemon/admin socket + Optional shell-glob comma-delim match string stat-pats + Optional selection priority (can abbreviate name): + critical, interesting, useful, noninteresting, debug + List shows a table of all available stats Run times (default forever), - once per seconds (default 1) + once per seconds (default 1) """, file=sys.stdout) @@ -565,6 +579,134 @@ def ping_monitor(cluster_handle, name, timeout): print(s) return 0 + +def maybe_daemon_command(parsed_args, childargs): + """ + Check if --admin-socket, daemon, or daemonperf command + if it is, returns (boolean handled, return code if handled == True) + """ + + daemon_perf = False + sockpath = None + if parsed_args.admin_socket: + sockpath = parsed_args.admin_socket + elif len(childargs) > 0 and childargs[0] in ["daemon", "daemonperf"]: + daemon_perf = (childargs[0] == "daemonperf") + # Treat "daemon " or "daemon " like --admin_daemon + # Handle "daemonperf " the same but requires no trailing args + require_args = 2 if daemon_perf else 3 + if len(childargs) >= require_args: + if childargs[1].find('/') >= 0: + sockpath = childargs[1] + else: + # try resolve daemon name + try: + sockpath = ceph_conf(parsed_args, 'admin_socket', + childargs[1]) + except Exception as e: + print('Can\'t get admin socket path: ' + str(e), file=sys.stderr) + return True, errno.EINVAL + # for both: + childargs = childargs[2:] + else: + print('{0} requires at least {1} arguments'.format(childargs[0], require_args), + file=sys.stderr) + return True, errno.EINVAL + + if sockpath and daemon_perf: + return True, daemonperf(childargs, sockpath) + elif sockpath: + try: + raw_write(admin_socket(sockpath, childargs, parsed_args.output_format)) + except Exception as e: + print('admin_socket: {0}'.format(e), file=sys.stderr) + return True, errno.EINVAL + return True, 0 + + return False, 0 + + +def isnum(s): + try: + float(s) + return True + except ValueError: + return False + +def daemonperf(childargs, sockpath): + """ + Handle daemonperf command; returns errno or 0 + + daemonperf [priority string] [statpats] [interval] [count] + daemonperf list|ls [statpats] + """ + + interval = 1 + count = None + statpats = None + priority = None + do_list = False + + def prio_from_name(arg): + + PRIOMAP = { + 'critical': PRIO_CRITICAL, + 'interesting': PRIO_INTERESTING, + 'useful': PRIO_USEFUL, + 'uninteresting': PRIO_UNINTERESTING, + 'debugonly': PRIO_DEBUGONLY, + } + + if arg in PRIOMAP: + return PRIOMAP[arg] + # allow abbreviation + for name, val in PRIOMAP.items(): + if name.startswith(arg): + return val + return None + + # consume and analyze non-numeric args + while len(childargs) and not isnum(childargs[0]): + arg = childargs.pop(0) + # 'list'? + if arg in ['list', 'ls']: + do_list = True; + continue + # prio? + prio = prio_from_name(arg) + if prio is not None: + priority = prio + continue + # statpats + statpats = arg.split(',') + + if priority is None: + priority = PRIO_DEFAULT + + if len(childargs) > 0: + try: + interval = float(childargs.pop(0)) + if interval < 0: + raise ValueError + except ValueError: + print('daemonperf: interval should be a positive number', file=sys.stderr) + return errno.EINVAL + + if len(childargs) > 0: + arg = childargs.pop(0) + if (not isnum(arg)) or (int(arg) < 0): + print('daemonperf: count should be a positive integer', file=sys.stderr) + return errno.EINVAL + count = int(arg) + + watcher = DaemonWatcher(sockpath, statpats, priority) + if do_list: + watcher.list() + else: + watcher.run(interval, count) + + return 0 + ### # main ### @@ -610,58 +752,9 @@ def main(): format = parsed_args.output_format - daemon_perf = False - sockpath = None - if parsed_args.admin_socket: - sockpath = parsed_args.admin_socket - elif len(childargs) > 0 and childargs[0] in ["daemon", "daemonperf"]: - daemon_perf = (childargs[0] == "daemonperf") - # Treat "daemon " or "daemon " like --admin_daemon - # Handle "daemonperf " the same but requires no trailing args - require_args = 2 if daemon_perf else 3 - if len(childargs) >= require_args: - if childargs[1].find('/') >= 0: - sockpath = childargs[1] - else: - # try resolve daemon name - try: - sockpath = ceph_conf(parsed_args, 'admin_socket', - childargs[1]) - except Exception as e: - print('Can\'t get admin socket path: ' + str(e), file=sys.stderr) - return errno.EINVAL - # for both: - childargs = childargs[2:] - else: - print('{0} requires at least {1} arguments'.format(childargs[0], require_args), - file=sys.stderr) - return errno.EINVAL - - if sockpath and daemon_perf: - interval = 1 - count = None - if len(childargs) > 0: - try: - interval = float(childargs[0]) - if interval < 0: - raise ValueError - except ValueError: - print('daemonperf: interval should be a positive number', file=sys.stderr) - return errno.EINVAL - if len(childargs) > 1: - if not childargs[1].isdigit(): - print('daemonperf: count should be a positive integer', file=sys.stderr) - return errno.EINVAL - count = int(childargs[1]) - DaemonWatcher(sockpath).run(interval, count) - return 0 - elif sockpath: - try: - raw_write(admin_socket(sockpath, childargs, format)) - except Exception as e: - print('admin_socket: {0}'.format(e), file=sys.stderr) - return errno.EINVAL - return 0 + done, ret = maybe_daemon_command(parsed_args, childargs) + if done: + return ret timeout = None if parsed_args.cluster_timeout: diff --git a/src/common/perf_counters.cc b/src/common/perf_counters.cc index c869880a1e242..8602e2b8ab244 100644 --- a/src/common/perf_counters.cc +++ b/src/common/perf_counters.cc @@ -378,11 +378,17 @@ void PerfCounters::dump_formatted_generic(Formatter *f, bool schema, f->dump_string("description", ""); } - if (d->nick != NULL && !suppress_nicks) { + if (d->nick != NULL) { f->dump_string("nick", d->nick); } else { f->dump_string("nick", ""); } + if (d->prio) { + int p = std::max(std::min(d->prio + prio_adjust, + (int)PerfCountersBuilder::PRIO_CRITICAL), + 0); + f->dump_int("priority", p); + } f->close_section(); } else { if (d->type & PERFCOUNTER_LONGRUNAVG) { @@ -453,48 +459,59 @@ PerfCountersBuilder::~PerfCountersBuilder() m_perf_counters = NULL; } -void PerfCountersBuilder::add_u64_counter(int idx, const char *name, - const char *description, const char *nick) +void PerfCountersBuilder::add_u64_counter( + int idx, const char *name, + const char *description, const char *nick, int prio) { - add_impl(idx, name, description, nick, PERFCOUNTER_U64 | PERFCOUNTER_COUNTER); + add_impl(idx, name, description, nick, prio, + PERFCOUNTER_U64 | PERFCOUNTER_COUNTER); } -void PerfCountersBuilder::add_u64(int idx, const char *name, - const char *description, const char *nick) +void PerfCountersBuilder::add_u64( + int idx, const char *name, + const char *description, const char *nick, int prio) { - add_impl(idx, name, description, nick, PERFCOUNTER_U64); + add_impl(idx, name, description, nick, prio, PERFCOUNTER_U64); } -void PerfCountersBuilder::add_u64_avg(int idx, const char *name, - const char *description, const char *nick) +void PerfCountersBuilder::add_u64_avg( + int idx, const char *name, + const char *description, const char *nick, int prio) { - add_impl(idx, name, description, nick, PERFCOUNTER_U64 | PERFCOUNTER_LONGRUNAVG); + add_impl(idx, name, description, nick, prio, + PERFCOUNTER_U64 | PERFCOUNTER_LONGRUNAVG); } -void PerfCountersBuilder::add_time(int idx, const char *name, - const char *description, const char *nick) +void PerfCountersBuilder::add_time( + int idx, const char *name, + const char *description, const char *nick, int prio) { - add_impl(idx, name, description, nick, PERFCOUNTER_TIME); + add_impl(idx, name, description, nick, prio, PERFCOUNTER_TIME); } -void PerfCountersBuilder::add_time_avg(int idx, const char *name, - const char *description, const char *nick) +void PerfCountersBuilder::add_time_avg( + int idx, const char *name, + const char *description, const char *nick, int prio) { - add_impl(idx, name, description, nick, PERFCOUNTER_TIME | PERFCOUNTER_LONGRUNAVG); + add_impl(idx, name, description, nick, prio, + PERFCOUNTER_TIME | PERFCOUNTER_LONGRUNAVG); } -void PerfCountersBuilder::add_histogram(int idx, const char *name, - PerfHistogramCommon::axis_config_d x_axis_config, - PerfHistogramCommon::axis_config_d y_axis_config, - const char *description, const char *nick) +void PerfCountersBuilder::add_histogram( + int idx, const char *name, + PerfHistogramCommon::axis_config_d x_axis_config, + PerfHistogramCommon::axis_config_d y_axis_config, + const char *description, const char *nick, int prio) { - add_impl(idx, name, description, nick, PERFCOUNTER_U64 | PERFCOUNTER_HISTOGRAM, + add_impl(idx, name, description, nick, prio, + PERFCOUNTER_U64 | PERFCOUNTER_HISTOGRAM, unique_ptr>{new PerfHistogram<>{x_axis_config, y_axis_config}}); } -void PerfCountersBuilder::add_impl(int idx, const char *name, - const char *description, const char *nick, int ty, - unique_ptr> histogram) +void PerfCountersBuilder::add_impl( + int idx, const char *name, + const char *description, const char *nick, int prio, int ty, + unique_ptr> histogram) { assert(idx > m_perf_counters->m_lower_bound); assert(idx < m_perf_counters->m_upper_bound); @@ -504,7 +521,12 @@ void PerfCountersBuilder::add_impl(int idx, const char *name, assert(data.type == PERFCOUNTER_NONE); data.name = name; data.description = description; + // nick must be <= 4 chars + if (nick) { + assert(strlen(nick) <= 4); + } data.nick = nick; + data.prio = prio; data.type = (enum perfcounter_type_d)ty; data.histogram = std::move(histogram); } diff --git a/src/common/perf_counters.h b/src/common/perf_counters.h index 11b616c353d30..19c01e3d08b6c 100644 --- a/src/common/perf_counters.h +++ b/src/common/perf_counters.h @@ -102,6 +102,7 @@ class PerfCounters const char *name; const char *description; const char *nick; + int prio = 0; enum perfcounter_type_d type; atomic64_t u64; atomic64_t avgcount; @@ -181,8 +182,9 @@ class PerfCounters m_name = s; } - void set_suppress_nicks(bool b) { - suppress_nicks = b; + /// adjust priority values by some value + void set_prio_adjust(int p) { + prio_adjust = p; } private: @@ -201,7 +203,7 @@ class PerfCounters std::string m_name; const std::string m_lock_name; - bool suppress_nicks = false; + int prio_adjust = 0; /** Protects m_data */ mutable Mutex m_lock; @@ -282,26 +284,47 @@ class PerfCountersBuilder PerfCountersBuilder(CephContext *cct, const std::string &name, int first, int last); ~PerfCountersBuilder(); + + // prio values: higher is better, and higher values get included in + // 'ceph daemonperf' (and similar) results. + enum { + PRIO_CRITICAL = 10, + PRIO_INTERESTING = 8, + PRIO_USEFUL = 5, + PRIO_UNINTERESTING = 2, + PRIO_DEBUGONLY = 0, + }; void add_u64(int key, const char *name, - const char *description=NULL, const char *nick = NULL); + const char *description=NULL, const char *nick = NULL, + int prio=0); void add_u64_counter(int key, const char *name, - const char *description=NULL, const char *nick = NULL); + const char *description=NULL, + const char *nick = NULL, + int prio=0); void add_u64_avg(int key, const char *name, - const char *description=NULL, const char *nick = NULL); + const char *description=NULL, + const char *nick = NULL, + int prio=0); void add_time(int key, const char *name, - const char *description=NULL, const char *nick = NULL); + const char *description=NULL, + const char *nick = NULL, + int prio=0); void add_time_avg(int key, const char *name, - const char *description=NULL, const char *nick = NULL); + const char *description=NULL, + const char *nick = NULL, + int prio=0); void add_histogram(int key, const char* name, - PerfHistogramCommon::axis_config_d x_axis_config, - PerfHistogramCommon::axis_config_d y_axis_config, - const char *description=NULL, const char* nick = NULL); + PerfHistogramCommon::axis_config_d x_axis_config, + PerfHistogramCommon::axis_config_d y_axis_config, + const char *description=NULL, + const char* nick = NULL, + int prio=0); PerfCounters* create_perf_counters(); private: PerfCountersBuilder(const PerfCountersBuilder &rhs); PerfCountersBuilder& operator=(const PerfCountersBuilder &rhs); void add_impl(int idx, const char *name, - const char *description, const char *nick, int ty, + const char *description, const char *nick, int prio, int ty, unique_ptr> histogram = nullptr); PerfCounters *m_perf_counters; diff --git a/src/mds/MDSRank.cc b/src/mds/MDSRank.cc index 10fc2baa6172f..ba3b6c70fff37 100644 --- a/src/mds/MDSRank.cc +++ b/src/mds/MDSRank.cc @@ -2429,43 +2429,60 @@ void MDSRank::create_logger() { PerfCountersBuilder mds_plb(g_ceph_context, "mds", l_mds_first, l_mds_last); - mds_plb.add_u64_counter(l_mds_request, "request", "Requests"); + mds_plb.add_u64_counter( + l_mds_request, "request", "Requests", "req", + PerfCountersBuilder::PRIO_CRITICAL); mds_plb.add_u64_counter(l_mds_reply, "reply", "Replies"); - mds_plb.add_time_avg(l_mds_reply_latency, "reply_latency", - "Reply latency", "rlat"); - mds_plb.add_u64_counter(l_mds_forward, "forward", "Forwarding request"); - + mds_plb.add_time_avg( + l_mds_reply_latency, "reply_latency", "Reply latency", "rlat", + PerfCountersBuilder::PRIO_CRITICAL); + mds_plb.add_u64_counter( + l_mds_forward, "forward", "Forwarding request", "fwd", + PerfCountersBuilder::PRIO_INTERESTING); mds_plb.add_u64_counter(l_mds_dir_fetch, "dir_fetch", "Directory fetch"); mds_plb.add_u64_counter(l_mds_dir_commit, "dir_commit", "Directory commit"); mds_plb.add_u64_counter(l_mds_dir_split, "dir_split", "Directory split"); mds_plb.add_u64_counter(l_mds_dir_merge, "dir_merge", "Directory merge"); mds_plb.add_u64(l_mds_inode_max, "inode_max", "Max inodes, cache size"); - mds_plb.add_u64(l_mds_inodes, "inodes", "Inodes", "inos"); + mds_plb.add_u64(l_mds_inodes, "inodes", "Inodes", "inos", + PerfCountersBuilder::PRIO_CRITICAL); mds_plb.add_u64(l_mds_inodes_top, "inodes_top", "Inodes on top"); mds_plb.add_u64(l_mds_inodes_bottom, "inodes_bottom", "Inodes on bottom"); - mds_plb.add_u64(l_mds_inodes_pin_tail, "inodes_pin_tail", "Inodes on pin tail"); + mds_plb.add_u64( + l_mds_inodes_pin_tail, "inodes_pin_tail", "Inodes on pin tail"); mds_plb.add_u64(l_mds_inodes_pinned, "inodes_pinned", "Inodes pinned"); mds_plb.add_u64(l_mds_inodes_expired, "inodes_expired", "Inodes expired"); - mds_plb.add_u64(l_mds_inodes_with_caps, "inodes_with_caps", "Inodes with capabilities"); - mds_plb.add_u64(l_mds_caps, "caps", "Capabilities", "caps"); + mds_plb.add_u64( + l_mds_inodes_with_caps, "inodes_with_caps", "Inodes with capabilities"); + mds_plb.add_u64(l_mds_caps, "caps", "Capabilities", "caps", + PerfCountersBuilder::PRIO_INTERESTING); mds_plb.add_u64(l_mds_subtrees, "subtrees", "Subtrees"); mds_plb.add_u64_counter(l_mds_traverse, "traverse", "Traverses"); mds_plb.add_u64_counter(l_mds_traverse_hit, "traverse_hit", "Traverse hits"); - mds_plb.add_u64_counter(l_mds_traverse_forward, "traverse_forward", "Traverse forwards"); - mds_plb.add_u64_counter(l_mds_traverse_discover, "traverse_discover", "Traverse directory discovers"); - mds_plb.add_u64_counter(l_mds_traverse_dir_fetch, "traverse_dir_fetch", "Traverse incomplete directory content fetchings"); - mds_plb.add_u64_counter(l_mds_traverse_remote_ino, "traverse_remote_ino", "Traverse remote dentries"); - mds_plb.add_u64_counter(l_mds_traverse_lock, "traverse_lock", "Traverse locks"); + mds_plb.add_u64_counter(l_mds_traverse_forward, "traverse_forward", + "Traverse forwards"); + mds_plb.add_u64_counter(l_mds_traverse_discover, "traverse_discover", + "Traverse directory discovers"); + mds_plb.add_u64_counter(l_mds_traverse_dir_fetch, "traverse_dir_fetch", + "Traverse incomplete directory content fetchings"); + mds_plb.add_u64_counter(l_mds_traverse_remote_ino, "traverse_remote_ino", + "Traverse remote dentries"); + mds_plb.add_u64_counter(l_mds_traverse_lock, "traverse_lock", + "Traverse locks"); mds_plb.add_u64(l_mds_load_cent, "load_cent", "Load per cent"); mds_plb.add_u64(l_mds_dispatch_queue_len, "q", "Dispatch queue length"); mds_plb.add_u64_counter(l_mds_exported, "exported", "Exports"); - mds_plb.add_u64_counter(l_mds_exported_inodes, "exported_inodes", "Exported inodes"); + mds_plb.add_u64_counter( + l_mds_exported_inodes, "exported_inodes", "Exported inodes", "exi", + PerfCountersBuilder::PRIO_INTERESTING); mds_plb.add_u64_counter(l_mds_imported, "imported", "Imports"); - mds_plb.add_u64_counter(l_mds_imported_inodes, "imported_inodes", "Imported inodes"); + mds_plb.add_u64_counter( + l_mds_imported_inodes, "imported_inodes", "Imported inodes", "imi", + PerfCountersBuilder::PRIO_INTERESTING); logger = mds_plb.create_perf_counters(); g_ceph_context->get_perfcounters_collection()->add(logger); } diff --git a/src/os/bluestore/BlueFS.cc b/src/os/bluestore/BlueFS.cc index 4cc34f7f036ba..c5d65dfa66f88 100644 --- a/src/os/bluestore/BlueFS.cc +++ b/src/os/bluestore/BlueFS.cc @@ -60,31 +60,42 @@ void BlueFS::_init_logger() b.add_u64_counter(l_bluefs_reclaim_bytes, "reclaim_bytes", "Bytes reclaimed by BlueStore"); b.add_u64(l_bluefs_db_total_bytes, "db_total_bytes", - "Total bytes (main db device)"); + "Total bytes (main db device)", + "b", PerfCountersBuilder::PRIO_USEFUL); b.add_u64(l_bluefs_db_used_bytes, "db_used_bytes", - "Used bytes (main db device)"); + "Used bytes (main db device)", + "u", PerfCountersBuilder::PRIO_USEFUL); b.add_u64(l_bluefs_wal_total_bytes, "wal_total_bytes", - "Total bytes (wal device)"); + "Total bytes (wal device)", + "walb", PerfCountersBuilder::PRIO_USEFUL); b.add_u64(l_bluefs_wal_used_bytes, "wal_used_bytes", - "Used bytes (wal device)"); + "Used bytes (wal device)", + "walu", PerfCountersBuilder::PRIO_USEFUL); b.add_u64(l_bluefs_slow_total_bytes, "slow_total_bytes", - "Total bytes (slow device)"); + "Total bytes (slow device)", + "slob", PerfCountersBuilder::PRIO_USEFUL); b.add_u64(l_bluefs_slow_used_bytes, "slow_used_bytes", - "Used bytes (slow device)"); - b.add_u64(l_bluefs_num_files, "num_files", "File count"); - b.add_u64(l_bluefs_log_bytes, "log_bytes", "Size of the metadata log"); + "Used bytes (slow device)", + "slou", PerfCountersBuilder::PRIO_USEFUL); + b.add_u64(l_bluefs_num_files, "num_files", "File count", + "f", PerfCountersBuilder::PRIO_USEFUL); + b.add_u64(l_bluefs_log_bytes, "log_bytes", "Size of the metadata log", + "jlen", PerfCountersBuilder::PRIO_INTERESTING); b.add_u64_counter(l_bluefs_log_compactions, "log_compactions", "Compactions of the metadata log"); b.add_u64_counter(l_bluefs_logged_bytes, "logged_bytes", - "Bytes written to the metadata log", "j"); + "Bytes written to the metadata log", "j", + PerfCountersBuilder::PRIO_CRITICAL); b.add_u64_counter(l_bluefs_files_written_wal, "files_written_wal", "Files written to WAL"); b.add_u64_counter(l_bluefs_files_written_sst, "files_written_sst", "Files written to SSTs"); b.add_u64_counter(l_bluefs_bytes_written_wal, "bytes_written_wal", - "Bytes written to WAL", "wal"); + "Bytes written to WAL", "wal", + PerfCountersBuilder::PRIO_CRITICAL); b.add_u64_counter(l_bluefs_bytes_written_sst, "bytes_written_sst", - "Bytes written to SSTs", "sst"); + "Bytes written to SSTs", "sst", + PerfCountersBuilder::PRIO_CRITICAL); logger = b.create_perf_counters(); cct->get_perfcounters_collection()->add(logger); } diff --git a/src/os/bluestore/BlueStore.cc b/src/os/bluestore/BlueStore.cc index b08a7bcab8ed3..95bbc34e8eb80 100644 --- a/src/os/bluestore/BlueStore.cc +++ b/src/os/bluestore/BlueStore.cc @@ -3421,15 +3421,18 @@ void BlueStore::_init_logger() PerfCountersBuilder b(cct, "bluestore", l_bluestore_first, l_bluestore_last); b.add_time_avg(l_bluestore_kv_flush_lat, "kv_flush_lat", - "Average kv_thread flush latency", "kflat"); + "Average kv_thread flush latency", + "fl_l", PerfCountersBuilder::PRIO_INTERESTING); b.add_time_avg(l_bluestore_kv_commit_lat, "kv_commit_lat", "Average kv_thread commit latency"); b.add_time_avg(l_bluestore_kv_lat, "kv_lat", - "Average kv_thread sync latency", "klat"); + "Average kv_thread sync latency", + "k_l", PerfCountersBuilder::PRIO_INTERESTING); b.add_time_avg(l_bluestore_state_prepare_lat, "state_prepare_lat", "Average prepare state latency"); b.add_time_avg(l_bluestore_state_aio_wait_lat, "state_aio_wait_lat", - "Average aio_wait state latency", "iolat"); + "Average aio_wait state latency", + "io_l", PerfCountersBuilder::PRIO_INTERESTING); b.add_time_avg(l_bluestore_state_io_done_lat, "state_io_done_lat", "Average io_done state latency"); b.add_time_avg(l_bluestore_state_kv_queued_lat, "state_kv_queued_lat", @@ -3449,13 +3452,17 @@ void BlueStore::_init_logger() b.add_time_avg(l_bluestore_state_done_lat, "state_done_lat", "Average done state latency"); b.add_time_avg(l_bluestore_throttle_lat, "throttle_lat", - "Average submit throttle latency", "tlat"); + "Average submit throttle latency", + "th_l", PerfCountersBuilder::PRIO_CRITICAL); b.add_time_avg(l_bluestore_submit_lat, "submit_lat", - "Average submit latency", "slat"); + "Average submit latency", + "s_l", PerfCountersBuilder::PRIO_CRITICAL); b.add_time_avg(l_bluestore_commit_lat, "commit_lat", - "Average commit latency", "clat"); + "Average commit latency", + "c_l", PerfCountersBuilder::PRIO_CRITICAL); b.add_time_avg(l_bluestore_read_lat, "read_lat", - "Average read latency", "rlat"); + "Average read latency", + "r_l", PerfCountersBuilder::PRIO_CRITICAL); b.add_time_avg(l_bluestore_read_onode_meta_lat, "read_onode_meta_lat", "Average read onode metadata latency"); b.add_time_avg(l_bluestore_read_wait_aio_lat, "read_wait_aio_lat", diff --git a/src/osd/OSD.cc b/src/osd/OSD.cc index b196f1fba9e0c..90110e3029965 100644 --- a/src/osd/OSD.cc +++ b/src/osd/OSD.cc @@ -514,8 +514,8 @@ void OSDService::init() objecter_finisher.start(); objecter->set_client_incarnation(0); - // exclude objecter from daemonperf output - objecter->get_logger()->set_suppress_nicks(true); + // deprioritize objecter in daemonperf output + objecter->get_logger()->set_prio_adjust(-3); watch_timer.init(); agent_timer.init(); @@ -2741,145 +2741,225 @@ void OSD::create_logger() }; - osd_plb.add_u64(l_osd_op_wip, "op_wip", - "Replication operations currently being processed (primary)"); // rep ops currently being processed (primary) - osd_plb.add_u64_counter(l_osd_op, "op", - "Client operations", "ops"); // client ops - osd_plb.add_u64_counter(l_osd_op_inb, "op_in_bytes", - "Client operations total write size", "wr"); // client op in bytes (writes) - osd_plb.add_u64_counter(l_osd_op_outb, "op_out_bytes", - "Client operations total read size", "rd"); // client op out bytes (reads) - osd_plb.add_time_avg(l_osd_op_lat, "op_latency", - "Latency of client operations (including queue time)", "lat"); // client op latency - osd_plb.add_time_avg(l_osd_op_process_lat, "op_process_latency", - "Latency of client operations (excluding queue time)"); // client op process latency - osd_plb.add_time_avg(l_osd_op_prepare_lat, "op_prepare_latency", - "Latency of client operations (excluding queue time and wait for finished)"); // client op prepare latency - - osd_plb.add_u64_counter(l_osd_op_r, "op_r", - "Client read operations"); // client reads - osd_plb.add_u64_counter(l_osd_op_r_outb, "op_r_out_bytes", - "Client data read"); // client read out bytes - osd_plb.add_time_avg(l_osd_op_r_lat, "op_r_latency", - "Latency of read operation (including queue time)"); // client read latency - osd_plb.add_histogram(l_osd_op_r_lat_outb_hist, "op_r_latency_out_bytes_histogram", - op_hist_x_axis_config, op_hist_y_axis_config, - "Histogram of operation latency (including queue time) + data read"); - osd_plb.add_time_avg(l_osd_op_r_process_lat, "op_r_process_latency", - "Latency of read operation (excluding queue time)"); // client read process latency - osd_plb.add_time_avg(l_osd_op_r_prepare_lat, "op_r_prepare_latency", - "Latency of read operations (excluding queue time and wait for finished)"); // client read prepare latency - osd_plb.add_u64_counter(l_osd_op_w, "op_w", - "Client write operations"); // client writes - osd_plb.add_u64_counter(l_osd_op_w_inb, "op_w_in_bytes", - "Client data written"); // client write in bytes - osd_plb.add_time_avg(l_osd_op_w_lat, "op_w_latency", - "Latency of write operation (including queue time)"); // client write latency - osd_plb.add_histogram(l_osd_op_w_lat_inb_hist, "op_w_latency_in_bytes_histogram", - op_hist_x_axis_config, op_hist_y_axis_config, - "Histogram of operation latency (including queue time) + data written"); - osd_plb.add_time_avg(l_osd_op_w_process_lat, "op_w_process_latency", - "Latency of write operation (excluding queue time)"); // client write process latency - osd_plb.add_time_avg(l_osd_op_w_prepare_lat, "op_w_prepare_latency", - "Latency of write operations (excluding queue time and wait for finished)"); // client write prepare latency - osd_plb.add_u64_counter(l_osd_op_rw, "op_rw", - "Client read-modify-write operations"); // client rmw - osd_plb.add_u64_counter(l_osd_op_rw_inb, "op_rw_in_bytes", - "Client read-modify-write operations write in"); // client rmw in bytes - osd_plb.add_u64_counter(l_osd_op_rw_outb,"op_rw_out_bytes", - "Client read-modify-write operations read out "); // client rmw out bytes - osd_plb.add_time_avg(l_osd_op_rw_lat, "op_rw_latency", - "Latency of read-modify-write operation (including queue time)"); // client rmw latency - osd_plb.add_histogram(l_osd_op_rw_lat_inb_hist, "op_rw_latency_in_bytes_histogram", - op_hist_x_axis_config, op_hist_y_axis_config, - "Histogram of rw operation latency (including queue time) + data written"); - osd_plb.add_histogram(l_osd_op_rw_lat_outb_hist, "op_rw_latency_out_bytes_histogram", - op_hist_x_axis_config, op_hist_y_axis_config, - "Histogram of rw operation latency (including queue time) + data read"); - osd_plb.add_time_avg(l_osd_op_rw_process_lat, "op_rw_process_latency", - "Latency of read-modify-write operation (excluding queue time)"); // client rmw process latency - osd_plb.add_time_avg(l_osd_op_rw_prepare_lat, "op_rw_prepare_latency", - "Latency of read-modify-write operations (excluding queue time and wait for finished)"); // client rmw prepare latency - - osd_plb.add_u64_counter(l_osd_sop, "subop", "Suboperations"); // subops - osd_plb.add_u64_counter(l_osd_sop_inb, "subop_in_bytes", "Suboperations total size"); // subop in bytes - osd_plb.add_time_avg(l_osd_sop_lat, "subop_latency", "Suboperations latency"); // subop latency - - osd_plb.add_u64_counter(l_osd_sop_w, "subop_w", "Replicated writes"); // replicated (client) writes - osd_plb.add_u64_counter(l_osd_sop_w_inb, "subop_w_in_bytes", "Replicated written data size"); // replicated write in bytes - osd_plb.add_time_avg(l_osd_sop_w_lat, "subop_w_latency", "Replicated writes latency"); // replicated write latency - osd_plb.add_u64_counter(l_osd_sop_pull, "subop_pull", "Suboperations pull requests"); // pull request - osd_plb.add_time_avg(l_osd_sop_pull_lat, "subop_pull_latency", "Suboperations pull latency"); - osd_plb.add_u64_counter(l_osd_sop_push, "subop_push", "Suboperations push messages"); // push (write) - osd_plb.add_u64_counter(l_osd_sop_push_inb, "subop_push_in_bytes", "Suboperations pushed size"); - osd_plb.add_time_avg(l_osd_sop_push_lat, "subop_push_latency", "Suboperations push latency"); - - osd_plb.add_u64_counter(l_osd_pull, "pull", "Pull requests sent"); // pull requests sent - osd_plb.add_u64_counter(l_osd_push, "push", "Push messages sent"); // push messages - osd_plb.add_u64_counter(l_osd_push_outb, "push_out_bytes", "Pushed size"); // pushed bytes - - osd_plb.add_u64_counter(l_osd_rop, "recovery_ops", - "Started recovery operations", "recop"); // recovery ops (started) + osd_plb.add_u64( + l_osd_op_wip, "op_wip", + "Replication operations currently being processed (primary)"); + osd_plb.add_u64_counter( + l_osd_op, "op", + "Client operations", + "ops", PerfCountersBuilder::PRIO_CRITICAL); + osd_plb.add_u64_counter( + l_osd_op_inb, "op_in_bytes", + "Client operations total write size", + "wr", PerfCountersBuilder::PRIO_INTERESTING); + osd_plb.add_u64_counter( + l_osd_op_outb, "op_out_bytes", + "Client operations total read size", + "rd", PerfCountersBuilder::PRIO_INTERESTING); + osd_plb.add_time_avg( + l_osd_op_lat, "op_latency", + "Latency of client operations (including queue time)", + "l", 9); + osd_plb.add_time_avg( + l_osd_op_process_lat, "op_process_latency", + "Latency of client operations (excluding queue time)"); + osd_plb.add_time_avg( + l_osd_op_prepare_lat, "op_prepare_latency", + "Latency of client operations (excluding queue time and wait for finished)"); + + osd_plb.add_u64_counter( + l_osd_op_r, "op_r", "Client read operations"); + osd_plb.add_u64_counter( + l_osd_op_r_outb, "op_r_out_bytes", "Client data read"); + osd_plb.add_time_avg( + l_osd_op_r_lat, "op_r_latency", + "Latency of read operation (including queue time)"); + osd_plb.add_histogram( + l_osd_op_r_lat_outb_hist, "op_r_latency_out_bytes_histogram", + op_hist_x_axis_config, op_hist_y_axis_config, + "Histogram of operation latency (including queue time) + data read"); + osd_plb.add_time_avg( + l_osd_op_r_process_lat, "op_r_process_latency", + "Latency of read operation (excluding queue time)"); + osd_plb.add_time_avg( + l_osd_op_r_prepare_lat, "op_r_prepare_latency", + "Latency of read operations (excluding queue time and wait for finished)"); + osd_plb.add_u64_counter( + l_osd_op_w, "op_w", "Client write operations"); + osd_plb.add_u64_counter( + l_osd_op_w_inb, "op_w_in_bytes", "Client data written"); + osd_plb.add_time_avg( + l_osd_op_w_lat, "op_w_latency", + "Latency of write operation (including queue time)"); + osd_plb.add_histogram( + l_osd_op_w_lat_inb_hist, "op_w_latency_in_bytes_histogram", + op_hist_x_axis_config, op_hist_y_axis_config, + "Histogram of operation latency (including queue time) + data written"); + osd_plb.add_time_avg( + l_osd_op_w_process_lat, "op_w_process_latency", + "Latency of write operation (excluding queue time)"); + osd_plb.add_time_avg( + l_osd_op_w_prepare_lat, "op_w_prepare_latency", + "Latency of write operations (excluding queue time and wait for finished)"); + osd_plb.add_u64_counter( + l_osd_op_rw, "op_rw", + "Client read-modify-write operations"); + osd_plb.add_u64_counter( + l_osd_op_rw_inb, "op_rw_in_bytes", + "Client read-modify-write operations write in"); + osd_plb.add_u64_counter( + l_osd_op_rw_outb,"op_rw_out_bytes", + "Client read-modify-write operations read out "); + osd_plb.add_time_avg( + l_osd_op_rw_lat, "op_rw_latency", + "Latency of read-modify-write operation (including queue time)"); + osd_plb.add_histogram( + l_osd_op_rw_lat_inb_hist, "op_rw_latency_in_bytes_histogram", + op_hist_x_axis_config, op_hist_y_axis_config, + "Histogram of rw operation latency (including queue time) + data written"); + osd_plb.add_histogram( + l_osd_op_rw_lat_outb_hist, "op_rw_latency_out_bytes_histogram", + op_hist_x_axis_config, op_hist_y_axis_config, + "Histogram of rw operation latency (including queue time) + data read"); + osd_plb.add_time_avg( + l_osd_op_rw_process_lat, "op_rw_process_latency", + "Latency of read-modify-write operation (excluding queue time)"); + osd_plb.add_time_avg( + l_osd_op_rw_prepare_lat, "op_rw_prepare_latency", + "Latency of read-modify-write operations (excluding queue time and wait for finished)"); + + osd_plb.add_u64_counter( + l_osd_sop, "subop", "Suboperations"); + osd_plb.add_u64_counter( + l_osd_sop_inb, "subop_in_bytes", "Suboperations total size"); + osd_plb.add_time_avg(l_osd_sop_lat, "subop_latency", "Suboperations latency"); + + osd_plb.add_u64_counter(l_osd_sop_w, "subop_w", "Replicated writes"); + osd_plb.add_u64_counter( + l_osd_sop_w_inb, "subop_w_in_bytes", "Replicated written data size"); + osd_plb.add_time_avg( + l_osd_sop_w_lat, "subop_w_latency", "Replicated writes latency"); + osd_plb.add_u64_counter( + l_osd_sop_pull, "subop_pull", "Suboperations pull requests"); + osd_plb.add_time_avg( + l_osd_sop_pull_lat, "subop_pull_latency", "Suboperations pull latency"); + osd_plb.add_u64_counter( + l_osd_sop_push, "subop_push", "Suboperations push messages"); + osd_plb.add_u64_counter( + l_osd_sop_push_inb, "subop_push_in_bytes", "Suboperations pushed size"); + osd_plb.add_time_avg( + l_osd_sop_push_lat, "subop_push_latency", "Suboperations push latency"); + + osd_plb.add_u64_counter(l_osd_pull, "pull", "Pull requests sent"); + osd_plb.add_u64_counter(l_osd_push, "push", "Push messages sent"); + osd_plb.add_u64_counter(l_osd_push_outb, "push_out_bytes", "Pushed size"); + + osd_plb.add_u64_counter( + l_osd_rop, "recovery_ops", + "Started recovery operations", + "rop", PerfCountersBuilder::PRIO_INTERESTING); osd_plb.add_u64(l_osd_loadavg, "loadavg", "CPU load"); - osd_plb.add_u64(l_osd_buf, "buffer_bytes", "Total allocated buffer size"); // total ceph::buffer bytes - osd_plb.add_u64(l_osd_history_alloc_bytes, "history_alloc_Mbytes"); // total ceph::buffer bytes in history - osd_plb.add_u64(l_osd_history_alloc_num, "history_alloc_num"); // total ceph::buffer num in history - osd_plb.add_u64(l_osd_cached_crc, "cached_crc", "Total number getting crc from crc_cache"); // total ceph::buffer buffer_cached_crc - osd_plb.add_u64(l_osd_cached_crc_adjusted, "cached_crc_adjusted", "Total number getting crc from crc_cache with adjusting"); // total ceph::buffer buffer_cached_crc_adjusted - - osd_plb.add_u64(l_osd_pg, "numpg", "Placement groups"); // num pgs - osd_plb.add_u64(l_osd_pg_primary, "numpg_primary", "Placement groups for which this osd is primary"); // num primary pgs - osd_plb.add_u64(l_osd_pg_replica, "numpg_replica", "Placement groups for which this osd is replica"); // num replica pgs - osd_plb.add_u64(l_osd_pg_stray, "numpg_stray", "Placement groups ready to be deleted from this osd"); // num stray pgs - osd_plb.add_u64(l_osd_hb_to, "heartbeat_to_peers", "Heartbeat (ping) peers we send to"); // heartbeat peers we send to - osd_plb.add_u64_counter(l_osd_map, "map_messages", "OSD map messages"); // osdmap messages - osd_plb.add_u64_counter(l_osd_mape, "map_message_epochs", "OSD map epochs"); // osdmap epochs - osd_plb.add_u64_counter(l_osd_mape_dup, "map_message_epoch_dups", "OSD map duplicates"); // dup osdmap epochs - osd_plb.add_u64_counter(l_osd_waiting_for_map, "messages_delayed_for_map", "Operations waiting for OSD map"); // dup osdmap epochs - osd_plb.add_u64_counter(l_osd_map_cache_hit, "osd_map_cache_hit", "osdmap cache hit"); - osd_plb.add_u64_counter(l_osd_map_cache_miss, "osd_map_cache_miss", "osdmap cache miss"); - osd_plb.add_u64_counter(l_osd_map_cache_miss_low, "osd_map_cache_miss_low", "osdmap cache miss below cache lower bound"); - osd_plb.add_u64_avg(l_osd_map_cache_miss_low_avg, "osd_map_cache_miss_low_avg", "osdmap cache miss, avg distance below cache lower bound"); + osd_plb.add_u64(l_osd_buf, "buffer_bytes", "Total allocated buffer size"); + osd_plb.add_u64(l_osd_history_alloc_bytes, "history_alloc_Mbytes"); + osd_plb.add_u64(l_osd_history_alloc_num, "history_alloc_num"); + osd_plb.add_u64( + l_osd_cached_crc, "cached_crc", "Total number getting crc from crc_cache"); + osd_plb.add_u64( + l_osd_cached_crc_adjusted, "cached_crc_adjusted", + "Total number getting crc from crc_cache with adjusting"); + + osd_plb.add_u64(l_osd_pg, "numpg", "Placement groups", + "pgs", PerfCountersBuilder::PRIO_USEFUL); + osd_plb.add_u64( + l_osd_pg_primary, "numpg_primary", + "Placement groups for which this osd is primary"); + osd_plb.add_u64( + l_osd_pg_replica, "numpg_replica", + "Placement groups for which this osd is replica"); + osd_plb.add_u64( + l_osd_pg_stray, "numpg_stray", + "Placement groups ready to be deleted from this osd"); + osd_plb.add_u64( + l_osd_hb_to, "heartbeat_to_peers", "Heartbeat (ping) peers we send to"); + osd_plb.add_u64_counter(l_osd_map, "map_messages", "OSD map messages"); + osd_plb.add_u64_counter(l_osd_mape, "map_message_epochs", "OSD map epochs"); + osd_plb.add_u64_counter( + l_osd_mape_dup, "map_message_epoch_dups", "OSD map duplicates"); + osd_plb.add_u64_counter( + l_osd_waiting_for_map, "messages_delayed_for_map", + "Operations waiting for OSD map"); + osd_plb.add_u64_counter( + l_osd_map_cache_hit, "osd_map_cache_hit", "osdmap cache hit"); + osd_plb.add_u64_counter( + l_osd_map_cache_miss, "osd_map_cache_miss", "osdmap cache miss"); + osd_plb.add_u64_counter( + l_osd_map_cache_miss_low, "osd_map_cache_miss_low", + "osdmap cache miss below cache lower bound"); + osd_plb.add_u64_avg( + l_osd_map_cache_miss_low_avg, "osd_map_cache_miss_low_avg", + "osdmap cache miss, avg distance below cache lower bound"); osd_plb.add_u64(l_osd_stat_bytes, "stat_bytes", "OSD size"); osd_plb.add_u64(l_osd_stat_bytes_used, "stat_bytes_used", "Used space"); osd_plb.add_u64(l_osd_stat_bytes_avail, "stat_bytes_avail", "Available space"); - osd_plb.add_u64_counter(l_osd_copyfrom, "copyfrom", "Rados \"copy-from\" operations"); + osd_plb.add_u64_counter( + l_osd_copyfrom, "copyfrom", "Rados \"copy-from\" operations"); osd_plb.add_u64_counter(l_osd_tier_promote, "tier_promote", "Tier promotions"); osd_plb.add_u64_counter(l_osd_tier_flush, "tier_flush", "Tier flushes"); - osd_plb.add_u64_counter(l_osd_tier_flush_fail, "tier_flush_fail", "Failed tier flushes"); - osd_plb.add_u64_counter(l_osd_tier_try_flush, "tier_try_flush", "Tier flush attempts"); - osd_plb.add_u64_counter(l_osd_tier_try_flush_fail, "tier_try_flush_fail", "Failed tier flush attempts"); - osd_plb.add_u64_counter(l_osd_tier_evict, "tier_evict", "Tier evictions"); - osd_plb.add_u64_counter(l_osd_tier_whiteout, "tier_whiteout", "Tier whiteouts"); - osd_plb.add_u64_counter(l_osd_tier_dirty, "tier_dirty", "Dirty tier flag set"); - osd_plb.add_u64_counter(l_osd_tier_clean, "tier_clean", "Dirty tier flag cleaned"); - osd_plb.add_u64_counter(l_osd_tier_delay, "tier_delay", "Tier delays (agent waiting)"); - osd_plb.add_u64_counter(l_osd_tier_proxy_read, "tier_proxy_read", "Tier proxy reads"); - osd_plb.add_u64_counter(l_osd_tier_proxy_write, "tier_proxy_write", "Tier proxy writes"); - - osd_plb.add_u64_counter(l_osd_agent_wake, "agent_wake", "Tiering agent wake up"); - osd_plb.add_u64_counter(l_osd_agent_skip, "agent_skip", "Objects skipped by agent"); - osd_plb.add_u64_counter(l_osd_agent_flush, "agent_flush", "Tiering agent flushes"); - osd_plb.add_u64_counter(l_osd_agent_evict, "agent_evict", "Tiering agent evictions"); - - osd_plb.add_u64_counter(l_osd_object_ctx_cache_hit, "object_ctx_cache_hit", "Object context cache hits"); - osd_plb.add_u64_counter(l_osd_object_ctx_cache_total, "object_ctx_cache_total", "Object context cache lookups"); + osd_plb.add_u64_counter( + l_osd_tier_flush_fail, "tier_flush_fail", "Failed tier flushes"); + osd_plb.add_u64_counter( + l_osd_tier_try_flush, "tier_try_flush", "Tier flush attempts"); + osd_plb.add_u64_counter( + l_osd_tier_try_flush_fail, "tier_try_flush_fail", + "Failed tier flush attempts"); + osd_plb.add_u64_counter( + l_osd_tier_evict, "tier_evict", "Tier evictions"); + osd_plb.add_u64_counter( + l_osd_tier_whiteout, "tier_whiteout", "Tier whiteouts"); + osd_plb.add_u64_counter( + l_osd_tier_dirty, "tier_dirty", "Dirty tier flag set"); + osd_plb.add_u64_counter( + l_osd_tier_clean, "tier_clean", "Dirty tier flag cleaned"); + osd_plb.add_u64_counter( + l_osd_tier_delay, "tier_delay", "Tier delays (agent waiting)"); + osd_plb.add_u64_counter( + l_osd_tier_proxy_read, "tier_proxy_read", "Tier proxy reads"); + osd_plb.add_u64_counter( + l_osd_tier_proxy_write, "tier_proxy_write", "Tier proxy writes"); + + osd_plb.add_u64_counter( + l_osd_agent_wake, "agent_wake", "Tiering agent wake up"); + osd_plb.add_u64_counter( + l_osd_agent_skip, "agent_skip", "Objects skipped by agent"); + osd_plb.add_u64_counter( + l_osd_agent_flush, "agent_flush", "Tiering agent flushes"); + osd_plb.add_u64_counter( + l_osd_agent_evict, "agent_evict", "Tiering agent evictions"); + + osd_plb.add_u64_counter( + l_osd_object_ctx_cache_hit, "object_ctx_cache_hit", "Object context cache hits"); + osd_plb.add_u64_counter( + l_osd_object_ctx_cache_total, "object_ctx_cache_total", "Object context cache lookups"); osd_plb.add_u64_counter(l_osd_op_cache_hit, "op_cache_hit"); - osd_plb.add_time_avg(l_osd_tier_flush_lat, "osd_tier_flush_lat", "Object flush latency"); - osd_plb.add_time_avg(l_osd_tier_promote_lat, "osd_tier_promote_lat", "Object promote latency"); - osd_plb.add_time_avg(l_osd_tier_r_lat, "osd_tier_r_lat", "Object proxy read latency"); - - osd_plb.add_u64_counter(l_osd_pg_info, "osd_pg_info", - "PG updated its info (using any method)"); - osd_plb.add_u64_counter(l_osd_pg_fastinfo, "osd_pg_fastinfo", - "PG updated its info using fastinfo attr"); - osd_plb.add_u64_counter(l_osd_pg_biginfo, "osd_pg_biginfo", - "PG updated its biginfo attr"); + osd_plb.add_time_avg( + l_osd_tier_flush_lat, "osd_tier_flush_lat", "Object flush latency"); + osd_plb.add_time_avg( + l_osd_tier_promote_lat, "osd_tier_promote_lat", "Object promote latency"); + osd_plb.add_time_avg( + l_osd_tier_r_lat, "osd_tier_r_lat", "Object proxy read latency"); + + osd_plb.add_u64_counter( + l_osd_pg_info, "osd_pg_info", "PG updated its info (using any method)"); + osd_plb.add_u64_counter( + l_osd_pg_fastinfo, "osd_pg_fastinfo", + "PG updated its info using fastinfo attr"); + osd_plb.add_u64_counter( + l_osd_pg_biginfo, "osd_pg_biginfo", "PG updated its biginfo attr"); logger = osd_plb.create_perf_counters(); cct->get_perfcounters_collection()->add(logger); diff --git a/src/osdc/Objecter.cc b/src/osdc/Objecter.cc index 0d8138d890921..134fd78308009 100644 --- a/src/osdc/Objecter.cc +++ b/src/osdc/Objecter.cc @@ -242,8 +242,8 @@ void Objecter::init() if (!logger) { PerfCountersBuilder pcb(cct, "objecter", l_osdc_first, l_osdc_last); - pcb.add_u64(l_osdc_op_active, "op_active", - "Operations active", "actv"); + pcb.add_u64(l_osdc_op_active, "op_active", "Operations active", "actv", + PerfCountersBuilder::PRIO_CRITICAL); pcb.add_u64(l_osdc_op_laggy, "op_laggy", "Laggy operations"); pcb.add_u64_counter(l_osdc_op_send, "op_send", "Sent operations"); pcb.add_u64_counter(l_osdc_op_send_bytes, "op_send_bytes", "Sent data"); @@ -251,12 +251,12 @@ void Objecter::init() pcb.add_u64_counter(l_osdc_op_reply, "op_reply", "Operation reply"); pcb.add_u64_counter(l_osdc_op, "op", "Operations"); - pcb.add_u64_counter(l_osdc_op_r, "op_r", - "Read operations", "read"); - pcb.add_u64_counter(l_osdc_op_w, "op_w", - "Write operations", "writ"); - pcb.add_u64_counter(l_osdc_op_rmw, "op_rmw", - "Read-modify-write operations"); + pcb.add_u64_counter(l_osdc_op_r, "op_r", "Read operations", "rd", + PerfCountersBuilder::PRIO_CRITICAL); + pcb.add_u64_counter(l_osdc_op_w, "op_w", "Write operations", "wr", + PerfCountersBuilder::PRIO_CRITICAL); + pcb.add_u64_counter(l_osdc_op_rmw, "op_rmw", "Read-modify-write operations", + "rdwr", PerfCountersBuilder::PRIO_INTERESTING); pcb.add_u64_counter(l_osdc_op_pg, "op_pg", "PG operation"); pcb.add_u64_counter(l_osdc_osdop_stat, "osdop_stat", "Stat operations"); diff --git a/src/pybind/ceph_daemon.py b/src/pybind/ceph_daemon.py index c3293d66f579b..48bd4e0d7cef6 100755 --- a/src/pybind/ceph_daemon.py +++ b/src/pybind/ceph_daemon.py @@ -15,7 +15,12 @@ import socket import struct import time -from collections import defaultdict, OrderedDict +from collections import OrderedDict +from fcntl import ioctl +from fnmatch import fnmatch +from prettytable import PrettyTable, HEADER +from signal import signal, SIGWINCH +from termios import TIOCGWINSZ from ceph_argparse import parse_json_funcsigs, validate_command @@ -82,6 +87,38 @@ def do_sockio(path, cmd_bytes): return ret +def _gettermsize(): + try: + rows, cols = struct.unpack('hhhh', ioctl(0, TIOCGWINSZ, 8*'\x00'))[0:2] + except IOError: + return 25, 80 + + return rows,cols + + +class Termsize(object): + + def __init__(self): + self.rows, self.cols = _gettermsize() + self.changed = False + + def update(self): + rows, cols = _gettermsize() + self.changed = self.changed or ( + (self.rows != rows) or (self.cols != cols) + ) + self.rows, self.cols = rows, cols + + def reset_changed(self): + self.changed = False + + def __str__(self): + return '%s(%dx%d, changed %s)' % (self.__class__, self.rows, self.cols, self.changed) + + def __repr__(self): + return 'Termsize(%d,%d,%s)' % (self.__class__, self.rows, self.cols, self.changed) + + class DaemonWatcher(object): """ Given a Ceph daemon's admin socket path, poll its performance counters @@ -105,12 +142,16 @@ class DaemonWatcher(object): BOLD_SEQ = "\033[1m" UNDERLINE_SEQ = "\033[4m" - def __init__(self, asok): + def __init__(self, asok, statpats=None, min_prio=0): self.asok_path = asok self._colored = False self._stats = None self._schema = None + self._statpats = statpats + self._stats_that_fit = dict() + self._min_prio = min_prio + self.termsize = Termsize() def supports_color(self, ostr): """ @@ -173,13 +214,40 @@ def col_width(self, nick): """ return max(len(nick), 4) + def get_stats_that_fit(self): + ''' + Get a possibly-truncated list of stats to display based on + current terminal width. Allow breaking mid-section. + ''' + current_fit = OrderedDict() + if self.termsize.changed or not self._stats_that_fit: + width = 0 + for section_name, names in self._stats.items(): + for name, stat_data in names.items(): + width += self.col_width(stat_data) + 1 + if width > self.termsize.cols: + break + if section_name not in current_fit: + current_fit[section_name] = OrderedDict() + current_fit[section_name][name] = stat_data + if width > self.termsize.cols: + break + + self.termsize.reset_changed() + changed = current_fit and (current_fit != self._stats_that_fit) + if changed: + self._stats_that_fit = current_fit + return self._stats_that_fit, changed + def _print_headers(self, ostr): """ Print a header row to `ostr` """ header = "" - for section_name, names in self._stats.items(): - section_width = sum([self.col_width(x)+1 for x in names.values()]) - 1 + stats, _ = self.get_stats_that_fit() + for section_name, names in stats.items(): + section_width = \ + sum([self.col_width(x) + 1 for x in names.values()]) - 1 pad = max(section_width - len(section_name), 0) pad_prefix = pad // 2 header += (pad_prefix * '-') @@ -190,7 +258,7 @@ def _print_headers(self, ostr): ostr.write(self.colorize(header, self.BLUE, True)) sub_header = "" - for section_name, names in self._stats.items(): + for section_name, names in stats.items(): for stat_name, stat_nick in names.items(): sub_header += self.UNDERLINE_SEQ \ + self.colorize( @@ -207,7 +275,10 @@ def _print_vals(self, ostr, dump, last_dump): `last_dump`. """ val_row = "" - for section_name, names in self._stats.items(): + fit, changed = self.get_stats_that_fit() + if changed: + self._print_headers(ostr) + for section_name, names in fit.items(): for stat_name, stat_nick in names.items(): stat_type = self._schema[section_name][stat_name]['type'] if bool(stat_type & COUNTER): @@ -233,6 +304,29 @@ def _print_vals(self, ostr, dump, last_dump): val_row = val_row[0:-len(self.colorize("|", self.BLUE))] ostr.write("{0}\n".format(val_row)) + def _should_include(self, sect, name, prio): + ''' + boolean: should we output this stat? + + 1) If self._statpats exists and the name filename-glob-matches + anything in the list, and prio is high enough, or + 2) If self._statpats doesn't exist and prio is high enough + + then yes. + ''' + if self._statpats: + sectname = '.'.join((sect, name)) + if not any([ + p for p in self._statpats + if fnmatch(name, p) or fnmatch(sectname, p) + ]): + return False + + if self._min_prio is not None and prio is not None: + return (prio >= self._min_prio) + + return True + def _load_schema(self): """ Populate our instance-local copy of the daemon's performance counter @@ -242,15 +336,20 @@ def _load_schema(self): admin_socket(self.asok_path, ["perf", "schema"]).decode('utf-8'), object_pairs_hook=OrderedDict) - # Build list of which stats we will display, based on which - # stats have a nickname + # Build list of which stats we will display self._stats = OrderedDict() for section_name, section_stats in self._schema.items(): for name, schema_data in section_stats.items(): - if schema_data.get('nick'): + prio = schema_data.get('priority', 0) + if self._should_include(section_name, name, prio): if section_name not in self._stats: self._stats[section_name] = OrderedDict() self._stats[section_name][name] = schema_data['nick'] + if not len(self._stats): + raise RuntimeError("no stats selected by filters") + + def _handle_sigwinch(self, signo, frame): + self.termsize.update() def run(self, interval, count=None, ostr=sys.stdout): """ @@ -266,12 +365,12 @@ def run(self, interval, count=None, ostr=sys.stdout): last_dump = json.loads(admin_socket(self.asok_path, ["perf", "dump"]).decode('utf-8')) rows_since_header = 0 - term_height = 25 try: + signal(SIGWINCH, self._handle_sigwinch) while True: dump = json.loads(admin_socket(self.asok_path, ["perf", "dump"]).decode('utf-8')) - if rows_since_header > term_height - 2: + if rows_since_header >= self.termsize.rows - 2: self._print_headers(ostr) rows_since_header = 0 self._print_vals(ostr, dump, last_dump) @@ -281,6 +380,27 @@ def run(self, interval, count=None, ostr=sys.stdout): break rows_since_header += 1 last_dump = dump - time.sleep(interval) + + # time.sleep() is interrupted by SIGWINCH; avoid that + end = time.time() + interval + while time.time() < end: + time.sleep(end - time.time()) + except KeyboardInterrupt: return + + def list(self, ostr=sys.stdout): + """ + Show all selected stats with section, full name, nick, and prio + """ + table = PrettyTable(('section', 'name', 'nick', 'prio')) + table.align['section'] = 'l' + table.align['name'] = 'l' + table.align['nick'] = 'l' + table.align['prio'] = 'r' + self._load_schema() + for section_name, section_stats in self._stats.items(): + for name, nick in section_stats.items(): + prio = self._schema[section_name][name].get('priority') or 0 + table.add_row((section_name, name, nick, prio)) + ostr.write(table.get_string(hrules=HEADER) + '\n')