Merge pull request #208 from prometheus/feature/toggle-console

Add the console to the main/graph ui.
This commit is contained in:
juliusv 2013-05-02 04:05:53 -07:00
commit 2b9ba56d61
12 changed files with 104 additions and 87 deletions

View File

@ -20,7 +20,3 @@ import (
func graphHandler(w http.ResponseWriter, r *http.Request) {
executeTemplate(w, "graph", nil)
}
func consoleHandler(w http.ResponseWriter, r *http.Request) {
executeTemplate(w, "console", nil)
}

View File

@ -2,6 +2,10 @@ body {
margin: 0;
}
a { color: black; }
a:hover { color: gray; }
a:active { color: black; }
.graph_container {
font-family: Arial, Helvetica, sans-serif;
}
@ -62,3 +66,15 @@ svg {
input[title=*]:hover:after {
content: attr(title);
}
.console {
white-space: pre;
overflow: scroll;
}
.ui-tabs {
padding: 0px;
}
.ui-widget {
font-size: 0.8em;
}

View File

@ -55,7 +55,7 @@ input[name=end_input], input[name=range_input] {
}
#navigation {
font-size: 20pt;
font-size: 16pt;
background-color: #333;
color: #F2F2F2;
line-height: 120%;

View File

@ -1,26 +0,0 @@
function submitQuery() {
var form = $("#queryForm");
$.ajax({
method: form.attr("method"),
url: form.attr("action"),
dataType: "html",
data: form.serialize(),
success: function(data, textStatus) {
$("#result").text(data);
},
error: function() {
alert("Error executing query!");
},
});
return false;
}
function bindHandlers() {
$.ajaxSetup({
cache: false
});
$("#queryForm").submit(submitQuery);
}
$(bindHandlers);

View File

@ -58,6 +58,7 @@ Prometheus.Graph.prototype.initialize = function() {
self.options['id'] = self.id;
self.options['range_input'] = self.options['range_input'] || "1h";
self.options['stacked_checked'] = self.options['stacked'] ? "checked" : "";
self.options['tab'] = self.options['tab'] || 0;
// Draw graph controls and container from Handlebars template.
@ -73,6 +74,22 @@ Prometheus.Graph.prototype.initialize = function() {
self.stacked = self.queryForm.find("input[name=stacked]");
self.insertMetric = self.queryForm.find("select[name=insert_metric]");
self.refreshInterval = self.queryForm.find("select[name=refresh]");
self.consoleTab = graphWrapper.find(".console");
self.graphTab = graphWrapper.find(".graph_container");
self.tabs = graphWrapper.find(".tabs");;
self.tab = $(self.tabs.find("> div")[self.options['tab']]); // active tab
self.tabs.tabs({
active: self.options['tab'],
activate: function(e, ui) {
storeGraphOptionsInUrl();
self.tab = ui.newPanel
if (self.tab.hasClass('reload')) { // reload if flagged with class 'reload'
self.submitQuery();
}
}
});
// Return moves focus back to expr instead of submitting.
self.insertMetric.bind('keydown', 'return', function(e) {
@ -98,7 +115,12 @@ Prometheus.Graph.prototype.initialize = function() {
self.refreshInterval.change(function() { self.updateRefresh() })
self.stacked.change(function() { self.updateGraph(); });
self.queryForm.submit(function() { self.submitQuery(); return false; });
self.queryForm.submit(function() {
self.consoleTab.addClass('reload');
self.graphTab.addClass('reload');
self.submitQuery();
return false;
});
self.spinner.hide();
self.queryForm.find("input[name=inc_range]").click(function() { self.increaseRange(); });
@ -168,6 +190,7 @@ Prometheus.Graph.prototype.getOptions = function() {
}
}
});
options['tab'] = self.tabs.tabs("option", "active");
return options;
};
@ -268,25 +291,28 @@ Prometheus.Graph.prototype.submitQuery = function() {
if (self.queryXhr) {
self.queryXhr.abort()
}
var url
var data
if (self.tab[0] == self.graphTab[0]) {
url = self.queryForm.attr("action")
data = self.queryForm.serialize()
dataType = "json"
success = function(json, textStatus) { self.handleGraphResponse(json, textStatus) }
} else {
url = '/api/query'
data = self.expr.serialize()
dataType = "text"
success = function(text, textStatus) { self.handleConsoleResponse(text, textStatus) }
}
self.queryXhr = $.ajax({
method: self.queryForm.attr("method"),
url: self.queryForm.attr("action"),
dataType: "json",
url: url,
dataType: dataType,
data: self.queryForm.serialize(),
success: function(json, textStatus) {
if (json.Type == "error") {
alert(json.Value);
return;
}
self.data = self.transformData(json);
if (self.data.length == 0) {
alert("No datapoints found.");
return;
}
self.updateGraph(true);
},
error: function() {
alert("Error executing query!");
success: success,
error: function(xhr, resp) {
alert("Error executing query: " + resp);
},
complete: function() {
var duration = new Date().getTime() - startTime;
@ -453,11 +479,31 @@ Prometheus.Graph.prototype.updateGraph = function(reloadGraph) {
Prometheus.Graph.prototype.resizeGraph = function() {
var self = this;
self.rickshawGraph.configure({
height: Math.max(self.graph.innerHeight(), 100),
width: Math.max(self.graph.innerWidth(), 200),
});
self.rickshawGraph.render();
};
}
Prometheus.Graph.prototype.handleGraphResponse = function(json, textStatus) {
var self = this
if (json.Type == "error") {
alert(json.Value);
return;
}
self.data = self.transformData(json);
if (self.data.length == 0) {
alert("No datapoints found.");
return;
}
self.graphTab.removeClass('reload');
self.updateGraph(true);
}
Prometheus.Graph.prototype.handleConsoleResponse = function(text, textStatus) {
var self = this;
self.consoleTab.removeClass('reload');
self.consoleTab.text(text);
}
function parseGraphOptionsFromUrl() {
var hashOptions = window.location.hash.slice(1);
@ -465,10 +511,11 @@ function parseGraphOptionsFromUrl() {
return [];
}
var optionsJSON = decodeURIComponent(window.location.hash.slice(1));
return JSON.parse(optionsJSON);
options = JSON.parse(optionsJSON);
return options;
}
function storeGraphOptionsInUrl(options) {
function storeGraphOptionsInUrl() {
var allGraphsOptions = [];
for (var i = 0; i < graphs.length; i++) {
allGraphsOptions.push(graphs[i].getOptions());
@ -508,5 +555,4 @@ function init() {
}
})
}
$(init);

View File

@ -1,17 +1,28 @@
<div id="graph_wrapper{{id}}">
<div class="grouping_box">
<form action="/api/query_range" method="GET" class="query_form">
<form action="/api/query_range" method="GET" class="query_form">
<div class="grouping_box">
<div class="head">
<div class="expr">
<input placeholder="Expression" type="text" name="expr" id="expr{{id}}" size="80" value="{{expr}}">
<select name="insert_metric">
<option value="">- Insert Metric -</option>
</select>
<input type="submit" value="Graph" name="submit">
</div>
</div>
<div class="eval_stats"></div>
<img src="/static/img/ajax-loader.gif" class="spinner" alt="ajax_spinner">
</div>
<div class="grouping_box tabs">
<ul>
<li><a href="#graph{{id}}">Graph</a></li>
<li><a href="#console{{id}}">Console</a></li>
</ul>
<div id="graph{{id}}" class="graph_container reload">
<div class="config">
<label for="range_input{{id}}">Range:</label>
<input type="button" value="-" name="dec_range">
<input title="Time range of graph" 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="3" value="{{range_input}}" >
<input type="button" value="+" name="inc_range">
<input type="hidden" name="range">
@ -34,18 +45,13 @@
<span class="opts">
<input type="checkbox" name="stacked" id="stacked{{id}}" {{stacked_checked}}>
<label for="stacked{{id}}">Stacked</label>
<input type="submit" value="Graph" name="submit">
</span>
</div>
<div class="graph"></div>
<div class="legend"></div>
</div>
<div class="eval_stats"></div>
</form>
<img src="/static/img/ajax-loader.gif" class="spinner" alt="ajax_spinner">
</div>
<div class="grouping_box">
<div class="graph_container">
<div class="graph"></div>
<div class="legend"></div>
<div id="console{{id}}" class="console reload"></div>
</div>
</div>
</form>
</div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 B

View File

@ -10,7 +10,6 @@
<body>
<div id="navigation">
<a href="/console">Console</a>
<a href="/graph">Graph</a>
<a href="/">Status</a>
</div>

View File

@ -1,19 +0,0 @@
{{define "head"}}
<script src="/static/js/exprBrowser.js"></script>
{{end}}
{{define "content"}}
<div class="grouping_box">
<form action="/api/query" method="GET" id="queryForm">
<label for="expr">Expression:</label>
<input type="text" name="expr" id="expr" size="100">
<input type="checkbox" name="json" id="json" value="JSON"><label for="json">JSON</label>
<input type="submit" value="Evaluate">
</form>
</div>
<div class="grouping_box">
<pre>
<div id="result"></div>
</pre>
</div>
{{end}}

View File

@ -49,7 +49,6 @@ func StartServing(appState *appstate.ApplicationState) {
exp.Handle("/", statusHandler)
exp.HandleFunc("/graph", graphHandler)
exp.HandleFunc("/console", consoleHandler)
exp.Handle("/api/", gorest.Handle())
exp.Handle("/metrics.json", prometheus.DefaultHandler)