Author: justi9
Date: 2007-11-12 10:04:11 -0500 (Mon, 12 Nov 2007)
New Revision: 1284
Modified:
mgmt/cumin/python/cumin/client.strings
mgmt/cumin/python/cumin/exchange.strings
mgmt/cumin/python/cumin/measurement.py
mgmt/cumin/python/cumin/measurement.strings
mgmt/cumin/python/cumin/model.py
mgmt/cumin/python/cumin/page.strings
mgmt/cumin/python/cumin/queue.py
mgmt/cumin/python/cumin/queue.strings
mgmt/cumin/resources/wooly.js
Log:
Big ajax and javascript update.
Adds a function to the js for changing xml tree into js objects.
Adds a cumin object with slots for type-specific listeners, eg queue
update listeners.
Adds a placeholder method to Element for finding regions of text we
want to update.
Makes the queue stats page ajax update.
Modified: mgmt/cumin/python/cumin/client.strings
===================================================================
--- mgmt/cumin/python/cumin/client.strings 2007-11-11 19:34:55 UTC (rev 1283)
+++ mgmt/cumin/python/cumin/client.strings 2007-11-12 15:04:11 UTC (rev 1284)
@@ -36,19 +36,16 @@
function updateClientStatus(id, data) {
updateStatus(id, data);
- var rates = data.root().dict("measurement", "name",
"rate");
+ var m = data.root().object().measurement;
+ var mdata = {
+ "tr": [
+ null,
+ {"td": [m.msgsProduced.rate, m.bytesProduced.rate]},
+ {"td": [m.msgsConsumed.rate, m.bytesConsumed.rate]}
+ ]
+ };
- var status = wooly.doc().elembyid(id);
- var trs =
status.elem("table").elem("tbody").elems("tr", 1);
- var tds = null;
-
- tds = trs.next().elems("td");
- tds.next().text().set(rates["msgsProduced"]);
- tds.next().text().set(rates["bytesProduced"]);
-
- tds = trs.next().elems("td");
- tds.next().text().set(rates["msgsConsumed"]);
- tds.next().text().set(rates["bytesConsumed"]);
+ wooly.doc().elembyid(id).descendant("table.tbody").update(mdata);
}
[ClientStatus.html]
Modified: mgmt/cumin/python/cumin/exchange.strings
===================================================================
--- mgmt/cumin/python/cumin/exchange.strings 2007-11-11 19:34:55 UTC (rev 1283)
+++ mgmt/cumin/python/cumin/exchange.strings 2007-11-12 15:04:11 UTC (rev 1284)
@@ -87,25 +87,17 @@
function updateExchangeStatus(id, data) {
updateStatus(id, data);
- var values = data.root().dict("measurement", "name",
"value");
- var rates = data.root().dict("measurement", "name",
"rate");
+ var m = data.root().object().measurement;
+ var mdata = {
+ "tr": [
+ null,
+ {"td": [m.msgReceives.rate, m.byteReceives.rate]},
+ {"td": [m.msgRoutes.rate, m.byteRoutes.rate]},
+ {"td": [m.msgDrops.value, m.byteDrops.value]}
+ ]
+ };
- var status = wooly.doc().elembyid(id);
-
- var trs =
status.elem("table").elem("tbody").elems("tr", 1);
- var tds = null;
-
- tds = trs.next().elems("td");
- tds.next().text().set(rates["msgReceives"]);
- tds.next().text().set(rates["byteReceives"]);
-
- tds = trs.next().elems("td");
- tds.next().text().set(rates["msgRoutes"]);
- tds.next().text().set(rates["byteRoutes"]);
-
- tds = trs.next().elems("td");
- tds.next().text().set(values["msgDrops"]);
- tds.next().text().set(values["byteDrops"]);
+ wooly.doc().elembyid(id).descendant("table.tbody").update(mdata);
}
[ExchangeStatus.html]
Modified: mgmt/cumin/python/cumin/measurement.py
===================================================================
--- mgmt/cumin/python/cumin/measurement.py 2007-11-11 19:34:55 UTC (rev 1283)
+++ mgmt/cumin/python/cumin/measurement.py 2007-11-12 15:04:11 UTC (rev 1284)
@@ -35,6 +35,9 @@
def render_item_title(self, session, measure):
return measure.title
+ def render_item_name(self, session, measure):
+ return measure.name
+
def render_item_value(self, session, measure):
if measure.link_cb:
branch = session.branch()
@@ -45,7 +48,7 @@
def render_item_extra(self, session, measure):
if measure.highlow:
- return "<small>high</small> %i
<small>low</small> %i" \
+ return "<small>high</small> <span
ph=\"1\">%i</span> <small>low</small> <span
ph=\"2\">%i</span>" \
% (measure.get_high() or 0, measure.get_low() or 0)
else:
unit = self.unit_abbrevs.get(measure.unit, measure.unit)
Modified: mgmt/cumin/python/cumin/measurement.strings
===================================================================
--- mgmt/cumin/python/cumin/measurement.strings 2007-11-11 19:34:55 UTC (rev 1283)
+++ mgmt/cumin/python/cumin/measurement.strings 2007-11-12 15:04:11 UTC (rev 1284)
@@ -1,7 +1,36 @@
+[MeasurementSet.javascript]
+function updateMeasurements(id, object) {
+ var table = wooly.doc().elembyid(id)
+ var trs = table.elem("tbody").elems("tr");
+ var tr = trs.next();
+ while (tr) {
+ var attr = tr.getattr("m");
+ if (attr) {
+ var m = object.measurement[attr];
+
+ var tds = tr.elems("td");
+ tds.next().text().set(m.value);
+
+ var td = tds.next();
+ var ph1 = td.placeholder("1");
+ var ph2 = td.placeholder("2");
+
+ if (ph1 && ph2) {
+ ph1.set(m.high);
+ ph2.set(m.low);
+ } else {
+ td.text().set(m.rate);
+ }
+ }
+
+ tr = trs.next();
+ }
+}
+
[MeasurementSet.html]
-<table class="mobjects">
+<table id="{id}" class="mobjects">
<tr>
<th style="width: 45%;">Statistic</th>
<th style="width: 20%;" class="ralign">Current</th>
@@ -12,7 +41,7 @@
</table>
[MeasurementSet.item_html]
-<tr>
+<tr m="{item_name}">
<th>{item_title}</th>
<td class="ralign">{item_value}</td>
<td class="ralign">{item_extra}</td>
Modified: mgmt/cumin/python/cumin/model.py
===================================================================
--- mgmt/cumin/python/cumin/model.py 2007-11-11 19:34:55 UTC (rev 1283)
+++ mgmt/cumin/python/cumin/model.py 2007-11-12 15:04:11 UTC (rev 1284)
@@ -383,8 +383,13 @@
return self.__low
def write_xml(self, writer):
- writer.write("<measurement name=\"%s\" value=\"%i\"
rate=\"%i\"/>" \
- % (self.name, self.get_value(), self.get_rate()))
+ hl = ""
+
+ if self.highlow:
+ hl = "high=\"%i\" low=\"%i\"" %
(self.get_high(), self.get_low())
+
+ writer.write("<measurement name=\"%s\" value=\"%i\"
rate=\"%i\" %s/>" \
+ % (self.name, self.get_value(), self.get_rate(), hl))
class Queue(CuminModelObject):
def __init__(self, model):
Modified: mgmt/cumin/python/cumin/page.strings
===================================================================
--- mgmt/cumin/python/cumin/page.strings 2007-11-11 19:34:55 UTC (rev 1283)
+++ mgmt/cumin/python/cumin/page.strings 2007-11-12 15:04:11 UTC (rev 1284)
@@ -547,11 +547,23 @@
}
[CuminPage.javascript]
-function updateStatus(id, data) {
- var ecount = data.elem("error-count").text().get();
+var cumin;
+
+(function() {
+ cumin = new Cumin();
+
+ function Cumin() {
+ this.queue = new Object();
+ this.queue.latest = new Object();
+ this.queue.listeners = new Array();
+ }
+}())
+
+function updateStatus(id, object) {
+ var ecount = object["error-count"];
var errors = ecount + " " + (ecount == "1" &&
"error" || "errors");
- var wcount = data.elem("warning-count").text().get();
+ var wcount = object["warning-count"];
var warnings = wcount + " " + (wcount == "1" &&
"warning" || "warnings");
var status = wooly.doc().elembyid(id);
Modified: mgmt/cumin/python/cumin/queue.py
===================================================================
--- mgmt/cumin/python/cumin/queue.py 2007-11-11 19:34:55 UTC (rev 1283)
+++ mgmt/cumin/python/cumin/queue.py 2007-11-12 15:04:11 UTC (rev 1284)
@@ -108,9 +108,6 @@
return "Queue '%s'" % queue.name
class QueueStatus(CuminStatus):
- def render_data_url(self, session, queue):
- return "queue.xml?id=%i" % queue.id
-
def render_consumers(self, session, queue):
return queue.get_measurement("consumers").get_value()
@@ -171,6 +168,9 @@
def get_title(self, session, queue):
return "Queue '%s'" % queue.name
+ def render_data_url(self, session, queue):
+ return "queue.xml?id=%i" % queue.id
+
def render_name(self, session, queue):
return queue.name
@@ -417,15 +417,14 @@
def __init__(self, app, name):
super(QueueStatistics.StatisticsCurrent, self).__init__(app, name)
- self.add_child(MeasurementSet(app, "general_stats",
"general"))
- self.add_child(MeasurementSet(app, "disk_stats",
"disk"))
+ self.add_child(MeasurementSet(app, "general",
"general"))
+ self.add_child(MeasurementSet(app, "disk", "disk"))
self.add_child(MeasurementSet \
- (app, "transactional_stats",
"transactional"))
+ (app, "transactional", "transactional"))
self.add_child(MeasurementSet \
- (app, "persistent_stats", "persistent"))
-
+ (app, "persistent", "persistent"))
self.add_child(MeasurementSet \
- (app, "transaction_stats",
"transaction"))
+ (app, "transaction", "transaction"))
def get_title(self, session, queue):
return "Current"
Modified: mgmt/cumin/python/cumin/queue.strings
===================================================================
--- mgmt/cumin/python/cumin/queue.strings 2007-11-11 19:34:55 UTC (rev 1283)
+++ mgmt/cumin/python/cumin/queue.strings 2007-11-12 15:04:11 UTC (rev 1284)
@@ -89,31 +89,21 @@
</script>
[QueueStatus.javascript]
-function updateQueueStatus(id, data) {
- updateStatus(id, data);
+function updateQueueStatus(id, queue) {
+ updateStatus(id, queue);
- var values = data.root().dict("measurement", "name",
"value");
- var rates = data.root().dict("measurement", "name",
"rate");
+ var m = queue.measurement;
+ var mdata = {
+ "tr": [
+ null,
+ {"td": [m.msgTotalEnqueues.rate, m.byteTotalEnqueues.rate]},
+ {"td": [m.msgTotalDequeues.rate, m.byteTotalDequeues.rate]},
+ {"td": [m.msgDepth.value, m.byteDepth.value]},
+ {"td": [m.msgDepth.rate, m.byteDepth.rate]}
+ ]
+ };
- var status = wooly.doc().elembyid(id);
- var trs =
status.elem("table").elem("tbody").elems("tr", 1);
- var tds = null;
-
- tds = trs.next().elems("td");
- tds.next().text().set(rates["msgTotalEnqueues"]);
- tds.next().text().set(rates["byteTotalEnqueues"]);
-
- tds = trs.next().elems("td");
- tds.next().text().set(rates["msgTotalDequeues"]);
- tds.next().text().set(rates["byteTotalDequeues"]);
-
- tds = trs.next().elems("td");
- tds.next().set(values["msgDepth"]);
- tds.next().set(values["byteDepth"]);
-
- tds = trs.next().elems("td");
- tds.next().text().set(rates["msgDepth"]);
- tds.next().text().set(rates["byteDepth"]);
+ wooly.doc().elembyid(id).descendant("table.tbody").update(mdata);
}
[QueueStatus.html]
@@ -151,10 +141,25 @@
</table>
</div>
<script>
- wooly.setIntervalUpdate("{id}", "{data_url}", updateQueueStatus,
3000);
+ cumin.queue.listeners["{id}"] = updateQueueStatus
</script>
+[QueueView.javascript]
+function updateQueue(data) {
+ var queue = data.root().object();
+
+ //wooly.dir(cumin.queue.listeners);
+
+ for (var id in cumin.queue.listeners) {
+ cumin.queue.listeners[id](id, queue);
+ }
+}
+
[QueueView.html]
+<script>
+ wooly.setIntervalUpdate("{data_url}", updateQueue, 3000);
+</script>
+
{status}
<h1><img src="resource?name=queue-36.png"> {title}</h1>
@@ -233,18 +238,24 @@
<tr>
<td class="twocol">
<h2>General</h2>
- {general_stats}
+ {general}
<h2>Persistent Messages</h2>
- {persistent_stats}
+ {persistent}
</td>
<td class="twocol">
<h2>Transactional Messages</h2>
- {transactional_stats}
+ {transactional}
<h2>Transactions</h2>
- {transaction_stats}
+ {transaction}
</td>
</tr>
</table>
+<script>
+ cumin.queue.listeners["{id}.general"] = updateMeasurements;
+ cumin.queue.listeners["{id}.persistent"] = updateMeasurements;
+ cumin.queue.listeners["{id}.transactional"] = updateMeasurements;
+ cumin.queue.listeners["{id}.transaction"] = updateMeasurements;
+</script>
[StatisticsHistory.html]
<h2>Depth</h2>
Modified: mgmt/cumin/resources/wooly.js
===================================================================
--- mgmt/cumin/resources/wooly.js 2007-11-11 19:34:55 UTC (rev 1283)
+++ mgmt/cumin/resources/wooly.js 2007-11-12 15:04:11 UTC (rev 1284)
@@ -6,7 +6,8 @@
function assert() {
for (var i = 0; i < arguments.length; i++) {
if (!arguments[i]) {
- throw new Error("Assertion failure in " +
arguments.callee.caller.prototype);
+ throw new Error("Assertion failure in " +
+ arguments.callee.caller.prototype);
}
}
}
@@ -23,6 +24,161 @@
}
}
+ function translate(node, parent) {
+ //log("node", node.nodeType, node, "parent", parent);
+
+ var first = node.firstChild;
+ var name = node.nodeName;
+
+ if (first && first.nodeType == 3 && parent) {
+ parent[name] = first.nodeValue;
+
+ return null;
+ }
+
+ var object = new Object();
+ var attrs = node.attributes;
+
+ if (parent) {
+ var keyattr = null;
+
+ if (attrs) {
+ keyattr = attrs.getNamedItem("id");
+
+ if (keyattr == null) {
+ keyattr = attrs.getNamedItem("key");
+ }
+
+ if (keyattr == null) {
+ keyattr = attrs.getNamedItem("name");
+ }
+
+ if (keyattr) {
+ var key = keyattr.nodeValue;
+ var extant = parent[name];
+
+ if (extant == null) {
+ extant = new Object();
+ parent[name] = extant;
+ }
+
+ extant[key] = object;
+ }
+ }
+
+ if (keyattr == null) {
+ var extant = parent[name];
+
+ if (extant == null) {
+ parent[name] = object;
+ } else {
+ var array;
+
+ if (extant instanceof Array) {
+ array = extant;
+ } else {
+ array = new Array();
+ array.push(extant);
+
+ parent[name] = array;
+ }
+
+ array.push(object);
+ }
+ }
+ }
+
+ var attr;
+
+ for (var i = 0; i < attrs.length; i++) {
+ attr = attrs[i];
+ object[attr.nodeName] = attr.nodeValue;
+ }
+
+ var childs = node.childNodes;
+
+ for (var i = 0; i < childs.length; i++) {
+ translate(childs[i], object);
+ }
+
+ return object;
+ }
+
+ function update(elem, elems, object) {
+ //log("update", "elem", elem, "elems", elems,
"object", object);
+
+ if (typeof(object) == "string") {
+ if (elem.firstChild.nodeType == 3) {
+ elem.firstChild.data = object;
+ }
+ } else if (object instanceof Array) {
+ for (var i = 0; i < object.length; i++) {
+ update(elems[i], elems, object[i]);
+ }
+ } else {
+ for (var child in object) {
+ var elems = elem.getElementsByTagName(child);
+ update(elems[0], elems, object[child]);
+ }
+ }
+ }
+
+ function descendant(elem, path) {
+ var names = path.split(".");
+ var node = elem;
+
+ for (var i = 0; i < names.length; i++) {
+ var elems = elem.getElementsByTagName(names[i]);
+
+ if (elems.length) {
+ node = elems[0];
+ } else {
+ break;
+ }
+ }
+
+ return node;
+ }
+
+ function find(nodeParent, nodeType, nodeName, attr, attrValue) {
+ assert(nodeParent);
+ assert(nodeType);
+
+ var children = nodeParent.childNodes;
+ var found;
+
+ for (var i = 0; i < children.length; i++) {
+ if (found) {
+ break;
+ }
+
+ var child = children[i];
+ var candidate = child;
+
+ if (child.nodeType != nodeType) {
+ candidate = null;
+ } else if (nodeName && child.nodeName.toLowerCase() != nodeName) {
+ candidate = null;
+ } else if (attr && child.nodeType == 1) {
+ var value = child.getAttribute(attr);
+
+ if (!value) {
+ candidate = null;
+ } else if (value != attrValue) {
+ candidate = null;
+ }
+ }
+
+ if (candidate) {
+ found = candidate;
+ } else {
+ found = find(child, nodeType, nodeName, attr, attrValue);
+ }
+ }
+
+ return found;
+ }
+
function Wooly() {
this.request = new XMLHttpRequest();
@@ -34,7 +190,7 @@
this.console = window.console;
}
- this.setIntervalUpdate = function(id, url, callback, interval) {
+ this.setIntervalUpdate = function(url, callback, interval) {
var req = this.request;
function fetch() {
@@ -43,20 +199,20 @@
req.send(null);
}
- var timerid = window.setInterval(fetch, interval);
+ var id = window.setInterval(fetch, interval);
function update() {
try {
if (req.readyState == 4 && req.status == 200) {
//dir(req);
- callback(id, wooly.doc(req.responseXML));
+ callback(wooly.doc(req.responseXML));
}
} catch (e) {
log(e);
// XXX might want to retry for a bit before we do
// this
- window.clearInterval(timerid);
+ window.clearInterval(id);
throw e;
}
}
@@ -134,13 +290,11 @@
for (var i = this.lastIndex + 1; i < this.nodes.length; i++) {
node = this.nodes[i];
- if (this.nodeType == null
- || node.nodeType == this.nodeType) {
- if (this.nodeName == null
- || node.nodeName.toLowerCase() == this.nodeName) {
+ if ((this.nodeType == null || node.nodeType == this.nodeType)
+ && (this.nodeName == null
+ || node.nodeName.toLowerCase() == this.nodeName)) {
this.lastIndex = i;
return new this.nodeClass(this.doc, node);
- }
}
}
@@ -172,6 +326,7 @@
this.add = function(content) {
if (typeof content == "string") {
+ // XXX flatten this out
this.add(new WoolyText(this.doc, null).set(content));
} else if (content.hasOwnProperty("node")) {
this.node.appendChild(content.node);
@@ -211,6 +366,20 @@
return dict;
}
+ this.object = function() {
+ return translate(this.node, null);
+ }
+
+ this.update = function(data) {
+ update(this.node, null, data);
+ }
+
+ this.descendant = function(path) {
+ var node = descendant(this.node, path);
+
+ return new WoolyElement(this.doc, node);
+ }
+
this.elems = function(name, start) {
if (start == null) {
start = 0;
@@ -232,15 +401,23 @@
}
this.text = function() {
- var children = this.node.childNodes;
+ var text = find(this.node, 3);
- for (var i = 0; i < children.length; i++) {
- var child = children[i];
+ if (text) {
+ return new WoolyText(this.doc, text);
+ } else {
+ return null;
+ }
+ }
- if (child.nodeType == 3) return new WoolyText(this.doc, child);
+ this.placeholder = function(name) {
+ var ph = find(this.node, 1, "span", "ph", name);
+
+ if (ph) {
+ return new WoolyElement(this.doc, ph);
+ } else {
+ return null;
}
-
- return null;
}
}