From 597c1f6a411f9ae867035aad7d2aa0f400f353e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 8 Jul 2015 17:41:36 +0200 Subject: [PATCH 1/3] feat(influxdb): began work on some influxdb enhancements, #2311 --- docs/sources/guides/gettingstarted.md | 1 - .../plugins/datasource/influxdb/funcEditor.js | 18 +++++++----------- .../influxdb/partials/query.editor.html | 11 +++++------ .../datasource/influxdb/queryBuilder.js | 7 +++++-- .../plugins/datasource/influxdb/queryCtrl.js | 14 +++++++++++++- .../test/specs/influx09-querybuilder-specs.js | 6 ++++++ 6 files changed, 36 insertions(+), 21 deletions(-) diff --git a/docs/sources/guides/gettingstarted.md b/docs/sources/guides/gettingstarted.md index a2939b3724a..4bb250ef55c 100644 --- a/docs/sources/guides/gettingstarted.md +++ b/docs/sources/guides/gettingstarted.md @@ -48,7 +48,6 @@ in the main Time Picker in the upper right, but they can also have relative time 2. To edit the graph you click on the graph title to open the panel menu, then `Edit`. 3. This should take you to the `Metrics` tab. In this tab you should see the editor for your default data source. - ## Drag-and-Drop panels You can Drag-and-Drop Panels within and between Rows. Click and hold the Panel title, and drag it to its new location. diff --git a/public/app/plugins/datasource/influxdb/funcEditor.js b/public/app/plugins/datasource/influxdb/funcEditor.js index 12731c0859d..05bcae6835b 100644 --- a/public/app/plugins/datasource/influxdb/funcEditor.js +++ b/public/app/plugins/datasource/influxdb/funcEditor.js @@ -11,30 +11,26 @@ function (angular, _, $) { .directive('influxdbFuncEditor', function($compile) { var funcSpanTemplate = '{{target.function}}('; + 'data-toggle="dropdown">{{field.func}}('; var paramTemplate = ''; return { restrict: 'A', + scope: { + field: "=", + }, link: function postLink($scope, elem) { var $funcLink = $(funcSpanTemplate); - $scope.functionMenu = _.map($scope.functions, function(func) { - return { - text: func, - click: "changeFunction('" + func + "');" - }; - }); - function clickFuncParam() { /*jshint validthis:true */ var $link = $(this); var $input = $link.next(); - $input.val($scope.target.column); + $input.val($scope.field.name); $input.css('width', ($link.width() + 16) + 'px'); $link.hide(); @@ -58,7 +54,7 @@ function (angular, _, $) { if ($input.val() !== '') { $link.text($input.val()); - $scope.target.column = $input.val(); + $scope.field.name = $input.val(); $scope.$apply($scope.get_data); } @@ -84,7 +80,7 @@ function (angular, _, $) { $input.typeahead({ source: function () { - return $scope.listColumns.apply(null, arguments); + return $scope.getFields.apply(null, arguments); }, minLength: 0, items: 20, diff --git a/public/app/plugins/datasource/influxdb/partials/query.editor.html b/public/app/plugins/datasource/influxdb/partials/query.editor.html index 89571c06022..81e0b07cbd9 100644 --- a/public/app/plugins/datasource/influxdb/partials/query.editor.html +++ b/public/app/plugins/datasource/influxdb/partials/query.editor.html @@ -65,10 +65,9 @@
  • SELECT
  • - @@ -114,8 +113,8 @@ -
  • - GROUP BY +
  • + GROUP BY
  • diff --git a/public/app/plugins/datasource/influxdb/queryBuilder.js b/public/app/plugins/datasource/influxdb/queryBuilder.js index a167abb81d6..ca7bb02496d 100644 --- a/public/app/plugins/datasource/influxdb/queryBuilder.js +++ b/public/app/plugins/datasource/influxdb/queryBuilder.js @@ -32,12 +32,15 @@ function (_) { if (type === 'TAG_KEYS') { query = 'SHOW TAG KEYS'; - measurement= this.target.measurement; + measurement = this.target.measurement; } else if (type === 'TAG_VALUES') { query = 'SHOW TAG VALUES'; - measurement= this.target.measurement; + measurement = this.target.measurement; } else if (type === 'MEASUREMENTS') { query = 'SHOW MEASUREMENTS'; + } else if (type === 'FIELDS') { + query = 'SHOW FIELD KEYS FROM "' + this.target.measurement + '"'; + return query; } if (measurement) { diff --git a/public/app/plugins/datasource/influxdb/queryCtrl.js b/public/app/plugins/datasource/influxdb/queryCtrl.js index d1a524d2277..16e74c8e6bf 100644 --- a/public/app/plugins/datasource/influxdb/queryCtrl.js +++ b/public/app/plugins/datasource/influxdb/queryCtrl.js @@ -21,9 +21,12 @@ function (angular, _, InfluxQueryBuilder) { $scope.init = function() { var target = $scope.target; - target.function = target.function || 'mean'; target.tags = target.tags || []; target.groupByTags = target.groupByTags || []; + target.fields = target.fields || [{ + name: 'value', + func: target.function || 'mean' + }]; $scope.queryBuilder = new InfluxQueryBuilder(target); @@ -94,6 +97,15 @@ function (angular, _, InfluxQueryBuilder) { $scope.$parent.get_data(); }; + $scope.getFields = function(query, callback) { + var fieldsQuery = $scope.queryBuilder.buildExploreQuery('FIELDS'); + return $scope.datasource.metricFindQuery(fieldsQuery) + .then(function(results) { + var fields = _.pluck(results, 'text'); + callback(fields); + }); + }; + $scope.toggleQueryMode = function () { $scope.target.rawQuery = !$scope.target.rawQuery; }; diff --git a/public/test/specs/influx09-querybuilder-specs.js b/public/test/specs/influx09-querybuilder-specs.js index 838e1950072..6a18f0013bd 100644 --- a/public/test/specs/influx09-querybuilder-specs.js +++ b/public/test/specs/influx09-querybuilder-specs.js @@ -130,6 +130,12 @@ define([ expect(query).to.be('SHOW TAG VALUES FROM "cpu" WITH KEY = "app" WHERE "host" =~ /server.*/'); }); + it('should build show field query', function() { + var builder = new InfluxQueryBuilder({measurement: 'cpu', tags: [{key: 'app', value: 'email'}]}); + var query = builder.buildExploreQuery('FIELDS'); + expect(query).to.be('SHOW FIELD KEYS FROM "cpu"'); + }); + }); }); From 50795adcf0acf21b14b1eabf890f1945cd919972 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 9 Jul 2015 16:36:47 +0200 Subject: [PATCH 2/3] feat(influxdb 0.9): field lookup and other enhancements, #2311 --- .../plugins/datasource/influxdb/funcEditor.js | 26 ++++++++++++++++--- .../influxdb/partials/query.editor.html | 2 +- .../datasource/influxdb/queryBuilder.js | 18 ++++++++++--- .../plugins/datasource/influxdb/queryCtrl.js | 14 ++-------- .../test/specs/influx09-querybuilder-specs.js | 14 ++++++++++ 5 files changed, 54 insertions(+), 20 deletions(-) diff --git a/public/app/plugins/datasource/influxdb/funcEditor.js b/public/app/plugins/datasource/influxdb/funcEditor.js index 05bcae6835b..7631363fa12 100644 --- a/public/app/plugins/datasource/influxdb/funcEditor.js +++ b/public/app/plugins/datasource/influxdb/funcEditor.js @@ -16,14 +16,32 @@ function (angular, _, $) { var paramTemplate = ''; + var functionList = [ + 'count', 'mean', 'sum', 'min', 'max', 'mode', 'distinct', 'median', + 'derivative', 'stddev', 'first', 'last', 'difference' + ]; + + var functionMenu = _.map(functionList, function(func) { + return { text: func, click: "changeFunction('" + func + "');" }; + }); + return { restrict: 'A', scope: { field: "=", + getFields: "&", + onChange: "&", }, link: function postLink($scope, elem) { var $funcLink = $(funcSpanTemplate); + $scope.functionMenu = functionMenu; + + $scope.changeFunction = function(func) { + $scope.field.func = func; + $scope.onChange(); + }; + function clickFuncParam() { /*jshint validthis:true */ @@ -55,7 +73,7 @@ function (angular, _, $) { $link.text($input.val()); $scope.field.name = $input.val(); - $scope.$apply($scope.get_data); + $scope.$apply($scope.onChange()); } $input.hide(); @@ -79,8 +97,10 @@ function (angular, _, $) { $input.attr('data-provide', 'typeahead'); $input.typeahead({ - source: function () { - return $scope.getFields.apply(null, arguments); + source: function (query, callback) { + return $scope.getFields().then(function(results) { + callback(results); + }); }, minLength: 0, items: 20, diff --git a/public/app/plugins/datasource/influxdb/partials/query.editor.html b/public/app/plugins/datasource/influxdb/partials/query.editor.html index 81e0b07cbd9..216f099d125 100644 --- a/public/app/plugins/datasource/influxdb/partials/query.editor.html +++ b/public/app/plugins/datasource/influxdb/partials/query.editor.html @@ -66,7 +66,7 @@ SELECT
  • diff --git a/public/app/plugins/datasource/influxdb/queryBuilder.js b/public/app/plugins/datasource/influxdb/queryBuilder.js index ca7bb02496d..717ae22847f 100644 --- a/public/app/plugins/datasource/influxdb/queryBuilder.js +++ b/public/app/plugins/datasource/influxdb/queryBuilder.js @@ -76,15 +76,25 @@ function (_) { throw "Metric measurement is missing"; } - var query = 'SELECT '; - var measurement = target.measurement; - var aggregationFunc = target.function || 'mean'; + if (!target.fields) { + target.fields = [{name: 'value', func: target.function || 'mean'}]; + } + var query = 'SELECT '; + var i; + for (i = 0; i < target.fields.length; i++) { + var field = target.fields[i]; + if (i > 0) { + query += ', '; + } + query += field.func + '(' + field.name + ')'; + } + + var measurement = target.measurement; if (!measurement.match('^/.*/') && !measurement.match(/^merge\(.*\)/)) { measurement = '"' + measurement+ '"'; } - query += aggregationFunc + '(value)'; query += ' FROM ' + measurement + ' WHERE '; var conditions = _.map(target.tags, function(tag, index) { return renderTagCondition(tag, index); diff --git a/public/app/plugins/datasource/influxdb/queryCtrl.js b/public/app/plugins/datasource/influxdb/queryCtrl.js index 16e74c8e6bf..e28c6bc034d 100644 --- a/public/app/plugins/datasource/influxdb/queryCtrl.js +++ b/public/app/plugins/datasource/influxdb/queryCtrl.js @@ -10,15 +10,6 @@ function (angular, _, InfluxQueryBuilder) { module.controller('InfluxQueryCtrl', function($scope, $timeout, $sce, templateSrv, $q) { - $scope.functionList = [ - 'count', 'mean', 'sum', 'min', 'max', 'mode', 'distinct', 'median', - 'derivative', 'stddev', 'first', 'last', 'difference' - ]; - - $scope.functionMenu = _.map($scope.functionList, function(func) { - return { text: func, click: "changeFunction('" + func + "');" }; - }); - $scope.init = function() { var target = $scope.target; target.tags = target.tags || []; @@ -97,12 +88,11 @@ function (angular, _, InfluxQueryBuilder) { $scope.$parent.get_data(); }; - $scope.getFields = function(query, callback) { + $scope.getFields = function() { var fieldsQuery = $scope.queryBuilder.buildExploreQuery('FIELDS'); return $scope.datasource.metricFindQuery(fieldsQuery) .then(function(results) { - var fields = _.pluck(results, 'text'); - callback(fields); + return _.pluck(results, 'text'); }); }; diff --git a/public/test/specs/influx09-querybuilder-specs.js b/public/test/specs/influx09-querybuilder-specs.js index 6a18f0013bd..b515cfab6fb 100644 --- a/public/test/specs/influx09-querybuilder-specs.js +++ b/public/test/specs/influx09-querybuilder-specs.js @@ -38,6 +38,20 @@ define([ }); }); + describe('series with multiple fields', function() { + var builder = new InfluxQueryBuilder({ + measurement: 'cpu', + tags: [], + fields: [{ name: 'tx_in', func: 'sum' }, { name: 'tx_out', func: 'mean' }] + }); + + var query = builder.build(); + + it('should generate correct query', function() { + expect(query).to.be('SELECT sum(tx_in), mean(tx_out) FROM "cpu" WHERE $timeFilter GROUP BY time($interval) ORDER BY asc'); + }); + }); + describe('series with multiple tags only', function() { var builder = new InfluxQueryBuilder({ measurement: 'cpu', From 150fd869a01c70a26432fe57dab6f814c4994a52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 9 Jul 2015 17:17:17 +0200 Subject: [PATCH 3/3] Finalized work on influxdb field and func selection, #2311 --- .../plugins/datasource/influxdb/funcEditor.js | 2 +- .../influxdb/partials/query.editor.html | 5 +++- .../plugins/datasource/influxdb/queryCtrl.js | 27 ++++++++++++++++++- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/public/app/plugins/datasource/influxdb/funcEditor.js b/public/app/plugins/datasource/influxdb/funcEditor.js index 7631363fa12..ae4248cf2a6 100644 --- a/public/app/plugins/datasource/influxdb/funcEditor.js +++ b/public/app/plugins/datasource/influxdb/funcEditor.js @@ -124,7 +124,7 @@ function (angular, _, $) { function addElementsAndCompile() { $funcLink.appendTo(elem); - var $paramLink = $('value'); + var $paramLink = $('' + $scope.field.name + ''); var $input = $(paramTemplate); $paramLink.appendTo(elem); diff --git a/public/app/plugins/datasource/influxdb/partials/query.editor.html b/public/app/plugins/datasource/influxdb/partials/query.editor.html index 216f099d125..d63e6853831 100644 --- a/public/app/plugins/datasource/influxdb/partials/query.editor.html +++ b/public/app/plugins/datasource/influxdb/partials/query.editor.html @@ -66,9 +66,12 @@ SELECT +
  • + +
  • diff --git a/public/app/plugins/datasource/influxdb/queryCtrl.js b/public/app/plugins/datasource/influxdb/queryCtrl.js index e28c6bc034d..a57737cba93 100644 --- a/public/app/plugins/datasource/influxdb/queryCtrl.js +++ b/public/app/plugins/datasource/influxdb/queryCtrl.js @@ -27,6 +27,8 @@ function (angular, _, InfluxQueryBuilder) { $scope.measurementSegment = new MetricSegment(target.measurement); } + $scope.addFieldSegment = MetricSegment.newPlusButton(); + $scope.tagSegments = []; _.each(target.tags, function(tag) { if (tag.condition) { @@ -92,7 +94,11 @@ function (angular, _, InfluxQueryBuilder) { var fieldsQuery = $scope.queryBuilder.buildExploreQuery('FIELDS'); return $scope.datasource.metricFindQuery(fieldsQuery) .then(function(results) { - return _.pluck(results, 'text'); + var values = _.pluck(results, 'text'); + if ($scope.target.fields.length > 1) { + values.splice(0, 0, "-- remove from select --"); + } + return values; }); }; @@ -161,6 +167,25 @@ function (angular, _, InfluxQueryBuilder) { .then(null, $scope.handleQueryError); }; + $scope.getFieldSegments = function() { + var fieldsQuery = $scope.queryBuilder.buildExploreQuery('FIELDS'); + return $scope.datasource.metricFindQuery(fieldsQuery) + .then($scope.transformToSegments) + .then(null, $scope.handleQueryError); + }; + + $scope.addField = function() { + $scope.target.fields.push({name: $scope.addFieldSegment.value, func: 'mean'}); + _.extend($scope.addFieldSegment, MetricSegment.newPlusButton()); + }; + + $scope.fieldChanged = function(field) { + if (field.name === '-- remove from select --') { + $scope.target.fields = _.without($scope.target.fields, field); + } + $scope.get_data(); + }; + $scope.getGroupByTagSegments = function(segment) { var query = $scope.queryBuilder.buildExploreQuery('TAG_KEYS');