[CalendarServer-changes] [15372] CalendarServer/trunk/calendarserver/tools/dashboard.py
source_changes at macosforge.org
source_changes at macosforge.org
Tue Dec 8 13:44:13 PST 2015
Revision: 15372
http://trac.calendarserver.org//changeset/15372
Author: cdaboo at apple.com
Date: 2015-12-08 13:44:13 -0800 (Tue, 08 Dec 2015)
Log Message:
-----------
Support quick ways to view groups of panels,.
Modified Paths:
--------------
CalendarServer/trunk/calendarserver/tools/dashboard.py
Modified: CalendarServer/trunk/calendarserver/tools/dashboard.py
===================================================================
--- CalendarServer/trunk/calendarserver/tools/dashboard.py 2015-12-05 16:56:31 UTC (rev 15371)
+++ CalendarServer/trunk/calendarserver/tools/dashboard.py 2015-12-08 21:44:13 UTC (rev 15372)
@@ -19,8 +19,7 @@
server as exposed by the L{DashboardProtocol} stats socket.
"""
-from getopt import getopt, GetoptError
-
+import argparse
import curses.panel
import errno
import fcntl
@@ -58,45 +57,26 @@
sys.exit(0)
-BOX_WIDTH = 52
-
def main():
- try:
- (optargs, _ignore_args) = getopt(
- sys.argv[1:], "hs:t", [
- "help",
- ],
- )
- except GetoptError, e:
- usage(e)
+ parser = argparse.ArgumentParser(description="Dashboard service for CalendarServer.")
+ parser.add_argument("-t", action="store_false", help="text output, not curses")
+ parser.add_argument("-s", default="localhost:8100", help="server host (and optional port), or unix socket path prefixed by 'unix:'")
+ args = parser.parse_args()
#
# Get configuration
#
- useCurses = True
- server = ("localhost", 8100)
-
- for opt, arg in optargs:
- if opt in ("-h", "--help"):
- usage()
-
- elif opt in ("-t"):
- useCurses = False
-
- elif opt in ("-s"):
- if not arg.startswith("unix:"):
- server = arg.split(":")
- if len(server) == 1:
- server.append(8100)
- else:
- server[1] = int(server[1])
- server = tuple(server)
- else:
- server = arg
-
+ useCurses = args.t
+ if not args.s.startswith("unix:"):
+ server = args.s.split(":")
+ if len(server) == 1:
+ server.append(8100)
else:
- raise NotImplementedError(opt)
+ server[1] = int(server[1])
+ server = tuple(server)
+ else:
+ server = args.s
if useCurses:
def _wrapped(stdscrn):
@@ -142,6 +122,10 @@
screen = None
registered_windows = {}
+ registered_window_sets = {
+ "H": ("HTTP Panels", [],),
+ "J": ("Jobs Panels", [],),
+ }
registered_order = []
def __init__(self, server, screen, usesCurses):
@@ -166,6 +150,17 @@
cls.registered_order.append(keypress)
+ @classmethod
+ def registerWindowSet(cls, wtype, keypress):
+ """
+ Register a set of window types along with a key press action. This allows the
+ controller to select the appropriate set of windows when its key is pressed,
+ and also provides help information to the L{HelpWindow} for each
+ available window set type.
+ """
+ cls.registered_window_sets[keypress][1].append(wtype)
+
+
def run(self):
"""
Create the initial window and run the L{scheduler}.
@@ -182,7 +177,7 @@
"""
# Toggle a specific window on or off
- if wtype is not None:
+ if isinstance(wtype, type):
if wtype not in [type(w) for w in self.windows]:
self.windows.append(wtype(self.usesCurses, self.client).makeWindow())
self.windows[-1].activate()
@@ -203,7 +198,11 @@
window.deactivate()
self.windows = []
top = 0
- ordered_windows = [self.registered_windows[i] for i in self.registered_order]
+ if wtype is None:
+ # All windows in registered order
+ ordered_windows = [self.registered_windows[i] for i in self.registered_order]
+ else:
+ ordered_windows = list(wtype)
for wtype in filter(lambda x: x.all, ordered_windows):
new_win = wtype(self.usesCurses, self.client).makeWindow(top=top)
logging.debug('created %r at panel level %r' % (new_win, new_win.z_order))
@@ -292,6 +291,8 @@
self.displayWindow(self.registered_windows["h"])
elif c in self.registered_windows:
self.displayWindow(self.registered_windows[c])
+ elif c in self.registered_window_sets:
+ self.displayWindow(self.registered_window_sets[c][1])
if not initialUpdate:
self.sched.enter(self.seconds, 0, self.updateDisplay, ())
@@ -390,6 +391,10 @@
all = True
clientItem = None
+ windowTitle = ""
+ formatWidth = 0
+ additionalRows = 0
+
def __init__(self, usesCurses, client):
self.usesCurses = usesCurses
self.client = client
@@ -399,11 +404,25 @@
def makeWindow(self, top=0, left=0):
+ self.updateRowCount()
+ self._createWindow(
+ self.windowTitle,
+ self.rowCount + self.additionalRows,
+ self.formatWidth,
+ begin_y=top, begin_x=left
+ )
+ return self
+
+
+ def updateRowCount(self):
+ """
+ Update L{self.rowCount} based on the current data
+ """
raise NotImplementedError()
def _createWindow(
- self, title, nlines, ncols=BOX_WIDTH, begin_y=0, begin_x=0
+ self, title, nlines, ncols, begin_y=0, begin_x=0
):
"""
Initialize a curses window based on the sizes required.
@@ -482,7 +501,6 @@
help = "dashboard help"
all = False
helpItems = (
- "",
"a - all windows",
"n - no windows",
" - (space) pause dashboard polling",
@@ -491,19 +509,20 @@
"q - exit the dashboard",
)
+ windowTitle = "Help"
+ formatWidth = 48
+ additionalRows = 3
+
def makeWindow(self, top=0, left=0):
term_w, _ignore_term_h = terminal_size()
- help_x_offset = term_w - BOX_WIDTH + 4
- self._createWindow(
- "Help",
- len(self.helpItems) + len(Dashboard.registered_windows) + 2,
- ncols=BOX_WIDTH - 4,
- begin_y=0,
- begin_x=help_x_offset,
- )
- return self
+ help_x_offset = term_w - self.formatWidth
+ return super(HelpWindow, self).makeWindow(0, help_x_offset)
+ def updateRowCount(self):
+ self.rowCount = len(self.helpItems) + len(filter(lambda x: len(x[1]) != 0, Dashboard.registered_window_sets.values())) + len(Dashboard.registered_windows)
+
+
def requiresUpdate(self):
return False
@@ -526,6 +545,13 @@
Dashboard.registered_windows.items(), key=lambda x: x[0]
):
items.append("{} - {}".format(keypress, wtype.help))
+
+ items.append("")
+ for key, value in Dashboard.registered_window_sets.items():
+ description, panels = value
+ if panels:
+ items.append("{} - {}".format(key, description))
+
items.extend(self.helpItems)
for item in items:
if self.usesCurses:
@@ -549,15 +575,15 @@
help = "server jobs"
clientItem = "jobs"
- FORMAT_WIDTH = 98
- def makeWindow(self, top=0, left=0):
- nlines = defaultIfNone(self.readItem("jobcount"), 0)
- self.rowCount = nlines
- self._createWindow("Jobs", self.rowCount + 6, ncols=self.FORMAT_WIDTH, begin_y=top, begin_x=left)
- return self
+ windowTitle = "Jobs"
+ formatWidth = 98
+ additionalRows = 6
+ def updateRowCount(self):
+ self.rowCount = defaultIfNone(self.readItem("jobcount"), 0)
+
def update(self):
records = defaultIfNone(self.clientData(), {})
if len(records) != self.rowCount:
@@ -640,7 +666,7 @@
safeDivision(total_time, total_completed, 1000.0)
)
if self.usesCurses:
- self.window.hline(y, x, "-", self.FORMAT_WIDTH - 2)
+ self.window.hline(y, x, "-", self.formatWidth - 2)
y += 1
self.window.addstr(y, x, s)
else:
@@ -662,18 +688,15 @@
help = "server child job assignments"
clientItem = "job_assignments"
- FORMAT_WIDTH = 40
- def makeWindow(self, top=0, left=0):
- slots = defaultIfNone(self.readItem(self.clientItem), {"workers": ()})["workers"]
- self.rowCount = len(slots)
- self._createWindow(
- "Job Assignments", self.rowCount + 5, self.FORMAT_WIDTH,
- begin_y=top, begin_x=left
- )
- return self
+ windowTitle = "Job Assignments"
+ formatWidth = 40
+ additionalRows = 5
+ def updateRowCount(self):
+ self.rowCount = len(defaultIfNone(self.readItem(self.clientItem), {"workers": ()})["workers"])
+
def update(self):
data = defaultIfNone(self.clientData(), {"workers": {}, "level": 0})
records = data["workers"]
@@ -736,7 +759,7 @@
total_completed,
)
if self.usesCurses:
- self.window.hline(y, x, "-", self.FORMAT_WIDTH - 2)
+ self.window.hline(y, x, "-", self.formatWidth - 2)
y += 1
self.window.addstr(y, x, s)
else:
@@ -758,18 +781,15 @@
help = "server child slots"
clientItem = "slots"
- FORMAT_WIDTH = 72
- def makeWindow(self, top=0, left=0):
- slots = defaultIfNone(self.readItem(self.clientItem), {"slots": ()})["slots"]
- self.rowCount = len(slots)
- self._createWindow(
- "HTTP Slots", self.rowCount + 5, self.FORMAT_WIDTH,
- begin_y=top, begin_x=left
- )
- return self
+ windowTitle = "HTTP Slots"
+ formatWidth = 72
+ additionalRows = 5
+ def updateRowCount(self):
+ self.rowCount = len(defaultIfNone(self.readItem(self.clientItem), {"slots": ()})["slots"])
+
def update(self):
data = defaultIfNone(self.clientData(), {"slots": {}, "overloaded": False})
records = data["slots"]
@@ -840,7 +860,7 @@
sum([record["total"] for record in records]),
)
if self.usesCurses:
- self.window.hline(y, x, "-", self.FORMAT_WIDTH - 2)
+ self.window.hline(y, x, "-", self.formatWidth - 2)
y += 1
self.window.addstr(y, x, s)
x += len(s) + 4
@@ -871,13 +891,14 @@
help = "system details"
clientItem = "stats_system"
- def makeWindow(self, top=0, left=0):
- slots = defaultIfNone(self.readItem(self.clientItem), (1, 2, 3, 4,))
- self.rowCount = len(slots)
- self._createWindow("System", self.rowCount + 3, begin_y=top, begin_x=left)
- return self
+ windowTitle = "System"
+ formatWidth = 52
+ additionalRows = 3
+ def updateRowCount(self):
+ self.rowCount = len(defaultIfNone(self.readItem(self.clientItem), (1, 2, 3, 4,)))
+
def update(self):
records = defaultIfNone(self.clientData(), {
"cpu use": 0.0,
@@ -952,13 +973,15 @@
help = "server request stats"
clientItem = "stats"
- FORMAT_WIDTH = 84
- def makeWindow(self, top=0, left=0):
- self._createWindow("Request Statistics", 8, self.FORMAT_WIDTH, begin_y=top, begin_x=left)
- return self
+ windowTitle = "Request Statistics"
+ formatWidth = 84
+ additionalRows = 4
+ def updateRowCount(self):
+ self.rowCount = 4
+
def update(self):
records = defaultIfNone(self.clientData(), {})
self.iter += 1
@@ -1031,18 +1054,19 @@
help = "server methods"
clientItem = "stats"
- FORMAT_WIDTH = 116
stats_keys = ("current", "1m", "5m", "1h",)
- def makeWindow(self, top=0, left=0):
+ windowTitle = "Methods"
+ formatWidth = 116
+ additionalRows = 7
+
+ def updateRowCount(self):
stats = defaultIfNone(self.clientData(), {})
methods = set()
for key in self.stats_keys:
methods.update(stats.get(key, {}).get("method", {}).keys())
nlines = len(methods)
self.rowCount = nlines
- self._createWindow("Methods", self.rowCount + 7, ncols=self.FORMAT_WIDTH, begin_y=top, begin_x=left)
- return self
def update(self):
@@ -1128,7 +1152,7 @@
*items
)
if self.usesCurses:
- self.window.hline(y, x, "-", self.FORMAT_WIDTH - 2)
+ self.window.hline(y, x, "-", self.formatWidth - 2)
y += 1
self.window.addstr(y, x, s1)
y += 1
@@ -1153,17 +1177,13 @@
help = "directory service stats"
clientItem = "directory"
- FORMAT_WIDTH = 89
+ windowTitle = "Directory Service"
+ formatWidth = 89
+ additionalRows = 8
- def makeWindow(self, top=0, left=0):
- nlines = len(defaultIfNone(self.readItem("directory"), {}))
- self.rowCount = nlines
- self._createWindow(
- "Directory Service", self.rowCount + 8, ncols=self.FORMAT_WIDTH,
- begin_y=top, begin_x=left
- )
- return self
+ def updateRowCount(self):
+ self.rowCount = len(defaultIfNone(self.readItem("directory"), {}))
def update(self):
@@ -1250,7 +1270,7 @@
"",
)
if self.usesCurses:
- self.window.hline(y, x, "-", self.FORMAT_WIDTH - 2)
+ self.window.hline(y, x, "-", self.formatWidth - 2)
y += 1
self.window.addstr(y, x, s)
self.window.addstr(y + 1, x, s_cached)
@@ -1269,13 +1289,21 @@
Dashboard.registerWindow(HelpWindow, "h")
Dashboard.registerWindow(SystemWindow, "s")
-Dashboard.registerWindow(AssignmentsWindow, "w")
Dashboard.registerWindow(RequestStatsWindow, "r")
+Dashboard.registerWindow(HTTPSlotsWindow, "c")
Dashboard.registerWindow(MethodsWindow, "m")
+Dashboard.registerWindow(AssignmentsWindow, "w")
Dashboard.registerWindow(JobsWindow, "j")
-Dashboard.registerWindow(HTTPSlotsWindow, "c")
Dashboard.registerWindow(DirectoryStatsWindow, "d")
+Dashboard.registerWindowSet(SystemWindow, "H")
+Dashboard.registerWindowSet(RequestStatsWindow, "H")
+Dashboard.registerWindowSet(HTTPSlotsWindow, "H")
+Dashboard.registerWindowSet(MethodsWindow, "H")
+Dashboard.registerWindowSet(SystemWindow, "J")
+Dashboard.registerWindowSet(AssignmentsWindow, "J")
+Dashboard.registerWindowSet(JobsWindow, "J")
+
if __name__ == "__main__":
main()
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.macosforge.org/pipermail/calendarserver-changes/attachments/20151208/8ee3d59b/attachment-0001.html>
More information about the calendarserver-changes
mailing list