From b297e72d5271e3bb2abd58796660cdeb4cc3d0db Mon Sep 17 00:00:00 2001 From: Dan Mick Date: Fri, 21 Apr 2017 11:15:34 -0700 Subject: [PATCH] ceph.in, pybind/ceph_daemon.py: add priority filtering Signed-off-by: Dan Mick --- src/ceph.in | 77 +++++++++++++++++++++++++++++++-------- src/pybind/ceph_daemon.py | 14 ++++--- 2 files changed, 71 insertions(+), 20 deletions(-) diff --git a/src/ceph.in b/src/ceph.in index 4b6684989122..62a8562aed81 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,11 +275,13 @@ 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} [stat-pats] [] [] +daemonperf {type.id | path} [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 Run times (default forever), - once per seconds (default 1) + once per seconds (default 1) """, file=sys.stdout) @@ -613,38 +624,74 @@ def maybe_daemon_command(parsed_args, childargs): return False, 0 -def isnum(object): +def isnum(s): try: - float(object) + float(s) return True except ValueError: return False def daemonperf(childargs, sockpath): - """ Handle daemonperf command; returns errno or 0 """ + """ + Handle daemonperf command; returns errno or 0 + + daemonperf [priority string] [statpats] [interval] [count] + """ + interval = 1 count = None statpats = None - - if len(childargs) > 0: - # optional leading comma-separated list arg - if not isnum(childargs[0]): - statpats = childargs.pop(0).split(',') + priority = None + + 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) + # prio? + priority = prio_from_name(arg) + if priority is not None: + continue; + # statpats + statpats = arg.split(',') + + if priority is None: + priority = PRIO_DEFAULT if len(childargs) > 0: try: - interval = float(childargs[0]) + 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) > 1: - if not childargs[1].isdigit(): + + 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(childargs[1]) - DaemonWatcher(sockpath, statpats).run(interval, count) + count = int(arg) + + DaemonWatcher(sockpath, statpats, priority).run(interval, count) + return 0 ### diff --git a/src/pybind/ceph_daemon.py b/src/pybind/ceph_daemon.py index 605872b1bc21..827f7abf22a2 100755 --- a/src/pybind/ceph_daemon.py +++ b/src/pybind/ceph_daemon.py @@ -15,7 +15,7 @@ import json import socket import struct import time -from collections import defaultdict, OrderedDict +from collections import OrderedDict from fcntl import ioctl from fnmatch import fnmatch from signal import signal, SIGWINCH @@ -135,7 +135,7 @@ class DaemonWatcher(object): BOLD_SEQ = "\033[1m" UNDERLINE_SEQ = "\033[4m" - def __init__(self, asok, statpats=None): + def __init__(self, asok, statpats=None, min_prio=0): self.asok_path = asok self._colored = False @@ -143,6 +143,7 @@ class DaemonWatcher(object): self._schema = None self._statpats = statpats self._stats_that_fit = dict() + self._min_prio = min_prio self.termsize = Termsize() def supports_color(self, ostr): @@ -297,7 +298,6 @@ class DaemonWatcher(object): ostr.write("{0}\n".format(val_row)) def _should_include(self, sect, name, prio): - MIN_PRIO = 5 ''' boolean: should we output this stat? @@ -307,7 +307,6 @@ class DaemonWatcher(object): then yes. ''' - print sect, name, self._statpats, if self._statpats: sectname = '.'.join((sect, name)) if not any([ @@ -316,7 +315,10 @@ class DaemonWatcher(object): ]): return False - return (prio >= MIN_PRIO) + if self._min_prio is not None and prio is not None: + return (prio >= self._min_prio) + + return True def _load_schema(self): """ @@ -336,6 +338,8 @@ class DaemonWatcher(object): 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() -- 2.47.3