Jelajahi Sumber

add groupby to querybuilder
remove unused aggregations

Sven Klemm 8 tahun lalu
induk
melakukan
4dbd83fac1

+ 21 - 0
public/app/plugins/datasource/postgres/partials/query.editor.html

@@ -51,6 +51,27 @@
       </div>
     </div>
 
+    <div class="gf-form-inline">
+      <div class="gf-form">
+        <label class="gf-form-label query-keyword width-7">
+          <span>GROUP BY</span>
+        </label>
+
+        <query-part-editor  ng-repeat="part in ctrl.queryModel.groupByParts"
+                            part="part" class="gf-form-label query-part"
+                            handle-event="ctrl.handleGroupByPartEvent(part, $index, $event)">
+        </query-part-editor>
+      </div>
+
+      <div class="gf-form">
+        <metric-segment segment="ctrl.groupBySegment" get-options="ctrl.getGroupByOptions()" on-change="ctrl.groupByAction(part, $index)"></metric-segment>
+      </div>
+
+      <div class="gf-form gf-form--grow">
+        <div class="gf-form-label gf-form-label--grow"></div>
+      </div>
+    </div>
+
   </div>
 
   <div class="gf-form-inline">

+ 1 - 4
public/app/plugins/datasource/postgres/postgres_query.ts

@@ -22,7 +22,7 @@ export default class PostgresQuery {
     target.alias = '';
 
     target.orderByTime = target.orderByTime || 'ASC';
-//    target.groupBy = target.groupBy || [{ type: 'time', params: ['$__interval'] }, { type: 'fill', params: ['null'] }];
+    target.groupBy = target.groupBy || [{ type: 'time', params: ['$__interval'] }, { type: 'fill', params: ['null'] }];
     target.select = target.select || [[{ type: 'field', params: ['value'] }]];
 
     this.updateProjection();
@@ -92,9 +92,6 @@ export default class PostgresQuery {
           if (partModel.def.category === categories.Aggregations) {
             return false;
           }
-          if (partModel.def.category === categories.Selectors) {
-            return false;
-          }
           return true;
         });
       });

+ 84 - 0
public/app/plugins/datasource/postgres/query_ctrl.ts

