176 lines
4.3 KiB
JavaScript
176 lines
4.3 KiB
JavaScript
var Console = function(container) {
|
|
this.container_ = container;
|
|
this.client_ = new TSDBClient();
|
|
this.loadJSAPI_();
|
|
};
|
|
|
|
|
|
Console.prototype.loadJSAPI_ = function() {
|
|
google.load('visualization', '1.1', {
|
|
packages: ['corechart'],
|
|
callback: this.jsapiLoaded_.bind(this),
|
|
});
|
|
};
|
|
|
|
|
|
Console.prototype.jsapiLoaded_ = function() {
|
|
var exprContainer = document.createElement('div');
|
|
exprContainer.className = 'expr';
|
|
this.container_.appendChild(exprContainer);
|
|
|
|
var form = document.createElement('form');
|
|
exprContainer.appendChild(form);
|
|
|
|
this.exprInput_ = document.createElement('input');
|
|
form.appendChild(this.exprInput_);
|
|
form.addEventListener('submit', this.onExprChange_.bind(this));
|
|
|
|
var chartContainer = document.createElement('div');
|
|
this.container_.appendChild(chartContainer);
|
|
|
|
this.charts_ = [
|
|
{
|
|
'title': 'Last 20 minutes',
|
|
'seconds': 120 * 10,
|
|
'resolution': 'full',
|
|
},
|
|
{
|
|
'title': 'Last 2 hours',
|
|
'seconds': 120 * 60,
|
|
'resolution': 'minute',
|
|
},
|
|
{
|
|
'title': 'Last 5 days',
|
|
'seconds': 120 * 60 * 60,
|
|
'resolution': 'hour',
|
|
},
|
|
{
|
|
'title': 'Last 120 days',
|
|
'seconds': 120 * 60 * 60 * 24,
|
|
'resolution': 'day',
|
|
},
|
|
];
|
|
for (var i = 0; i < this.charts_.length; i++) {
|
|
var obj = this.charts_[i];
|
|
obj.container = document.createElement('div');
|
|
obj.container.className = 'chart';
|
|
chartContainer.appendChild(obj.container);
|
|
}
|
|
|
|
this.expr_ = decodeURIComponent(window.location.hash.substring(1));
|
|
// Ensure that the URL is properly encoded for copy & paste.
|
|
window.location.hash = encodeURIComponent(this.expr_);
|
|
this.exprInput_.value = this.expr_;
|
|
window.addEventListener('hashchange', this.onHashChange_.bind(this));
|
|
|
|
this.loadCharts_();
|
|
};
|
|
|
|
|
|
Console.prototype.onExprChange_ = function(e) {
|
|
window.location.hash = encodeURIComponent(this.exprInput_.value);
|
|
e.preventDefault();
|
|
};
|
|
|
|
|
|
Console.prototype.onHashChange_ = function(e) {
|
|
this.expr_ = decodeURIComponent(window.location.hash.substring(1));
|
|
this.exprInput_.value = this.expr_;
|
|
this.loadCharts_();
|
|
};
|
|
|
|
|
|
Console.prototype.loadCharts_ = function() {
|
|
if (!this.expr_) {
|
|
return;
|
|
}
|
|
|
|
for (var i = 0; i < this.charts_.length; i++) {
|
|
var options = this.charts_[i];
|
|
if (options.instance) {
|
|
options.instance.destroy();
|
|
}
|
|
options.instance = new Chart(this.client_, this.expr_, options);
|
|
}
|
|
};
|
|
|
|
|
|
var Chart = function(client, expr, options) {
|
|
this.options_ = options;
|
|
this.watch_ = client.watch(
|
|
expr, this.options_.seconds, this.options_.resolution,
|
|
this.drawChart_.bind(this));
|
|
};
|
|
|
|
|
|
Chart.prototype.drawChart_ = function(data) {
|
|
var dataTable = new google.visualization.DataTable();
|
|
dataTable.addColumn('date', 'Timestamp');
|
|
|
|
for (var i = data.length - 1; i >= 0; i--) {
|
|
var ts = data[i];
|
|
if (!ts.timestamps_values.length) {
|
|
data.splice(i, 1);
|
|
continue;
|
|
}
|
|
var tags = [];
|
|
for (var key in ts.tags) {
|
|
tags.push(key + '=' + ts.tags[key]);
|
|
}
|
|
dataTable.addColumn('number', tags.join(','));
|
|
}
|
|
for (var i = 0; i < data.length; i++) {
|
|
var ts = data[i];
|
|
for (var j = 0; j < ts.timestamps_values.length; j++) {
|
|
var row = [new Date(ts.timestamps_values[j][0] * 1000)];
|
|
for (var k = 0; k < i; k++) {
|
|
row.push(null);
|
|
}
|
|
row.push(ts.timestamps_values[j][1]);
|
|
for (var k = i + 1; k < data.length; k++) {
|
|
row.push(null);
|
|
}
|
|
dataTable.addRow(row);
|
|
}
|
|
};
|
|
|
|
var options = {
|
|
title: this.options_.title,
|
|
legend: {
|
|
position: 'bottom'
|
|
},
|
|
hAxis: {
|
|
gridlines: {
|
|
count: -1,
|
|
},
|
|
},
|
|
explorer: {
|
|
actions: [
|
|
'dragToZoom',
|
|
'rightClickToReset',
|
|
],
|
|
},
|
|
};
|
|
|
|
// It'd be great to use the material design charts here, but they fail to load
|
|
// ~25% of the time, which is a non-starter.
|
|
if (this.chartObj_) {
|
|
this.chartObj_.clearChart();
|
|
}
|
|
this.chartObj_ = new google.visualization.LineChart(this.options_.container);
|
|
this.chartObj_.draw(dataTable, options);
|
|
};
|
|
|
|
|
|
Chart.prototype.destroy = function() {
|
|
this.watch_.destroy();
|
|
if (this.chartObj_) {
|
|
this.chartObj_.clearChart();
|
|
}
|
|
};
|
|
|
|
|
|
document.addEventListener('DOMContentLoaded', function(e) {
|
|
new Console(document.getElementById('container'));
|
|
});
|