Commit 6ff1144a by Torkel Ödegaard

refactoring: prometheus PR #6140

parents 787fea90 d018d2a2
...@@ -7,6 +7,7 @@ import moment from 'moment'; ...@@ -7,6 +7,7 @@ import moment from 'moment';
import kbn from 'app/core/utils/kbn'; import kbn from 'app/core/utils/kbn';
import * as dateMath from 'app/core/utils/datemath'; import * as dateMath from 'app/core/utils/datemath';
import PrometheusMetricFindQuery from './metric_find_query'; import PrometheusMetricFindQuery from './metric_find_query';
import TableModel from 'app/core/table_model';
var durationSplitRegexp = /(\d+)(ms|s|m|h|d|w|M|y)/; var durationSplitRegexp = /(\d+)(ms|s|m|h|d|w|M|y)/;
...@@ -20,7 +21,6 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS ...@@ -20,7 +21,6 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS
this.directUrl = instanceSettings.directUrl; this.directUrl = instanceSettings.directUrl;
this.basicAuth = instanceSettings.basicAuth; this.basicAuth = instanceSettings.basicAuth;
this.withCredentials = instanceSettings.withCredentials; this.withCredentials = instanceSettings.withCredentials;
this.lastErrors = {};
this._request = function(method, url, requestId) { this._request = function(method, url, requestId) {
var options: any = { var options: any = {
...@@ -74,7 +74,7 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS ...@@ -74,7 +74,7 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS
options = _.clone(options); options = _.clone(options);
_.each(options.targets, target => { for (let target of options.targets) {
if (!target.expr || target.hide) { if (!target.expr || target.hide) {
return; return;
} }
...@@ -91,31 +91,33 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS ...@@ -91,31 +91,33 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS
var range = Math.ceil(end - start); var range = Math.ceil(end - start);
target.step = query.step = this.adjustStep(query.step, this.intervalSeconds(options.interval), range); target.step = query.step = this.adjustStep(query.step, this.intervalSeconds(options.interval), range);
queries.push(query); queries.push(query);
}); }
// No valid targets, return the empty result to save a round trip. // No valid targets, return the empty result to save a round trip.
if (_.isEmpty(queries)) { if (_.isEmpty(queries)) {
var d = $q.defer(); return $q.when({ data: [] });
d.resolve({ data: [] });
return d.promise;
} }
var allQueryPromise = _.map(queries, query => { var allQueryPromise = _.map(queries, query => {
return this.performTimeSeriesQuery(query, start, end); return this.performTimeSeriesQuery(query, start, end);
}); });
return $q.all(allQueryPromise).then(function(allResponse) { return $q.all(allQueryPromise).then(responseList => {
var result = []; var result = [];
var index = 0;
_.each(allResponse, function(response, index) { _.each(responseList, (response, index) => {
if (response.status === 'error') { if (response.status === 'error') {
self.lastErrors.query = response.error;
throw response.error; throw response.error;
} }
delete self.lastErrors.query;
_.each(response.data.data.result, function(metricData) { if (activeTargets[index].format === "table") {
result.push(self.transformMetricData(metricData, activeTargets[index], start, end)); result.push(self.transformMetricDataToTable(response.data.data.result));
}); } else {
for (let metricData of response.data.data.result) {
result.push(self.transformMetricData(metricData, activeTargets[index], start, end));
}
}
}); });
return { data: result }; return { data: result };
...@@ -273,6 +275,44 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS ...@@ -273,6 +275,44 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS
return { target: metricLabel, datapoints: dps }; return { target: metricLabel, datapoints: dps };
}; };
this.transformMetricDataToTable = function(series) {
var table = new TableModel();
var self = this;
var i, j;
if (series.length === 0) {
return table;
}
_.each(series, function(series, seriesIndex) {
if (seriesIndex === 0) {
table.columns.push({text: 'Time', type: 'time'});
_.each(_.keys(series.metric), function(key) {
table.columns.push({text: key});
});
table.columns.push({text: 'Value'});
}
if (series.values) {
for (i = 0; i < series.values.length; i++) {
var values = series.values[i];
var reordered = [values[0] * 1000];
if (series.metric) {
for (var key in series.metric) {
if (series.metric.hasOwnProperty(key)) {
reordered.push(series.metric[key]);
}
}
}
reordered.push(parseFloat(values[1]));
table.rows.push(reordered);
}
}
});
return table;
};
this.createMetricLabel = function(labelData, options) { this.createMetricLabel = function(labelData, options) {
if (_.isUndefined(options) || _.isEmpty(options.legendFormat)) { if (_.isUndefined(options) || _.isEmpty(options.legendFormat)) {
return this.getOriginalMetricName(labelData); return this.getOriginalMetricName(labelData);
......
...@@ -42,6 +42,10 @@ ...@@ -42,6 +42,10 @@
</div> </div>
<div class="gf-form"> <div class="gf-form">
<label class="gf-form-label">Format as</label>
<div class="gf-form-select-wrapper">
<select class="gf-form-input gf-size-auto" ng-model="ctrl.target.format" ng-options="f.value as f.text for f in ctrl.formats" ng-change="ctrl.refresh()"></select>
</div>
<label class="gf-form-label"> <label class="gf-form-label">
<a href="{{ctrl.linkToPrometheus}}" target="_blank" bs-tooltip="'Link to Graph in Prometheus'"> <a href="{{ctrl.linkToPrometheus}}" target="_blank" bs-tooltip="'Link to Graph in Prometheus'">
<i class="fa fa-share-square-o"></i> <i class="fa fa-share-square-o"></i>
......
...@@ -12,6 +12,7 @@ class PrometheusQueryCtrl extends QueryCtrl { ...@@ -12,6 +12,7 @@ class PrometheusQueryCtrl extends QueryCtrl {
metric: any; metric: any;
resolutions: any; resolutions: any;
formats: any;
oldTarget: any; oldTarget: any;
suggestMetrics: any; suggestMetrics: any;
linkToPrometheus: any; linkToPrometheus: any;
...@@ -23,15 +24,20 @@ class PrometheusQueryCtrl extends QueryCtrl { ...@@ -23,15 +24,20 @@ class PrometheusQueryCtrl extends QueryCtrl {
var target = this.target; var target = this.target;
target.expr = target.expr || ''; target.expr = target.expr || '';
target.intervalFactor = target.intervalFactor || 2; target.intervalFactor = target.intervalFactor || 2;
target.format = target.format || this.getDefaultFormat();
this.metric = ''; this.metric = '';
this.resolutions = _.map([1,2,3,4,5,10], function(f) { this.resolutions = _.map([1,2,3,4,5,10], function(f) {
return {factor: f, label: '1/' + f}; return {factor: f, label: '1/' + f};
}); });
this.formats = [
{text: 'Time series', value: 'time_series'},
{text: 'Table', value: 'table'},
];
$scope.$on('typeahead-updated', () => { $scope.$on('typeahead-updated', () => {
this.$scope.$apply(() => { this.$scope.$apply(() => {
this.target.expr += this.target.metric; this.target.expr += this.target.metric;
this.metric = ''; this.metric = '';
this.refreshMetricData(); this.refreshMetricData();
...@@ -48,6 +54,13 @@ class PrometheusQueryCtrl extends QueryCtrl { ...@@ -48,6 +54,13 @@ class PrometheusQueryCtrl extends QueryCtrl {
this.updateLink(); this.updateLink();
} }
getDefaultFormat() {
if (this.panelCtrl.panel.type === 'table') {
return 'table';
}
return 'time_series';
}
refreshMetricData() { refreshMetricData() {
if (!_.isEqual(this.oldTarget, this.target)) { if (!_.isEqual(this.oldTarget, this.target)) {
this.oldTarget = angular.copy(this.target); this.oldTarget = angular.copy(this.target);
......
...@@ -160,4 +160,28 @@ describe('PrometheusDatasource', function() { ...@@ -160,4 +160,28 @@ describe('PrometheusDatasource', function() {
expect(results[0].time).to.be(1443454528 * 1000); expect(results[0].time).to.be(1443454528 * 1000);
}); });
}); });
describe('When resultFormat is table', function() {
var response = {
status: "success",
data: {
resultType: "matrix",
result: [{
metric: {"__name__": "test", job: "testjob"},
values: [[1443454528, "3846"]]
}]
}
};
it('should return table model', function() {
var table = ctx.ds.transformMetricDataToTable(response.data.result);
expect(table.type).to.be('table');
expect(table.rows).to.eql([ [ 1443454528000, 'test', 'testjob', 3846 ] ]);
expect(table.columns).to.eql(
[ { text: 'Time', type: 'time' },
{ text: '__name__' },
{ text: 'job' },
{ text: 'Value' }
]
);
});
});
}); });
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