mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
stackdriver: break out aggretation logic into its own directive and controller. also adds tests for new dropdown population logic
This commit is contained in:
parent
b700c6b0e4
commit
7666e7bfe3
42
public/app/plugins/datasource/stackdriver/partials/query.aggregation.html
Executable file
42
public/app/plugins/datasource/stackdriver/partials/query.aggregation.html
Executable file
@ -0,0 +1,42 @@
|
||||
<div class="gf-form-inline">
|
||||
<div class="gf-form">
|
||||
<label class="gf-form-label query-keyword width-9">Aggregation</label>
|
||||
<div class="gf-form-select-wrapper gf-form-select-wrapper--caret-indent">
|
||||
<select class="gf-form-input width-12" ng-model="target.aggregation.crossSeriesReducer" ng-options="f.value as f.text for f in getAggOptions()"
|
||||
ng-change="onAggregationChange(target.aggregation.crossSeriesReducer)"></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gf-form gf-form--grow">
|
||||
<label class="gf-form-label gf-form-label--grow">
|
||||
<a ng-click="target.showAggregationOptions = !target.showAggregationOptions">
|
||||
<i class="fa fa-caret-down" ng-show="target.showAggregationOptions"></i>
|
||||
<i class="fa fa-caret-right" ng-hide="target.showAggregationOptions"></i>
|
||||
Advanced Options
|
||||
</a>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gf-form-group" ng-if="target.showAggregationOptions">
|
||||
<div class="gf-form offset-width-9">
|
||||
<label class="gf-form-label query-keyword width-12">Aligner</label>
|
||||
<div class="gf-form-select-wrapper gf-form-select-wrapper--caret-indent">
|
||||
<select class="gf-form-input width-14" ng-model="target.aggregation.perSeriesAligner" ng-options="f.value as f.text for f in getAlignOptions()"
|
||||
ng-change="onAlignmentChange(target.aggregation.perSeriesAligner)"></select>
|
||||
</div>
|
||||
|
||||
<div class="gf-form gf-form--grow">
|
||||
<div class="gf-form-label gf-form-label--grow"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gf-form offset-width-9">
|
||||
<label class="gf-form-label query-keyword width-12">Alignment Period</label>
|
||||
<div class="gf-form-select-wrapper gf-form-select-wrapper--caret-indent">
|
||||
<select class="gf-form-input width-14" ng-model="target.aggregation.alignmentPeriod" ng-options="f.value as f.text for f in alignmentPeriods"
|
||||
ng-change="refresh()"></select>
|
||||
</div>
|
||||
|
||||
<div class="gf-form gf-form--grow">
|
||||
<div class="gf-form-label gf-form-label--grow"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -31,48 +31,7 @@
|
||||
<div class="gf-form-label gf-form-label--grow"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gf-form-inline">
|
||||
<div class="gf-form">
|
||||
<label class="gf-form-label query-keyword width-9">Aggregation</label>
|
||||
<div class="gf-form-select-wrapper gf-form-select-wrapper--caret-indent">
|
||||
<select class="gf-form-input width-12" ng-model="ctrl.target.aggregation.crossSeriesReducer" ng-options="f.value as f.text for f in ctrl.getAggOptions()"
|
||||
ng-change="ctrl.refresh()"></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gf-form gf-form--grow">
|
||||
<label class="gf-form-label gf-form-label--grow">
|
||||
<a ng-click="ctrl.target.showAggregationOptions = !ctrl.target.showAggregationOptions">
|
||||
<i class="fa fa-caret-down" ng-show="ctrl.target.showAggregationOptions"></i>
|
||||
<i class="fa fa-caret-right" ng-hide="ctrl.target.showAggregationOptions"></i>
|
||||
Advanced Options
|
||||
</a>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gf-form-group" ng-if="ctrl.target.showAggregationOptions">
|
||||
<div class="gf-form offset-width-9">
|
||||
<label class="gf-form-label query-keyword width-12">Aligner</label>
|
||||
<div class="gf-form-select-wrapper gf-form-select-wrapper--caret-indent">
|
||||
<select class="gf-form-input width-14" ng-model="ctrl.target.aggregation.perSeriesAligner" ng-options="f.value as f.text for f in ctrl.getAlignOptions()"
|
||||
ng-change="ctrl.refresh()"></select>
|
||||
</div>
|
||||
|
||||
<div class="gf-form gf-form--grow">
|
||||
<div class="gf-form-label gf-form-label--grow"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="gf-form offset-width-9">
|
||||
<label class="gf-form-label query-keyword width-12">Alignment Period</label>
|
||||
<div class="gf-form-select-wrapper gf-form-select-wrapper--caret-indent">
|
||||
<select class="gf-form-input width-14" ng-model="ctrl.target.aggregation.alignmentPeriod" ng-options="f.value as f.text for f in ctrl.stackdriverConstants.alignmentPeriods"
|
||||
ng-change="ctrl.refresh()"></select>
|
||||
</div>
|
||||
|
||||
<div class="gf-form gf-form--grow">
|
||||
<div class="gf-form-label gf-form-label--grow"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<stackdriver-aggregation target="ctrl.target" refresh="ctrl.refresh()"></stackdriver-aggregation>
|
||||
<div class="gf-form-inline">
|
||||
<div class="gf-form">
|
||||
<span class="gf-form-label query-keyword width-9">Alias By</span>
|
||||
|
@ -0,0 +1,73 @@
|
||||
import angular from 'angular';
|
||||
import _ from 'lodash';
|
||||
import * as options from './constants';
|
||||
|
||||
export class StackdriverAggregation {
|
||||
constructor() {
|
||||
return {
|
||||
templateUrl: 'public/app/plugins/datasource/stackdriver/partials/query.aggregation.html',
|
||||
controller: 'StackdriverAggregationCtrl',
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
target: '=',
|
||||
refresh: '&',
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class StackdriverAggregationCtrl {
|
||||
target: any;
|
||||
alignOptions: any[];
|
||||
aggOptions: any[];
|
||||
refresh: () => void;
|
||||
|
||||
constructor(private $scope) {
|
||||
this.aggOptions = options.aggOptions;
|
||||
this.alignOptions = options.alignOptions;
|
||||
$scope.alignmentPeriods = options.alignmentPeriods;
|
||||
$scope.getAlignOptions = this.getAlignOptions;
|
||||
$scope.getAggOptions = this.getAggOptions;
|
||||
$scope.onAlignmentChange = this.onAlignmentChange;
|
||||
$scope.onAggregationChange = this.onAggregationChange;
|
||||
this.refresh = $scope.refresh;
|
||||
}
|
||||
|
||||
onAlignmentChange(newVal) {
|
||||
if (newVal === 'ALIGN_NONE') {
|
||||
this.target.aggregation.crossSeriesReducer = 'REDUCE_NONE';
|
||||
}
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
onAggregationChange(newVal) {
|
||||
if (newVal !== 'REDUCE_NONE') {
|
||||
const newAlignmentOption = options.alignOptions.find(o => o.value !== 'ALIGN_NONE');
|
||||
this.target.aggregation.perSeriesAligner = newAlignmentOption ? newAlignmentOption.value : '';
|
||||
}
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
getAlignOptions() {
|
||||
return !this.target.valueType
|
||||
? options.alignOptions
|
||||
: options.alignOptions.filter(i => {
|
||||
return (
|
||||
i.valueTypes.indexOf(this.target.valueType) !== -1 && i.metricKinds.indexOf(this.target.metricKind) !== -1
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
getAggOptions() {
|
||||
return !this.target.metricKind
|
||||
? options.aggOptions
|
||||
: options.aggOptions.filter(i => {
|
||||
return (
|
||||
i.valueTypes.indexOf(this.target.valueType) !== -1 && i.metricKinds.indexOf(this.target.metricKind) !== -1
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
angular.module('grafana.controllers').directive('stackdriverAggregation', StackdriverAggregation);
|
||||
angular.module('grafana.controllers').controller('StackdriverAggregationCtrl', StackdriverAggregationCtrl);
|
@ -1,8 +1,8 @@
|
||||
import _ from 'lodash';
|
||||
import { QueryCtrl } from 'app/plugins/sdk';
|
||||
import appEvents from 'app/core/app_events';
|
||||
import * as options from './constants';
|
||||
import { FilterSegments, DefaultRemoveFilterValue } from './filter_segments';
|
||||
import './query_aggregation_ctrl';
|
||||
|
||||
export interface QueryMeta {
|
||||
rawQuery: string;
|
||||
@ -55,8 +55,6 @@ export class StackdriverQueryCtrl extends QueryCtrl {
|
||||
valueType: '',
|
||||
};
|
||||
|
||||
alignOptions: any[];
|
||||
aggOptions: any[];
|
||||
groupBySegments: any[];
|
||||
removeSegment: any;
|
||||
showHelp: boolean;
|
||||
@ -74,9 +72,6 @@ export class StackdriverQueryCtrl extends QueryCtrl {
|
||||
|
||||
this.panelCtrl.events.on('data-received', this.onDataReceived.bind(this), $scope);
|
||||
this.panelCtrl.events.on('data-error', this.onDataError.bind(this), $scope);
|
||||
this.stackdriverConstants = options;
|
||||
this.aggOptions = options.aggOptions;
|
||||
this.alignOptions = options.alignOptions;
|
||||
|
||||
this.getCurrentProject()
|
||||
.then(this.getMetricTypes.bind(this))
|
||||
@ -155,6 +150,9 @@ export class StackdriverQueryCtrl extends QueryCtrl {
|
||||
|
||||
this.metricLabels = data.results[this.target.refId].meta.metricLabels;
|
||||
this.resourceLabels = data.results[this.target.refId].meta.resourceLabels;
|
||||
|
||||
this.target.valueType = data.results[this.target.refId].meta.valueType;
|
||||
this.target.metricKind = data.results[this.target.refId].meta.metricKind;
|
||||
resolve();
|
||||
} catch (error) {
|
||||
resolve();
|
||||
@ -264,31 +262,6 @@ export class StackdriverQueryCtrl extends QueryCtrl {
|
||||
}
|
||||
}
|
||||
|
||||
getAlignOptions() {
|
||||
return !this.target.valueType
|
||||
? options.alignOptions
|
||||
: options.alignOptions.filter(i => {
|
||||
return (
|
||||
i.valueTypes.indexOf(this.target.valueType) !== -1 && i.metricKinds.indexOf(this.target.metricKind) !== -1
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
getAggOptions() {
|
||||
if (this.target.aggregation.perSeriesAligner === 'ALIGN_NONE') {
|
||||
this.target.aggregation.crossSeriesReducer = options.aggOptions[0].value;
|
||||
return options.aggOptions.slice(0, 1);
|
||||
}
|
||||
|
||||
return !this.target.metricKind
|
||||
? options.aggOptions
|
||||
: options.aggOptions.filter(i => {
|
||||
return (
|
||||
i.valueTypes.indexOf(this.target.valueType) !== -1 && i.metricKinds.indexOf(this.target.metricKind) !== -1
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
onDataReceived(dataList) {
|
||||
this.lastQueryError = null;
|
||||
this.lastQueryMeta = null;
|
||||
@ -297,8 +270,6 @@ export class StackdriverQueryCtrl extends QueryCtrl {
|
||||
if (anySeriesFromQuery) {
|
||||
this.lastQueryMeta = anySeriesFromQuery.meta;
|
||||
this.lastQueryMeta.rawQueryString = decodeURIComponent(this.lastQueryMeta.rawQuery);
|
||||
this.target.valueType = anySeriesFromQuery.meta.valueType;
|
||||
this.target.metricKind = anySeriesFromQuery.meta.metricKind;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,81 @@
|
||||
import { StackdriverAggregationCtrl } from '../query_aggregation_ctrl';
|
||||
|
||||
describe('StackdriverAggregationCtrl', () => {
|
||||
let ctrl;
|
||||
describe('aggregation and alignment options', () => {
|
||||
beforeEach(() => {
|
||||
ctrl = createCtrlWithFakes();
|
||||
});
|
||||
describe('when new query result is returned from the server', () => {
|
||||
describe('and result is double and gauge', () => {
|
||||
beforeEach(async () => {
|
||||
ctrl.target.valueType = 'DOUBLE';
|
||||
ctrl.target.metricKind = 'GAUGE';
|
||||
});
|
||||
|
||||
it('should populate all aggregate options except two', () => {
|
||||
const result = ctrl.getAggOptions();
|
||||
expect(result.length).toBe(11);
|
||||
expect(result.map(o => o.value)).toEqual(
|
||||
expect.not.arrayContaining(['REDUCE_COUNT_TRUE', 'REDUCE_COUNT_FALSE'])
|
||||
);
|
||||
});
|
||||
|
||||
it('should populate all alignment options except two', () => {
|
||||
const result = ctrl.getAlignOptions();
|
||||
console.log(result.map(o => o.value));
|
||||
expect(result.length).toBe(10);
|
||||
expect(result.map(o => o.value)).toEqual(
|
||||
expect.not.arrayContaining(['REDUCE_COUNT_TRUE', 'REDUCE_COUNT_FALSE'])
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when a user a user select ALIGN_NONE and a reducer is selected', () => {
|
||||
beforeEach(async () => {
|
||||
ctrl.target.aggregation.crossSeriesReducer = 'RANDOM_REDUCER';
|
||||
ctrl.onAlignmentChange('ALIGN_NONE');
|
||||
});
|
||||
it('should set REDUCE_NONE as selected aggregation', () => {
|
||||
expect(ctrl.target.aggregation.crossSeriesReducer).toBe('REDUCE_NONE');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when a user a user select a reducer and no alignment is selected', () => {
|
||||
beforeEach(async () => {
|
||||
ctrl.target.aggregation.crossSeriesReducer = 'REDUCE_NONE';
|
||||
ctrl.target.aggregation.perSeriesAligner = 'ALIGN_NONE';
|
||||
ctrl.onAggregationChange('ALIGN_NONE');
|
||||
});
|
||||
|
||||
it('should set an alignment', () => {
|
||||
expect(ctrl.target.aggregation.perSeriesAligner).not.toBe('ALIGN_NONE');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function createCtrlWithFakes() {
|
||||
StackdriverAggregationCtrl.prototype.target = createTarget();
|
||||
return new StackdriverAggregationCtrl({ refresh: () => {} });
|
||||
}
|
||||
|
||||
function createTarget(existingFilters?: string[]) {
|
||||
return {
|
||||
project: {
|
||||
id: '',
|
||||
name: '',
|
||||
},
|
||||
metricType: 'ametric',
|
||||
refId: 'A',
|
||||
aggregation: {
|
||||
crossSeriesReducer: '',
|
||||
alignmentPeriod: '',
|
||||
perSeriesAligner: '',
|
||||
groupBys: [],
|
||||
},
|
||||
filters: existingFilters || [],
|
||||
aliasBy: '',
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user