mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
stackdriver: improve segments for group bys in query editor
This commit is contained in:
parent
add23d9716
commit
d0a565d853
@ -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,32 @@ func TestStackdriver(t *testing.T) {
|
||||
"target": "target",
|
||||
"metricType": "a/metric/type",
|
||||
"primaryAggregation": "REDUCE_MEAN",
|
||||
"view": "FULL",
|
||||
})
|
||||
|
||||
queries, err := executor.buildQueries(tsdbQuery)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
So(len(queries), ShouldEqual, 1)
|
||||
So(queries[0].RefID, ShouldEqual, "A")
|
||||
So(queries[0].Target, ShouldEqual, "target")
|
||||
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() {
|
||||
tsdbQuery.Queries[0].Model = simplejson.NewFromAny(map[string]interface{}{
|
||||
"target": "target",
|
||||
"metricType": "a/metric/type",
|
||||
"primaryAggregation": "REDUCE_NONE",
|
||||
"groupBys": []interface{}{"metric.label.group1", "metric.label.group2"},
|
||||
"view": "FULL",
|
||||
})
|
||||
|
||||
queries, err := executor.buildQueries(tsdbQuery)
|
||||
@ -65,33 +93,11 @@ func TestStackdriver(t *testing.T) {
|
||||
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.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\"")
|
||||
})
|
||||
|
||||
Convey("and query has group bys", func() {
|
||||
tsdbQuery.Queries[0].Model = simplejson.NewFromAny(map[string]interface{}{
|
||||
"target": "target",
|
||||
"metricType": "a/metric/type",
|
||||
"primaryAggregation": "REDUCE_NONE",
|
||||
"groupBys": []interface{}{"metric.label.group1", "metric.label.group2"},
|
||||
})
|
||||
|
||||
queries, err := executor.buildQueries(tsdbQuery)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
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(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();
|
||||
}
|
||||
|
@ -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: [],
|
||||
},
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user