From b61f30de94eaa01c9a956d1edba4052a2d0889d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Mon, 18 May 2015 10:49:34 +0200 Subject: [PATCH] Lots of progress on InfluxDB Query Editor, show tag keys, values and measurement dropdowns now take into account already selected tags or measurements, so you can start with tag keys and the select measurement, #1525 --- .../plugins/datasource/influxdb/datasource.js | 30 ++++------ .../datasource/influxdb/queryBuilder.js | 38 +++++++++++-- .../plugins/datasource/influxdb/queryCtrl.js | 20 +++---- .../test/specs/influx09-querybuilder-specs.js | 56 ++++++++++++------- 4 files changed, 93 insertions(+), 51 deletions(-) diff --git a/public/app/plugins/datasource/influxdb/datasource.js b/public/app/plugins/datasource/influxdb/datasource.js index 35fb495c740..56b01772c55 100644 --- a/public/app/plugins/datasource/influxdb/datasource.js +++ b/public/app/plugins/datasource/influxdb/datasource.js @@ -74,7 +74,7 @@ function (angular, _, kbn, InfluxSeries, InfluxQueryBuilder) { }); }; - InfluxDatasource.prototype.metricFindQuery = function (query, queryType) { + InfluxDatasource.prototype.metricFindQuery = function (query) { var interpolated; try { interpolated = templateSrv.replace(query); @@ -83,39 +83,33 @@ function (angular, _, kbn, InfluxSeries, InfluxQueryBuilder) { return $q.reject(err); } - console.log('metricFindQuery called with: ' + [query, queryType].join(', ')); - - return this._seriesQuery(interpolated, queryType).then(function (results) { + return this._seriesQuery(interpolated).then(function (results) { if (!results || results.results.length === 0) { return []; } var influxResults = results.results[0]; if (!influxResults.series) { return []; } - - console.log('metric find query response', results); var series = influxResults.series[0]; - switch (queryType) { - case 'MEASUREMENTS': + if (query.indexOf('SHOW MEASUREMENTS') === 0) { return _.map(series.values, function(value) { return { text: value[0], expandable: true }; }); - case 'TAG_KEYS': - var tagKeys = _.flatten(series.values); - return _.map(tagKeys, function(tagKey) { return { text: tagKey, expandable: true }; }); - case 'TAG_VALUES': - var tagValues = _.flatten(series.values); - return _.map(tagValues, function(tagValue) { return { text: tagValue, expandable: true }; }); - default: // template values service does not pass in a a query type - var flattenedValues = _.flatten(series.values); - return _.map(flattenedValues, function(value) { return { text: value, expandable: true }; }); } + + var flattenedValues = _.flatten(series.values); + return _.map(flattenedValues, function(value) { return { text: value, expandable: true }; }); }); }; function retry(deferred, callback, delay) { return callback().then(undefined, function(reason) { if (reason.status !== 0 || reason.status >= 300) { - reason.message = 'InfluxDB Error:
' + reason.data; + if (reason.data && reason.data.error) { + reason.message = 'InfluxDB Error Response: ' + reason.data.error; + } + else { + reason.message = 'InfluxDB Error: ' + reason.message; + } deferred.reject(reason); } else { diff --git a/public/app/plugins/datasource/influxdb/queryBuilder.js b/public/app/plugins/datasource/influxdb/queryBuilder.js index fa2069ea35d..1b522ba8eca 100644 --- a/public/app/plugins/datasource/influxdb/queryBuilder.js +++ b/public/app/plugins/datasource/influxdb/queryBuilder.js @@ -14,11 +14,41 @@ function (_) { return this.target.rawQuery ? this._modifyRawQuery() : this._buildQuery(); }; - p.showTagsQuery = function() { - var query = 'SHOW TAG KEYS'; + p.buildExploreQuery = function(type, withKey) { + var query; + var measurement; - if (this.target.measurement) { - query += ' FROM "' + this.target.measurement + '"'; + if (type === 'TAG_KEYS') { + query = 'SHOW TAG KEYS'; + measurement= this.target.measurement; + } else if (type === 'TAG_VALUES') { + query = 'SHOW TAG VALUES'; + measurement= this.target.measurement; + } else if (type === 'MEASUREMENTS') { + query = 'SHOW MEASUREMENTS'; + } + + if (measurement) { + query += ' FROM "' + measurement + '"'; + } + + if (withKey) { + query += ' WITH KEY = "' + withKey + '"'; + } + + if (this.target.tags && this.target.tags.length > 0) { + var whereConditions = _.reduce(this.target.tags, function(memo, tag) { + // do not add a condition for the key we want to explore for + if (tag.key === withKey) { + return memo; + } + memo.push(' ' + tag.key + '=' + "'" + tag.value + "'"); + return memo; + }, []); + + if (whereConditions.length > 0) { + query += ' WHERE' + whereConditions.join('AND'); + } } return query; diff --git a/public/app/plugins/datasource/influxdb/queryCtrl.js b/public/app/plugins/datasource/influxdb/queryCtrl.js index 826ef26565d..828ab3809b0 100644 --- a/public/app/plugins/datasource/influxdb/queryCtrl.js +++ b/public/app/plugins/datasource/influxdb/queryCtrl.js @@ -108,7 +108,8 @@ function (angular, _, InfluxQueryBuilder) { }; $scope.getMeasurements = function () { - return $scope.datasource.metricFindQuery('SHOW MEASUREMENTS', 'MEASUREMENTS') + var query = $scope.queryBuilder.buildExploreQuery('MEASUREMENTS'); + return $scope.datasource.metricFindQuery(query) .then($scope.transformToSegments) .then($scope.addTemplateVariableSegments) .then(null, $scope.handleQueryError); @@ -133,13 +134,12 @@ function (angular, _, InfluxQueryBuilder) { }; $scope.getTagsOrValues = function(segment, index) { - var query, queryType; + var query; + if (segment.type === 'key' || segment.type === 'plus-button') { - queryType = 'TAG_KEYS'; - query = $scope.queryBuilder.showTagsQuery(); + query = $scope.queryBuilder.buildExploreQuery('TAG_KEYS'); } else if (segment.type === 'value') { - queryType = 'TAG_VALUES'; - query = 'SHOW TAG VALUES FROM "' + $scope.target.measurement + '" WITH KEY = ' + $scope.tagSegments[index-2].value; + query = $scope.queryBuilder.buildExploreQuery('TAG_VALUES', $scope.tagSegments[index-2].value); } else if (segment.type === 'condition') { return $q.when([new MetricSegment('AND'), new MetricSegment('OR')]); } @@ -147,11 +147,11 @@ function (angular, _, InfluxQueryBuilder) { return $q.when([]); } - return $scope.datasource.metricFindQuery(query, queryType) + return $scope.datasource.metricFindQuery(query) .then($scope.transformToSegments) .then($scope.addTemplateVariableSegments) .then(function(results) { - if (queryType === 'TAG_KEYS' && segment.type === 'key') { + if (segment.type === 'key') { results.splice(0, 0, angular.copy($scope.removeTagFilterSegment)); } return results; @@ -160,9 +160,9 @@ function (angular, _, InfluxQueryBuilder) { }; $scope.getGroupByTagSegments = function(segment) { - var query = 'SHOW TAG KEYS FROM "' + $scope.target.measurement + '"'; + var query = $scope.queryBuilder.buildExploreQuery('TAG_KEYS'); - return $scope.datasource.metricFindQuery(query, 'TAG_KEYS') + return $scope.datasource.metricFindQuery(query) .then($scope.transformToSegments) .then($scope.addTemplateVariableSegments) .then(function(results) { diff --git a/public/test/specs/influx09-querybuilder-specs.js b/public/test/specs/influx09-querybuilder-specs.js index 81602da51f7..2b1660f0a90 100644 --- a/public/test/specs/influx09-querybuilder-specs.js +++ b/public/test/specs/influx09-querybuilder-specs.js @@ -62,30 +62,48 @@ define([ }); }); - describe('when building tag keys query', function() { + describe('when building explore queries', function() { - describe('given picked measurement', function() { - it('build query with measurement filter', function() { - var builder = new InfluxQueryBuilder({ measurement: 'cpu', tags: [] }); - var query = builder.showTagsQuery(); - expect(query).to.be('SHOW TAG KEYS FROM "cpu"'); - }); + it('should only have measurement condition in tag keys query given query with measurement', function() { + var builder = new InfluxQueryBuilder({ measurement: 'cpu', tags: [] }); + var query = builder.buildExploreQuery('TAG_KEYS'); + expect(query).to.be('SHOW TAG KEYS FROM "cpu"'); }); - describe('given no picked measurement', function() { - it('build query without filter', function() { - var builder = new InfluxQueryBuilder({ measurement: '', tags: [] }); - var query = builder.showTagsQuery(); - expect(query).to.be('SHOW TAG KEYS'); - }); + it('should have no conditions in tags keys query given query with no measurement or tag', function() { + var builder = new InfluxQueryBuilder({ measurement: '', tags: [] }); + var query = builder.buildExploreQuery('TAG_KEYS'); + expect(query).to.be('SHOW TAG KEYS'); }); - describe('given an existing tag', function() { - it('build query with filter', function() { - var builder = new InfluxQueryBuilder({ measurement: '', tags: [{key: 'host', value: 'se1'}] }); - var query = builder.showTagsQuery(); - expect(query).to.be('SHOW TAG KEYS'); - }); + it('should have where condition in tag keys query with tags', function() { + var builder = new InfluxQueryBuilder({ measurement: '', tags: [{key: 'host', value: 'se1'}] }); + var query = builder.buildExploreQuery('TAG_KEYS'); + expect(query).to.be("SHOW TAG KEYS WHERE host='se1'"); + }); + + it('should have no conditions in measurement query for query with no tags', function() { + var builder = new InfluxQueryBuilder({ measurement: '', tags: [] }); + var query = builder.buildExploreQuery('MEASUREMENTS'); + expect(query).to.be('SHOW MEASUREMENTS'); + }); + + it('should have where condition in measurement query for query with tags', function() { + var builder = new InfluxQueryBuilder({measurement: '', tags: [{key: 'app', value: 'email'}]}); + var query = builder.buildExploreQuery('MEASUREMENTS'); + expect(query).to.be("SHOW MEASUREMENTS WHERE app='email'"); + }); + + it('should have where tag name IN filter in tag values query for query with one tag', function() { + var builder = new InfluxQueryBuilder({measurement: '', tags: [{key: 'app', value: 'asdsadsad'}]}); + var query = builder.buildExploreQuery('TAG_VALUES', 'app'); + expect(query).to.be('SHOW TAG VALUES WITH KEY = "app"'); + }); + + it('should have measurement tag condition and tag name IN filter in tag values query', function() { + var builder = new InfluxQueryBuilder({measurement: 'cpu', tags: [{key: 'app', value: 'email'}, {key: 'host', value: 'server1'}]}); + var query = builder.buildExploreQuery('TAG_VALUES', 'app'); + expect(query).to.be('SHOW TAG VALUES FROM "cpu" WITH KEY = "app" WHERE host=\'server1\''); }); });