mirror of
https://github.com/prometheus/prometheus.git
synced 2025-01-13 06:47:28 -08:00
Merge pull request #208 from prometheus/feature/toggle-console
Add the console to the main/graph ui.
This commit is contained in:
commit
2b9ba56d61
|
@ -20,7 +20,3 @@ import (
|
||||||
func graphHandler(w http.ResponseWriter, r *http.Request) {
|
func graphHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
executeTemplate(w, "graph", nil)
|
executeTemplate(w, "graph", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func consoleHandler(w http.ResponseWriter, r *http.Request) {
|
|
||||||
executeTemplate(w, "console", nil)
|
|
||||||
}
|
|
||||||
|
|
|
@ -2,6 +2,10 @@ body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a { color: black; }
|
||||||
|
a:hover { color: gray; }
|
||||||
|
a:active { color: black; }
|
||||||
|
|
||||||
.graph_container {
|
.graph_container {
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
}
|
}
|
||||||
|
@ -62,3 +66,15 @@ svg {
|
||||||
input[title=*]:hover:after {
|
input[title=*]:hover:after {
|
||||||
content: attr(title);
|
content: attr(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.console {
|
||||||
|
white-space: pre;
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-tabs {
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
.ui-widget {
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ input[name=end_input], input[name=range_input] {
|
||||||
}
|
}
|
||||||
|
|
||||||
#navigation {
|
#navigation {
|
||||||
font-size: 20pt;
|
font-size: 16pt;
|
||||||
background-color: #333;
|
background-color: #333;
|
||||||
color: #F2F2F2;
|
color: #F2F2F2;
|
||||||
line-height: 120%;
|
line-height: 120%;
|
||||||
|
|
|
@ -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);
|
|
|
@ -58,6 +58,7 @@ Prometheus.Graph.prototype.initialize = function() {
|
||||||
self.options['id'] = self.id;
|
self.options['id'] = self.id;
|
||||||
self.options['range_input'] = self.options['range_input'] || "1h";
|
self.options['range_input'] = self.options['range_input'] || "1h";
|
||||||
self.options['stacked_checked'] = self.options['stacked'] ? "checked" : "";
|
self.options['stacked_checked'] = self.options['stacked'] ? "checked" : "";
|
||||||
|
self.options['tab'] = self.options['tab'] || 0;
|
||||||
|
|
||||||
// Draw graph controls and container from Handlebars template.
|
// 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.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]");
|
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.
|
// Return moves focus back to expr instead of submitting.
|
||||||
self.insertMetric.bind('keydown', 'return', function(e) {
|
self.insertMetric.bind('keydown', 'return', function(e) {
|
||||||
|
@ -98,7 +115,12 @@ Prometheus.Graph.prototype.initialize = function() {
|
||||||
self.refreshInterval.change(function() { self.updateRefresh() })
|
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.consoleTab.addClass('reload');
|
||||||
|
self.graphTab.addClass('reload');
|
||||||
|
self.submitQuery();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
self.spinner.hide();
|
self.spinner.hide();
|
||||||
|
|
||||||
self.queryForm.find("input[name=inc_range]").click(function() { self.increaseRange(); });
|
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;
|
return options;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -268,25 +291,28 @@ Prometheus.Graph.prototype.submitQuery = function() {
|
||||||
if (self.queryXhr) {
|
if (self.queryXhr) {
|
||||||
self.queryXhr.abort()
|
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({
|
self.queryXhr = $.ajax({
|
||||||
method: self.queryForm.attr("method"),
|
method: self.queryForm.attr("method"),
|
||||||
url: self.queryForm.attr("action"),
|
url: url,
|
||||||
dataType: "json",
|
dataType: dataType,
|
||||||
data: self.queryForm.serialize(),
|
data: self.queryForm.serialize(),
|
||||||
success: function(json, textStatus) {
|
success: success,
|
||||||
if (json.Type == "error") {
|
error: function(xhr, resp) {
|
||||||
alert(json.Value);
|
alert("Error executing query: " + resp);
|
||||||
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!");
|
|
||||||
},
|
},
|
||||||
complete: function() {
|
complete: function() {
|
||||||
var duration = new Date().getTime() - startTime;
|
var duration = new Date().getTime() - startTime;
|
||||||
|
@ -453,11 +479,31 @@ Prometheus.Graph.prototype.updateGraph = function(reloadGraph) {
|
||||||
Prometheus.Graph.prototype.resizeGraph = function() {
|
Prometheus.Graph.prototype.resizeGraph = function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
self.rickshawGraph.configure({
|
self.rickshawGraph.configure({
|
||||||
height: Math.max(self.graph.innerHeight(), 100),
|
|
||||||
width: Math.max(self.graph.innerWidth(), 200),
|
width: Math.max(self.graph.innerWidth(), 200),
|
||||||
});
|
});
|
||||||
self.rickshawGraph.render();
|
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() {
|
function parseGraphOptionsFromUrl() {
|
||||||
var hashOptions = window.location.hash.slice(1);
|
var hashOptions = window.location.hash.slice(1);
|
||||||
|
@ -465,10 +511,11 @@ function parseGraphOptionsFromUrl() {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
var optionsJSON = decodeURIComponent(window.location.hash.slice(1));
|
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 = [];
|
var allGraphsOptions = [];
|
||||||
for (var i = 0; i < graphs.length; i++) {
|
for (var i = 0; i < graphs.length; i++) {
|
||||||
allGraphsOptions.push(graphs[i].getOptions());
|
allGraphsOptions.push(graphs[i].getOptions());
|
||||||
|
@ -508,5 +555,4 @@ function init() {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
$(init);
|
$(init);
|
||||||
|
|
|
@ -1,17 +1,28 @@
|
||||||
<div id="graph_wrapper{{id}}">
|
<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="head">
|
||||||
<div class="expr">
|
<div class="expr">
|
||||||
<input placeholder="Expression" type="text" name="expr" id="expr{{id}}" size="80" value="{{expr}}">
|
<input placeholder="Expression" type="text" name="expr" id="expr{{id}}" size="80" value="{{expr}}">
|
||||||
<select name="insert_metric">
|
<select name="insert_metric">
|
||||||
<option value="">- Insert Metric -</option>
|
<option value="">- Insert Metric -</option>
|
||||||
</select>
|
</select>
|
||||||
|
<input type="submit" value="Graph" name="submit">
|
||||||
</div>
|
</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">
|
<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 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="button" value="+" name="inc_range">
|
||||||
<input type="hidden" name="range">
|
<input type="hidden" name="range">
|
||||||
|
|
||||||
|
@ -34,18 +45,13 @@
|
||||||
<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>
|
||||||
<input type="submit" value="Graph" name="submit">
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="graph"></div>
|
||||||
|
<div class="legend"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="eval_stats"></div>
|
<div id="console{{id}}" class="console reload"></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>
|
</div>
|
||||||
</div>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
BIN
web/static/vendor/jqueryui/themes/base/images/ui-bg_glass_65_ffffff_1x400.png
vendored
Normal file
BIN
web/static/vendor/jqueryui/themes/base/images/ui-bg_glass_65_ffffff_1x400.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 105 B |
BIN
web/static/vendor/jqueryui/themes/base/images/ui-bg_glass_75_e6e6e6_1x400.png
vendored
Normal file
BIN
web/static/vendor/jqueryui/themes/base/images/ui-bg_glass_75_e6e6e6_1x400.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 110 B |
BIN
web/static/vendor/jqueryui/themes/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png
vendored
Normal file
BIN
web/static/vendor/jqueryui/themes/base/images/ui-bg_highlight-soft_75_cccccc_1x100.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 101 B |
|
@ -10,7 +10,6 @@
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="navigation">
|
<div id="navigation">
|
||||||
<a href="/console">Console</a>
|
|
||||||
<a href="/graph">Graph</a>
|
<a href="/graph">Graph</a>
|
||||||
<a href="/">Status</a>
|
<a href="/">Status</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -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}}
|
|
|
@ -49,7 +49,6 @@ func StartServing(appState *appstate.ApplicationState) {
|
||||||
|
|
||||||
exp.Handle("/", statusHandler)
|
exp.Handle("/", statusHandler)
|
||||||
exp.HandleFunc("/graph", graphHandler)
|
exp.HandleFunc("/graph", graphHandler)
|
||||||
exp.HandleFunc("/console", consoleHandler)
|
|
||||||
|
|
||||||
exp.Handle("/api/", gorest.Handle())
|
exp.Handle("/api/", gorest.Handle())
|
||||||
exp.Handle("/metrics.json", prometheus.DefaultHandler)
|
exp.Handle("/metrics.json", prometheus.DefaultHandler)
|
||||||
|
|
Loading…
Reference in a new issue