From 618d4f0a9de54bddd603e12e3a8f74f6004214b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Fri, 27 Mar 2015 13:49:05 +0100 Subject: [PATCH 001/149] Testing kariosdb datasource, hm.. needs a lot of work --- pkg/api/frontendsettings.go | 6 +- .../plugins/datasource/kairosdb/datasource.js | 420 ++++++++++++++++++ .../datasource/kairosdb/partials/config.html | 1 + .../kairosdb/partials/query.editor.html | 384 ++++++++++++++++ .../plugins/datasource/kairosdb/plugin.json | 17 + .../plugins/datasource/kairosdb/queryCtrl.js | 379 ++++++++++++++++ 6 files changed, 1204 insertions(+), 3 deletions(-) create mode 100644 src/app/plugins/datasource/kairosdb/datasource.js create mode 100644 src/app/plugins/datasource/kairosdb/partials/config.html create mode 100644 src/app/plugins/datasource/kairosdb/partials/query.editor.html create mode 100644 src/app/plugins/datasource/kairosdb/plugin.json create mode 100644 src/app/plugins/datasource/kairosdb/queryCtrl.js diff --git a/pkg/api/frontendsettings.go b/pkg/api/frontendsettings.go index e42a2deedf2..3af191a7af7 100644 --- a/pkg/api/frontendsettings.go +++ b/pkg/api/frontendsettings.go @@ -1,11 +1,10 @@ package api import ( - "errors" - "fmt" "strconv" "github.com/grafana/grafana/pkg/bus" + "github.com/grafana/grafana/pkg/log" "github.com/grafana/grafana/pkg/middleware" m "github.com/grafana/grafana/pkg/models" "github.com/grafana/grafana/pkg/plugins" @@ -45,7 +44,8 @@ func getFrontendSettingsMap(c *middleware.Context) (map[string]interface{}, erro meta, exists := plugins.DataSources[ds.Type] if !exists { - return nil, errors.New(fmt.Sprintf("Could not find plugin definition for data source: %v", ds.Type)) + log.Error(3, "Could not find plugin definition for data source: %v", ds.Type) + continue } dsMap["meta"] = meta diff --git a/src/app/plugins/datasource/kairosdb/datasource.js b/src/app/plugins/datasource/kairosdb/datasource.js new file mode 100644 index 00000000000..e055c118956 --- /dev/null +++ b/src/app/plugins/datasource/kairosdb/datasource.js @@ -0,0 +1,420 @@ +define([ + 'angular', + 'lodash', + 'kbn', + './queryCtrl', +], +function (angular, _, kbn) { + 'use strict'; + + var module = angular.module('grafana.services'); + var tagList = null; + + module.factory('KairosDBDatasource', function($q, $http) { + + function KairosDBDatasource(datasource) { + this.type = datasource.type; + this.editorSrc = 'plugins/datasources/kairosdb/kairosdb.editor.html'; + this.url = datasource.url; + this.name = datasource.name; + this.supportMetrics = true; + this.grafanaDB = datasource.grafanaDB; + } + + // Called once per panel (graph) + KairosDBDatasource.prototype.query = function(options) { + var start = options.range.from; + var end = options.range.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; + return !target.hide + ? {alias: alias, + exouter: target.exOuter} + : 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); + }; + + /////////////////////////////////////////////////////////////////////// + /// Query methods + /////////////////////////////////////////////////////////////////////// + + KairosDBDatasource.prototype.performTimeSeriesQuery = function(queries, start, end) { + var reqBody = { + metrics: queries + }; + reqBody.cache_time=0; + convertToKairosTime(start,reqBody,'start'); + convertToKairosTime(end,reqBody,'end'); + var options = { + method: 'POST', + url: '/api/v1/datapoints/query', + data: reqBody + }; + + options.url = this.url + options.url; + return $http(options); + }; + + /** + * Gets the list of metrics + * @returns {*|Promise} + */ + KairosDBDatasource.prototype.performMetricSuggestQuery = function() { + var options = { + url : this.url + '/api/v1/metricnames', + method : 'GET' + }; + return $http(options).then(function(results) { + if (!results.data) { + return []; + } + return results.data.results; + }); + + }; + + KairosDBDatasource.prototype.performTagSuggestQuery = function(metricname,range,type,keyValue) { + if(tagList && (metricname === tagList.metricName) && (range.from === tagList.range.from) && + (range.to === tagList.range.to)) { + return getTagListFromResponse(tagList.results,type,keyValue); + } + tagList = { + metricName:metricname, + range:range + }; + var body = { + metrics : [{name : metricname}] + }; + convertToKairosTime(range.from,body,'start'); + convertToKairosTime(range.to,body,'end'); + var options = { + url : this.url + '/api/v1/datapoints/query/tags', + method : 'POST', + data : body + }; + return $http(options).then(function(results) { + tagList.results = results; + return getTagListFromResponse(results,type,keyValue); + }); + + }; + + ///////////////////////////////////////////////////////////////////////// + /// Formatting methods + //////////////////////////////////////////////////////////////////////// + + function getTagListFromResponse(results,type,keyValue) { + if (!results.data) { + return []; + } + if(type==="key") { + return _.keys(results.data.queries[0].results[0].tags); + } + else if(type==="value" && _.has(results.data.queries[0].results[0].tags,keyValue)) { + return results.data.queries[0].results[0].tags[keyValue]; + } + return []; + } + + /** + * 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) { + var sample_size = series.sample_size; + console.log("sample_size:" + sample_size + " samples"); + + _.each(series.results, function (result) { + + //var target = result.name; + 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 = PeakFilter(datapoints, 10); + output.push({ target: target, datapoints: datapoints }); + }); + index ++; + }); + var output2 = { data: _.flatten(output) }; + + return output2; + } + + function convertTargetToQuery(options,target) { + if (!target.metric || target.hide) { + return null; + } + + var query = { + name: target.metric + }; + + query.aggregators = []; + if(target.downsampling!=='(NONE)') { + 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); + } + + if(target.groupByTags || target.nonTagGroupBys) { + query.group_by = []; + if(target.groupByTags) {query.group_by.push({name: "tag", tags: angular.copy(target.groupByTags)});} + 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) { + 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'; + + } + switch(unit) { + case 'ms': + unit = 'milliseconds'; + break; + case 's': + unit = 'seconds'; + break; + case 'm': + unit = 'minutes'; + break; + case 'h': + unit = 'hours'; + break; + case 'd': + unit = 'days'; + break; + case 'w': + unit = 'weeks'; + break; + case 'M': + unit = 'months'; + break; + case 'y': + unit = 'years'; + break; + default: + console.log("Unknown interval ", intervalString); + break; + } + + return { + "value": value, + "unit": unit + }; + + }; + + function convertToKairosTime(date, response_obj, start_stop_name) { + var name; + if (_.isString(date)) { + if (date === 'now') { + return; + } + else if (date.indexOf('now-') >= 0) { + + name = start_stop_name + "_relative"; + + date = date.substring(4); + var re_date = /(\d+)\s*(\D+)/; + var result = re_date.exec(date); + if (result) { + var value = result[1]; + var unit = result[2]; + switch(unit) { + case 'ms': + unit = 'milliseconds'; + break; + case 's': + unit = 'seconds'; + break; + case 'm': + unit = 'minutes'; + break; + case 'h': + unit = 'hours'; + break; + case 'd': + unit = 'days'; + break; + case 'w': + unit = 'weeks'; + break; + case 'M': + unit = 'months'; + break; + case 'y': + unit = 'years'; + break; + default: + console.log("Unknown date ", date); + break; + } + response_obj[name] = { + "value": value, + "unit": unit + }; + return; + } + console.log("Unparseable date", date); + return; + } + date = kbn.parseDate(date); + } + + if(_.isDate(date)) { + name = start_stop_name + "_absolute"; + response_obj[name] = date.getTime(); + return; + } + + console.log("Date is neither string nor date"); + } + + 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/src/app/plugins/datasource/kairosdb/partials/config.html b/src/app/plugins/datasource/kairosdb/partials/config.html new file mode 100644 index 00000000000..384edeaeafe --- /dev/null +++ b/src/app/plugins/datasource/kairosdb/partials/config.html @@ -0,0 +1 @@ +
diff --git a/src/app/plugins/datasource/kairosdb/partials/query.editor.html b/src/app/plugins/datasource/kairosdb/partials/query.editor.html new file mode 100644 index 00000000000..8a794e7fdf2 --- /dev/null +++ b/src/app/plugins/datasource/kairosdb/partials/query.editor.html @@ -0,0 +1,384 @@ +
+
+ +
+ + +
    +
  • + {{targetLetters[$index]}} +
  • +
  • + + + +
  • +
  • + +
  • +
  • + + + + +
  • + +
  • +  Peak filter + +
  • +
+ +
+
+ +
+ +
+
+
+
+ +
+
+
    +
  • + +
  • + +
  • + Downsampling with +
  • +
  • + +
  • + + +
  • + every +
  • +
  • + + + + +
  • +
+
+
+
diff --git a/src/app/plugins/datasource/kairosdb/plugin.json b/src/app/plugins/datasource/kairosdb/plugin.json new file mode 100644 index 00000000000..bdbf27c5fa8 --- /dev/null +++ b/src/app/plugins/datasource/kairosdb/plugin.json @@ -0,0 +1,17 @@ +{ + "pluginType": "datasource", + "name": "KairosDB", + + "type": "kairosdb", + "serviceName": "KairosDBDatasource", + + "module": "plugins/datasource/kairosdb/datasource", + + "partials": { + "config": "app/plugins/datasource/kairosdb/partials/config.html", + "query": "app/plugins/datasource/kairosdb/partials/query.editor.html" + }, + + "metrics": true, + "annotations": false +} diff --git a/src/app/plugins/datasource/kairosdb/queryCtrl.js b/src/app/plugins/datasource/kairosdb/queryCtrl.js new file mode 100644 index 00000000000..fef1e4d39f4 --- /dev/null +++ b/src/app/plugins/datasource/kairosdb/queryCtrl.js @@ -0,0 +1,379 @@ +define([ + 'angular', + 'lodash' +], +function (angular, _) { + 'use strict'; + + var module = angular.module('grafana.controllers'); + var metricList = null; + var targetLetters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O']; + + module.controller('KairosDBTargetCtrl', function($scope) { + + $scope.init = function() { + $scope.metric = { + list: ["Loading..."], + value: "Loading..." + }; + $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.targetLetters = targetLetters; + $scope.updateMetricList(); + $scope.target.errors = validateTarget($scope.target); + }; + + $scope.targetBlur = function() { + $scope.target.metric = $scope.metric.value; + $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.duplicate = function() { + var clone = angular.copy($scope.target); + $scope.panel.targets.push(clone); + }; + $scope.moveMetricQuery = function(fromIndex, toIndex) { + _.move($scope.panel.targets, fromIndex, toIndex); + }; + + ////////////////////////////// + // SUGGESTION QUERIES + ////////////////////////////// + + $scope.updateMetricList = function() { + $scope.metricListLoading = true; + metricList = []; + $scope.datasource.performMetricSuggestQuery().then(function(series) { + metricList = series; + $scope.metric.list = series; + if ($scope.target.metric) + $scope.metric.value = $scope.target.metric; + else + $scope.metric.value = ""; + $scope.metricListLoading = false; + return metricList; + }); + }; + + $scope.suggestTagKeys = function(query, callback) { + $scope.updateTimeRange(); + callback($scope.datasource + .performTagSuggestQuery($scope.target.metric,$scope.rangeUnparsed, 'key','')); + + }; + + $scope.suggestTagValues = function(query, callback) { + callback($scope.datasource + .performTagSuggestQuery($scope.target.metric,$scope.rangeUnparsed, 'value',$scope.target.currentTagKey)); + }; + + ////////////////////////////// + // FILTER 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 = []; + } + console.log($scope.target.groupBy.tagKey); + 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 MetricListToObject(MetricList) { + var result = {}; + var Metric; + var MetricArray = []; + var MetricCnt = 0; + for (var i =0;i < MetricList.length; i++) { + Metric = MetricList[i]; + MetricArray = Metric.split('.'); + if(!result.hasOwnProperty(MetricArray[0])) { + result[MetricArray[0]] = {}; + } + if(!result[MetricArray[0]].hasOwnProperty(MetricArray[1])) { + result[MetricArray[0]][MetricArray[1]] = []; + } + result[MetricArray[0]][MetricArray[1]].push(MetricArray[2]); + } + return result; + } + + 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; + } + + }); + +}); From 15188c4a885c9f884a867e6711c2461f1a87d033 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Sun, 29 Mar 2015 20:13:32 +0200 Subject: [PATCH 002/149] Moved kairosdb data source to correct folder --- {src => public}/app/plugins/datasource/kairosdb/datasource.js | 0 .../app/plugins/datasource/kairosdb/partials/config.html | 0 .../app/plugins/datasource/kairosdb/partials/query.editor.html | 0 {src => public}/app/plugins/datasource/kairosdb/plugin.json | 0 {src => public}/app/plugins/datasource/kairosdb/queryCtrl.js | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename {src => public}/app/plugins/datasource/kairosdb/datasource.js (100%) rename {src => public}/app/plugins/datasource/kairosdb/partials/config.html (100%) rename {src => public}/app/plugins/datasource/kairosdb/partials/query.editor.html (100%) rename {src => public}/app/plugins/datasource/kairosdb/plugin.json (100%) rename {src => public}/app/plugins/datasource/kairosdb/queryCtrl.js (100%) diff --git a/src/app/plugins/datasource/kairosdb/datasource.js b/public/app/plugins/datasource/kairosdb/datasource.js similarity index 100% rename from src/app/plugins/datasource/kairosdb/datasource.js rename to public/app/plugins/datasource/kairosdb/datasource.js diff --git a/src/app/plugins/datasource/kairosdb/partials/config.html b/public/app/plugins/datasource/kairosdb/partials/config.html similarity index 100% rename from src/app/plugins/datasource/kairosdb/partials/config.html rename to public/app/plugins/datasource/kairosdb/partials/config.html diff --git a/src/app/plugins/datasource/kairosdb/partials/query.editor.html b/public/app/plugins/datasource/kairosdb/partials/query.editor.html similarity index 100% rename from src/app/plugins/datasource/kairosdb/partials/query.editor.html rename to public/app/plugins/datasource/kairosdb/partials/query.editor.html diff --git a/src/app/plugins/datasource/kairosdb/plugin.json b/public/app/plugins/datasource/kairosdb/plugin.json similarity index 100% rename from src/app/plugins/datasource/kairosdb/plugin.json rename to public/app/plugins/datasource/kairosdb/plugin.json diff --git a/src/app/plugins/datasource/kairosdb/queryCtrl.js b/public/app/plugins/datasource/kairosdb/queryCtrl.js similarity index 100% rename from src/app/plugins/datasource/kairosdb/queryCtrl.js rename to public/app/plugins/datasource/kairosdb/queryCtrl.js From 795cee13c8b011c8e2ccbf7b0fe12a83de699503 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Sun, 29 Mar 2015 20:30:42 +0200 Subject: [PATCH 003/149] KairosDB data source plugin is messy, needs a lot of clean up & refactoring, please help --- .../plugins/datasource/kairosdb/datasource.js | 2 +- .../plugins/datasource/kairosdb/queryCtrl.js | 26 ++++++------------- 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/public/app/plugins/datasource/kairosdb/datasource.js b/public/app/plugins/datasource/kairosdb/datasource.js index e055c118956..bcce19cb83f 100644 --- a/public/app/plugins/datasource/kairosdb/datasource.js +++ b/public/app/plugins/datasource/kairosdb/datasource.js @@ -217,7 +217,7 @@ function (angular, _, kbn) { if(chosenAggregator.sampling_rate) { returnedAggregator.sampling = KairosDBDatasource.prototype.convertToKairosInterval(chosenAggregator.sampling_rate); returnedAggregator.align_sampling = true; - returnedAggregator.align_start_time=true; + returnedAggregator.align_start_time =true; } if(chosenAggregator.unit) { returnedAggregator.unit = chosenAggregator.unit+'s'; diff --git a/public/app/plugins/datasource/kairosdb/queryCtrl.js b/public/app/plugins/datasource/kairosdb/queryCtrl.js index fef1e4d39f4..73321d3016a 100644 --- a/public/app/plugins/datasource/kairosdb/queryCtrl.js +++ b/public/app/plugins/datasource/kairosdb/queryCtrl.js @@ -53,30 +53,26 @@ function (angular, _) { _.move($scope.panel.targets, fromIndex, toIndex); }; - ////////////////////////////// - // SUGGESTION QUERIES - ////////////////////////////// - + // Fetch metric list $scope.updateMetricList = function() { $scope.metricListLoading = true; metricList = []; $scope.datasource.performMetricSuggestQuery().then(function(series) { metricList = series; $scope.metric.list = series; - if ($scope.target.metric) + if ($scope.target.metric) { $scope.metric.value = $scope.target.metric; - else + } + else { $scope.metric.value = ""; + } $scope.metricListLoading = false; return metricList; }); }; $scope.suggestTagKeys = function(query, callback) { - $scope.updateTimeRange(); - callback($scope.datasource - .performTagSuggestQuery($scope.target.metric,$scope.rangeUnparsed, 'key','')); - + callback($scope.datasource.performTagSuggestQuery($scope.target.metric, $scope.rangeUnparsed, 'key','')); }; $scope.suggestTagValues = function(query, callback) { @@ -84,10 +80,7 @@ function (angular, _) { .performTagSuggestQuery($scope.target.metric,$scope.rangeUnparsed, 'value',$scope.target.currentTagKey)); }; - ////////////////////////////// - // FILTER by TAG - ////////////////////////////// - + // Filter metric by tag $scope.addFilterTag = function() { if (!$scope.addFilterTagMode) { $scope.addFilterTagMode = true; @@ -333,10 +326,7 @@ function (angular, _) { alert(message); }; - ////////////////////////////// - // VALIDATION - ////////////////////////////// - + // Validation function MetricListToObject(MetricList) { var result = {}; var Metric; From 66f5411402f87d7ba4ca34e96b83dd97601f0e19 Mon Sep 17 00:00:00 2001 From: Masaori Koshiba Date: Sun, 12 Apr 2015 18:39:41 +0900 Subject: [PATCH 004/149] Fix class names in query.editor.html of KairosDB Plugin --- .../kairosdb/partials/query.editor.html | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/public/app/plugins/datasource/kairosdb/partials/query.editor.html b/public/app/plugins/datasource/kairosdb/partials/query.editor.html index 8a794e7fdf2..23ddecabc4e 100644 --- a/public/app/plugins/datasource/kairosdb/partials/query.editor.html +++ b/public/app/plugins/datasource/kairosdb/partials/query.editor.html @@ -10,7 +10,7 @@
  • - +
  • @@ -98,13 +98,13 @@
  • {{key}} = {{value}} - +
  • - +
  • @@ -130,12 +130,12 @@ - +
  • - - + +
  • @@ -152,7 +152,7 @@
  • {{key}} - +
  • @@ -163,13 +163,13 @@
  • {{_.values(groupByObject)}} - +
  • - +
  • @@ -190,7 +190,7 @@ - +
  • @@ -204,7 +204,7 @@ - +
  • @@ -219,7 +219,7 @@ - +
  • @@ -233,13 +233,13 @@ - +
  • - - + +
  • @@ -285,7 +285,7 @@ - + @@ -375,7 +375,7 @@ - + From ed69ddedbf2a58a2ae24a1bf11320983624fe8c4 Mon Sep 17 00:00:00 2001 From: Masaori Koshiba Date: Sun, 12 Apr 2015 19:46:19 +0900 Subject: [PATCH 005/149] Fix styles warned by jscs --- public/app/plugins/datasource/kairosdb/datasource.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/app/plugins/datasource/kairosdb/datasource.js b/public/app/plugins/datasource/kairosdb/datasource.js index bcce19cb83f..7376c528ce9 100644 --- a/public/app/plugins/datasource/kairosdb/datasource.js +++ b/public/app/plugins/datasource/kairosdb/datasource.js @@ -27,7 +27,7 @@ function (angular, _, kbn) { var end = options.range.to; var queries = _.compact(_.map(options.targets, _.partial(convertTargetToQuery, options))); - var plotParams = _.compact(_.map(options.targets, function(target){ + var plotParams = _.compact(_.map(options.targets, function(target) { var alias = target.alias; if (typeof target.alias == 'undefined' || target.alias == "") alias = target.metric; From ae2201ef6f50dd79ae4165c6e969df6d93e59d09 Mon Sep 17 00:00:00 2001 From: Masaori Koshiba Date: Sun, 12 Apr 2015 20:03:43 +0900 Subject: [PATCH 006/149] Add space after keywords --- .../plugins/datasource/kairosdb/datasource.js | 54 +++++++-------- .../plugins/datasource/kairosdb/queryCtrl.js | 68 +++++++++---------- 2 files changed, 61 insertions(+), 61 deletions(-) diff --git a/public/app/plugins/datasource/kairosdb/datasource.js b/public/app/plugins/datasource/kairosdb/datasource.js index 7376c528ce9..ecd4564f72f 100644 --- a/public/app/plugins/datasource/kairosdb/datasource.js +++ b/public/app/plugins/datasource/kairosdb/datasource.js @@ -86,7 +86,7 @@ function (angular, _, kbn) { }; KairosDBDatasource.prototype.performTagSuggestQuery = function(metricname,range,type,keyValue) { - if(tagList && (metricname === tagList.metricName) && (range.from === tagList.range.from) && + if (tagList && (metricname === tagList.metricName) && (range.from === tagList.range.from) && (range.to === tagList.range.to)) { return getTagListFromResponse(tagList.results,type,keyValue); } @@ -119,10 +119,10 @@ function (angular, _, kbn) { if (!results.data) { return []; } - if(type==="key") { + if (type==="key") { return _.keys(results.data.queries[0].results[0].tags); } - else if(type==="value" && _.has(results.data.queries[0].results[0].tags,keyValue)) { + else if (type==="value" && _.has(results.data.queries[0].results[0].tags,keyValue)) { return results.data.queries[0].results[0].tags[keyValue]; } return []; @@ -134,13 +134,13 @@ function (angular, _, kbn) { * @returns {*} */ function handleQueryError(results) { - if(results.data.errors && !_.isEmpty(results.data.errors)) { + if (results.data.errors && !_.isEmpty(results.data.errors)) { var errors = { message: results.data.errors[0] }; return $q.reject(errors); } - else{ + else { return $q.reject(results); } } @@ -158,15 +158,15 @@ function (angular, _, kbn) { var target = plotParams[index].alias; var details = " ( "; _.each(result.group_by,function(element) { - if(element.name==="tag") { + if (element.name==="tag") { _.each(element.group,function(value, key) { details+= key+"="+value+" "; }); } - else if(element.name==="value") { + else if (element.name==="value") { details+= 'value_group='+element.group.group_number+" "; } - else if(element.name==="time") { + else if (element.name==="time") { details+= 'time_group='+element.group.group_number+" "; } }); @@ -201,7 +201,7 @@ function (angular, _, kbn) { }; query.aggregators = []; - if(target.downsampling!=='(NONE)') { + if (target.downsampling!=='(NONE)') { query.aggregators.push({ name: target.downsampling, align_sampling: true, @@ -209,46 +209,46 @@ function (angular, _, kbn) { sampling: KairosDBDatasource.prototype.convertToKairosInterval(target.sampling || options.interval) }); } - if(target.horizontalAggregators) { + if (target.horizontalAggregators) { _.each(target.horizontalAggregators,function(chosenAggregator) { var returnedAggregator = { name:chosenAggregator.name }; - if(chosenAggregator.sampling_rate) { + if (chosenAggregator.sampling_rate) { returnedAggregator.sampling = KairosDBDatasource.prototype.convertToKairosInterval(chosenAggregator.sampling_rate); returnedAggregator.align_sampling = true; returnedAggregator.align_start_time =true; } - if(chosenAggregator.unit) { + if (chosenAggregator.unit) { returnedAggregator.unit = chosenAggregator.unit+'s'; } - if(chosenAggregator.factor && chosenAggregator.name==='div') { + if (chosenAggregator.factor && chosenAggregator.name==='div') { returnedAggregator.divisor = chosenAggregator.factor; } - else if(chosenAggregator.factor && chosenAggregator.name==='scale') { + else if (chosenAggregator.factor && chosenAggregator.name==='scale') { returnedAggregator.factor = chosenAggregator.factor; } - if(chosenAggregator.percentile) { + if (chosenAggregator.percentile) { returnedAggregator.percentile = chosenAggregator.percentile; } query.aggregators.push(returnedAggregator); }); } - if(_.isEmpty(query.aggregators)) { + if (_.isEmpty(query.aggregators)) { delete query.aggregators; } - if(target.tags) { + if (target.tags) { query.tags = angular.copy(target.tags); } - if(target.groupByTags || target.nonTagGroupBys) { + if (target.groupByTags || target.nonTagGroupBys) { query.group_by = []; - if(target.groupByTags) {query.group_by.push({name: "tag", tags: angular.copy(target.groupByTags)});} - if(target.nonTagGroupBys) { + if (target.groupByTags) {query.group_by.push({name: "tag", tags: angular.copy(target.groupByTags)});} + if (target.nonTagGroupBys) { _.each(target.nonTagGroupBys,function(rawGroupBy) { var formattedGroupBy = angular.copy(rawGroupBy); - if(formattedGroupBy.name==='time') { + if (formattedGroupBy.name==='time') { formattedGroupBy.range_size=KairosDBDatasource.prototype.convertToKairosInterval(formattedGroupBy.range_size); } query.group_by.push(formattedGroupBy); @@ -266,7 +266,7 @@ function (angular, _, kbn) { var interval_regex = /(\d+(?:\.\d+)?)([Mwdhmsy])/; var interval_regex_ms = /(\d+(?:\.\d+)?)(ms)/; var matches = intervalString.match(interval_regex_ms); - if(!matches) { + if (!matches) { matches = intervalString.match(interval_regex); } if (!matches) { @@ -276,12 +276,12 @@ function (angular, _, kbn) { 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');} + 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'; } - switch(unit) { + switch (unit) { case 'ms': unit = 'milliseconds'; break; @@ -334,7 +334,7 @@ function (angular, _, kbn) { if (result) { var value = result[1]; var unit = result[2]; - switch(unit) { + switch (unit) { case 'ms': unit = 'milliseconds'; break; @@ -375,7 +375,7 @@ function (angular, _, kbn) { date = kbn.parseDate(date); } - if(_.isDate(date)) { + if (_.isDate(date)) { name = start_stop_name + "_absolute"; response_obj[name] = date.getTime(); return; @@ -403,7 +403,7 @@ function (angular, _, kbn) { if (prvDelta >= limit && nxtDelta < limit) datapoints[LastIndx][0] = datapoints[LastIndx - 1][0]; - for (var i = 1; i < arrLength - 1; i++){ + 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) diff --git a/public/app/plugins/datasource/kairosdb/queryCtrl.js b/public/app/plugins/datasource/kairosdb/queryCtrl.js index 73321d3016a..bb0f74a68b3 100644 --- a/public/app/plugins/datasource/kairosdb/queryCtrl.js +++ b/public/app/plugins/datasource/kairosdb/queryCtrl.js @@ -94,7 +94,7 @@ function (angular, _) { $scope.validateFilterTag(); if (!$scope.target.errors.tags) { - if(!_.has($scope.target.tags,$scope.target.currentTagKey)) { + if (!_.has($scope.target.tags,$scope.target.currentTagKey)) { $scope.target.tags[$scope.target.currentTagKey] = []; } $scope.target.tags[$scope.target.currentTagKey].push($scope.target.currentTagValue); @@ -108,7 +108,7 @@ function (angular, _) { $scope.removeFilterTag = function(key) { delete $scope.target.tags[key]; - if(_.size($scope.target.tags)===0) { + if (_.size($scope.target.tags)===0) { $scope.target.tags = null; } $scope.targetBlur(); @@ -116,7 +116,7 @@ function (angular, _) { $scope.validateFilterTag = function() { $scope.target.errors.tags = null; - if(!$scope.target.currentTagKey || !$scope.target.currentTagValue) { + if (!$scope.target.currentTagKey || !$scope.target.currentTagValue) { $scope.target.errors.tags = "You must specify a tag name and value."; } }; @@ -136,7 +136,7 @@ function (angular, _) { $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.isTagGroupBy) { if (!$scope.target.groupByTags) { $scope.target.groupByTags = []; } @@ -147,15 +147,15 @@ function (angular, _) { } $scope.target.groupBy.tagKey = ''; } - else { + 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) { + 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; } @@ -171,7 +171,7 @@ function (angular, _) { $scope.removeGroupByTag = function(index) { $scope.target.groupByTags.splice(index, 1); - if(_.size($scope.target.groupByTags)===0) { + if (_.size($scope.target.groupByTags)===0) { $scope.target.groupByTags = null; } $scope.targetBlur(); @@ -179,7 +179,7 @@ function (angular, _) { $scope.removeNonTagGroupBy = function(index) { $scope.target.nonTagGroupBys.splice(index, 1); - if(_.size($scope.target.nonTagGroupBys)===0) { + if (_.size($scope.target.nonTagGroupBys)===0) { $scope.target.nonTagGroupBys = null; } $scope.targetBlur(); @@ -196,32 +196,32 @@ function (angular, _) { delete $scope.target.errors.groupBy; var errors = {}; $scope.isGroupByValid = true; - if($scope.isTagGroupBy) { - if(!$scope.target.groupBy.tagKey) { + 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)) { + 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) { + if ($scope.isTimeGroupBy) { try { $scope.datasource.convertToKairosInterval($scope.target.groupBy.timeInterval); - } catch(err) { + } catch (err) { errors.timeInterval = err.message; $scope.isGroupByValid = false; } - if(!$scope.target.groupBy.groupCount || !isInt($scope.target.groupBy.groupCount)) { + if (!$scope.target.groupBy.groupCount || !isInt($scope.target.groupBy.groupCount)) { errors.groupCount = "Group count must be an integer"; $scope.isGroupByValid = false; } } - if(!_.isEmpty(errors)) { + if (!_.isEmpty(errors)) { $scope.target.errors.groupBy = errors; } }; @@ -245,17 +245,17 @@ function (angular, _) { $scope.validateHorizontalAggregator(); // nb: if error is found, means that user clicked on cross : cancels input - if(_.isEmpty($scope.target.errors.horAggregator)) { + 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;} + 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(); } @@ -270,7 +270,7 @@ function (angular, _) { $scope.removeHorizontalAggregator = function(index) { $scope.target.horizontalAggregators.splice(index, 1); - if(_.size($scope.target.horizontalAggregators)===0) { + if (_.size($scope.target.horizontalAggregators)===0) { $scope.target.horizontalAggregators = null; } @@ -290,26 +290,26 @@ function (angular, _) { delete $scope.target.errors.horAggregator; var errors = {}; $scope.isAggregatorValid = true; - if($scope.hasSamplingRate) { + if ($scope.hasSamplingRate) { try { $scope.datasource.convertToKairosInterval($scope.target.horAggregator.samplingRate); - } catch(err) { + } catch (err) { errors.samplingRate = err.message; $scope.isAggregatorValid = false; } } - if($scope.hasFactor) { - if(!$scope.target.horAggregator.factor) { + 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') { + 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 || + 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'; @@ -317,7 +317,7 @@ function (angular, _) { } } - if(!_.isEmpty(errors)) { + if (!_.isEmpty(errors)) { $scope.target.errors.horAggregator = errors; } }; @@ -335,10 +335,10 @@ function (angular, _) { for (var i =0;i < MetricList.length; i++) { Metric = MetricList[i]; MetricArray = Metric.split('.'); - if(!result.hasOwnProperty(MetricArray[0])) { + if (!result.hasOwnProperty(MetricArray[0])) { result[MetricArray[0]] = {}; } - if(!result[MetricArray[0]].hasOwnProperty(MetricArray[1])) { + if (!result[MetricArray[0]].hasOwnProperty(MetricArray[1])) { result[MetricArray[0]][MetricArray[1]] = []; } result[MetricArray[0]][MetricArray[1]].push(MetricArray[2]); @@ -357,7 +357,7 @@ function (angular, _) { if (target.sampling) { $scope.datasource.convertToKairosInterval(target.sampling); } - } catch(err) { + } catch (err) { errs.sampling = err.message; } From 2b5fa599fbcffad8e938a5574bf8257a16f86566 Mon Sep 17 00:00:00 2001 From: Masaori Koshiba Date: Sun, 12 Apr 2015 20:11:42 +0900 Subject: [PATCH 007/149] Fix styles warned by jshint --- .../plugins/datasource/kairosdb/datasource.js | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/public/app/plugins/datasource/kairosdb/datasource.js b/public/app/plugins/datasource/kairosdb/datasource.js index ecd4564f72f..086b07b88e6 100644 --- a/public/app/plugins/datasource/kairosdb/datasource.js +++ b/public/app/plugins/datasource/kairosdb/datasource.js @@ -29,8 +29,9 @@ function (angular, _, kbn) { 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 == "") + if (typeof target.alias === 'undefined' || target.alias === "") { alias = target.metric; + } return !target.hide ? {alias: alias, exouter: target.exOuter} @@ -171,8 +172,9 @@ function (angular, _, kbn) { } }); details+= ") "; - if (details != " ( ) ") + if (details !== " ( ) ") { target += details; + } var datapoints = []; for (var i = 0; i < result.values.length; i++) { @@ -180,8 +182,9 @@ function (angular, _, kbn) { var v = result.values[i][1]; datapoints[i] = [v, t]; } - if (plotParams[index].exouter) - datapoints = PeakFilter(datapoints, 10); + if (plotParams[index].exouter) { + datapoints = new PeakFilter(datapoints, 10); + } output.push({ target: target, datapoints: datapoints }); }); index ++; @@ -387,27 +390,31 @@ function (angular, _, kbn) { function PeakFilter(dataIn, limit) { var datapoints = dataIn; var arrLength = datapoints.length; - if (arrLength <= 3) + 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) + 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) + 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) + if (prvDelta >= limit && nxtDelta >= limit) { datapoints[i][0] = (datapoints[i-1][0] + datapoints[i+1][0]) / 2; + } } return datapoints; From ddb4b928a06c531f79576d85272e51173575b901 Mon Sep 17 00:00:00 2001 From: Masaori Koshiba Date: Sun, 12 Apr 2015 20:18:01 +0900 Subject: [PATCH 008/149] Delete MetricListToObject which never used --- .../plugins/datasource/kairosdb/queryCtrl.js | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/public/app/plugins/datasource/kairosdb/queryCtrl.js b/public/app/plugins/datasource/kairosdb/queryCtrl.js index bb0f74a68b3..20b77c59644 100644 --- a/public/app/plugins/datasource/kairosdb/queryCtrl.js +++ b/public/app/plugins/datasource/kairosdb/queryCtrl.js @@ -327,25 +327,6 @@ function (angular, _) { }; // Validation - function MetricListToObject(MetricList) { - var result = {}; - var Metric; - var MetricArray = []; - var MetricCnt = 0; - for (var i =0;i < MetricList.length; i++) { - Metric = MetricList[i]; - MetricArray = Metric.split('.'); - if (!result.hasOwnProperty(MetricArray[0])) { - result[MetricArray[0]] = {}; - } - if (!result[MetricArray[0]].hasOwnProperty(MetricArray[1])) { - result[MetricArray[0]][MetricArray[1]] = []; - } - result[MetricArray[0]][MetricArray[1]].push(MetricArray[2]); - } - return result; - } - function validateTarget(target) { var errs = {}; From a2b751976e7472ce0ab0ce6e303d7285bc584ec4 Mon Sep 17 00:00:00 2001 From: Masaori Koshiba Date: Sun, 12 Apr 2015 20:41:09 +0900 Subject: [PATCH 009/149] Add space before and after binary operators --- .../plugins/datasource/kairosdb/datasource.js | 44 +++++++++---------- .../plugins/datasource/kairosdb/queryCtrl.js | 18 ++++---- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/public/app/plugins/datasource/kairosdb/datasource.js b/public/app/plugins/datasource/kairosdb/datasource.js index 086b07b88e6..cc1ee79c852 100644 --- a/public/app/plugins/datasource/kairosdb/datasource.js +++ b/public/app/plugins/datasource/kairosdb/datasource.js @@ -55,7 +55,7 @@ function (angular, _, kbn) { var reqBody = { metrics: queries }; - reqBody.cache_time=0; + reqBody.cache_time = 0; convertToKairosTime(start,reqBody,'start'); convertToKairosTime(end,reqBody,'end'); var options = { @@ -120,10 +120,10 @@ function (angular, _, kbn) { if (!results.data) { return []; } - if (type==="key") { + if (type === "key") { return _.keys(results.data.queries[0].results[0].tags); } - else if (type==="value" && _.has(results.data.queries[0].results[0].tags,keyValue)) { + else if (type === "value" && _.has(results.data.queries[0].results[0].tags,keyValue)) { return results.data.queries[0].results[0].tags[keyValue]; } return []; @@ -159,19 +159,19 @@ function (angular, _, kbn) { var target = plotParams[index].alias; var details = " ( "; _.each(result.group_by,function(element) { - if (element.name==="tag") { + if (element.name === "tag") { _.each(element.group,function(value, key) { - details+= key+"="+value+" "; + details += key + "=" + value + " "; }); } - else if (element.name==="value") { - details+= 'value_group='+element.group.group_number+" "; + else if (element.name === "value") { + details += 'value_group=' + element.group.group_number + " "; } - else if (element.name==="time") { - details+= 'time_group='+element.group.group_number+" "; + else if (element.name === "time") { + details += 'time_group=' + element.group.group_number + " "; } }); - details+= ") "; + details += ") "; if (details !== " ( ) ") { target += details; } @@ -204,7 +204,7 @@ function (angular, _, kbn) { }; query.aggregators = []; - if (target.downsampling!=='(NONE)') { + if (target.downsampling !== '(NONE)') { query.aggregators.push({ name: target.downsampling, align_sampling: true, @@ -223,13 +223,13 @@ function (angular, _, kbn) { returnedAggregator.align_start_time =true; } if (chosenAggregator.unit) { - returnedAggregator.unit = chosenAggregator.unit+'s'; + returnedAggregator.unit = chosenAggregator.unit + 's'; } - if (chosenAggregator.factor && chosenAggregator.name==='div') { + if (chosenAggregator.factor && chosenAggregator.name === 'div') { returnedAggregator.divisor = chosenAggregator.factor; } - else if (chosenAggregator.factor && chosenAggregator.name==='scale') { - returnedAggregator.factor = chosenAggregator.factor; + else if (chosenAggregator.factor && chosenAggregator.name === 'scale') { + returnedAggregator.factor = chosenAggregator.factor; } if (chosenAggregator.percentile) { returnedAggregator.percentile = chosenAggregator.percentile; @@ -249,10 +249,10 @@ function (angular, _, kbn) { query.group_by = []; if (target.groupByTags) {query.group_by.push({name: "tag", tags: angular.copy(target.groupByTags)});} if (target.nonTagGroupBys) { - _.each(target.nonTagGroupBys,function(rawGroupBy) { + _.each(target.nonTagGroupBys, function(rawGroupBy) { var formattedGroupBy = angular.copy(rawGroupBy); - if (formattedGroupBy.name==='time') { - formattedGroupBy.range_size=KairosDBDatasource.prototype.convertToKairosInterval(formattedGroupBy.range_size); + if (formattedGroupBy.name === 'time') { + formattedGroupBy.range_size = KairosDBDatasource.prototype.convertToKairosInterval(formattedGroupBy.range_size); } query.group_by.push(formattedGroupBy); }); @@ -278,9 +278,9 @@ function (angular, _, kbn) { 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); + 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'; } @@ -413,7 +413,7 @@ function (angular, _, kbn) { 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; + datapoints[i][0] = (datapoints[i - 1][0] + datapoints[i + 1][0]) / 2; } } diff --git a/public/app/plugins/datasource/kairosdb/queryCtrl.js b/public/app/plugins/datasource/kairosdb/queryCtrl.js index 20b77c59644..0de3c953152 100644 --- a/public/app/plugins/datasource/kairosdb/queryCtrl.js +++ b/public/app/plugins/datasource/kairosdb/queryCtrl.js @@ -108,7 +108,7 @@ function (angular, _) { $scope.removeFilterTag = function(key) { delete $scope.target.tags[key]; - if (_.size($scope.target.tags)===0) { + if (_.size($scope.target.tags) === 0) { $scope.target.tags = null; } $scope.targetBlur(); @@ -171,7 +171,7 @@ function (angular, _) { $scope.removeGroupByTag = function(index) { $scope.target.groupByTags.splice(index, 1); - if (_.size($scope.target.groupByTags)===0) { + if (_.size($scope.target.groupByTags) === 0) { $scope.target.groupByTags = null; } $scope.targetBlur(); @@ -179,16 +179,16 @@ function (angular, _) { $scope.removeNonTagGroupBy = function(index) { $scope.target.nonTagGroupBys.splice(index, 1); - if (_.size($scope.target.nonTagGroupBys)===0) { + 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.isTagGroupBy = $scope.target.currentGroupByType === 'tag'; + $scope.isValueGroupBy = $scope.target.currentGroupByType === 'value'; + $scope.isTimeGroupBy = $scope.target.currentGroupByType === 'time'; $scope.validateGroupBy(); }; @@ -270,7 +270,7 @@ function (angular, _) { $scope.removeHorizontalAggregator = function(index) { $scope.target.horizontalAggregators.splice(index, 1); - if (_.size($scope.target.horizontalAggregators)===0) { + if (_.size($scope.target.horizontalAggregators) === 0) { $scope.target.horizontalAggregators = null; } @@ -282,7 +282,7 @@ function (angular, _) { $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.hasPercentile = 'percentile' === $scope.target.currentHorizontalAggregatorName; $scope.validateHorizontalAggregator(); }; @@ -303,7 +303,7 @@ function (angular, _) { 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') { + else if (parseInt($scope.target.horAggregator.factor) === 0 && $scope.target.currentHorizontalAggregatorName === 'div') { errors.factor = 'Cannot divide by 0'; $scope.isAggregatorValid = false; } From 88bf0cdb9e6a734e30d9355f64f69fd30a5d35b9 Mon Sep 17 00:00:00 2001 From: Masaori Koshiba Date: Sun, 12 Apr 2015 20:51:35 +0900 Subject: [PATCH 010/149] Fix styles around 'function' --- public/app/plugins/datasource/kairosdb/datasource.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/public/app/plugins/datasource/kairosdb/datasource.js b/public/app/plugins/datasource/kairosdb/datasource.js index cc1ee79c852..a93febf9ff4 100644 --- a/public/app/plugins/datasource/kairosdb/datasource.js +++ b/public/app/plugins/datasource/kairosdb/datasource.js @@ -149,18 +149,18 @@ function (angular, _, kbn) { function handleKairosDBQueryResponse(plotParams, results) { var output = []; var index = 0; - _.each(results.data.queries, function (series) { + _.each(results.data.queries, function(series) { var sample_size = series.sample_size; console.log("sample_size:" + sample_size + " samples"); - _.each(series.results, function (result) { + _.each(series.results, function(result) { //var target = result.name; var target = plotParams[index].alias; var details = " ( "; - _.each(result.group_by,function(element) { + _.each(result.group_by, function(element) { if (element.name === "tag") { - _.each(element.group,function(value, key) { + _.each(element.group, function(value, key) { details += key + "=" + value + " "; }); } @@ -213,7 +213,7 @@ function (angular, _, kbn) { }); } if (target.horizontalAggregators) { - _.each(target.horizontalAggregators,function(chosenAggregator) { + _.each(target.horizontalAggregators, function(chosenAggregator) { var returnedAggregator = { name:chosenAggregator.name }; From 76b517b361235e9478eb84d994be74e0761b5a49 Mon Sep 17 00:00:00 2001 From: William Wei Date: Fri, 17 Apr 2015 15:51:26 +0800 Subject: [PATCH 011/149] allow graphite metrics name contain '~' when a metrics name contains '~', id does not impact graph display. but you can not use grafana UI to edit metrics with realtime graphite query. --- public/app/plugins/datasource/graphite/lexer.js | 1 + 1 file changed, 1 insertion(+) diff --git a/public/app/plugins/datasource/graphite/lexer.js b/public/app/plugins/datasource/graphite/lexer.js index 7306737d96e..ffb65121a60 100644 --- a/public/app/plugins/datasource/graphite/lexer.js +++ b/public/app/plugins/datasource/graphite/lexer.js @@ -119,6 +119,7 @@ define([ identifierStartTable[i] = i >= 48 && i <= 57 || // 0-9 i === 36 || // $ + i === 126 || // ~ i >= 65 && i <= 90 || // A-Z i === 95 || // _ i === 45 || // - From d57ffad5e176f938c7d48670c5d7b4b7c4a956a1 Mon Sep 17 00:00:00 2001 From: Masaori Koshiba Date: Sun, 19 Apr 2015 21:39:23 +0900 Subject: [PATCH 012/149] Add a space between arguments --- .../plugins/datasource/kairosdb/datasource.js | 22 +++++++++---------- .../plugins/datasource/kairosdb/queryCtrl.js | 6 ++--- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/public/app/plugins/datasource/kairosdb/datasource.js b/public/app/plugins/datasource/kairosdb/datasource.js index a93febf9ff4..5fc25590dbd 100644 --- a/public/app/plugins/datasource/kairosdb/datasource.js +++ b/public/app/plugins/datasource/kairosdb/datasource.js @@ -44,7 +44,7 @@ function (angular, _, kbn) { d.resolve({ data: [] }); return d.promise; } - return this.performTimeSeriesQuery(queries, start, end).then(handleKairosDBQueryResponseAlias,handleQueryError); + return this.performTimeSeriesQuery(queries, start, end).then(handleKairosDBQueryResponseAlias, handleQueryError); }; /////////////////////////////////////////////////////////////////////// @@ -56,8 +56,8 @@ function (angular, _, kbn) { metrics: queries }; reqBody.cache_time = 0; - convertToKairosTime(start,reqBody,'start'); - convertToKairosTime(end,reqBody,'end'); + convertToKairosTime(start, reqBody, 'start'); + convertToKairosTime(end, reqBody, 'end'); var options = { method: 'POST', url: '/api/v1/datapoints/query', @@ -86,10 +86,10 @@ function (angular, _, kbn) { }; - KairosDBDatasource.prototype.performTagSuggestQuery = function(metricname,range,type,keyValue) { + KairosDBDatasource.prototype.performTagSuggestQuery = function(metricname, range, type, keyValue) { if (tagList && (metricname === tagList.metricName) && (range.from === tagList.range.from) && (range.to === tagList.range.to)) { - return getTagListFromResponse(tagList.results,type,keyValue); + return getTagListFromResponse(tagList.results, type, keyValue); } tagList = { metricName:metricname, @@ -98,8 +98,8 @@ function (angular, _, kbn) { var body = { metrics : [{name : metricname}] }; - convertToKairosTime(range.from,body,'start'); - convertToKairosTime(range.to,body,'end'); + convertToKairosTime(range.from, body, 'start'); + convertToKairosTime(range.to, body, 'end'); var options = { url : this.url + '/api/v1/datapoints/query/tags', method : 'POST', @@ -107,7 +107,7 @@ function (angular, _, kbn) { }; return $http(options).then(function(results) { tagList.results = results; - return getTagListFromResponse(results,type,keyValue); + return getTagListFromResponse(results, type, keyValue); }); }; @@ -116,14 +116,14 @@ function (angular, _, kbn) { /// Formatting methods //////////////////////////////////////////////////////////////////////// - function getTagListFromResponse(results,type,keyValue) { + function getTagListFromResponse(results, type, keyValue) { if (!results.data) { return []; } if (type === "key") { return _.keys(results.data.queries[0].results[0].tags); } - else if (type === "value" && _.has(results.data.queries[0].results[0].tags,keyValue)) { + else if (type === "value" && _.has(results.data.queries[0].results[0].tags, keyValue)) { return results.data.queries[0].results[0].tags[keyValue]; } return []; @@ -194,7 +194,7 @@ function (angular, _, kbn) { return output2; } - function convertTargetToQuery(options,target) { + function convertTargetToQuery(options, target) { if (!target.metric || target.hide) { return null; } diff --git a/public/app/plugins/datasource/kairosdb/queryCtrl.js b/public/app/plugins/datasource/kairosdb/queryCtrl.js index 0de3c953152..30c658629b9 100644 --- a/public/app/plugins/datasource/kairosdb/queryCtrl.js +++ b/public/app/plugins/datasource/kairosdb/queryCtrl.js @@ -72,12 +72,12 @@ function (angular, _) { }; $scope.suggestTagKeys = function(query, callback) { - callback($scope.datasource.performTagSuggestQuery($scope.target.metric, $scope.rangeUnparsed, 'key','')); + callback($scope.datasource.performTagSuggestQuery($scope.target.metric, $scope.rangeUnparsed, 'key', '')); }; $scope.suggestTagValues = function(query, callback) { callback($scope.datasource - .performTagSuggestQuery($scope.target.metric,$scope.rangeUnparsed, 'value',$scope.target.currentTagKey)); + .performTagSuggestQuery($scope.target.metric, $scope.rangeUnparsed, 'value', $scope.target.currentTagKey)); }; // Filter metric by tag @@ -94,7 +94,7 @@ function (angular, _) { $scope.validateFilterTag(); if (!$scope.target.errors.tags) { - if (!_.has($scope.target.tags,$scope.target.currentTagKey)) { + if (!_.has($scope.target.tags, $scope.target.currentTagKey)) { $scope.target.tags[$scope.target.currentTagKey] = []; } $scope.target.tags[$scope.target.currentTagKey].push($scope.target.currentTagValue); From 05c27d8340e518ef52f1ada15e810c131c5935b1 Mon Sep 17 00:00:00 2001 From: Masaori Koshiba Date: Sun, 19 Apr 2015 21:52:04 +0900 Subject: [PATCH 013/149] Rename 'KairosDBTargetCtrl' to 'KairosDBQueryCtrl' --- .../plugins/datasource/kairosdb/partials/query.editor.html | 4 ++-- public/app/plugins/datasource/kairosdb/queryCtrl.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/public/app/plugins/datasource/kairosdb/partials/query.editor.html b/public/app/plugins/datasource/kairosdb/partials/query.editor.html index 23ddecabc4e..dc272ebbf4c 100644 --- a/public/app/plugins/datasource/kairosdb/partials/query.editor.html +++ b/public/app/plugins/datasource/kairosdb/partials/query.editor.html @@ -2,7 +2,7 @@
    @@ -345,7 +345,7 @@
    -
    +
    • diff --git a/public/app/plugins/datasource/kairosdb/queryCtrl.js b/public/app/plugins/datasource/kairosdb/queryCtrl.js index 30c658629b9..9aad7c41fc9 100644 --- a/public/app/plugins/datasource/kairosdb/queryCtrl.js +++ b/public/app/plugins/datasource/kairosdb/queryCtrl.js @@ -9,7 +9,7 @@ function (angular, _) { var metricList = null; var targetLetters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O']; - module.controller('KairosDBTargetCtrl', function($scope) { + module.controller('KairosDBQueryCtrl', function($scope) { $scope.init = function() { $scope.metric = { From dbc07827cfa206aefff43b6211f39e04bed2eb99 Mon Sep 17 00:00:00 2001 From: Masaori Koshiba Date: Sun, 19 Apr 2015 23:40:48 +0900 Subject: [PATCH 014/149] Add a basic test of KairosDBDatasource --- .../test/specs/kairosdb-datasource-specs.js | 63 +++++++++++++++++++ public/test/test-main.js | 2 +- 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 public/test/specs/kairosdb-datasource-specs.js diff --git a/public/test/specs/kairosdb-datasource-specs.js b/public/test/specs/kairosdb-datasource-specs.js new file mode 100644 index 00000000000..43004656573 --- /dev/null +++ b/public/test/specs/kairosdb-datasource-specs.js @@ -0,0 +1,63 @@ +define([ + 'helpers', + 'plugins/datasource/kairosdb/datasource' +], function(helpers) { + 'use strict'; + + describe('KairosDBDatasource', function() { + var ctx = new helpers.ServiceTestContext(); + + beforeEach(module('grafana.services')); + beforeEach(ctx.providePhase(['templateSrv'])); + beforeEach(ctx.createService('KairosDBDatasource')); + beforeEach(function() { + ctx.ds = new ctx.service({ url: ''}); + }); + + describe('When querying kairosdb with one target using query editor target spec', function() { + var results; + var urlExpected = "/api/v1/datapoints/query"; + var bodyExpected = { + metrics: [{ name: "test" }], + cache_time: 0, + start_relative: { + value: "1", + unit: "hours" + } + }; + + var query = { + range: { from: 'now-1h', to: 'now' }, + targets: [{ metric: 'test', downsampling: '(NONE)'}] + }; + + var response = { + queries: [{ + sample_size: 60, + results: [{ + name: "test", + values: [[1420070400000, 1]] + }] + }] + }; + + beforeEach(function() { + ctx.$httpBackend.expect('POST', urlExpected, bodyExpected).respond(response); + ctx.ds.query(query).then(function(data) { results = data; }); + ctx.$httpBackend.flush(); + }); + + it('should generate the correct query', function() { + ctx.$httpBackend.verifyNoOutstandingExpectation(); + }); + + it('should return series list', function() { + expect(results.data.length).to.be(1); + expect(results.data[0].target).to.be('test'); + }); + + }); + + }); + +}); diff --git a/public/test/test-main.js b/public/test/test-main.js index a38f8dca32b..b6fca85e9e5 100644 --- a/public/test/test-main.js +++ b/public/test/test-main.js @@ -128,6 +128,7 @@ require([ 'specs/influxQueryBuilder-specs', 'specs/influx09-querybuilder-specs', 'specs/influxdb-datasource-specs', + 'specs/kairosdb-datasource-specs', 'specs/graph-ctrl-specs', 'specs/graph-specs', 'specs/graph-tooltip-specs', @@ -150,4 +151,3 @@ require([ window.__karma__.start(); }); }); - From cc9d2fc139bdf4a9846fdd9b3c113e91aba3804b Mon Sep 17 00:00:00 2001 From: Masaori Koshiba Date: Sun, 19 Apr 2015 23:51:48 +0900 Subject: [PATCH 015/149] Suppress LOG in test --- public/app/plugins/datasource/kairosdb/datasource.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/public/app/plugins/datasource/kairosdb/datasource.js b/public/app/plugins/datasource/kairosdb/datasource.js index 5fc25590dbd..da3f8ca665f 100644 --- a/public/app/plugins/datasource/kairosdb/datasource.js +++ b/public/app/plugins/datasource/kairosdb/datasource.js @@ -150,9 +150,6 @@ function (angular, _, kbn) { var output = []; var index = 0; _.each(results.data.queries, function(series) { - var sample_size = series.sample_size; - console.log("sample_size:" + sample_size + " samples"); - _.each(series.results, function(result) { //var target = result.name; From c762ad8db2185983f2c6d2c362abbb3f3284827d Mon Sep 17 00:00:00 2001 From: Masaori Koshiba Date: Mon, 20 Apr 2015 00:49:16 +0900 Subject: [PATCH 016/149] Refactoring KairosDB Plugin --- .../plugins/datasource/kairosdb/datasource.js | 171 ++++++++---------- .../plugins/datasource/kairosdb/queryCtrl.js | 11 +- 2 files changed, 88 insertions(+), 94 deletions(-) diff --git a/public/app/plugins/datasource/kairosdb/datasource.js b/public/app/plugins/datasource/kairosdb/datasource.js index da3f8ca665f..9d25b694891 100644 --- a/public/app/plugins/datasource/kairosdb/datasource.js +++ b/public/app/plugins/datasource/kairosdb/datasource.js @@ -32,18 +32,24 @@ function (angular, _, kbn) { if (typeof target.alias === 'undefined' || target.alias === "") { alias = target.metric; } - return !target.hide - ? {alias: alias, - exouter: target.exOuter} - : null; + + 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); }; @@ -53,18 +59,19 @@ function (angular, _, kbn) { KairosDBDatasource.prototype.performTimeSeriesQuery = function(queries, start, end) { var reqBody = { - metrics: queries + metrics: queries, + cache_time: 0 }; - reqBody.cache_time = 0; + convertToKairosTime(start, reqBody, 'start'); convertToKairosTime(end, reqBody, 'end'); + var options = { method: 'POST', - url: '/api/v1/datapoints/query', + url: this.url + '/api/v1/datapoints/query', data: reqBody }; - options.url = this.url + options.url; return $http(options); }; @@ -77,39 +84,41 @@ function (angular, _, kbn) { url : this.url + '/api/v1/metricnames', method : 'GET' }; + return $http(options).then(function(results) { if (!results.data) { return []; } return results.data.results; }); - }; KairosDBDatasource.prototype.performTagSuggestQuery = function(metricname, range, type, keyValue) { if (tagList && (metricname === tagList.metricName) && (range.from === tagList.range.from) && - (range.to === tagList.range.to)) { + (range.to === tagList.range.to)) { return getTagListFromResponse(tagList.results, type, keyValue); } tagList = { - metricName:metricname, - range:range + metricName: metricname, + range: range }; var body = { metrics : [{name : metricname}] }; + convertToKairosTime(range.from, body, 'start'); convertToKairosTime(range.to, body, 'end'); + var options = { url : this.url + '/api/v1/datapoints/query/tags', method : 'POST', data : body }; + return $http(options).then(function(results) { tagList.results = results; return getTagListFromResponse(results, type, keyValue); }); - }; ///////////////////////////////////////////////////////////////////////// @@ -120,13 +129,15 @@ function (angular, _, kbn) { if (!results.data) { return []; } - if (type === "key") { + else if (type === "key") { return _.keys(results.data.queries[0].results[0].tags); } else if (type === "value" && _.has(results.data.queries[0].results[0].tags, keyValue)) { return results.data.queries[0].results[0].tags[keyValue]; } - return []; + else { + return []; + } } /** @@ -151,10 +162,9 @@ function (angular, _, kbn) { var index = 0; _.each(results.data.queries, function(series) { _.each(series.results, function(result) { - - //var target = result.name; var target = plotParams[index].alias; var details = " ( "; + _.each(result.group_by, function(element) { if (element.name === "tag") { _.each(element.group, function(value, key) { @@ -168,10 +178,13 @@ function (angular, _, kbn) { details += 'time_group=' + element.group.group_number + " "; } }); + details += ") "; + if (details !== " ( ) ") { target += details; } + var datapoints = []; for (var i = 0; i < result.values.length; i++) { @@ -184,11 +197,11 @@ function (angular, _, kbn) { } output.push({ target: target, datapoints: datapoints }); }); - index ++; - }); - var output2 = { data: _.flatten(output) }; - return output2; + index++; + }); + + return { data: _.flatten(output) }; } function convertTargetToQuery(options, target) { @@ -201,6 +214,7 @@ function (angular, _, kbn) { }; query.aggregators = []; + if (target.downsampling !== '(NONE)') { query.aggregators.push({ name: target.downsampling, @@ -209,31 +223,37 @@ function (angular, _, kbn) { 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; } @@ -244,7 +264,9 @@ function (angular, _, kbn) { if (target.groupByTags || target.nonTagGroupBys) { query.group_by = []; - if (target.groupByTags) {query.group_by.push({name: "tag", tags: angular.copy(target.groupByTags)});} + if (target.groupByTags) { + query.group_by.push({name: "tag", tags: angular.copy(target.groupByTags)}); + } if (target.nonTagGroupBys) { _.each(target.nonTagGroupBys, function(rawGroupBy) { var formattedGroupBy = angular.copy(rawGroupBy); @@ -276,102 +298,46 @@ function (angular, _, kbn) { 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');} + 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'; - - } - switch (unit) { - case 'ms': - unit = 'milliseconds'; - break; - case 's': - unit = 'seconds'; - break; - case 'm': - unit = 'minutes'; - break; - case 'h': - unit = 'hours'; - break; - case 'd': - unit = 'days'; - break; - case 'w': - unit = 'weeks'; - break; - case 'M': - unit = 'months'; - break; - case 'y': - unit = 'years'; - break; - default: - console.log("Unknown interval ", intervalString); - break; } return { - "value": value, - "unit": unit + 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) { - - name = start_stop_name + "_relative"; - 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]; - switch (unit) { - case 'ms': - unit = 'milliseconds'; - break; - case 's': - unit = 'seconds'; - break; - case 'm': - unit = 'minutes'; - break; - case 'h': - unit = 'hours'; - break; - case 'd': - unit = 'days'; - break; - case 'w': - unit = 'weeks'; - break; - case 'M': - unit = 'months'; - break; - case 'y': - unit = 'years'; - break; - default: - console.log("Unknown date ", date); - break; - } + response_obj[name] = { - "value": value, - "unit": unit + value: value, + unit: convertToKairosDBTimeUnit(unit) }; return; } console.log("Unparseable date", date); return; } + date = kbn.parseDate(date); } @@ -384,6 +350,30 @@ function (angular, _, kbn) { console.log("Date is neither string nor date"); } + 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; @@ -417,7 +407,6 @@ function (angular, _, kbn) { return datapoints; } - //////////////////////////////////////////////////////////////////////// return KairosDBDatasource; }); diff --git a/public/app/plugins/datasource/kairosdb/queryCtrl.js b/public/app/plugins/datasource/kairosdb/queryCtrl.js index 9aad7c41fc9..6370afc7c0e 100644 --- a/public/app/plugins/datasource/kairosdb/queryCtrl.js +++ b/public/app/plugins/datasource/kairosdb/queryCtrl.js @@ -37,6 +37,7 @@ function (angular, _) { $scope.get_data(); } }; + $scope.panelBlur = function() { _.each($scope.panel.targets, function(target) { target.downsampling = $scope.panel.downsampling; @@ -49,6 +50,7 @@ function (angular, _) { var clone = angular.copy($scope.target); $scope.panel.targets.push(clone); }; + $scope.moveMetricQuery = function(fromIndex, toIndex) { _.move($scope.panel.targets, fromIndex, toIndex); }; @@ -140,7 +142,6 @@ function (angular, _) { if (!$scope.target.groupByTags) { $scope.target.groupByTags = []; } - console.log($scope.target.groupBy.tagKey); if (!_.contains($scope.target.groupByTags, $scope.target.groupBy.tagKey)) { $scope.target.groupByTags.push($scope.target.groupBy.tagKey); $scope.targetBlur(); @@ -202,12 +203,14 @@ function (angular, _) { 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); @@ -265,7 +268,6 @@ function (angular, _) { $scope.hasUnit = false; $scope.hasFactor = false; $scope.hasPercentile = false; - }; $scope.removeHorizontalAggregator = function(index) { @@ -279,7 +281,7 @@ function (angular, _) { $scope.changeHorAggregationInput = function() { $scope.hasSamplingRate = _.contains(['avg','dev','max','min','sum','least_squares','count','percentile'], - $scope.target.currentHorizontalAggregatorName); + $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; @@ -290,6 +292,7 @@ function (angular, _) { delete $scope.target.errors.horAggregator; var errors = {}; $scope.isAggregatorValid = true; + if ($scope.hasSamplingRate) { try { $scope.datasource.convertToKairosInterval($scope.target.horAggregator.samplingRate); @@ -298,6 +301,7 @@ function (angular, _) { $scope.isAggregatorValid = false; } } + if ($scope.hasFactor) { if (!$scope.target.horAggregator.factor) { errors.factor = 'You must supply a numeric value for this aggregator'; @@ -308,6 +312,7 @@ function (angular, _) { $scope.isAggregatorValid = false; } } + if ($scope.hasPercentile) { if (!$scope.target.horAggregator.percentile || $scope.target.horAggregator.percentile<=0 || From 0a23a996bcc786fa6128c4fb49d1635e593a08e1 Mon Sep 17 00:00:00 2001 From: Masaori Koshiba Date: Sat, 25 Apr 2015 16:12:10 +0900 Subject: [PATCH 017/149] Remove targetLetters --- .../app/plugins/datasource/kairosdb/partials/query.editor.html | 3 --- public/app/plugins/datasource/kairosdb/queryCtrl.js | 2 -- 2 files changed, 5 deletions(-) diff --git a/public/app/plugins/datasource/kairosdb/partials/query.editor.html b/public/app/plugins/datasource/kairosdb/partials/query.editor.html index dc272ebbf4c..052bea2d078 100644 --- a/public/app/plugins/datasource/kairosdb/partials/query.editor.html +++ b/public/app/plugins/datasource/kairosdb/partials/query.editor.html @@ -48,9 +48,6 @@
    -
    + + +