mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
add groupby to querybuilder
remove unused aggregations
This commit is contained in:
parent
571ecdc740
commit
4dbd83fac1
@ -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">
|
||||
|
@ -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;
|
||||
});
|
||||
});
|
||||
|
@ -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,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,
|
||||
|
Loading…
Reference in New Issue
Block a user