mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Elasticsearch: Add Moving Function Pipeline Aggregation (#28131)
* Elasticsearch: Add Moving Function Pipeline Aggregation * Removing support for moving average in 7.x * Fixing getMetricAggTypes to handle undefined esVersion * Adding moving_fn to go code * Update public/app/plugins/datasource/elasticsearch/metric_agg.ts Co-authored-by: Giordano Ricci <grdnricci@gmail.com> * Adding test for esversion 70 * Removing default value for script, adding placeholder instead * Fixing formatting * Adding code for handling missing or obsolete aggregations Co-authored-by: Giordano Ricci <grdnricci@gmail.com>
This commit is contained in:
parent
af8589a4ba
commit
4ed7612e57
@ -45,6 +45,7 @@ var metricAggType = map[string]string{
|
|||||||
"percentiles": "Percentiles",
|
"percentiles": "Percentiles",
|
||||||
"cardinality": "Unique Count",
|
"cardinality": "Unique Count",
|
||||||
"moving_avg": "Moving Average",
|
"moving_avg": "Moving Average",
|
||||||
|
"moving_fn": "Moving Function",
|
||||||
"cumulative_sum": "Cumulative Sum",
|
"cumulative_sum": "Cumulative Sum",
|
||||||
"derivative": "Derivative",
|
"derivative": "Derivative",
|
||||||
"bucket_script": "Bucket Script",
|
"bucket_script": "Bucket Script",
|
||||||
@ -64,6 +65,7 @@ var extendedStats = map[string]string{
|
|||||||
|
|
||||||
var pipelineAggType = map[string]string{
|
var pipelineAggType = map[string]string{
|
||||||
"moving_avg": "moving_avg",
|
"moving_avg": "moving_avg",
|
||||||
|
"moving_fn": "moving_fn",
|
||||||
"cumulative_sum": "cumulative_sum",
|
"cumulative_sum": "cumulative_sum",
|
||||||
"derivative": "derivative",
|
"derivative": "derivative",
|
||||||
"bucket_script": "bucket_script",
|
"bucket_script": "bucket_script",
|
||||||
|
@ -44,6 +44,7 @@ export class ElasticMetricAggCtrl {
|
|||||||
$scope.settingsLinkText = '';
|
$scope.settingsLinkText = '';
|
||||||
$scope.variablesLinkText = '';
|
$scope.variablesLinkText = '';
|
||||||
$scope.aggDef = _.find($scope.metricAggTypes, { value: $scope.agg.type });
|
$scope.aggDef = _.find($scope.metricAggTypes, { value: $scope.agg.type });
|
||||||
|
$scope.isValidAgg = $scope.aggDef != null;
|
||||||
|
|
||||||
if (queryDef.isPipelineAgg($scope.agg.type)) {
|
if (queryDef.isPipelineAgg($scope.agg.type)) {
|
||||||
if (queryDef.isPipelineAggWithMultipleBucketPaths($scope.agg.type)) {
|
if (queryDef.isPipelineAggWithMultipleBucketPaths($scope.agg.type)) {
|
||||||
@ -105,6 +106,13 @@ export class ElasticMetricAggCtrl {
|
|||||||
$scope.updateMovingAvgModelSettings();
|
$scope.updateMovingAvgModelSettings();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'moving_fn': {
|
||||||
|
const movingFunctionOptions = queryDef.getPipelineOptions($scope.agg);
|
||||||
|
_.each(movingFunctionOptions, opt => {
|
||||||
|
$scope.agg.settings[opt.text] = $scope.agg.settings[opt.text] || opt.default;
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'raw_document':
|
case 'raw_document':
|
||||||
case 'raw_data': {
|
case 'raw_data': {
|
||||||
$scope.agg.settings.size = $scope.agg.settings.size || 500;
|
$scope.agg.settings.size = $scope.agg.settings.size || 500;
|
||||||
@ -115,7 +123,7 @@ export class ElasticMetricAggCtrl {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($scope.aggDef.supportsInlineScript) {
|
if ($scope.aggDef?.supportsInlineScript) {
|
||||||
// I know this stores the inline script twice
|
// I know this stores the inline script twice
|
||||||
// but having it like this simplifes the query_builder
|
// but having it like this simplifes the query_builder
|
||||||
const inlineScript = $scope.agg.inlineScript;
|
const inlineScript = $scope.agg.inlineScript;
|
||||||
|
@ -10,12 +10,18 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="gf-form">
|
<div class="gf-form" ng-if="isValidAgg">
|
||||||
<metric-segment-model property="agg.type" options="metricAggTypes" on-change="onTypeChange()" custom="false" css-class="width-10"></metric-segment-model>
|
<metric-segment-model property="agg.type" options="metricAggTypes" on-change="onTypeChange()" custom="false" css-class="width-10"></metric-segment-model>
|
||||||
<metric-segment-model ng-if="aggDef.requiresField" property="agg.field" get-options="getFieldsInternal()" on-change="onChange()" css-class="width-12"></metric-segment-model>
|
<metric-segment-model ng-if="aggDef.requiresField" property="agg.field" get-options="getFieldsInternal()" on-change="onChange()" css-class="width-12"></metric-segment-model>
|
||||||
<metric-segment-model ng-if="aggDef.isPipelineAgg && !aggDef.supportsMultipleBucketPaths" property="agg.pipelineAgg" options="pipelineAggOptions" on-change="onChangeInternal()" custom="false" css-class="width-12"></metric-segment-model>
|
<metric-segment-model ng-if="aggDef.isPipelineAgg && !aggDef.supportsMultipleBucketPaths" property="agg.pipelineAgg" options="pipelineAggOptions" on-change="onChangeInternal()" custom="false" css-class="width-12"></metric-segment-model>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="gf-form gf-form--grow" ng-if="!isValidAgg">
|
||||||
|
<label class="gf-form-label gf-form-label--grow">
|
||||||
|
<em>This aggregation is no longer supported by your version of Elasticsearch</em>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="gf-form gf-form--grow" ng-if="aggDef.isPipelineAgg && aggDef.supportsMultipleBucketPaths">
|
<div class="gf-form gf-form--grow" ng-if="aggDef.isPipelineAgg && aggDef.supportsMultipleBucketPaths">
|
||||||
<label class="gf-form-label gf-form-label--grow">
|
<label class="gf-form-label gf-form-label--grow">
|
||||||
<a ng-click="toggleVariables()">
|
<a ng-click="toggleVariables()">
|
||||||
@ -26,7 +32,7 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="gf-form gf-form--grow">
|
<div class="gf-form gf-form--grow" ng-if="isValidAgg">
|
||||||
<label class="gf-form-label gf-form-label--grow">
|
<label class="gf-form-label gf-form-label--grow">
|
||||||
<a ng-click="toggleOptions()" ng-if="settingsLinkText">
|
<a ng-click="toggleOptions()" ng-if="settingsLinkText">
|
||||||
<icon name="'angle-down'" ng-show="showOptions"></icon>
|
<icon name="'angle-down'" ng-show="showOptions"></icon>
|
||||||
@ -71,6 +77,25 @@
|
|||||||
<input type="text" class="gf-form-input max-width-12" ng-model="agg.settings.format" ng-blur="onChangeInternal()" spellcheck='false'>
|
<input type="text" class="gf-form-input max-width-12" ng-model="agg.settings.format" ng-blur="onChangeInternal()" spellcheck='false'>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div ng-if="agg.type === 'moving_fn'">
|
||||||
|
|
||||||
|
<div class="gf-form offset-width-7">
|
||||||
|
<label class="gf-form-label width-10">Window</label>
|
||||||
|
<input type="number" class="gf-form-input max-width-12" ng-model="agg.settings.window" ng-blur="onChangeInternal()" spellcheck='false'>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="gf-form offset-width-7">
|
||||||
|
<label class="gf-form-label width-10">Script</label>
|
||||||
|
<input type="text" class="gf-form-input max-width-12" ng-model="agg.settings.script" ng-blur="onChangeInternal()" spellcheck='false' placeholder="eg. MovingFunctions.unweightedAvg(values)">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="gf-form offset-width-7">
|
||||||
|
<label class="gf-form-label width-10">Shift</label>
|
||||||
|
<input type="number" class="gf-form-input max-width-12" ng-model="agg.settings.shift" ng-blur="onChangeInternal()" spellcheck='false'>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
<div ng-if="agg.type === 'moving_avg'">
|
<div ng-if="agg.type === 'moving_avg'">
|
||||||
<div class="gf-form offset-width-7">
|
<div class="gf-form offset-width-7">
|
||||||
<label class="gf-form-label width-10">Model</label>
|
<label class="gf-form-label width-10">Model</label>
|
||||||
|
@ -57,6 +57,14 @@ export const metricAggTypes = [
|
|||||||
requiresField: false,
|
requiresField: false,
|
||||||
isPipelineAgg: true,
|
isPipelineAgg: true,
|
||||||
minVersion: 2,
|
minVersion: 2,
|
||||||
|
maxVersion: 60,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Moving Function',
|
||||||
|
value: 'moving_fn',
|
||||||
|
requiresField: false,
|
||||||
|
isPipelineAgg: true,
|
||||||
|
minVersion: 70,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: 'Derivative',
|
text: 'Derivative',
|
||||||
@ -151,6 +159,7 @@ export const pipelineOptions: any = {
|
|||||||
{ text: 'predict', default: undefined },
|
{ text: 'predict', default: undefined },
|
||||||
{ text: 'minimize', default: false },
|
{ text: 'minimize', default: false },
|
||||||
],
|
],
|
||||||
|
moving_fn: [{ text: 'window', default: 5 }, { text: 'script' }],
|
||||||
derivative: [{ text: 'unit', default: undefined }],
|
derivative: [{ text: 'unit', default: undefined }],
|
||||||
cumulative_sum: [{ text: 'format', default: undefined }],
|
cumulative_sum: [{ text: 'format', default: undefined }],
|
||||||
bucket_script: [],
|
bucket_script: [],
|
||||||
@ -175,8 +184,10 @@ export const movingAvgModelSettings: any = {
|
|||||||
|
|
||||||
export function getMetricAggTypes(esVersion: any) {
|
export function getMetricAggTypes(esVersion: any) {
|
||||||
return _.filter(metricAggTypes, f => {
|
return _.filter(metricAggTypes, f => {
|
||||||
if (f.minVersion) {
|
if (f.minVersion || f.maxVersion) {
|
||||||
return f.minVersion <= esVersion;
|
const minVersion = f.minVersion || 0;
|
||||||
|
const maxVersion = f.maxVersion || esVersion;
|
||||||
|
return esVersion >= minVersion && esVersion <= maxVersion;
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -162,8 +162,21 @@ describe('ElasticQueryDef', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('using esversion 5', () => {
|
describe('using esversion 5', () => {
|
||||||
|
const metricAggTypes = queryDef.getMetricAggTypes(5);
|
||||||
test('should get pipeline aggs', () => {
|
test('should get pipeline aggs', () => {
|
||||||
expect(queryDef.getMetricAggTypes(5).length).toBe(15);
|
expect(metricAggTypes.length).toBe(15);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('using esversion 70', () => {
|
||||||
|
const metricAggTypes = queryDef.getMetricAggTypes(70);
|
||||||
|
test('should get pipeline aggs', () => {
|
||||||
|
expect(metricAggTypes.length).toBe(15);
|
||||||
|
});
|
||||||
|
test('should get pipeline aggs with moving function', () => {
|
||||||
|
expect(metricAggTypes.some(m => m.value === 'moving_fn')).toBeTruthy();
|
||||||
|
});
|
||||||
|
test('should get pipeline aggs without moving average', () => {
|
||||||
|
expect(metricAggTypes.some(m => m.value === 'moving_avg')).toBeFalsy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user