diff options
| author | Ted Ross <tross@apache.org> | 2009-02-26 21:26:47 +0000 |
|---|---|---|
| committer | Ted Ross <tross@apache.org> | 2009-02-26 21:26:47 +0000 |
| commit | adbb618fa2ae734cc9f87e57ae15df14c77edf77 (patch) | |
| tree | a6301e3a66a976d7cb1e6dd1b23fd71f625d0542 /qpid/python | |
| parent | 7b30a9adbf13432dd8d7bf0abe868ed773d2ad16 (diff) | |
| download | qpid-python-adbb618fa2ae734cc9f87e57ae15df14c77edf77.tar.gz | |
Improvements to qpid-stat:
Support for exchanges and queues
Sorting and limiting
Improved table formatting
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@748315 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid/python')
| -rwxr-xr-x | qpid/python/commands/qpid-stat | 216 | ||||
| -rw-r--r-- | qpid/python/qpid/disp.py | 138 |
2 files changed, 275 insertions, 79 deletions
diff --git a/qpid/python/commands/qpid-stat b/qpid/python/commands/qpid-stat index 2ac0cad9af..9d41f4e966 100755 --- a/qpid/python/commands/qpid-stat +++ b/qpid/python/commands/qpid-stat @@ -26,11 +26,14 @@ import locale import socket import re from qmf.console import Session, Console -from qpid.disp import Display +from qpid.disp import Display, Header, Sorter _host = "localhost" _top = False _types = "" +_limit = 50 +_increasing = False +_sortcol = None pattern = re.compile("^\\d+\\.\\d+\\.\\d+\\.\\d+:\\d+$") def Usage (): @@ -48,23 +51,15 @@ def Usage (): print " -b Show Brokers" print " -c Show Connections" # print " -s Show Sessions" -# print " -e Show Exchanges" -# print " -q Show Queues" + print " -e Show Exchanges" + print " -q Show Queues" + print + print " -S [--sort-by] COLNAME Sort by column name" + print " -I [--increasing] Sort by increasing value (default = decreasing)" + print " -L [--limit] NUM Limit output to NUM rows (default = 50)" print sys.exit (1) -def num(value): - if value < 2000: - return str(value) - value /= 1000 - if value < 2000: - return str(value) + "k" - value /= 1000 - if value < 2000: - return str(value) + "m" - value /= 1000 - return str(value) + "g" - class IpAddr: def __init__(self, text): if text.find("@") != -1: @@ -93,7 +88,6 @@ class IpAddr: class Broker(object): def __init__(self, qmf, broker): self.broker = broker - list = qmf.getObjects(_class="connection", _package="org.apache.qpid.broker", _broker=broker) bobj = qmf.getObjects(_class="broker", _package="org.apache.qpid.broker", _broker=broker)[0] self.currentTime = bobj.getTimestamps()[0] try: @@ -104,17 +98,23 @@ class Broker(object): self.sessions = {} self.exchanges = {} self.queues = {} + package = "org.apache.qpid.broker" + + list = qmf.getObjects(_class="connection", _package=package, _broker=broker) for conn in list: if pattern.match(conn.address): self.connections[conn.getObjectId()] = conn - list = qmf.getObjects(_class="session", _package="org.apache.qpid.broker", _broker=broker) + + list = qmf.getObjects(_class="session", _package=package, _broker=broker) for sess in list: if sess.connectionRef in self.connections: self.sessions[sess.getObjectId()] = sess - list = qmf.getObjects(_class="exchange", _package="org.apache.qpid.broker", _broker=broker) + + list = qmf.getObjects(_class="exchange", _package=package, _broker=broker) for exchange in list: self.exchanges[exchange.getObjectId()] = exchange - list = qmf.getObjects(_class="queue", _package="org.apache.qpid.broker", _broker=broker) + + list = qmf.getObjects(_class="queue", _package=package, _broker=broker) for queue in list: self.queues[queue.getObjectId()] = queue @@ -209,34 +209,45 @@ class BrokerManager(Console): def displayBroker(self, subs): disp = Display(prefix=" ") - heads = ('Broker', 'cluster', 'uptime', 'conn', 'sess', 'exch', 'queue') + heads = [] + heads.append(Header('broker')) + heads.append(Header('cluster')) + heads.append(Header('uptime', Header.DURATION)) + heads.append(Header('conn', Header.KMG)) + heads.append(Header('sess', Header.KMG)) + heads.append(Header('exch', Header.KMG)) + heads.append(Header('queue', Header.KMG)) rows = [] for broker in self.brokers: if self.cluster: ctext = "%s(%s)" % (self.cluster.clusterName, self.cluster.status) else: ctext = "<standalone>" - utext = "" - if broker.getUptime() > 0: - utext = disp.duration(broker.getUptime()) - row = (broker.getName(), ctext, utext, - str(len(broker.connections)), str(len(broker.sessions)), - str(len(broker.exchanges)), str(len(broker.queues))) + row = (broker.getName(), ctext, broker.getUptime(), + len(broker.connections), len(broker.sessions), + len(broker.exchanges), len(broker.queues)) rows.append(row) - disp.table("Brokers", heads, rows) + title = "Brokers" + if _sortcol: + sorter = Sorter(heads, rows, _sortcol, _limit, _increasing) + dispRows = sorter.getSorted() + else: + dispRows = rows + disp.formattedTable(title, heads, dispRows) def displayConn(self, subs): disp = Display(prefix=" ") heads = [] if self.cluster: - heads.append('broker') - heads.append('client addr') - heads.append('client(pid)') - heads.append('auth') - heads.append('connected') - heads.append('idle') - heads.append('msgIn') - heads.append('msgOut') + heads.append(Header('broker')) + heads.append(Header('client-addr')) + heads.append(Header('cproc')) + heads.append(Header('cpid')) + heads.append(Header('auth')) + heads.append(Header('connected', Header.DURATION)) + heads.append(Header('idle', Header.DURATION)) + heads.append(Header('msgIn', Header.KMG)) + heads.append(Header('msgOut', Header.KMG)) rows = [] for broker in self.brokers: for oid in broker.connections: @@ -245,27 +256,24 @@ class BrokerManager(Console): if self.cluster: row.append(broker.getName()) row.append(conn.address) - procpid = "" - if conn.remoteProcessName: - procpid += conn.remoteProcessName - if conn.remotePid: - procpid += "(%d)" % conn.remotePid - row.append(procpid) + row.append(conn.remoteProcessName) + row.append(conn.remotePid) row.append(conn.authIdentity) - row.append(disp.duration(broker.getCurrentTime() - conn.getTimestamps()[1])) + row.append(broker.getCurrentTime() - conn.getTimestamps()[1]) idle = broker.getCurrentTime() - conn.getTimestamps()[0] - if idle < 10000000000: - itext = "" - else: - itext = disp.duration(idle) - row.append(itext) - row.append(num(conn.framesFromClient)) - row.append(num(conn.framesToClient)) + row.append(broker.getCurrentTime() - conn.getTimestamps()[0]) + row.append(conn.framesFromClient) + row.append(conn.framesToClient) rows.append(row) title = "Connections" if self.cluster: title += " for cluster '%s'" % self.cluster.clusterName - disp.table(title, heads, rows) + if _sortcol: + sorter = Sorter(heads, rows, _sortcol, _limit, _increasing) + dispRows = sorter.getSorted() + else: + dispRows = rows + disp.formattedTable(title, heads, dispRows) def displaySession(self, subs): disp = Display(prefix=" ") @@ -274,17 +282,17 @@ class BrokerManager(Console): disp = Display(prefix=" ") heads = [] if self.cluster: - heads.append('broker') - heads.append("exchange") - heads.append("type") - heads.append("dur") - heads.append("bind") - heads.append("msgIn") - heads.append("msgOut") - heads.append("msgDrop") - heads.append("byteIn") - heads.append("byteOut") - heads.append("byteDrop") + heads.append(Header('broker')) + heads.append(Header("exchange")) + heads.append(Header("type")) + heads.append(Header("dur", Header.Y)) + heads.append(Header("bind", Header.KMG)) + heads.append(Header("msgIn", Header.KMG)) + heads.append(Header("msgOut", Header.KMG)) + heads.append(Header("msgDrop", Header.KMG)) + heads.append(Header("byteIn", Header.KMG)) + heads.append(Header("byteOut", Header.KMG)) + heads.append(Header("byteDrop", Header.KMG)) rows = [] for broker in self.brokers: for oid in broker.exchanges: @@ -292,31 +300,80 @@ class BrokerManager(Console): row = [] if self.cluster: row.append(broker.getName()) - if ex.durable: - dur = "Y" - else: - dur = "" row.append(ex.name) row.append(ex.type) - row.append(dur) - row.append(num(ex.bindingCount)) - row.append(num(ex.msgReceives)) - row.append(num(ex.msgRoutes)) - row.append(num(ex.msgDrops)) - row.append(num(ex.byteReceives)) - row.append(num(ex.byteRoutes)) - row.append(num(ex.byteDrops)) + row.append(ex.durable) + row.append(ex.bindingCount) + row.append(ex.msgReceives) + row.append(ex.msgRoutes) + row.append(ex.msgDrops) + row.append(ex.byteReceives) + row.append(ex.byteRoutes) + row.append(ex.byteDrops) rows.append(row) title = "Exchanges" if self.cluster: title += " for cluster '%s'" % self.cluster.clusterName - disp.table(title, heads, rows) + if _sortcol: + sorter = Sorter(heads, rows, _sortcol, _limit, _increasing) + dispRows = sorter.getSorted() + else: + dispRows = rows + disp.formattedTable(title, heads, dispRows) + + def displayQueue(self, subs): + disp = Display(prefix=" ") + heads = [] + if self.cluster: + heads.append(Header('broker')) + heads.append(Header("queue")) + heads.append(Header("dur", Header.Y)) + heads.append(Header("autoDel", Header.Y)) + heads.append(Header("excl", Header.Y)) + heads.append(Header("msg", Header.KMG)) + heads.append(Header("msgIn", Header.KMG)) + heads.append(Header("msgOut", Header.KMG)) + heads.append(Header("bytes", Header.KMG)) + heads.append(Header("bytesIn", Header.KMG)) + heads.append(Header("bytesOut", Header.KMG)) + heads.append(Header("cons", Header.KMG)) + heads.append(Header("bind", Header.KMG)) + rows = [] + for broker in self.brokers: + for oid in broker.queues: + q = broker.queues[oid] + row = [] + if self.cluster: + row.append(broker.getName()) + row.append(q.name) + row.append(q.durable) + row.append(q.autoDelete) + row.append(q.exclusive) + row.append(q.msgDepth) + row.append(q.msgTotalEnqueues) + row.append(q.msgTotalDequeues) + row.append(q.byteDepth) + row.append(q.byteTotalEnqueues) + row.append(q.byteTotalDequeues) + row.append(q.consumerCount) + row.append(q.bindingCount) + rows.append(row) + title = "Queues" + if self.cluster: + title += " for cluster '%s'" % self.cluster.clusterName + if _sortcol: + sorter = Sorter(heads, rows, _sortcol, _limit, _increasing) + dispRows = sorter.getSorted() + else: + dispRows = rows + disp.formattedTable(title, heads, dispRows) def displayMain(self, main, subs): if main == 'b': self.displayBroker(subs) elif main == 'c': self.displayConn(subs) elif main == 's': self.displaySession(subs) elif main == 'e': self.displayExchange(subs) + elif main == 'q': self.displayQueue(subs) def display(self): self._getCluster() @@ -339,8 +396,8 @@ class BrokerManager(Console): ## try: - longOpts = ("top", "numeric") - (optlist, encArgs) = getopt.gnu_getopt(sys.argv[1:], "bc", longOpts) + longOpts = ("top", "numeric", "sort-by=", "limit=", "increasing") + (optlist, encArgs) = getopt.gnu_getopt(sys.argv[1:], "bceqS:L:I", longOpts) except: Usage() @@ -355,6 +412,12 @@ for opt in optlist: _top = True elif opt[0] == "-n" or opt[0] == "--numeric": _numeric = True + elif opt[0] == "-S" or opt[0] == "--sort-by": + _sortcol = opt[1] + elif opt[0] == "-I" or opt[0] == "--increasing": + _increasing = True + elif opt[0] == "-L" or opt[0] == "--limit": + _limit = int(opt[1]) elif len(opt[0]) == 2: char = opt[0][1] if "bcseq".find(char) != -1: @@ -380,6 +443,7 @@ except KeyboardInterrupt: print except Exception,e: print "Failed:", e.args + #raise # TODO: Remove before flight sys.exit(1) bm.Disconnect() diff --git a/qpid/python/qpid/disp.py b/qpid/python/qpid/disp.py index eb55616f32..1b315c9d98 100644 --- a/qpid/python/qpid/disp.py +++ b/qpid/python/qpid/disp.py @@ -21,16 +21,108 @@ from time import strftime, gmtime +class Header: + """ """ + NONE = 1 + KMG = 2 + YN = 3 + Y = 4 + TIME_LONG = 5 + TIME_SHORT = 6 + DURATION = 7 + + def __init__(self, text, format=NONE): + self.text = text + self.format = format + + def __repr__(self): + return self.text + + def __str__(self): + return self.text + + def formatted(self, value): + try: + if value == None: + return '' + if self.format == Header.NONE: + return value + if self.format == Header.KMG: + return self.num(value) + if self.format == Header.YN: + if value: + return 'Y' + return 'N' + if self.format == Header.Y: + if value: + return 'Y' + return '' + if self.format == Header.TIME_LONG: + return strftime("%c", gmtime(value / 1000000000)) + if self.format == Header.TIME_SHORT: + return strftime("%X", gmtime(value / 1000000000)) + if self.format == Header.DURATION: + if value < 0: value = 0 + sec = value / 1000000000 + min = sec / 60 + hour = min / 60 + day = hour / 24 + result = "" + if day > 0: + result = "%dd " % day + if hour > 0 or result != "": + result += "%dh " % (hour % 24) + if min > 0 or result != "": + result += "%dm " % (min % 60) + result += "%ds" % (sec % 60) + return result + except: + return "?" + + def numCell(self, value, tag): + fp = float(value) / 1000. + if fp < 10.0: + return "%1.2f%c" % (fp, tag) + if fp < 100.0: + return "%2.1f%c" % (fp, tag) + return "%4d%c" % (value / 1000, tag) + + def num(self, value): + if value < 1000: + return "%4d" % value + if value < 1000000: + return self.numCell(value, 'k') + value /= 1000 + if value < 1000000: + return self.numCell(value, 'm') + value /= 1000 + return self.numCell(value, 'g') + + class Display: """ Display formatting for QPID Management CLI """ - def __init__ (self, spacing=2, prefix=" "): + def __init__(self, spacing=2, prefix=" "): self.tableSpacing = spacing self.tablePrefix = prefix self.timestampFormat = "%X" - def table (self, title, heads, rows): - """ Print a formatted table with autosized columns """ + def formattedTable(self, title, heads, rows): + fRows = [] + for row in rows: + fRow = [] + col = 0 + for cell in row: + fRow.append(heads[col].formatted(cell)) + col += 1 + fRows.append(fRow) + headtext = [] + for head in heads: + headtext.append(head.text) + self.table(title, headtext, fRows) + + def table(self, title, heads, rows): + """ Print a table with autosized columns """ # Pad the rows to the number of heads for row in rows: @@ -100,3 +192,43 @@ class Display: result += "%dm " % (min % 60) result += "%ds" % (sec % 60) return result + +class Sortable: + """ """ + def __init__(self, row, sortIndex): + self.row = row + self.sortIndex = sortIndex + if sortIndex >= len(row): + raise Exception("sort index exceeds row boundary") + + def __cmp__(self, other): + return cmp(self.row[self.sortIndex], other.row[self.sortIndex]) + + def getRow(self): + return self.row + +class Sorter: + """ """ + def __init__(self, heads, rows, sortCol, limit=0, inc=True): + col = 0 + for head in heads: + if head.text == sortCol: + break + col += 1 + if col == len(heads): + raise Exception("sortCol '%s', not found in headers" % sortCol) + + list = [] + for row in rows: + list.append(Sortable(row, col)) + list.sort(reverse=not inc) + count = 0 + self.sorted = [] + for row in list: + self.sorted.append(row.getRow()) + count += 1 + if count == limit: + break + + def getSorted(self): + return self.sorted |