@@ -29,6 +29,7 @@ export class PostgresQueryCtrl extends QueryCtrl {
   tableSegment: any;
   timeColumnSegment: any;
   selectMenu: any;
+  groupBySegment: any;
 
   /** @ngInject **/
   constructor($scope, $injector, private templateSrv, private $q, private uiSegmentSrv) {
@@ -59,6 +60,8 @@ export class PostgresQueryCtrl extends QueryCtrl {
     this.timeColumnSegment = uiSegmentSrv.newSegment(this.target.timeColumn);
 
     this.buildSelectMenu();
+    this.groupBySegment = this.uiSegmentSrv.newPlusButton();
+
     this.panelCtrl.events.on('data-received', this.onDataReceived.bind(this), $scope);
     this.panelCtrl.events.on('data-error', this.onDataError.bind(this), $scope);
   }
@@ -224,6 +227,87 @@ export class PostgresQueryCtrl extends QueryCtrl {
     }
   }
 
+  handleGroupByPartEvent(part, index, evt) {
+    switch (evt.name) {
+      case 'get-param-options': {
+        var columnQuery = "SELECT column_name FROM information_schema.columns WHERE ";
+        columnQuery += " table_schema = '" + this.target.schema + "'";
+        columnQuery += " AND table_name = '" + this.target.table + "'";
+
+        return this.datasource
+          .metricFindQuery(columnQuery)
+          .then(this.transformToSegments(true))
+          .catch(this.handleQueryError.bind(this));
+      }
+      case 'part-param-changed': {
+        this.panelCtrl.refresh();
+        break;
+      }
+      case 'action': {
+        this.queryModel.removeGroupByPart(part, index);
+        this.panelCtrl.refresh();
+        break;
+      }
+      case 'get-part-actions': {
+        return this.$q.when([{ text: 'Remove', value: 'remove-part' }]);
+      }
+    }
+  }
+
+  getGroupByOptions() {
+    var columnQuery = "SELECT column_name FROM information_schema.columns WHERE ";
+    columnQuery += " table_schema = '" + this.target.schema + "'";
+    columnQuery += " AND table_name = '" + this.target.table + "'";
+
+
+    return this.datasource
+      .metricFindQuery(columnQuery)
+      .then(tags => {
+        var options = [];
+        if (!this.queryModel.hasFill()) {
+          options.push(this.uiSegmentSrv.newSegment({ value: 'fill(null)' }));
+        }
+        if (!this.target.limit) {
+          options.push(this.uiSegmentSrv.newSegment({ value: 'LIMIT' }));
+        }
+        if (!this.target.slimit) {
+          options.push(this.uiSegmentSrv.newSegment({ value: 'SLIMIT' }));
+        }
+        if (this.target.orderByTime === 'ASC') {
+          options.push(this.uiSegmentSrv.newSegment({ value: 'ORDER BY time DESC' }));
+        }
+        if (!this.queryModel.hasGroupByTime()) {
+          options.push(this.uiSegmentSrv.newSegment({ value: 'time($interval)' }));
+        }
+        for (let tag of tags) {
+          options.push(this.uiSegmentSrv.newSegment({ value: 'tag(' + tag.text + ')' }));
+        }
+        return options;
+      })
+      .catch(this.handleQueryError.bind(this));
+  }
+
+  groupByAction() {
+    switch (this.groupBySegment.value) {
+      case 'LIMIT': {
+        this.target.limit = 10;
+        break;
+      }
+      case 'ORDER BY time DESC': {
+        this.target.orderByTime = 'DESC';
+        break;
+      }
+      default: {
+        this.queryModel.addGroupBy(this.groupBySegment.value);
+      }
+    }
+
+    var plusButton = this.uiSegmentSrv.newPlusButton();
+    this.groupBySegment.value = plusButton.value;
+    this.groupBySegment.html = plusButton.html;
+    this.panelCtrl.refresh();
+  }
+
   handleQueryError(err) {
     this.error = err.message || 'Failed to issue metric query';
     return [];

+ 4 - 146
public/app/plugins/datasource/postgres/query_part.ts

@@ -4,9 +4,6 @@ import { QueryPartDef, QueryPart, functionRenderer, suffixRenderer } from 'app/c
 var index = [];
 var categories = {
   Aggregations: [],
-  Selectors: [],
-  Transformations: [],
-  Predictors: [],
   Math: [],
   Aliasing: [],
   Fields: [],
@@ -44,10 +41,6 @@ function replaceAggregationAddStrategy(selectParts, partModel) {
       selectParts[i] = partModel;
       return;
     }
-    if (part.def.category === categories.Selectors) {
-      selectParts[i] = partModel;
-      return;
-    }
   }
 
   selectParts.splice(1, 0, partModel);
@@ -147,34 +140,10 @@ register({
 
 // transformations
 
-register({
-  type: 'derivative',
-  addStrategy: addTransformationStrategy,
-  category: categories.Transformations,
-  params: [
-    {
-      name: 'duration',
-      type: 'interval',
-      options: ['1s', '10s', '1m', '5m', '10m', '15m', '1h'],
-    },
-  ],
-  defaultParams: ['10s'],
-  renderer: functionRenderer,
-});
-
-register({
-  type: 'spread',
-  addStrategy: addTransformationStrategy,
-  category: categories.Transformations,
-  params: [],
-  defaultParams: [],
-  renderer: functionRenderer,
-});
-
 register({
   type: 'non_negative_derivative',
   addStrategy: addTransformationStrategy,
-  category: categories.Transformations,
+  category: categories.Aggregations,
   params: [
     {
       name: 'duration',
@@ -186,46 +155,10 @@ register({
   renderer: functionRenderer,
 });
 
-register({
-  type: 'difference',
-  addStrategy: addTransformationStrategy,
-  category: categories.Transformations,
-  params: [],
-  defaultParams: [],
-  renderer: functionRenderer,
-});
-
-register({
-  type: 'non_negative_difference',
-  addStrategy: addTransformationStrategy,
-  category: categories.Transformations,
-  params: [],
-  defaultParams: [],
-  renderer: functionRenderer,
-});
-
-register({
-  type: 'moving_average',
-  addStrategy: addTransformationStrategy,
-  category: categories.Transformations,
-  params: [{ name: 'window', type: 'int', options: [5, 10, 20, 30, 40] }],
-  defaultParams: [10],
-  renderer: functionRenderer,
-});
-
-register({
-  type: 'cumulative_sum',
-  addStrategy: addTransformationStrategy,
-  category: categories.Transformations,
-  params: [],
-  defaultParams: [],
-  renderer: functionRenderer,
-});
-
 register({
   type: 'stddev',
   addStrategy: addTransformationStrategy,
-  category: categories.Transformations,
+  category: categories.Aggregations,
   params: [],
   defaultParams: [],
   renderer: functionRenderer,
@@ -259,60 +192,11 @@ register({
   renderer: functionRenderer,
 });
 
-register({
-  type: 'elapsed',
-  addStrategy: addTransformationStrategy,
-  category: categories.Transformations,
-  params: [
-    {
-      name: 'duration',
-      type: 'interval',
-      options: ['1s', '10s', '1m', '5m', '10m', '15m', '1h'],
-    },
-  ],
-  defaultParams: ['10s'],
-  renderer: functionRenderer,
-});
-
-// predictions
-register({
-  type: 'holt_winters',
-  addStrategy: addTransformationStrategy,
-  category: categories.Predictors,
-  params: [
-    { name: 'number', type: 'int', options: [5, 10, 20, 30, 40] },
-    { name: 'season', type: 'int', options: [0, 1, 2, 5, 10] },
-  ],
-  defaultParams: [10, 2],
-  renderer: functionRenderer,
-});
-
-register({
-  type: 'holt_winters_with_fit',
-  addStrategy: addTransformationStrategy,
-  category: categories.Predictors,
-  params: [
-    { name: 'number', type: 'int', options: [5, 10, 20, 30, 40] },
-    { name: 'season', type: 'int', options: [0, 1, 2, 5, 10] },
-  ],
-  defaultParams: [10, 2],
-  renderer: functionRenderer,
-});
-
 // Selectors
-register({
-  type: 'bottom',
-  addStrategy: replaceAggregationAddStrategy,
-  category: categories.Selectors,
-  params: [{ name: 'count', type: 'int' }],
-  defaultParams: [3],
-  renderer: functionRenderer,
-});
-
 register({
   type: 'max',
   addStrategy: replaceAggregationAddStrategy,
-  category: categories.Selectors,
+  category: categories.Aggregations,
   params: [],
   defaultParams: [],
   renderer: functionRenderer,
@@ -321,38 +205,12 @@ register({
 register({
   type: 'min',
   addStrategy: replaceAggregationAddStrategy,
-  category: categories.Selectors,
+  category: categories.Aggregations,
   params: [],
   defaultParams: [],
   renderer: functionRenderer,
 });
 
-register({
-  type: 'percentile',
-  addStrategy: replaceAggregationAddStrategy,
-  category: categories.Selectors,
-  params: [{ name: 'nth', type: 'int' }],
-  defaultParams: [95],
-  renderer: functionRenderer,
-});
-
-register({
-  type: 'top',
-  addStrategy: replaceAggregationAddStrategy,
-  category: categories.Selectors,
-  params: [{ name: 'count', type: 'int' }],
-  defaultParams: [3],
-  renderer: functionRenderer,
-});
-
-register({
-  type: 'tag',
-  category: groupByTimeFunctions,
-  params: [{ name: 'tag', type: 'string', dynamicLookup: true }],
-  defaultParams: ['tag'],
-  renderer: fieldRenderer,
-});
-
 register({
   type: 'math',
   addStrategy: addMathStrategy,