Add per graph auto-refresh option to web UI.

This adds a drop-down menu to select/disable a auto-refresh interval.
This commit is contained in:
Johannes 'fish' Ziemke 2013-04-17 16:49:21 +02:00
parent 888b64c781
commit 712bf5e2f9
3 changed files with 61 additions and 20 deletions

View file

@ -54,3 +54,11 @@ svg {
height: 10px; height: 10px;
margin: 2px 2px 0 8px; margin: 2px 2px 0 8px;
} }
.refresh_interval {
width: 102px
}
input[title=*]:hover:after {
content: attr(title);
}

View file

@ -22,6 +22,8 @@ var Prometheus = Prometheus || {};
var graphs = []; var graphs = [];
var graphTemplate; var graphTemplate;
var SECOND = 1000;
Prometheus.Graph = function(element, options) { Prometheus.Graph = function(element, options) {
this.el = element; this.el = element;
this.options = options; this.options = options;
@ -70,6 +72,7 @@ Prometheus.Graph.prototype.initialize = function() {
self.rangeInput = self.queryForm.find("input[name=range_input]"); self.rangeInput = self.queryForm.find("input[name=range_input]");
self.stacked = self.queryForm.find("input[name=stacked]"); self.stacked = self.queryForm.find("input[name=stacked]");
self.insertMetric = self.queryForm.find("select[name=insert_metric]"); self.insertMetric = self.queryForm.find("select[name=insert_metric]");
self.refreshInterval = self.queryForm.find("select[name=refresh]");
// Return moves focus back to expr instead of submitting. // Return moves focus back to expr instead of submitting.
self.insertMetric.bind('keydown', 'return', function(e) { self.insertMetric.bind('keydown', 'return', function(e) {
@ -92,6 +95,7 @@ Prometheus.Graph.prototype.initialize = function() {
self.endDate.val(""); self.endDate.val("");
} }
self.endDate.change(function() { self.submitQuery() }); self.endDate.change(function() { self.submitQuery() });
self.refreshInterval.change(function() { self.updateRefresh() })
self.stacked.change(function() { self.updateGraph(); }); self.stacked.change(function() { self.updateGraph(); });
self.queryForm.submit(function() { self.submitQuery(); return false; }); self.queryForm.submit(function() { self.submitQuery(); return false; });
@ -167,9 +171,10 @@ Prometheus.Graph.prototype.getOptions = function() {
return options; return options;
}; };
Prometheus.Graph.prototype.parseRange = function(rangeText) { Prometheus.Graph.prototype.parseDuration = function(rangeText) {
var rangeRE = new RegExp("^([0-9]+)([ywdhms]+)$"); var rangeRE = new RegExp("^([0-9]+)([ywdhms]+)$");
var matches = rangeText.match(rangeRE); var matches = rangeText.match(rangeRE);
if (!matches) { return };
if (matches.length != 3) { if (matches.length != 3) {
return 60; return 60;
} }
@ -180,9 +185,9 @@ Prometheus.Graph.prototype.parseRange = function(rangeText) {
Prometheus.Graph.prototype.increaseRange = function() { Prometheus.Graph.prototype.increaseRange = function() {
var self = this; var self = this;
var rangeSeconds = self.parseRange(self.rangeInput.val()); var rangeSeconds = self.parseDuration(self.rangeInput.val());
for (var i = 0; i < Prometheus.Graph.stepValues.length; i++) { for (var i = 0; i < Prometheus.Graph.stepValues.length; i++) {
if (rangeSeconds < self.parseRange(Prometheus.Graph.stepValues[i])) { if (rangeSeconds < self.parseDuration(Prometheus.Graph.stepValues[i])) {
self.rangeInput.val(Prometheus.Graph.stepValues[i]); self.rangeInput.val(Prometheus.Graph.stepValues[i]);
if (self.expr.val()) { if (self.expr.val()) {
self.submitQuery(); self.submitQuery();
@ -194,9 +199,9 @@ Prometheus.Graph.prototype.increaseRange = function() {
Prometheus.Graph.prototype.decreaseRange = function() { Prometheus.Graph.prototype.decreaseRange = function() {
var self = this; var self = this;
var rangeSeconds = self.parseRange(self.rangeInput.val()); var rangeSeconds = self.parseDuration(self.rangeInput.val());
for (var i = Prometheus.Graph.stepValues.length - 1; i >= 0; i--) { for (var i = Prometheus.Graph.stepValues.length - 1; i >= 0; i--) {
if (rangeSeconds > self.parseRange(Prometheus.Graph.stepValues[i])) { if (rangeSeconds > self.parseDuration(Prometheus.Graph.stepValues[i])) {
self.rangeInput.val(Prometheus.Graph.stepValues[i]); self.rangeInput.val(Prometheus.Graph.stepValues[i]);
if (self.expr.val()) { if (self.expr.val()) {
self.submitQuery(); self.submitQuery();
@ -235,13 +240,13 @@ Prometheus.Graph.prototype.setEndDate = function(date) {
Prometheus.Graph.prototype.increaseEnd = function() { Prometheus.Graph.prototype.increaseEnd = function() {
var self = this; var self = this;
self.setEndDate(new Date(self.getOrSetEndDate() + self.parseRange(self.rangeInput.val()) * 1000/2 )) // increase by 1/2 range & convert ms in s self.setEndDate(new Date(self.getOrSetEndDate() + self.parseDuration(self.rangeInput.val()) * 1000/2 )) // increase by 1/2 range & convert ms in s
self.submitQuery(); self.submitQuery();
}; };
Prometheus.Graph.prototype.decreaseEnd = function() { Prometheus.Graph.prototype.decreaseEnd = function() {
var self = this; var self = this;
self.setEndDate(new Date(self.getOrSetEndDate() - self.parseRange(self.rangeInput.val()) * 1000/2 )) self.setEndDate(new Date(self.getOrSetEndDate() - self.parseDuration(self.rangeInput.val()) * 1000/2 ))
self.submitQuery(); self.submitQuery();
}; };
@ -253,14 +258,17 @@ Prometheus.Graph.prototype.submitQuery = function() {
var startTime = new Date().getTime(); var startTime = new Date().getTime();
var rangeSeconds = self.parseRange(self.rangeInput.val()); var rangeSeconds = self.parseDuration(self.rangeInput.val());
self.queryForm.find("input[name=range]").val(rangeSeconds); self.queryForm.find("input[name=range]").val(rangeSeconds);
var resolution = self.queryForm.find("input[name=step_input]").val() || Math.max(Math.floor(rangeSeconds / 250), 1); var resolution = self.queryForm.find("input[name=step_input]").val() || Math.max(Math.floor(rangeSeconds / 250), 1);
self.queryForm.find("input[name=step]").val(resolution); self.queryForm.find("input[name=step]").val(resolution);
var endDate = self.getEndDate() / 1000; var endDate = self.getEndDate() / 1000;
self.queryForm.find("input[name=end]").val(endDate); self.queryForm.find("input[name=end]").val(endDate);
$.ajax({ if (self.queryXhr) {
self.queryXhr.abort()
}
self.queryXhr = $.ajax({
method: self.queryForm.attr("method"), method: self.queryForm.attr("method"),
url: self.queryForm.attr("action"), url: self.queryForm.attr("action"),
dataType: "json", dataType: "json",
@ -288,6 +296,22 @@ Prometheus.Graph.prototype.submitQuery = function() {
}); });
}; };
Prometheus.Graph.prototype.updateRefresh = function() {
var self = this;
if (self.timeoutID) {
window.clearTimeout(self.timeoutID)
}
interval = self.parseDuration(self.refreshInterval.val());
if (!interval) { return };
self.timeoutID = window.setTimeout(function() {
self.submitQuery()
self.updateRefresh()
}, interval * SECOND)
}
Prometheus.Graph.prototype.renderLabels = function(labels) { Prometheus.Graph.prototype.renderLabels = function(labels) {
var labelStrings = []; var labelStrings = [];
for (label in labels) { for (label in labels) {

View file

@ -11,17 +11,26 @@
<div class="config"> <div class="config">
<label for="range_input{{id}}">Range:</label> <label for="range_input{{id}}">Range:</label>
<input type="button" value="-" name="dec_range"> <input type="button" value="-" name="dec_range">
<input type="text" name="range_input" id="range_input{{id}}" size="2" value="{{range_input}}" > <input title="Time range of graph" type="text" name="range_input" id="range_input{{id}}" size="2" value="{{range_input}}" >
<input type="hidden" name="range">
<input type="button" value="+" name="inc_range"> <input type="button" value="+" name="inc_range">
<input type="hidden" name="range">
<input type="button" value="&larr;" name="dec_end"> <input type="button" value="&larr;" name="dec_end">
<input placeholder="Until" type="text" name="end_input" id="end{{id}}" size="16" value="{{end }}"> <input title="End time of graph" placeholder="Until" type="text" name="end_input" id="end{{id}}" size="16" value="{{end }}">
<input type="button" value="&rarr;" name="inc_end"> <input type="button" value="&rarr;" name="inc_end">
<input type="hidden" name="end"> <input type="hidden" name="end">
<input placeholder="Resolution (s)" type="text" name="step_input" id="step_input{{id}}" value ="{{step_input}}" size="10"> <input title="Resolution in seconds" placeholder="Res. (s)" type="text" name="step_input" id="step_input{{id}}" value="{{step_input}}" size="6">
<input type="hidden" name="step"> <input type="hidden" name="step">
<label for="refresh">↻</label>
<select title="Auto-refresh interval" name="refresh" class="refresh_interval">
<option>disabled</option>
<option>2m</option>
<option>3m</option>
<option>5m</option>
<option>10m</option>
<option>15m</option>
</select>
<span class="opts"> <span class="opts">
<input type="checkbox" name="stacked" id="stacked{{id}}" {{stacked_checked}}> <input type="checkbox" name="stacked" id="stacked{{id}}" {{stacked_checked}}>
<label for="stacked{{id}}">Stacked</label> <label for="stacked{{id}}">Stacked</label>