summaryrefslogtreecommitdiff
path: root/src/pmwebapi/jsdemos/blinkenlights/blinkenlights.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/pmwebapi/jsdemos/blinkenlights/blinkenlights.js')
-rw-r--r--src/pmwebapi/jsdemos/blinkenlights/blinkenlights.js170
1 files changed, 170 insertions, 0 deletions
diff --git a/src/pmwebapi/jsdemos/blinkenlights/blinkenlights.js b/src/pmwebapi/jsdemos/blinkenlights/blinkenlights.js
new file mode 100644
index 0000000..03bb315
--- /dev/null
+++ b/src/pmwebapi/jsdemos/blinkenlights/blinkenlights.js
@@ -0,0 +1,170 @@
+var pm_root = "http://" + location.hostname + ":" + location.port + "/pmapi";
+var pm_context = -1;
+
+// ----------------------------------------------------------------------
+
+function Predicate(name,index,operator,threshold) {
+ this.name = name;
+ this.index = index;
+ this.operator = operator;
+ this.threshold = threshold;
+ this.inames = {};
+}
+
+Predicate.prototype.to_string = function() {
+ return this.name + "[" + this.index + "] "
+ + this.operator + " " + this.threshold;
+};
+
+Predicate.prototype.get_iname = function(iid) {
+ if (!(iid in this.inames)) {
+ var pm_url = pm_root + "/" + pm_context + "/_indom?name=" + this.name + "&instance=" + iid;
+ var predicate = this;
+ $.getJSON(pm_url, function(data, status) {
+ // TODOXXX error check: should return 1 instance
+ predicate.inames[iid] = data.instances[0].name;
+ });
+
+ return "..."; // will be reloaded next cycle
+ }
+
+ return this.inames[iid];
+}
+
+Predicate.prototype.test = function(elt,data_dict,index) {
+ if (this.index == "*" && typeof(index) == "undefined") {
+ var predicate = this;
+ $.each(data_dict[this.name].instances, function(i,_instance) {
+ predicate.test(elt,data_dict,i);
+ });
+ return;
+ }
+
+ if (typeof(index) == "undefined") index = this.index;
+
+ var metric = data_dict[this.name].instances[index].value;
+ var iid = data_dict[this.name].instances[index].instance;
+ var result = 0, error = "";
+ if (this.operator == "<") result = metric < this.threshold;
+ else if (this.operator == ">") result = metric > this.threshold;
+ else if (this.operator == "<=") result = metric <= this.threshold;
+ else if (this.operator == ">=") result = metric >= this.threshold;
+ else if (this.operator == "==") result = metric == this.threshold;
+ else { error = "unknown operator '" + this.operator + "'"; result = -1; }
+
+ // TODOXXX avoid $("#blinkenlights").empty() by using existing li's??
+ var bclass = result < 0 ? "error" : result ? "on" : "off";
+
+ var source = "<strong>" + metric + "</strong> -- "
+ + this.name + " ( " + this.get_iname(iid) + " : " + iid + " ) "
+ + this.operator + " " + this.threshold;
+ var content = "<span>" + source + "</span>"
+ + (result < 0 ? " -- error: " + error : "");
+
+ elt.append("<li class=\"" + bclass + "\">" + content + "</li>");
+};
+
+var predicates = [];
+
+function parsePredicate(src) {
+ var matches = /^([^[ ]+)\s*(\[\d+\]|\[\*\]|\[\]|)\s*(<=|>=|==|<|>)\s*(\S*)$/.exec(src);
+ if (matches == null) return null;
+ var name = matches[1];
+ var index = matches[2]; index = index == "" ? "*" : index.substring(1,index.length-1);
+ var operator = matches[3];
+ var threshold = parseFloat(matches[4]); // TODOXXX what about other types?; accepts 40foobar
+ if (isNaN(threshold)) return null;
+
+ console.log ("create predicate " + name + " : " + index + " : " + operator + " : " + threshold)
+
+ return new Predicate(name,index,operator,threshold);
+}
+
+// ----------------------------------------------------------------------
+
+var updateInterval = 10000; // milliseconds
+var updateIntervalID = 1;
+
+function setUpdateInterval(i) {
+ if (updateIntervalID >= 0) { clearInterval(updateIntervalID); }
+ if (i > updateInterval) { pm_context = -1; } // will likely need a new context
+ updateInterval = i;
+ updateIntervalID = setInterval(updateBlinkenlights, updateInterval);
+}
+
+// default mode
+var pm_context_type = "hostspec";
+var pm_context_spec = "localhost";
+
+function setPMContextType(k) {
+ pm_context_type = k;
+ pm_context = -1;
+ updateBlinkenlights();
+}
+function setPMContextSpec(i) {
+ pm_context_spec = i;
+ pm_context = -1;
+ updateBlinkenlights();
+}
+
+
+function updateBlinkenlights() {
+ var pm_url;
+
+ if (pm_context < 0) {
+ pm_url = pm_root
+ + "/context?"
+ + pm_context_type + "=" + encodeURIComponent(pm_context_spec)
+ + "&polltimeout=" + Math.floor(5*updateInterval/1000);
+ $.getJSON(pm_url, function(data, status) {
+ pm_context = data.context;
+ setTimeout(updateBlinkenlights, 100); // retry soon
+ }).error(function() { pm_context = -1; });
+ return; // will retry one cycle later
+ }
+
+ if(predicates.length == 0) {
+ $("#blinkenlights").html("<b>No predicates requested...</b>");
+ return;
+ }
+
+ // ajax request for JSON data
+ pm_url = pm_root + "/" + pm_context + "/_fetch?names=";
+ $.each(predicates, function(i, predicate) {
+ if (i > 0) pm_url += ",";
+ pm_url += predicate.name;
+ });
+ $.getJSON(pm_url, function(data, status) {
+ // update data_dict
+ var data_dict = {};
+ $.each(data.values, function(i, value) {
+ data_dict[value.name] = value;
+ });
+ // update status field
+ theDate = new Date(0);
+ theDate.setUTCSeconds(data.timestamp.s);
+ theDate.setUTCMilliseconds(data.timestamp.us/1000);
+ $("#status").html("Timestamp: " + theDate.toString());
+ // update the view
+ $("#blinkenlights").empty();
+ $.each(predicates, function(i, predicate) {
+ predicate.test($("#blinkenlights"), data_dict);
+ });
+ }).error(function() {
+ $("#blinkenlights").html("<b>error accessing server, retrying...</b>");
+ pm_context = -1; });
+}
+
+function loadBlinkenlights() {
+ $("#header").html("pcp blinkenlights demo");
+ $("#content").html("<ul id=\"blinkenlights\"><li>loading...</li></ul>");
+
+ // start timer for updateBlinkenlights
+ updateBlinkenlights();
+ setUpdateInterval(updateInterval);
+}
+
+$(document).ready(function() {
+ loadBlinkenlights();
+ // TODOXXX add support for editing mode
+});