<mon.id> may be 'mon.*' for all mons
daemon {type.id|path} <cmd>
Same as --admin-daemon, but auto-find admin socket
-daemonperf {type.id | path} [<interval>] [<count>]
+daemonperf {type.id | path} [stat-pats] [<interval>] [<count>]
Get selected perf stats from daemon/admin socket
+ Optional shell-glob comma-delim match string stat-pats
Run <count> times (default forever),
once per <interval> seconds (default 1)
""", file=sys.stdout)
return False, 0
+def isnum(object):
+ try:
+ float(object)
+ return True
+ except ValueError:
+ return False
+
def daemonperf(childargs, sockpath):
""" Handle daemonperf command; returns errno or 0 """
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(',')
+
if len(childargs) > 0:
try:
interval = float(childargs[0])
print('daemonperf: count should be a positive integer', file=sys.stderr)
return errno.EINVAL
count = int(childargs[1])
- DaemonWatcher(sockpath).run(interval, count)
+ DaemonWatcher(sockpath, statpats).run(interval, count)
return 0
###
import time
from collections import defaultdict, OrderedDict
from fcntl import ioctl
+from fnmatch import fnmatch
from signal import signal, SIGWINCH
from termios import TIOCGWINSZ
BOLD_SEQ = "\033[1m"
UNDERLINE_SEQ = "\033[4m"
- def __init__(self, asok):
+ def __init__(self, asok, statpats=None):
self.asok_path = asok
self._colored = False
self._stats = None
self._schema = None
+ self._statpats = statpats
self._stats_that_fit = dict()
self.termsize = Termsize()
val_row = val_row[0:-len(self.colorize("|", self.BLUE))]
ostr.write("{0}\n".format(val_row))
+ def _should_include(self, sect, name, prio):
+ MIN_PRIO = 5
+ '''
+ 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.
+ '''
+ print sect, name, self._statpats,
+ 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
+
+ return (prio >= MIN_PRIO)
+
def _load_schema(self):
"""
Populate our instance-local copy of the daemon's performance counter
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')
+ 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']