Bläddra i källkod

stackdriver: improve segments for group bys in query editor

Daniel Lee 7 år sedan
förälder
incheckning
d0a565d853

+ 9 - 3
pkg/tsdb/stackdriver/stackdriver_test.go

@@ -29,6 +29,7 @@ func TestStackdriver(t *testing.T) {
 						Model: simplejson.NewFromAny(map[string]interface{}{
 							"target":     "target",
 							"metricType": "a/metric/type",
+							"view":       "FULL",
 						}),
 						RefId: "A",
 					},
@@ -42,11 +43,12 @@ func TestStackdriver(t *testing.T) {
 				So(len(queries), ShouldEqual, 1)
 				So(queries[0].RefID, ShouldEqual, "A")
 				So(queries[0].Target, ShouldEqual, "target")
-				So(len(queries[0].Params), ShouldEqual, 4)
+				So(len(queries[0].Params), ShouldEqual, 5)
 				So(queries[0].Params["interval.startTime"][0], ShouldEqual, "2018-03-15T13:00:00Z")
 				So(queries[0].Params["interval.endTime"][0], ShouldEqual, "2018-03-15T13:34:00Z")
 				So(queries[0].Params["aggregation.perSeriesAligner"][0], ShouldEqual, "ALIGN_NONE")
 				So(queries[0].Params["filter"][0], ShouldEqual, "metric.type=\"a/metric/type\"")
+				So(queries[0].Params["view"][0], ShouldEqual, "FULL")
 			})
 
 			Convey("and query has aggregation mean set", func() {
@@ -54,6 +56,7 @@ func TestStackdriver(t *testing.T) {
 					"target":             "target",
 					"metricType":         "a/metric/type",
 					"primaryAggregation": "REDUCE_MEAN",
+					"view":               "FULL",
 				})
 
 				queries, err := executor.buildQueries(tsdbQuery)
@@ -62,13 +65,14 @@ func TestStackdriver(t *testing.T) {
 				So(len(queries), ShouldEqual, 1)
 				So(queries[0].RefID, ShouldEqual, "A")
 				So(queries[0].Target, ShouldEqual, "target")
-				So(len(queries[0].Params), ShouldEqual, 6)
+				So(len(queries[0].Params), ShouldEqual, 7)
 				So(queries[0].Params["interval.startTime"][0], ShouldEqual, "2018-03-15T13:00:00Z")
 				So(queries[0].Params["interval.endTime"][0], ShouldEqual, "2018-03-15T13:34:00Z")
 				So(queries[0].Params["aggregation.crossSeriesReducer"][0], ShouldEqual, "REDUCE_MEAN")
 				So(queries[0].Params["aggregation.perSeriesAligner"][0], ShouldEqual, "ALIGN_MEAN")
 				So(queries[0].Params["aggregation.alignmentPeriod"][0], ShouldEqual, "+60s")
 				So(queries[0].Params["filter"][0], ShouldEqual, "metric.type=\"a/metric/type\"")
+				So(queries[0].Params["view"][0], ShouldEqual, "FULL")
 			})
 
 			Convey("and query has group bys", func() {
@@ -77,6 +81,7 @@ func TestStackdriver(t *testing.T) {
 					"metricType":         "a/metric/type",
 					"primaryAggregation": "REDUCE_NONE",
 					"groupBys":           []interface{}{"metric.label.group1", "metric.label.group2"},
+					"view":               "FULL",
 				})
 
 				queries, err := executor.buildQueries(tsdbQuery)
@@ -85,13 +90,14 @@ func TestStackdriver(t *testing.T) {
 				So(len(queries), ShouldEqual, 1)
 				So(queries[0].RefID, ShouldEqual, "A")
 				So(queries[0].Target, ShouldEqual, "target")
-				So(len(queries[0].Params), ShouldEqual, 5)
+				So(len(queries[0].Params), ShouldEqual, 6)
 				So(queries[0].Params["interval.startTime"][0], ShouldEqual, "2018-03-15T13:00:00Z")
 				So(queries[0].Params["interval.endTime"][0], ShouldEqual, "2018-03-15T13:34:00Z")
 				So(queries[0].Params["aggregation.perSeriesAligner"][0], ShouldEqual, "ALIGN_NONE")
 				So(queries[0].Params["aggregation.groupByFields"][0], ShouldEqual, "metric.label.group1")
 				So(queries[0].Params["aggregation.groupByFields"][1], ShouldEqual, "metric.label.group2")
 				So(queries[0].Params["filter"][0], ShouldEqual, "metric.type=\"a/metric/type\"")
+				So(queries[0].Params["view"][0], ShouldEqual, "FULL")
 			})
 
 		})

+ 2 - 2
public/app/plugins/datasource/stackdriver/datasource.ts

@@ -16,8 +16,8 @@ export default class StackdriverDatasource {
       refId: t.refId,
       datasourceId: this.id,
       metricType: t.metricType,
-      primaryAggregation: 'REDUCE_MEAN', //t.aggregation.crossSeriesReducer,
-      // groupBys: t.aggregation.groupBys,
+      primaryAggregation: t.aggregation.crossSeriesReducer,
+      groupBys: t.aggregation.groupBys,
       view: t.view || 'FULL',
     }));
 

+ 31 - 23
public/app/plugins/datasource/stackdriver/query_ctrl.ts

