Commit cb49e11e by Torkel Ödegaard

feat(live): panel sdk/api refactorings

parent 7366cef1
......@@ -30,11 +30,6 @@ function (angular, _, config) {
$scope.toggleRow = function(row) {
row.collapse = row.collapse ? false : true;
if (!row.collapse) {
$timeout(function() {
$scope.$broadcast('render');
});
}
};
$scope.addPanel = function(panel) {
......
......@@ -53,21 +53,14 @@ class MetricsPanelCtrl extends PanelCtrl {
this.datasources = this.datasourceSrv.getMetricSources();
}
loadSnapshot(data) {
// null op
return data;
}
refresh() {
// ignore fetching data if another panel is in fullscreen
if (this.otherPanelInFullscreenMode()) { return; }
// if we have snapshot data use that
if (this.panel.snapshotData) {
if (this.loadSnapshot) {
this.updateTimeRange();
this.loadSnapshot(this.panel.snapshotData);
}
this.updateTimeRange();
this.events.emit('load-snapshot', this.panel.snapshotData);
return;
}
......@@ -83,15 +76,13 @@ class MetricsPanelCtrl extends PanelCtrl {
// load datasource service
this.datasourceSrv.get(this.panel.datasource)
.then(this.issueQueries.bind(this))
.then(() => {
this.loading = false;
}).catch(err => {
console.log('Panel data error:', err);
.then(this.handleQueryResult.bind(this))
.catch(err => {
this.loading = false;
this.error = err.message || "Timeseries data request error";
this.inspector = {error: err};
this.events.emit('data-error', err);
console.log('Panel data error:', err);
});
}
......@@ -184,29 +175,24 @@ class MetricsPanelCtrl extends PanelCtrl {
};
this.setTimeQueryStart();
try {
return datasource.query(metricsQuery).then(results => {
this.setTimeQueryEnd();
// check for if data source returns subject
if (results && results.subscribe) {
this.handleDataStream(results);
return;
}
return datasource.query(metricsQuery);
}
if (this.dashboard.snapshot) {
this.panel.snapshotData = results;
}
handleQueryResult(result) {
this.setTimeQueryEnd();
this.loading = false;
return this.events.emit('data-received', results);
});
} catch (err) {
return this.$q.reject(err);
// check for if data source returns subject
if (result && result.subscribe) {
this.handleDataStream(result);
return;
}
if (this.dashboard.snapshot) {
this.panel.snapshotData = result;
}
}
dataHandler(data) {
return data;
return this.events.emit('data-received', result.data);
}
handleDataStream(stream) {
......
......@@ -121,7 +121,7 @@ module.directive('panelResizer', function($rootScope) {
}
scope.$apply(function() {
ctrl.broadcastRender();
ctrl.render();
});
}
......
......@@ -16,38 +16,34 @@ export function GraphiteDatasource(instanceSettings, $q, backendSrv, templateSrv
this.render_method = instanceSettings.render_method || 'POST';
this.query = function(options) {
try {
var graphOptions = {
from: this.translateTime(options.rangeRaw.from, false),
until: this.translateTime(options.rangeRaw.to, true),
targets: options.targets,
format: options.format,
cacheTimeout: options.cacheTimeout || this.cacheTimeout,
maxDataPoints: options.maxDataPoints,
};
var params = this.buildGraphiteParams(graphOptions, options.scopedVars);
if (params.length === 0) {
return $q.when([]);
}
if (options.format === 'png') {
return $q.when(this.url + '/render' + '?' + params.join('&'));
}
var graphOptions = {
from: this.translateTime(options.rangeRaw.from, false),
until: this.translateTime(options.rangeRaw.to, true),
targets: options.targets,
format: options.format,
cacheTimeout: options.cacheTimeout || this.cacheTimeout,
maxDataPoints: options.maxDataPoints,
};
var params = this.buildGraphiteParams(graphOptions, options.scopedVars);
if (params.length === 0) {
return $q.when([]);
}
var httpOptions: any = {method: this.render_method, url: '/render'};
if (options.format === 'png') {
return $q.when(this.url + '/render' + '?' + params.join('&'));
}
if (httpOptions.method === 'GET') {
httpOptions.url = httpOptions.url + '?' + params.join('&');
} else {
httpOptions.data = params.join('&');
httpOptions.headers = { 'Content-Type': 'application/x-www-form-urlencoded' };
}
var httpOptions: any = {method: this.render_method, url: '/render'};
return this.doGraphiteRequest(httpOptions).then(this.convertDataPointsToMs);
} catch (err) {
return $q.reject(err);
if (httpOptions.method === 'GET') {
httpOptions.url = httpOptions.url + '?' + params.join('&');
} else {
httpOptions.data = params.join('&');
httpOptions.headers = { 'Content-Type': 'application/x-www-form-urlencoded' };
}
return this.doGraphiteRequest(httpOptions).then(this.convertDataPointsToMs);
};
this.convertDataPointsToMs = function(result) {
......
......@@ -160,17 +160,17 @@ class GraphCtrl extends MetricsPanelCtrl {
this.render([]);
}
onDataReceived(results) {
onDataReceived(dataList) {
// png renderer returns just a url
if (_.isString(results)) {
this.render(results);
if (_.isString(dataList)) {
this.render(dataList);
return;
}
this.datapointsWarning = false;
this.datapointsCount = 0;
this.datapointsOutside = false;
this.seriesList = _.map(results.data, (series, i) => this.seriesHandler(series, i));
this.seriesList = dataList.map(this.seriesHandler.bind(this));
this.datapointsWarning = this.datapointsCount === 0 || this.datapointsOutside;
this.annotationsPromise.then(annotations => {
......
......@@ -14,47 +14,19 @@ describe('GraphCtrl', function() {
beforeEach(ctx.providePhase());
beforeEach(ctx.createPanelController(GraphCtrl));
describe('get_data with 2 series', function() {
beforeEach(function() {
ctx.annotationsSrv.getAnnotations = sinon.stub().returns(ctx.$q.when([]));
ctx.datasource.query = sinon.stub().returns(ctx.$q.when({
data: [
{ target: 'test.cpu1', datapoints: [[1, 10]]},
{ target: 'test.cpu2', datapoints: [[1, 10]]}
]
}));
ctx.ctrl.render = sinon.spy();
ctx.ctrl.refreshData(ctx.datasource);
ctx.scope.$digest();
});
it('should send time series to render', function() {
var data = ctx.ctrl.render.getCall(0).args[0];
expect(data.length).to.be(2);
});
describe('get_data failure following success', function() {
beforeEach(function() {
ctx.datasource.query = sinon.stub().returns(ctx.$q.reject('Datasource Error'));
ctx.ctrl.refreshData(ctx.datasource);
ctx.scope.$digest();
});
});
beforeEach(() => {
ctx.ctrl.annotationsPromise = Promise.resolve({});
ctx.ctrl.updateTimeRange();
});
describe('msResolution with second resolution timestamps', function() {
beforeEach(function() {
ctx.datasource.query = sinon.stub().returns(ctx.$q.when({
data: [
{ target: 'test.cpu1', datapoints: [[1234567890, 45], [1234567899, 60]]},
{ target: 'test.cpu2', datapoints: [[1236547890, 55], [1234456709, 90]]}
]
}));
var data = [
{ target: 'test.cpu1', datapoints: [[1234567890, 45], [1234567899, 60]]},
{ target: 'test.cpu2', datapoints: [[1236547890, 55], [1234456709, 90]]}
];
ctx.ctrl.panel.tooltip.msResolution = false;
ctx.ctrl.refreshData(ctx.datasource);
ctx.scope.$digest();
ctx.ctrl.onDataReceived(data);
});
it('should not show millisecond resolution tooltip', function() {
......@@ -64,15 +36,12 @@ describe('GraphCtrl', function() {
describe('msResolution with millisecond resolution timestamps', function() {
beforeEach(function() {
ctx.datasource.query = sinon.stub().returns(ctx.$q.when({
data: [
{ target: 'test.cpu1', datapoints: [[1234567890000, 45], [1234567899000, 60]]},
{ target: 'test.cpu2', datapoints: [[1236547890001, 55], [1234456709000, 90]]}
]
}));
var data = [
{ target: 'test.cpu1', datapoints: [[1234567890000, 45], [1234567899000, 60]]},
{ target: 'test.cpu2', datapoints: [[1236547890001, 55], [1234456709000, 90]]}
];
ctx.ctrl.panel.tooltip.msResolution = false;
ctx.ctrl.refreshData(ctx.datasource);
ctx.scope.$digest();
ctx.ctrl.onDataReceived(data);
});
it('should show millisecond resolution tooltip', function() {
......@@ -82,15 +51,12 @@ describe('GraphCtrl', function() {
describe('msResolution with millisecond resolution timestamps but with trailing zeroes', function() {
beforeEach(function() {
ctx.datasource.query = sinon.stub().returns(ctx.$q.when({
data: [
{ target: 'test.cpu1', datapoints: [[1234567890000, 45], [1234567899000, 60]]},
{ target: 'test.cpu2', datapoints: [[1236547890000, 55], [1234456709000, 90]]}
]
}));
var data = [
{ target: 'test.cpu1', datapoints: [[1234567890000, 45], [1234567899000, 60]]},
{ target: 'test.cpu2', datapoints: [[1236547890000, 55], [1234456709000, 90]]}
];
ctx.ctrl.panel.tooltip.msResolution = false;
ctx.ctrl.refreshData(ctx.datasource);
ctx.scope.$digest();
ctx.ctrl.onDataReceived(data);
});
it('should not show millisecond resolution tooltip', function() {
......@@ -100,16 +66,13 @@ describe('GraphCtrl', function() {
describe('msResolution with millisecond resolution timestamps in one of the series', function() {
beforeEach(function() {
ctx.datasource.query = sinon.stub().returns(ctx.$q.when({
data: [
{ target: 'test.cpu1', datapoints: [[1234567890000, 45], [1234567899000, 60]]},
{ target: 'test.cpu2', datapoints: [[1236547890010, 55], [1234456709000, 90]]},
{ target: 'test.cpu3', datapoints: [[1236547890000, 65], [1234456709000, 120]]}
]
}));
var data = [
{ target: 'test.cpu1', datapoints: [[1234567890000, 45], [1234567899000, 60]]},
{ target: 'test.cpu2', datapoints: [[1236547890010, 55], [1234456709000, 90]]},
{ target: 'test.cpu3', datapoints: [[1236547890000, 65], [1234456709000, 120]]}
];
ctx.ctrl.panel.tooltip.msResolution = false;
ctx.ctrl.refreshData(ctx.datasource);
ctx.scope.$digest();
ctx.ctrl.onDataReceived(data);
});
it('should show millisecond resolution tooltip', function() {
......
......@@ -45,7 +45,7 @@ class SingleStatCtrl extends MetricsPanelCtrl {
static templateUrl = 'module.html';
series: any[];
data: any[];
data: any;
fontSizes: any[];
unitFormats: any[];
......@@ -53,6 +53,9 @@ class SingleStatCtrl extends MetricsPanelCtrl {
constructor($scope, $injector, private $location, private linkSrv) {
super($scope, $injector);
_.defaults(this.panel, panelDefaults);
this.events.on('data-received', this.onDataReceived.bind(this));
this.events.on('data-error', this.onDataError.bind(this));
}
initEditMode() {
......@@ -68,23 +71,27 @@ class SingleStatCtrl extends MetricsPanelCtrl {
this.render();
}
refreshData(datasource) {
return this.issueQueries(datasource)
.then(this.dataHandler.bind(this))
.catch(err => {
this.series = [];
this.render();
throw err;
});
}
loadSnapshot(snapshotData) {
// give element time to get attached and get dimensions
this.$timeout(() => this.dataHandler(snapshotData), 50);
}
dataHandler(results) {
this.series = _.map(results.data, this.seriesHandler.bind(this));
onDataError(err) {
this.onDataReceived({data: []});
}
onDataReceived(dataList) {
this.series = dataList.map(this.seriesHandler.bind(this));
var data: any = {};
this.setValues(data);
data.thresholds = this.panel.thresholds.split(',').map(function(strVale) {
return Number(strVale.trim());
});
data.colorMap = this.panel.colors;
this.data = data;
this.render();
}
......@@ -155,20 +162,6 @@ class SingleStatCtrl extends MetricsPanelCtrl {
return result;
}
render() {
var data: any = {};
this.setValues(data);
data.thresholds = this.panel.thresholds.split(',').map(function(strVale) {
return Number(strVale.trim());
});
data.colorMap = this.panel.colors;
this.data = data;
this.broadcastRender();
}
setValues(data) {
data.flotpairs = [];
......
......@@ -23,12 +23,11 @@ describe('SingleStatCtrl', function() {
beforeEach(function() {
setupFunc();
ctx.datasource.query = sinon.stub().returns(ctx.$q.when({
data: [{target: 'test.cpu1', datapoints: ctx.datapoints}]
}));
var data = [
{target: 'test.cpu1', datapoints: ctx.datapoints}
];
ctx.ctrl.refreshData(ctx.datasource);
ctx.scope.$digest();
ctx.ctrl.onDataReceived(data);
ctx.data = ctx.ctrl.data;
});
};
......
......@@ -57,6 +57,9 @@ class TablePanelCtrl extends MetricsPanelCtrl {
}
_.defaults(this.panel, panelDefaults);
this.events.on('data-received', this.onDataReceived.bind(this));
this.events.on('data-error', this.onDataError.bind(this));
}
initEditMode() {
......@@ -70,7 +73,7 @@ class TablePanelCtrl extends MetricsPanelCtrl {
return menu;
}
refreshData(datasource) {
issueQueries(datasource) {
this.pageIndex = 0;
if (this.panel.transform === 'annotations') {
......@@ -80,36 +83,19 @@ class TablePanelCtrl extends MetricsPanelCtrl {
});
}
return this.issueQueries(datasource).catch(err => {
this.render();
throw err;
});
return super.issueQueries(datasource);
}
toggleColumnSort(col, colIndex) {
if (this.panel.sort.col === colIndex) {
if (this.panel.sort.desc) {
this.panel.sort.desc = false;
} else {
this.panel.sort.col = null;
}
} else {
this.panel.sort.col = colIndex;
this.panel.sort.desc = true;
}
onDataError(err) {
this.dataRaw = [];
this.render();
}
dataHandler(results) {
this.dataRaw = results.data;
onDataReceived(dataList) {
this.dataRaw = dataList;
this.pageIndex = 0;
this.render();
}
render() {
// automatically correct transform mode
// based on data
// automatically correct transform mode based on data
if (this.dataRaw && this.dataRaw.length) {
if (this.dataRaw[0].type === 'table') {
this.panel.transform = 'table';
......@@ -126,7 +112,22 @@ class TablePanelCtrl extends MetricsPanelCtrl {
this.table = transformDataToTable(this.dataRaw, this.panel);
this.table.sort(this.panel.sort);
this.broadcastRender(this.table);
this.render(this.table);
}
toggleColumnSort(col, colIndex) {
if (this.panel.sort.col === colIndex) {
if (this.panel.sort.desc) {
this.panel.sort.desc = false;
} else {
this.panel.sort.col = null;
}
} else {
this.panel.sort.col = colIndex;
this.panel.sort.desc = true;
}
this.render();
}
exportCsv() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment