diff --git a/CHANGELOG.md b/CHANGELOG.md index 6cd518f11eb..d4f292a2205 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,8 @@ ### Breaking changes -**InfluxDB 0.8.x** The data source for the old version of influxdb (0.8.x) is no longer included in default builds. Can easily be installed via plugin system, closes #3523 +**InfluxDB 0.8.x** The data source for the old version of influxdb (0.8.x) is no longer included in default builds. Can easily be installed via improved plugin system, closes #3523 +**KairosDB** The data source is no longer included in default builds. Can easily be installed via improved plugin system, closes #3524 # 2.6.1 (unrelased, 2.6.x branch) diff --git a/public/app/plugins/datasource/kairosdb/datasource.js b/public/app/plugins/datasource/kairosdb/datasource.js deleted file mode 100644 index 287b5ce7292..00000000000 --- a/public/app/plugins/datasource/kairosdb/datasource.js +++ /dev/null @@ -1,489 +0,0 @@ -define([ - 'angular', - 'lodash', - 'app/core/utils/datemath', - 'app/core/utils/kbn', - './queryCtrl', - './directives', -], -function (angular, _, dateMath, kbn) { - 'use strict'; - - var module = angular.module('grafana.services'); - - module.factory('KairosDBDatasource', function($q, backendSrv, templateSrv) { - - function KairosDBDatasource(datasource) { - this.type = datasource.type; - this.url = datasource.url; - this.name = datasource.name; - this.supportMetrics = true; - } - - // Called once per panel (graph) - KairosDBDatasource.prototype.query = function(options) { - var start = options.rangeRaw.from; - var end = options.rangeRaw.to; - - var queries = _.compact(_.map(options.targets, _.partial(convertTargetToQuery, options))); - var plotParams = _.compact(_.map(options.targets, function(target) { - var alias = target.alias; - if (typeof target.alias === 'undefined' || target.alias === "") { - alias = target.metric; - } - - if (!target.hide) { - return { alias: alias, exouter: target.exOuter }; - } - else { - return null; - } - })); - - var handleKairosDBQueryResponseAlias = _.partial(handleKairosDBQueryResponse, plotParams); - - // No valid targets, return the empty result to save a round trip. - if (_.isEmpty(queries)) { - var d = $q.defer(); - d.resolve({ data: [] }); - return d.promise; - } - - return this.performTimeSeriesQuery(queries, start, end).then(handleKairosDBQueryResponseAlias, handleQueryError); - }; - - KairosDBDatasource.prototype.performTimeSeriesQuery = function(queries, start, end) { - var reqBody = { - metrics: queries, - cache_time: 0 - }; - - convertToKairosTime(start, reqBody, 'start'); - convertToKairosTime(end, reqBody, 'end'); - - var options = { - method: 'POST', - url: this.url + '/api/v1/datapoints/query', - data: reqBody - }; - - return backendSrv.datasourceRequest(options); - }; - - /** - * Gets the list of metrics - * @returns {*|Promise} - */ - KairosDBDatasource.prototype._performMetricSuggestQuery = function(metric) { - var options = { - url: this.url + '/api/v1/metricnames', - method: 'GET' - }; - - return backendSrv.datasourceRequest(options).then(function(response) { - if (!response.data) { - return $q.when([]); - } - var metrics = []; - _.each(response.data.results, function(r) { - if (r.indexOf(metric) >= 0) { - metrics.push(r); - } - }); - return metrics; - }); - }; - - KairosDBDatasource.prototype._performMetricKeyLookup = function(metric) { - if(!metric) { return $q.when([]); } - - var options = { - method: 'POST', - url: this.url + '/api/v1/datapoints/query/tags', - data: { - metrics: [{ name: metric }], - cache_time: 0, - start_absolute: 0 - } - }; - - return backendSrv.datasourceRequest(options).then(function(result) { - if (!result.data) { - return $q.when([]); - } - var tagks = []; - _.each(result.data.queries[0].results[0].tags, function(tagv, tagk) { - if(tagks.indexOf(tagk) === -1) { - tagks.push(tagk); - } - }); - return tagks; - }); - }; - - KairosDBDatasource.prototype._performMetricKeyValueLookup = function(metric, key) { - if(!metric || !key) { - return $q.when([]); - } - - var options = { - method: 'POST', - url: this.url + '/api/v1/datapoints/query/tags', - data: { - metrics: [{ name: metric }], - cache_time: 0, - start_absolute: 0 - } - }; - - return backendSrv.datasourceRequest(options).then(function(result) { - if (!result.data) { - return $q.when([]); - } - return result.data.queries[0].results[0].tags[key]; - }); - }; - - KairosDBDatasource.prototype.performTagSuggestQuery = function(metric) { - var options = { - url: this.url + '/api/v1/datapoints/query/tags', - method: 'POST', - data: { - metrics: [{ name: metric }], - cache_time: 0, - start_absolute: 0 - } - }; - - return backendSrv.datasourceRequest(options).then(function(response) { - if (!response.data) { - return []; - } - else { - return response.data.queries[0].results[0]; - } - }); - }; - - KairosDBDatasource.prototype.metricFindQuery = function(query) { - if (!query) { return $q.when([]); } - - var interpolated; - try { - interpolated = templateSrv.replace(query); - } - catch (err) { - return $q.reject(err); - } - - var responseTransform = function(result) { - return _.map(result, function(value) { - return {text: value}; - }); - }; - - var metrics_regex = /metrics\((.*)\)/; - var tag_names_regex = /tag_names\((.*)\)/; - var tag_values_regex = /tag_values\((.*),\s?(.*?)\)/; - - var metrics_query = interpolated.match(metrics_regex); - if (metrics_query) { - return this._performMetricSuggestQuery(metrics_query[1]).then(responseTransform); - } - - var tag_names_query = interpolated.match(tag_names_regex); - if (tag_names_query) { - return this._performMetricKeyLookup(tag_names_query[1]).then(responseTransform); - } - - var tag_values_query = interpolated.match(tag_values_regex); - if (tag_values_query) { - return this._performMetricKeyValueLookup(tag_values_query[1], tag_values_query[2]).then(responseTransform); - } - - return $q.when([]); - }; - - ///////////////////////////////////////////////////////////////////////// - /// Formatting methods - //////////////////////////////////////////////////////////////////////// - - /** - * Requires a verion of KairosDB with every CORS defects fixed - * @param results - * @returns {*} - */ - function handleQueryError(results) { - if (results.data.errors && !_.isEmpty(results.data.errors)) { - var errors = { - message: results.data.errors[0] - }; - return $q.reject(errors); - } - else { - return $q.reject(results); - } - } - - function handleKairosDBQueryResponse(plotParams, results) { - var output = []; - var index = 0; - _.each(results.data.queries, function(series) { - _.each(series.results, function(result) { - var target = plotParams[index].alias; - var details = " ( "; - - _.each(result.group_by, function(element) { - if (element.name === "tag") { - _.each(element.group, function(value, key) { - details += key + "=" + value + " "; - }); - } - else if (element.name === "value") { - details += 'value_group=' + element.group.group_number + " "; - } - else if (element.name === "time") { - details += 'time_group=' + element.group.group_number + " "; - } - }); - - details += ") "; - - if (details !== " ( ) ") { - target += details; - } - - var datapoints = []; - - for (var i = 0; i < result.values.length; i++) { - var t = Math.floor(result.values[i][0]); - var v = result.values[i][1]; - datapoints[i] = [v, t]; - } - if (plotParams[index].exouter) { - datapoints = new PeakFilter(datapoints, 10); - } - output.push({ target: target, datapoints: datapoints }); - }); - - index++; - }); - - return { data: _.flatten(output) }; - } - - function convertTargetToQuery(options, target) { - if (!target.metric || target.hide) { - return null; - } - - var query = { - name: templateSrv.replace(target.metric) - }; - - query.aggregators = []; - - if (target.downsampling !== '(NONE)') { - if (target.downsampling === undefined) { - target.downsampling = 'avg'; - target.sampling = '10s'; - } - query.aggregators.push({ - name: target.downsampling, - align_sampling: true, - align_start_time: true, - sampling: KairosDBDatasource.prototype.convertToKairosInterval(target.sampling || options.interval) - }); - } - - if (target.horizontalAggregators) { - _.each(target.horizontalAggregators, function(chosenAggregator) { - var returnedAggregator = { - name:chosenAggregator.name - }; - - if (chosenAggregator.sampling_rate) { - returnedAggregator.sampling = KairosDBDatasource.prototype.convertToKairosInterval(chosenAggregator.sampling_rate); - returnedAggregator.align_sampling = true; - returnedAggregator.align_start_time =true; - } - - if (chosenAggregator.unit) { - returnedAggregator.unit = chosenAggregator.unit + 's'; - } - - if (chosenAggregator.factor && chosenAggregator.name === 'div') { - returnedAggregator.divisor = chosenAggregator.factor; - } - else if (chosenAggregator.factor && chosenAggregator.name === 'scale') { - returnedAggregator.factor = chosenAggregator.factor; - } - - if (chosenAggregator.percentile) { - returnedAggregator.percentile = chosenAggregator.percentile; - } - query.aggregators.push(returnedAggregator); - }); - } - - if (_.isEmpty(query.aggregators)) { - delete query.aggregators; - } - - if (target.tags) { - query.tags = angular.copy(target.tags); - _.forOwn(query.tags, function(value, key) { - query.tags[key] = _.map(value, function(tag) { return templateSrv.replace(tag); }); - }); - } - - if (target.groupByTags || target.nonTagGroupBys) { - query.group_by = []; - if (target.groupByTags) { - query.group_by.push({ - name: "tag", - tags: _.map(angular.copy(target.groupByTags), function(tag) { return templateSrv.replace(tag); }) - }); - } - - if (target.nonTagGroupBys) { - _.each(target.nonTagGroupBys, function(rawGroupBy) { - var formattedGroupBy = angular.copy(rawGroupBy); - if (formattedGroupBy.name === 'time') { - formattedGroupBy.range_size = KairosDBDatasource.prototype.convertToKairosInterval(formattedGroupBy.range_size); - } - query.group_by.push(formattedGroupBy); - }); - } - } - return query; - } - - /////////////////////////////////////////////////////////////////////// - /// Time conversion functions specifics to KairosDB - ////////////////////////////////////////////////////////////////////// - - KairosDBDatasource.prototype.convertToKairosInterval = function(intervalString) { - intervalString = templateSrv.replace(intervalString); - - var interval_regex = /(\d+(?:\.\d+)?)([Mwdhmsy])/; - var interval_regex_ms = /(\d+(?:\.\d+)?)(ms)/; - var matches = intervalString.match(interval_regex_ms); - if (!matches) { - matches = intervalString.match(interval_regex); - } - if (!matches) { - throw new Error('Invalid interval string, expecting a number followed by one of "y M w d h m s ms"'); - } - - var value = matches[1]; - var unit = matches[2]; - if (value%1 !== 0) { - if (unit === 'ms') { - throw new Error('Invalid interval value, cannot be smaller than the millisecond'); - } - value = Math.round(kbn.intervals_in_seconds[unit] * value * 1000); - unit = 'ms'; - } - - return { - value: value, - unit: convertToKairosDBTimeUnit(unit) - }; - }; - - function convertToKairosTime(date, response_obj, start_stop_name) { - var name; - - if (_.isString(date)) { - if (date === 'now') { - return; - } - else if (date.indexOf('now-') >= 0 && date.indexOf('/') === -1) { - date = date.substring(4); - name = start_stop_name + "_relative"; - var re_date = /(\d+)\s*(\D+)/; - var result = re_date.exec(date); - - if (result) { - var value = result[1]; - var unit = result[2]; - - response_obj[name] = { - value: value, - unit: convertToKairosDBTimeUnit(unit) - }; - return; - } - console.log("Unparseable date", date); - return; - } - - date = dateMath.parse(date, start_stop_name === 'end'); - } - - name = start_stop_name + "_absolute"; - response_obj[name] = date.valueOf(); - } - - function convertToKairosDBTimeUnit(unit) { - switch (unit) { - case 'ms': - return 'milliseconds'; - case 's': - return 'seconds'; - case 'm': - return 'minutes'; - case 'h': - return 'hours'; - case 'd': - return 'days'; - case 'w': - return 'weeks'; - case 'M': - return 'months'; - case 'y': - return 'years'; - default: - console.log("Unknown unit ", unit); - return ''; - } - } - - function PeakFilter(dataIn, limit) { - var datapoints = dataIn; - var arrLength = datapoints.length; - if (arrLength <= 3) { - return datapoints; - } - var LastIndx = arrLength - 1; - - // Check first point - var prvDelta = Math.abs((datapoints[1][0] - datapoints[0][0]) / datapoints[0][0]); - var nxtDelta = Math.abs((datapoints[1][0] - datapoints[2][0]) / datapoints[2][0]); - if (prvDelta >= limit && nxtDelta < limit) { - datapoints[0][0] = datapoints[1][0]; - } - - // Check last point - prvDelta = Math.abs((datapoints[LastIndx - 1][0] - datapoints[LastIndx - 2][0]) / datapoints[LastIndx - 2][0]); - nxtDelta = Math.abs((datapoints[LastIndx - 1][0] - datapoints[LastIndx][0]) / datapoints[LastIndx][0]); - if (prvDelta >= limit && nxtDelta < limit) { - datapoints[LastIndx][0] = datapoints[LastIndx - 1][0]; - } - - for (var i = 1; i < arrLength - 1; i++) { - prvDelta = Math.abs((datapoints[i][0] - datapoints[i - 1][0]) / datapoints[i - 1][0]); - nxtDelta = Math.abs((datapoints[i][0] - datapoints[i + 1][0]) / datapoints[i + 1][0]); - if (prvDelta >= limit && nxtDelta >= limit) { - datapoints[i][0] = (datapoints[i - 1][0] + datapoints[i + 1][0]) / 2; - } - } - - return datapoints; - } - - return KairosDBDatasource; - }); - -}); diff --git a/public/app/plugins/datasource/kairosdb/directives.js b/public/app/plugins/datasource/kairosdb/directives.js deleted file mode 100644 index 6a24ff1f787..00000000000 --- a/public/app/plugins/datasource/kairosdb/directives.js +++ /dev/null @@ -1,17 +0,0 @@ -define([ - 'angular', -], -function (angular) { - 'use strict'; - - var module = angular.module('grafana.directives'); - - module.directive('metricQueryEditorKairosdb', function() { - return {controller: 'KairosDBQueryCtrl', templateUrl: 'app/plugins/datasource/kairosdb/partials/query.editor.html'}; - }); - - module.directive('metricQueryOptionsKairosdb', function() { - return {templateUrl: 'app/plugins/datasource/kairosdb/partials/query.options.html'}; - }); - -}); diff --git a/public/app/plugins/datasource/kairosdb/partials/config.html b/public/app/plugins/datasource/kairosdb/partials/config.html deleted file mode 100644 index 384edeaeafe..00000000000 --- a/public/app/plugins/datasource/kairosdb/partials/config.html +++ /dev/null @@ -1 +0,0 @@ -
diff --git a/public/app/plugins/datasource/kairosdb/partials/query.editor.html b/public/app/plugins/datasource/kairosdb/partials/query.editor.html deleted file mode 100644 index 2fa6880abd9..00000000000 --- a/public/app/plugins/datasource/kairosdb/partials/query.editor.html +++ /dev/null @@ -1,331 +0,0 @@ -
- - - - -
-
- - -
- -
-
- - -
- -
-
- - -
- -
-
- - diff --git a/public/app/plugins/datasource/kairosdb/partials/query.options.html b/public/app/plugins/datasource/kairosdb/partials/query.options.html deleted file mode 100644 index 21bc109b426..00000000000 --- a/public/app/plugins/datasource/kairosdb/partials/query.options.html +++ /dev/null @@ -1,37 +0,0 @@ -
-
- -
-
-
diff --git a/public/app/plugins/datasource/kairosdb/plugin.json b/public/app/plugins/datasource/kairosdb/plugin.json deleted file mode 100644 index df31b024d87..00000000000 --- a/public/app/plugins/datasource/kairosdb/plugin.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "pluginType": "datasource", - "name": "KairosDB", - - "type": "kairosdb", - "serviceName": "KairosDBDatasource", - - "module": "app/plugins/datasource/kairosdb/datasource", - - "partials": { - "config": "app/plugins/datasource/kairosdb/partials/config.html" - }, - - "metrics": true, - "annotations": false -} diff --git a/public/app/plugins/datasource/kairosdb/queryCtrl.js b/public/app/plugins/datasource/kairosdb/queryCtrl.js deleted file mode 100644 index 86178c934b8..00000000000 --- a/public/app/plugins/datasource/kairosdb/queryCtrl.js +++ /dev/null @@ -1,332 +0,0 @@ -define([ - 'angular', - 'lodash' -], -function (angular, _) { - 'use strict'; - - var module = angular.module('grafana.controllers'); - - module.controller('KairosDBQueryCtrl', function($scope) { - - $scope.init = function() { - $scope.panel.stack = false; - if (!$scope.panel.downsampling) { - $scope.panel.downsampling = 'avg'; - } - if (!$scope.target.downsampling) { - $scope.target.downsampling = $scope.panel.downsampling; - $scope.target.sampling = $scope.panel.sampling; - } - $scope.target.errors = validateTarget($scope.target); - }; - - $scope.targetBlur = function() { - $scope.target.errors = validateTarget($scope.target); - if (!_.isEqual($scope.oldTarget, $scope.target) && _.isEmpty($scope.target.errors)) { - $scope.oldTarget = angular.copy($scope.target); - $scope.get_data(); - } - }; - - $scope.panelBlur = function() { - _.each($scope.panel.targets, function(target) { - target.downsampling = $scope.panel.downsampling; - target.sampling = $scope.panel.sampling; - }); - $scope.get_data(); - }; - - $scope.getTextValues = function(metricFindResult) { - return _.map(metricFindResult, function(value) { return value.text; }); - }; - - $scope.suggestMetrics = function(query, callback) { - $scope.datasource.metricFindQuery('metrics(' + query + ')') - .then($scope.getTextValues) - .then(callback); - }; - - $scope.suggestTagKeys = function(query, callback) { - $scope.datasource.metricFindQuery('tag_names(' + $scope.target.metric + ')') - .then($scope.getTextValues) - .then(callback); - }; - - $scope.suggestTagValues = function(query, callback) { - $scope.datasource.metricFindQuery('tag_values(' + $scope.target.metric + ',' + $scope.target.currentTagKey + ')') - .then($scope.getTextValues) - .then(callback); - }; - - // Filter metric by tag - $scope.addFilterTag = function() { - if (!$scope.addFilterTagMode) { - $scope.addFilterTagMode = true; - $scope.validateFilterTag(); - return; - } - - if (!$scope.target.tags) { - $scope.target.tags = {}; - } - - $scope.validateFilterTag(); - if (!$scope.target.errors.tags) { - if (!_.has($scope.target.tags, $scope.target.currentTagKey)) { - $scope.target.tags[$scope.target.currentTagKey] = []; - } - $scope.target.tags[$scope.target.currentTagKey].push($scope.target.currentTagValue); - $scope.target.currentTagKey = ''; - $scope.target.currentTagValue = ''; - $scope.targetBlur(); - } - - $scope.addFilterTagMode = false; - }; - - $scope.removeFilterTag = function(key) { - delete $scope.target.tags[key]; - if (_.size($scope.target.tags) === 0) { - $scope.target.tags = null; - } - $scope.targetBlur(); - }; - - $scope.validateFilterTag = function() { - $scope.target.errors.tags = null; - if (!$scope.target.currentTagKey || !$scope.target.currentTagValue) { - $scope.target.errors.tags = "You must specify a tag name and value."; - } - }; - - ////////////////////////////// - // GROUP BY - ////////////////////////////// - - $scope.addGroupBy = function() { - if (!$scope.addGroupByMode) { - $scope.addGroupByMode = true; - $scope.target.currentGroupByType = 'tag'; - $scope.isTagGroupBy = true; - $scope.validateGroupBy(); - return; - } - $scope.validateGroupBy(); - // nb: if error is found, means that user clicked on cross : cancels input - if (_.isEmpty($scope.target.errors.groupBy)) { - if ($scope.isTagGroupBy) { - if (!$scope.target.groupByTags) { - $scope.target.groupByTags = []; - } - if (!_.contains($scope.target.groupByTags, $scope.target.groupBy.tagKey)) { - $scope.target.groupByTags.push($scope.target.groupBy.tagKey); - $scope.targetBlur(); - } - $scope.target.groupBy.tagKey = ''; - } - else { - if (!$scope.target.nonTagGroupBys) { - $scope.target.nonTagGroupBys = []; - } - var groupBy = { - name: $scope.target.currentGroupByType - }; - if ($scope.isValueGroupBy) {groupBy.range_size = $scope.target.groupBy.valueRange;} - else if ($scope.isTimeGroupBy) { - groupBy.range_size = $scope.target.groupBy.timeInterval; - groupBy.group_count = $scope.target.groupBy.groupCount; - } - $scope.target.nonTagGroupBys.push(groupBy); - } - $scope.targetBlur(); - } - $scope.isTagGroupBy = false; - $scope.isValueGroupBy = false; - $scope.isTimeGroupBy = false; - $scope.addGroupByMode = false; - }; - - $scope.removeGroupByTag = function(index) { - $scope.target.groupByTags.splice(index, 1); - if (_.size($scope.target.groupByTags) === 0) { - $scope.target.groupByTags = null; - } - $scope.targetBlur(); - }; - - $scope.removeNonTagGroupBy = function(index) { - $scope.target.nonTagGroupBys.splice(index, 1); - if (_.size($scope.target.nonTagGroupBys) === 0) { - $scope.target.nonTagGroupBys = null; - } - $scope.targetBlur(); - }; - - $scope.changeGroupByInput = function() { - $scope.isTagGroupBy = $scope.target.currentGroupByType === 'tag'; - $scope.isValueGroupBy = $scope.target.currentGroupByType === 'value'; - $scope.isTimeGroupBy = $scope.target.currentGroupByType === 'time'; - $scope.validateGroupBy(); - }; - - $scope.validateGroupBy = function() { - delete $scope.target.errors.groupBy; - var errors = {}; - $scope.isGroupByValid = true; - if ($scope.isTagGroupBy) { - if (!$scope.target.groupBy.tagKey) { - $scope.isGroupByValid = false; - errors.tagKey = 'You must supply a tag name'; - } - } - - if ($scope.isValueGroupBy) { - if (!$scope.target.groupBy.valueRange || !isInt($scope.target.groupBy.valueRange)) { - errors.valueRange = "Range must be an integer"; - $scope.isGroupByValid = false; - } - } - - if ($scope.isTimeGroupBy) { - try { - $scope.datasource.convertToKairosInterval($scope.target.groupBy.timeInterval); - } catch (err) { - errors.timeInterval = err.message; - $scope.isGroupByValid = false; - } - if (!$scope.target.groupBy.groupCount || !isInt($scope.target.groupBy.groupCount)) { - errors.groupCount = "Group count must be an integer"; - $scope.isGroupByValid = false; - } - } - - if (!_.isEmpty(errors)) { - $scope.target.errors.groupBy = errors; - } - }; - - function isInt(n) { - return parseInt(n) % 1 === 0; - } - - ////////////////////////////// - // HORIZONTAL AGGREGATION - ////////////////////////////// - - $scope.addHorizontalAggregator = function() { - if (!$scope.addHorizontalAggregatorMode) { - $scope.addHorizontalAggregatorMode = true; - $scope.target.currentHorizontalAggregatorName = 'avg'; - $scope.hasSamplingRate = true; - $scope.validateHorizontalAggregator(); - return; - } - - $scope.validateHorizontalAggregator(); - // nb: if error is found, means that user clicked on cross : cancels input - if (_.isEmpty($scope.target.errors.horAggregator)) { - if (!$scope.target.horizontalAggregators) { - $scope.target.horizontalAggregators = []; - } - var aggregator = { - name:$scope.target.currentHorizontalAggregatorName - }; - if ($scope.hasSamplingRate) {aggregator.sampling_rate = $scope.target.horAggregator.samplingRate;} - if ($scope.hasUnit) {aggregator.unit = $scope.target.horAggregator.unit;} - if ($scope.hasFactor) {aggregator.factor = $scope.target.horAggregator.factor;} - if ($scope.hasPercentile) {aggregator.percentile = $scope.target.horAggregator.percentile;} - $scope.target.horizontalAggregators.push(aggregator); - $scope.targetBlur(); - } - - $scope.addHorizontalAggregatorMode = false; - $scope.hasSamplingRate = false; - $scope.hasUnit = false; - $scope.hasFactor = false; - $scope.hasPercentile = false; - }; - - $scope.removeHorizontalAggregator = function(index) { - $scope.target.horizontalAggregators.splice(index, 1); - if (_.size($scope.target.horizontalAggregators) === 0) { - $scope.target.horizontalAggregators = null; - } - - $scope.targetBlur(); - }; - - $scope.changeHorAggregationInput = function() { - $scope.hasSamplingRate = _.contains(['avg','dev','max','min','sum','least_squares','count','percentile'], - $scope.target.currentHorizontalAggregatorName); - $scope.hasUnit = _.contains(['sampler','rate'], $scope.target.currentHorizontalAggregatorName); - $scope.hasFactor = _.contains(['div','scale'], $scope.target.currentHorizontalAggregatorName); - $scope.hasPercentile = 'percentile' === $scope.target.currentHorizontalAggregatorName; - $scope.validateHorizontalAggregator(); - }; - - $scope.validateHorizontalAggregator = function() { - delete $scope.target.errors.horAggregator; - var errors = {}; - $scope.isAggregatorValid = true; - - if ($scope.hasSamplingRate) { - try { - $scope.datasource.convertToKairosInterval($scope.target.horAggregator.samplingRate); - } catch (err) { - errors.samplingRate = err.message; - $scope.isAggregatorValid = false; - } - } - - if ($scope.hasFactor) { - if (!$scope.target.horAggregator.factor) { - errors.factor = 'You must supply a numeric value for this aggregator'; - $scope.isAggregatorValid = false; - } - else if (parseInt($scope.target.horAggregator.factor) === 0 && $scope.target.currentHorizontalAggregatorName === 'div') { - errors.factor = 'Cannot divide by 0'; - $scope.isAggregatorValid = false; - } - } - - if ($scope.hasPercentile) { - if (!$scope.target.horAggregator.percentile || - $scope.target.horAggregator.percentile<=0 || - $scope.target.horAggregator.percentile>1) { - errors.percentile = 'Percentile must be between 0 and 1'; - $scope.isAggregatorValid = false; - } - } - - if (!_.isEmpty(errors)) { - $scope.target.errors.horAggregator = errors; - } - }; - - $scope.alert = function(message) { - alert(message); - }; - - // Validation - function validateTarget(target) { - var errs = {}; - - if (!target.metric) { - errs.metric = "You must supply a metric name."; - } - - try { - if (target.sampling) { - $scope.datasource.convertToKairosInterval(target.sampling); - } - } catch (err) { - errs.sampling = err.message; - } - - return errs; - } - - }); - -});