@@ -10,8 +10,8 @@ export interface LabelType {
 export interface QueryMeta {
   rawQuery: string;
   rawQueryString: string;
-  metricLabels: LabelType[];
-  resourceLabels: LabelType[];
+  metricLabels: { [key: string]: string[] };
+  resourceLabels: { [key: string]: string[] };
 }
 export class StackdriverQueryCtrl extends QueryCtrl {
   static templateUrl = 'partials/query.editor.html';
@@ -152,34 +152,42 @@ export class StackdriverQueryCtrl extends QueryCtrl {
   }
 
   getGroupBys() {
-    const metricLabels = Object.keys(this.metricLabels).map(l => {
-      return this.uiSegmentSrv.newSegment({
-        value: `metric.label.${l}`,
-        expandable: false,
+    const metricLabels = Object.keys(this.metricLabels)
+      .filter(ml => {
+        return this.target.aggregation.groupBys.indexOf('metric.label.' + ml) === -1;
+      })
+      .map(l => {
+        return this.uiSegmentSrv.newSegment({
+          value: `metric.label.${l}`,
+          expandable: false,
+        });
       });
-    });
 
-    const resourceLabels = Object.keys(this.resourceLabels).map(l => {
-      return this.uiSegmentSrv.newSegment({
-        value: `resource.label.${l}`,
-        expandable: false,
+    const resourceLabels = Object.keys(this.resourceLabels)
+      .filter(ml => {
+        return this.target.aggregation.groupBys.indexOf('resource.label.' + ml) === -1;
+      })
+      .map(l => {
+        return this.uiSegmentSrv.newSegment({
+          value: `resource.label.${l}`,
+          expandable: false,
+        });
       });
-    });
 
     return Promise.resolve([...metricLabels, ...resourceLabels]);
   }
 
-  groupByChanged(segment, index) {
-    this.target.aggregation.groupBys = _.reduce(
-      this.groupBySegments,
-      function(memo, seg) {
-        if (!seg.fake) {
-          memo.push(seg.value);
-        }
-        return memo;
-      },
-      []
-    );
+  groupByChanged(segment) {
+    segment.type = 'value';
+
+    const reducer = (memo, seg) => {
+      if (!seg.fake) {
+        memo.push(seg.value);
+      }
+      return memo;
+    };
+
+    this.target.aggregation.groupBys = this.groupBySegments.reduce(reducer, []);
     this.ensurePlusButton(this.groupBySegments);
     this.refresh();
   }

+ 99 - 0
public/app/plugins/datasource/stackdriver/specs/query_ctrl.test.ts

@@ -0,0 +1,99 @@
+import { StackdriverQueryCtrl } from '../query_ctrl';
+
+describe('StackdriverQueryCtrl', () => {
+  let ctrl;
+  let result;
+
+  beforeEach(() => {
+    ctrl = createCtrlWithFakes();
+  });
+
+  describe('when labels are fetched', () => {
+    beforeEach(async () => {
+      ctrl.metricLabels = { 'metric-key-1': ['metric-value-1'] };
+      ctrl.resourceLabels = { 'resource-key-1': ['resource-value-1'] };
+
+      result = await ctrl.getGroupBys();
+    });
+
+    it('should populate group bys segments', () => {
+      expect(result.length).toBe(2);
+      expect(result[0].value).toBe('metric.label.metric-key-1');
+      expect(result[1].value).toBe('resource.label.resource-key-1');
+    });
+  });
+
+  describe('when a group by label is selected', () => {
+    beforeEach(async () => {
+      ctrl.metricLabels = {
+        'metric-key-1': ['metric-value-1'],
+        'metric-key-2': ['metric-value-2'],
+      };
+      ctrl.resourceLabels = {
+        'resource-key-1': ['resource-value-1'],
+        'resource-key-2': ['resource-value-2'],
+      };
+      ctrl.target.aggregation.groupBys = ['metric.label.metric-key-1', 'resource.label.resource-key-1'];
+
+      result = await ctrl.getGroupBys();
+    });
+
+    it('should not be used to populate group bys segments', () => {
+      expect(result.length).toBe(2);
+      expect(result[0].value).toBe('metric.label.metric-key-2');
+      expect(result[1].value).toBe('resource.label.resource-key-2');
+    });
+  });
+
+  describe('when a group by is selected', () => {
+    beforeEach(() => {
+      const segment = { value: 'groupby1' };
+      ctrl.groupBySegments = [segment];
+      ctrl.groupByChanged(segment);
+    });
+
+    it('should be added to group bys list', () => {
+      expect(ctrl.target.aggregation.groupBys.length).toBe(1);
+    });
+  });
+});
+
+function createCtrlWithFakes() {
+  StackdriverQueryCtrl.prototype.panelCtrl = {
+    events: { on: () => {} },
+    panel: { scopedVars: [], targets: [] },
+    refresh: () => {},
+  };
+  StackdriverQueryCtrl.prototype.target = createTarget();
+  StackdriverQueryCtrl.prototype.getMetricTypes = () => {
+    return Promise.resolve();
+  };
+  StackdriverQueryCtrl.prototype.getLabels = () => {
+    return Promise.resolve();
+  };
+
+  const fakeSegmentServer = {
+    newSegment: obj => {
+      return { value: obj.value };
+    },
+    newPlusButton: () => {},
+  };
+  return new StackdriverQueryCtrl(null, null, fakeSegmentServer, null);
+}
+
+function createTarget() {
+  return {
+    project: {
+      id: '',
+      name: '',
+    },
+    metricType: 'ametric',
+    refId: 'A',
+    aggregation: {
+      crossSeriesReducer: '',
+      alignmentPeriod: '',
+      perSeriesAligner: '',
+      groupBys: [],
+    },
+  };
+}