define([ 'angular', 'lodash', './query_def' ], function (angular, _, queryDef) { 'use strict'; var module = angular.module('grafana.directives'); module.directive('elasticMetricAgg', function() { return { templateUrl: 'public/app/plugins/datasource/elasticsearch/partials/metric_agg.html', controller: 'ElasticMetricAggCtrl', restrict: 'E', scope: { target: "=", index: "=", onChange: "&", getFields: "&", esVersion: '=' } }; }); module.controller('ElasticMetricAggCtrl', function($scope, uiSegmentSrv, $q, $rootScope) { var metricAggs = $scope.target.metrics; $scope.metricAggTypes = queryDef.getMetricAggTypes($scope.esVersion); $scope.extendedStats = queryDef.extendedStats; $scope.pipelineAggOptions = []; $scope.modelSettingsValues = {}; $scope.init = function() { $scope.agg = metricAggs[$scope.index]; $scope.validateModel(); $scope.updatePipelineAggOptions(); }; $scope.updatePipelineAggOptions = function() { $scope.pipelineAggOptions = queryDef.getPipelineAggOptions($scope.target); }; $rootScope.onAppEvent('elastic-query-updated', function() { $scope.index = _.indexOf(metricAggs, $scope.agg); $scope.updatePipelineAggOptions(); $scope.validateModel(); }, $scope); $scope.validateModel = function() { $scope.isFirst = $scope.index === 0; $scope.isSingle = metricAggs.length === 1; $scope.settingsLinkText = ''; $scope.aggDef = _.find($scope.metricAggTypes, {value: $scope.agg.type}); if (queryDef.isPipelineAgg($scope.agg.type)) { $scope.agg.pipelineAgg = $scope.agg.pipelineAgg || 'select metric'; $scope.agg.field = $scope.agg.pipelineAgg; var pipelineOptions = queryDef.getPipelineOptions($scope.agg); if (pipelineOptions.length > 0) { _.each(pipelineOptions, function(opt) { $scope.agg.settings[opt.text] = $scope.agg.settings[opt.text] || opt.default; }); $scope.settingsLinkText = 'Options'; } } else if (!$scope.agg.field) { $scope.agg.field = 'select field'; } switch($scope.agg.type) { case 'cardinality': { var precision_threshold = $scope.agg.settings.precision_threshold || ''; $scope.settingsLinkText = 'Precision threshold: ' + precision_threshold; break; } case 'percentiles': { $scope.agg.settings.percents = $scope.agg.settings.percents || [25,50,75,95,99]; $scope.settingsLinkText = 'Values: ' + $scope.agg.settings.percents.join(','); break; } case 'extended_stats': { if (_.keys($scope.agg.meta).length === 0) { $scope.agg.meta.std_deviation_bounds_lower = true; $scope.agg.meta.std_deviation_bounds_upper = true; } var stats = _.reduce($scope.agg.meta, function(memo, val, key) { if (val) { var def = _.find($scope.extendedStats, {value: key}); memo.push(def.text); } return memo; }, []); $scope.settingsLinkText = 'Stats: ' + stats.join(', '); break; } case 'moving_avg': { $scope.movingAvgModelTypes = queryDef.movingAvgModelOptions; $scope.modelSettings = queryDef.getMovingAvgSettings($scope.agg.settings.model, true); $scope.updateMovingAvgModelSettings(); break; } case 'raw_document': { $scope.agg.settings.size = $scope.agg.settings.size || 500; $scope.settingsLinkText = 'Size: ' + $scope.agg.settings.size ; $scope.target.metrics.splice(0,$scope.target.metrics.length, $scope.agg); $scope.target.bucketAggs = []; break; } } if ($scope.aggDef.supportsInlineScript) { // I know this stores the inline script twice // but having it like this simplifes the query_builder var inlineScript = $scope.agg.inlineScript; if (inlineScript) { $scope.agg.settings.script = {inline: inlineScript}; } else { delete $scope.agg.settings.script; } if ($scope.settingsLinkText === '') { $scope.settingsLinkText = 'Options'; } } }; $scope.toggleOptions = function() { $scope.showOptions = !$scope.showOptions; $scope.updatePipelineAggOptions(); }; $scope.onChangeInternal = function() { $scope.onChange(); }; $scope.updateMovingAvgModelSettings = function () { var modelSettingsKeys = []; var modelSettings = queryDef.getMovingAvgSettings($scope.agg.settings.model, false); for (var i=0; i < modelSettings.length; i++) { modelSettingsKeys.push(modelSettings[i].value); } for (var key in $scope.agg.settings.settings) { if (($scope.agg.settings.settings[key] === null) || (modelSettingsKeys.indexOf(key) === -1)) { delete $scope.agg.settings.settings[key]; } } }; $scope.onChangeClearInternal = function() { delete $scope.agg.settings.minimize; $scope.onChange(); }; $scope.onTypeChange = function() { $scope.agg.settings = {}; $scope.agg.meta = {}; $scope.showOptions = false; $scope.updatePipelineAggOptions(); $scope.onChange(); }; $scope.getFieldsInternal = function() { if ($scope.agg.type === 'cardinality') { return $scope.getFields(); } return $scope.getFields({$fieldType: 'number'}); }; $scope.addMetricAgg = function() { var addIndex = metricAggs.length; var id = _.reduce($scope.target.bucketAggs.concat($scope.target.metrics), function(max, val) { return parseInt(val.id) > max ? parseInt(val.id) : max; }, 0); metricAggs.splice(addIndex, 0, {type: "count", field: "select field", id: (id+1).toString()}); $scope.onChange(); }; $scope.removeMetricAgg = function() { metricAggs.splice($scope.index, 1); $scope.onChange(); }; $scope.toggleShowMetric = function() { $scope.agg.hide = !$scope.agg.hide; if (!$scope.agg.hide) { delete $scope.agg.hide; } $scope.onChange(); }; $scope.init(); }); });