mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
feat(live): panel sdk/api refactorings
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
if (this.dashboard.snapshot) {
|
||||
this.panel.snapshotData = results;
|
||||
}
|
||||
|
||||
return this.events.emit('data-received', results);
|
||||
});
|
||||
} catch (err) {
|
||||
return this.$q.reject(err);
|
||||
}
|
||||
return datasource.query(metricsQuery);
|
||||
}
|
||||
|
||||
dataHandler(data) {
|
||||
return data;
|
||||
handleQueryResult(result) {
|
||||
this.setTimeQueryEnd();
|
||||
this.loading = false;
|
||||
|
||||
// check for if data source returns subject
|
||||
if (result && result.subscribe) {
|
||||
this.handleDataStream(result);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.dashboard.snapshot) {
|
||||
this.panel.snapshotData = result;
|
||||
}
|
||||
|
||||
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 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 httpOptions: any = {method: this.render_method, url: '/render'};
|
||||
|
||||
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);
|
||||
} catch (err) {
|
||||
return $q.reject(err);
|
||||
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 httpOptions: any = {method: this.render_method, url: '/render'};
|
||||
|
||||
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() {
|
||||
|
||||
Reference in New Issue
Block a user