2018-10-14 15:39:34 +02:00
|
|
|
import coreModule from 'app/core/core_module';
|
2017-12-28 09:18:57 +01:00
|
|
|
import _ from 'lodash';
|
|
|
|
|
import * as queryDef from './query_def';
|
2019-06-24 22:15:03 +02:00
|
|
|
import { ElasticsearchAggregation } from './types';
|
2019-10-14 09:27:47 +01:00
|
|
|
import { GrafanaRootScope } from 'app/routes/GrafanaCtrl';
|
|
|
|
|
import { CoreEvents } from 'app/types';
|
2017-12-28 09:18:57 +01:00
|
|
|
|
2020-10-08 03:24:54 -07:00
|
|
|
function createDefaultMetric(id = 0): ElasticsearchAggregation {
|
|
|
|
|
return { type: 'count', field: 'select field', id: (id + 1).toString() };
|
|
|
|
|
}
|
|
|
|
|
|
2017-12-28 09:18:57 +01:00
|
|
|
export class ElasticMetricAggCtrl {
|
2018-11-28 09:20:49 +01:00
|
|
|
/** @ngInject */
|
2019-12-05 09:04:03 +00:00
|
|
|
constructor($scope: any, uiSegmentSrv: any, $rootScope: GrafanaRootScope) {
|
2019-06-24 22:15:03 +02:00
|
|
|
const metricAggs: ElasticsearchAggregation[] = $scope.target.metrics;
|
2015-12-14 15:08:34 +01:00
|
|
|
$scope.metricAggTypes = queryDef.getMetricAggTypes($scope.esVersion);
|
2015-09-07 13:13:19 +02:00
|
|
|
$scope.extendedStats = queryDef.extendedStats;
|
2015-12-10 10:43:00 +01:00
|
|
|
$scope.pipelineAggOptions = [];
|
2017-01-04 00:31:15 +00:00
|
|
|
$scope.modelSettingsValues = {};
|
2015-09-05 09:05:09 +02:00
|
|
|
|
2018-09-04 14:27:03 +02:00
|
|
|
$scope.init = () => {
|
2015-09-05 15:41:04 +02:00
|
|
|
$scope.agg = metricAggs[$scope.index];
|
2015-09-05 18:31:42 +02:00
|
|
|
$scope.validateModel();
|
2015-12-10 10:43:00 +01:00
|
|
|
$scope.updatePipelineAggOptions();
|
2015-12-09 13:55:06 +01:00
|
|
|
};
|
|
|
|
|
|
2018-09-04 14:27:03 +02:00
|
|
|
$scope.updatePipelineAggOptions = () => {
|
2020-10-08 03:24:54 -07:00
|
|
|
$scope.pipelineAggOptions = queryDef.getPipelineAggOptions($scope.target, $scope.agg);
|
2015-09-06 14:45:12 +02:00
|
|
|
};
|
2015-09-05 09:05:09 +02:00
|
|
|
|
2017-12-28 09:18:57 +01:00
|
|
|
$rootScope.onAppEvent(
|
2019-10-14 09:27:47 +01:00
|
|
|
CoreEvents.elasticQueryUpdated,
|
2018-09-04 14:27:03 +02:00
|
|
|
() => {
|
2017-12-28 09:18:57 +01:00
|
|
|
$scope.index = _.indexOf(metricAggs, $scope.agg);
|
|
|
|
|
$scope.updatePipelineAggOptions();
|
|
|
|
|
$scope.validateModel();
|
|
|
|
|
},
|
|
|
|
|
$scope
|
|
|
|
|
);
|
2015-09-05 09:05:09 +02:00
|
|
|
|
2018-09-04 14:27:03 +02:00
|
|
|
$scope.validateModel = () => {
|
2015-09-05 20:22:54 +02:00
|
|
|
$scope.isFirst = $scope.index === 0;
|
|
|
|
|
$scope.isSingle = metricAggs.length === 1;
|
2015-09-05 19:55:58 +02:00
|
|
|
$scope.settingsLinkText = '';
|
2018-11-16 16:54:25 +01:00
|
|
|
$scope.variablesLinkText = '';
|
2017-12-28 09:18:57 +01:00
|
|
|
$scope.aggDef = _.find($scope.metricAggTypes, { value: $scope.agg.type });
|
2020-11-11 10:42:28 -07:00
|
|
|
$scope.isValidAgg = $scope.aggDef != null;
|
2015-09-05 19:55:58 +02:00
|
|
|
|
2015-12-10 17:42:31 +01:00
|
|
|
if (queryDef.isPipelineAgg($scope.agg.type)) {
|
2018-11-16 16:54:25 +01:00
|
|
|
if (queryDef.isPipelineAggWithMultipleBucketPaths($scope.agg.type)) {
|
|
|
|
|
$scope.variablesLinkText = 'Options';
|
|
|
|
|
|
|
|
|
|
if ($scope.agg.settings.script) {
|
|
|
|
|
$scope.variablesLinkText = 'Script: ' + $scope.agg.settings.script.replace(new RegExp('params.', 'g'), '');
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
$scope.agg.pipelineAgg = $scope.agg.pipelineAgg || 'select metric';
|
|
|
|
|
$scope.agg.field = $scope.agg.pipelineAgg;
|
|
|
|
|
}
|
2015-12-10 17:03:46 +01:00
|
|
|
|
2018-08-29 14:27:29 +02:00
|
|
|
const pipelineOptions = queryDef.getPipelineOptions($scope.agg);
|
2015-12-11 12:41:40 +01:00
|
|
|
if (pipelineOptions.length > 0) {
|
2018-09-04 14:27:03 +02:00
|
|
|
_.each(pipelineOptions, opt => {
|
2015-12-11 12:41:40 +01:00
|
|
|
$scope.agg.settings[opt.text] = $scope.agg.settings[opt.text] || opt.default;
|
|
|
|
|
});
|
2015-12-11 09:44:37 +01:00
|
|
|
$scope.settingsLinkText = 'Options';
|
|
|
|
|
}
|
2015-12-10 11:46:19 +01:00
|
|
|
} else if (!$scope.agg.field) {
|
|
|
|
|
$scope.agg.field = 'select field';
|
2015-12-10 11:17:14 +01:00
|
|
|
}
|
2017-12-28 09:18:57 +01:00
|
|
|
switch ($scope.agg.type) {
|
2016-04-28 19:23:45 -03:00
|
|
|
case 'cardinality': {
|
2018-09-03 11:00:46 +02:00
|
|
|
const precisionThreshold = $scope.agg.settings.precision_threshold || '';
|
|
|
|
|
$scope.settingsLinkText = 'Precision threshold: ' + precisionThreshold;
|
2016-04-28 19:23:45 -03:00
|
|
|
break;
|
|
|
|
|
}
|
2015-09-05 20:22:54 +02:00
|
|
|
case 'percentiles': {
|
2017-12-28 09:18:57 +01:00
|
|
|
$scope.agg.settings.percents = $scope.agg.settings.percents || [25, 50, 75, 95, 99];
|
2015-12-11 18:20:53 +01:00
|
|
|
$scope.settingsLinkText = 'Values: ' + $scope.agg.settings.percents.join(',');
|
2015-09-05 20:22:54 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case 'extended_stats': {
|
2017-12-28 09:18:57 +01:00
|
|
|
if (_.keys($scope.agg.meta).length === 0) {
|
2015-12-11 18:20:53 +01:00
|
|
|
$scope.agg.meta.std_deviation_bounds_lower = true;
|
|
|
|
|
$scope.agg.meta.std_deviation_bounds_upper = true;
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-29 14:27:29 +02:00
|
|
|
const stats = _.reduce(
|
2017-12-28 09:18:57 +01:00
|
|
|
$scope.agg.meta,
|
2018-09-04 14:27:03 +02:00
|
|
|
(memo, val, key) => {
|
2017-12-28 09:18:57 +01:00
|
|
|
if (val) {
|
2019-04-15 12:11:52 +02:00
|
|
|
const def: any = _.find($scope.extendedStats, { value: key });
|
2017-12-28 09:18:57 +01:00
|
|
|
memo.push(def.text);
|
|
|
|
|
}
|
|
|
|
|
return memo;
|
|
|
|
|
},
|
2020-07-08 11:05:20 +02:00
|
|
|
[] as string[]
|
2017-12-28 09:18:57 +01:00
|
|
|
);
|
2015-09-08 09:10:26 +02:00
|
|
|
|
2015-12-11 18:20:53 +01:00
|
|
|
$scope.settingsLinkText = 'Stats: ' + stats.join(', ');
|
2015-11-05 08:36:51 +01:00
|
|
|
break;
|
|
|
|
|
}
|
2017-01-04 00:31:15 +00:00
|
|
|
case 'moving_avg': {
|
|
|
|
|
$scope.movingAvgModelTypes = queryDef.movingAvgModelOptions;
|
|
|
|
|
$scope.modelSettings = queryDef.getMovingAvgSettings($scope.agg.settings.model, true);
|
|
|
|
|
$scope.updateMovingAvgModelSettings();
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-11-11 10:42:28 -07:00
|
|
|
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;
|
|
|
|
|
}
|
2020-07-15 15:20:39 +02:00
|
|
|
case 'raw_document':
|
|
|
|
|
case 'raw_data': {
|
2017-06-02 23:56:48 +00:00
|
|
|
$scope.agg.settings.size = $scope.agg.settings.size || 500;
|
2017-12-28 09:18:57 +01:00
|
|
|
$scope.settingsLinkText = 'Size: ' + $scope.agg.settings.size;
|
|
|
|
|
$scope.target.metrics.splice(0, $scope.target.metrics.length, $scope.agg);
|
2017-06-03 02:50:10 +00:00
|
|
|
|
2015-11-05 08:36:51 +01:00
|
|
|
$scope.target.bucketAggs = [];
|
2015-12-11 18:20:53 +01:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-11-11 10:42:28 -07:00
|
|
|
if ($scope.aggDef?.supportsInlineScript) {
|
2015-12-11 18:20:53 +01:00
|
|
|
// I know this stores the inline script twice
|
|
|
|
|
// but having it like this simplifes the query_builder
|
2018-08-29 14:27:29 +02:00
|
|
|
const inlineScript = $scope.agg.inlineScript;
|
2015-12-11 18:20:53 +01:00
|
|
|
if (inlineScript) {
|
2017-12-28 09:18:57 +01:00
|
|
|
$scope.agg.settings.script = { inline: inlineScript };
|
2015-12-11 18:20:53 +01:00
|
|
|
} else {
|
|
|
|
|
delete $scope.agg.settings.script;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($scope.settingsLinkText === '') {
|
|
|
|
|
$scope.settingsLinkText = 'Options';
|
2015-09-05 20:22:54 +02:00
|
|
|
}
|
2015-09-05 18:31:42 +02:00
|
|
|
}
|
2015-09-06 14:45:12 +02:00
|
|
|
};
|
2015-09-05 18:31:42 +02:00
|
|
|
|
2018-09-04 14:27:03 +02:00
|
|
|
$scope.toggleOptions = () => {
|
2015-09-05 15:41:04 +02:00
|
|
|
$scope.showOptions = !$scope.showOptions;
|
2015-12-10 10:43:00 +01:00
|
|
|
$scope.updatePipelineAggOptions();
|
2015-12-09 09:04:48 +01:00
|
|
|
};
|
|
|
|
|
|
2018-11-16 16:54:25 +01:00
|
|
|
$scope.toggleVariables = () => {
|
|
|
|
|
$scope.showVariables = !$scope.showVariables;
|
|
|
|
|
};
|
|
|
|
|
|
2018-09-04 14:27:03 +02:00
|
|
|
$scope.onChangeInternal = () => {
|
2015-12-09 09:04:48 +01:00
|
|
|
$scope.onChange();
|
2015-09-05 18:31:42 +02:00
|
|
|
};
|
|
|
|
|
|
2018-09-04 14:27:03 +02:00
|
|
|
$scope.updateMovingAvgModelSettings = () => {
|
2018-08-29 14:27:29 +02:00
|
|
|
const modelSettingsKeys = [];
|
|
|
|
|
const modelSettings = queryDef.getMovingAvgSettings($scope.agg.settings.model, false);
|
2018-08-30 09:03:11 +02:00
|
|
|
for (let i = 0; i < modelSettings.length; i++) {
|
2017-01-04 00:31:15 +00:00
|
|
|
modelSettingsKeys.push(modelSettings[i].value);
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-29 14:27:29 +02:00
|
|
|
for (const key in $scope.agg.settings.settings) {
|
2017-12-28 09:18:57 +01:00
|
|
|
if ($scope.agg.settings.settings[key] === null || modelSettingsKeys.indexOf(key) === -1) {
|
2017-01-04 00:31:15 +00:00
|
|
|
delete $scope.agg.settings.settings[key];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2018-09-04 14:27:03 +02:00
|
|
|
$scope.onChangeClearInternal = () => {
|
2017-01-04 00:31:15 +00:00
|
|
|
delete $scope.agg.settings.minimize;
|
|
|
|
|
$scope.onChange();
|
|
|
|
|
};
|
|
|
|
|
|
2018-09-04 14:27:03 +02:00
|
|
|
$scope.onTypeChange = () => {
|
2015-09-05 18:31:42 +02:00
|
|
|
$scope.agg.settings = {};
|
2015-09-07 13:13:19 +02:00
|
|
|
$scope.agg.meta = {};
|
|
|
|
|
$scope.showOptions = false;
|
2018-11-08 00:46:13 +01:00
|
|
|
|
|
|
|
|
// reset back to metric/group by query
|
2020-07-15 15:20:39 +02:00
|
|
|
if (
|
|
|
|
|
$scope.target.bucketAggs.length === 0 &&
|
|
|
|
|
($scope.agg.type !== 'raw_document' || $scope.agg.type !== 'raw_data')
|
|
|
|
|
) {
|
2018-11-08 00:46:13 +01:00
|
|
|
$scope.target.bucketAggs = [queryDef.defaultBucketAgg()];
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-16 16:54:25 +01:00
|
|
|
$scope.showVariables = queryDef.isPipelineAggWithMultipleBucketPaths($scope.agg.type);
|
2015-12-10 17:01:29 +01:00
|
|
|
$scope.updatePipelineAggOptions();
|
2015-09-05 18:31:42 +02:00
|
|
|
$scope.onChange();
|
|
|
|
|
};
|
2015-09-05 09:05:09 +02:00
|
|
|
|
2018-09-04 14:27:03 +02:00
|
|
|
$scope.getFieldsInternal = () => {
|
2017-03-07 00:36:33 -07:00
|
|
|
if ($scope.agg.type === 'cardinality') {
|
|
|
|
|
return $scope.getFields();
|
|
|
|
|
}
|
2017-12-28 09:18:57 +01:00
|
|
|
return $scope.getFields({ $fieldType: 'number' });
|
2015-09-22 09:31:58 +02:00
|
|
|
};
|
|
|
|
|
|
2018-09-04 14:27:03 +02:00
|
|
|
$scope.addMetricAgg = () => {
|
2018-08-29 14:27:29 +02:00
|
|
|
const addIndex = metricAggs.length;
|
2015-09-05 12:24:14 +02:00
|
|
|
|
2018-08-29 14:27:29 +02:00
|
|
|
const id = _.reduce(
|
2017-12-28 09:18:57 +01:00
|
|
|
$scope.target.bucketAggs.concat($scope.target.metrics),
|
2018-09-04 14:27:03 +02:00
|
|
|
(max, val) => {
|
2018-09-05 16:51:31 +02:00
|
|
|
return parseInt(val.id, 10) > max ? parseInt(val.id, 10) : max;
|
2017-12-28 09:18:57 +01:00
|
|
|
},
|
|
|
|
|
0
|
|
|
|
|
);
|
2015-09-05 12:24:14 +02:00
|
|
|
|
2020-10-08 03:24:54 -07:00
|
|
|
metricAggs.splice(addIndex, 0, createDefaultMetric(id));
|
2015-09-05 20:22:54 +02:00
|
|
|
$scope.onChange();
|
2015-09-05 15:41:04 +02:00
|
|
|
};
|
2015-09-05 09:05:09 +02:00
|
|
|
|
2018-09-04 14:27:03 +02:00
|
|
|
$scope.removeMetricAgg = () => {
|
2020-10-08 03:24:54 -07:00
|
|
|
const metricBeingRemoved = metricAggs[$scope.index];
|
|
|
|
|
const metricsToRemove = queryDef.getAncestors($scope.target, metricBeingRemoved);
|
|
|
|
|
const newMetricAggs = metricAggs.filter(m => !metricsToRemove.includes(m.id));
|
|
|
|
|
if (newMetricAggs.length > 0) {
|
|
|
|
|
metricAggs.splice(0, metricAggs.length, ...newMetricAggs);
|
|
|
|
|
} else {
|
|
|
|
|
metricAggs.splice(0, metricAggs.length, createDefaultMetric());
|
|
|
|
|
}
|
2015-09-05 15:41:04 +02:00
|
|
|
$scope.onChange();
|
|
|
|
|
};
|
2015-09-05 09:05:09 +02:00
|
|
|
|
2018-09-04 14:27:03 +02:00
|
|
|
$scope.toggleShowMetric = () => {
|
2015-12-11 12:41:40 +01:00
|
|
|
$scope.agg.hide = !$scope.agg.hide;
|
|
|
|
|
if (!$scope.agg.hide) {
|
|
|
|
|
delete $scope.agg.hide;
|
|
|
|
|
}
|
|
|
|
|
$scope.onChange();
|
|
|
|
|
};
|
|
|
|
|
|
2015-09-05 15:41:04 +02:00
|
|
|
$scope.init();
|
2017-12-28 09:18:57 +01:00
|
|
|
}
|
|
|
|
|
}
|
2015-09-05 09:05:09 +02:00
|
|
|
|
2018-11-28 09:20:49 +01:00
|
|
|
export function elasticMetricAgg() {
|
|
|
|
|
return {
|
|
|
|
|
templateUrl: 'public/app/plugins/datasource/elasticsearch/partials/metric_agg.html',
|
|
|
|
|
controller: ElasticMetricAggCtrl,
|
|
|
|
|
restrict: 'E',
|
|
|
|
|
scope: {
|
|
|
|
|
target: '=',
|
|
|
|
|
index: '=',
|
|
|
|
|
onChange: '&',
|
|
|
|
|
getFields: '&',
|
|
|
|
|
esVersion: '=',
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-14 15:39:34 +02:00
|
|
|
coreModule.directive('elasticMetricAgg', elasticMetricAgg);
|