浏览代码

refactoring: prometheus PR #6140

Torkel Ödegaard 8 年之前
父节点
当前提交
6ff1144abf

+ 53 - 13
public/app/plugins/datasource/prometheus/datasource.ts

@@ -7,6 +7,7 @@ import moment from 'moment';
 import kbn from 'app/core/utils/kbn';
 import * as dateMath from 'app/core/utils/datemath';
 import PrometheusMetricFindQuery from './metric_find_query';
+import TableModel from 'app/core/table_model';
 
 var durationSplitRegexp = /(\d+)(ms|s|m|h|d|w|M|y)/;
 
@@ -20,7 +21,6 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS
   this.directUrl = instanceSettings.directUrl;
   this.basicAuth = instanceSettings.basicAuth;
   this.withCredentials = instanceSettings.withCredentials;
-  this.lastErrors = {};
 
   this._request = function(method, url, requestId) {
     var options: any = {
@@ -74,7 +74,7 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS
 
     options = _.clone(options);
 
-    _.each(options.targets, target => {
+    for (let target of options.targets) {
       if (!target.expr || target.hide) {
         return;
       }
@@ -91,31 +91,33 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS
       var range = Math.ceil(end - start);
       target.step = query.step = this.adjustStep(query.step, this.intervalSeconds(options.interval), range);
       queries.push(query);
-    });
+    }
 
     // No valid targets, return the empty result to save a round trip.
     if (_.isEmpty(queries)) {
-      var d = $q.defer();
-      d.resolve({ data: [] });
-      return d.promise;
+      return $q.when({ data: [] });
     }
 
     var allQueryPromise = _.map(queries, query => {
       return this.performTimeSeriesQuery(query, start, end);
     });
 
-    return $q.all(allQueryPromise).then(function(allResponse) {
+    return $q.all(allQueryPromise).then(responseList => {
       var result = [];
+      var index = 0;
 
-      _.each(allResponse, function(response, index) {
+      _.each(responseList, (response, index) => {
         if (response.status === 'error') {
-          self.lastErrors.query = response.error;
           throw response.error;
         }
-        delete self.lastErrors.query;
-        _.each(response.data.data.result, function(metricData) {
-          result.push(self.transformMetricData(metricData, activeTargets[index], start, end));
-        });
+
+        if (activeTargets[index].format === "table") {
+          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 };
@@ -273,6 +275,44 @@ export function PrometheusDatasource(instanceSettings, $q, backendSrv, templateS
     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) {
     if (_.isUndefined(options) || _.isEmpty(options.legendFormat)) {
       return this.getOriginalMetricName(labelData);

+ 4 - 0
public/app/plugins/datasource/prometheus/partials/query.editor.html

@@ -42,6 +42,10 @@
 		</div>
 
 		<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">
 				<a href="{{ctrl.linkToPrometheus}}" target="_blank" bs-tooltip="'Link to Graph in Prometheus'">
 					<i class="fa fa-share-square-o"></i>

+ 14 - 1
public/app/plugins/datasource/prometheus/query_ctrl.ts

@@ -12,6 +12,7 @@ class PrometheusQueryCtrl extends QueryCtrl {
 
   metric: any;
   resolutions: any;
+  formats: any;
   oldTarget: any;
   suggestMetrics: any;
   linkToPrometheus: any;
@@ -23,15 +24,20 @@ class PrometheusQueryCtrl extends QueryCtrl {
     var target = this.target;
     target.expr = target.expr || '';
     target.intervalFactor = target.intervalFactor || 2;
+    target.format = target.format || this.getDefaultFormat();
 
     this.metric = '';
     this.resolutions = _.map([1,2,3,4,5,10], function(f) {
       return {factor: f, label: '1/' + f};
     });
 
+    this.formats = [
+      {text: 'Time series', value: 'time_series'},
+      {text: 'Table', value: 'table'},
+    ];
+
     $scope.$on('typeahead-updated', () => {
       this.$scope.$apply(() => {
-
         this.target.expr += this.target.metric;
         this.metric = '';
         this.refreshMetricData();
@@ -48,6 +54,13 @@ class PrometheusQueryCtrl extends QueryCtrl {
     this.updateLink();
   }
 
+  getDefaultFormat() {
+    if (this.panelCtrl.panel.type === 'table') {
+      return 'table';
+    }
+    return 'time_series';
+  }
+
   refreshMetricData() {
     if (!_.isEqual(this.oldTarget, this.target)) {
       this.oldTarget = angular.copy(this.target);

+ 24 - 0
public/app/plugins/datasource/prometheus/specs/datasource_specs.ts

@@ -160,4 +160,28 @@ describe('PrometheusDatasource', function() {
       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' }
+        ]
+      );
+    });
+  });
 });