Commit d0a565d8 by Daniel Lee

stackdriver: improve segments for group bys in query editor

parent add23d97
......@@ -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")
})
})
......
......@@ -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',
}));
......
......@@ -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();
}
......
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: [],
},
};
}
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