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..ae4248cf2a6 100644
--- a/public/app/plugins/datasource/influxdb/funcEditor.js
+++ b/public/app/plugins/datasource/influxdb/funcEditor.js
@@ -11,22 +11,36 @@ function (angular, _, $) {
.directive('influxdbFuncEditor', function($compile) {
var funcSpanTemplate = '{{target.function}}(';
+ 'data-toggle="dropdown">{{field.func}}(';
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 = _.map($scope.functions, function(func) {
- return {
- text: func,
- click: "changeFunction('" + func + "');"
- };
- });
+ $scope.functionMenu = functionMenu;
+
+ $scope.changeFunction = function(func) {
+ $scope.field.func = func;
+ $scope.onChange();
+ };
function clickFuncParam() {
/*jshint validthis:true */
@@ -34,7 +48,7 @@ function (angular, _, $) {
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,8 +72,8 @@ function (angular, _, $) {
if ($input.val() !== '') {
$link.text($input.val());
- $scope.target.column = $input.val();
- $scope.$apply($scope.get_data);
+ $scope.field.name = $input.val();
+ $scope.$apply($scope.onChange());
}
$input.hide();
@@ -83,8 +97,10 @@ function (angular, _, $) {
$input.attr('data-provide', 'typeahead');
$input.typeahead({
- source: function () {
- return $scope.listColumns.apply(null, arguments);
+ source: function (query, callback) {
+ return $scope.getFields().then(function(results) {
+ callback(results);
+ });
},
minLength: 0,
items: 20,
@@ -108,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 89571c06022..d63e6853831 100644
--- a/public/app/plugins/datasource/influxdb/partials/query.editor.html
+++ b/public/app/plugins/datasource/influxdb/partials/query.editor.html
@@ -65,10 +65,12 @@
SELECT
-
-
- {{target.function}}(value)
-
+
+
+
+
+
+
@@ -114,8 +116,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..717ae22847f 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) {
@@ -73,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 d1a524d2277..a57737cba93 100644
--- a/public/app/plugins/datasource/influxdb/queryCtrl.js
+++ b/public/app/plugins/datasource/influxdb/queryCtrl.js
@@ -10,20 +10,14 @@ 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.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);
@@ -33,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) {
@@ -94,6 +90,18 @@ function (angular, _, InfluxQueryBuilder) {
$scope.$parent.get_data();
};
+ $scope.getFields = function() {
+ var fieldsQuery = $scope.queryBuilder.buildExploreQuery('FIELDS');
+ return $scope.datasource.metricFindQuery(fieldsQuery)
+ .then(function(results) {
+ var values = _.pluck(results, 'text');
+ if ($scope.target.fields.length > 1) {
+ values.splice(0, 0, "-- remove from select --");
+ }
+ return values;
+ });
+ };
+
$scope.toggleQueryMode = function () {
$scope.target.rawQuery = !$scope.target.rawQuery;
};
@@ -159,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');
diff --git a/public/test/specs/influx09-querybuilder-specs.js b/public/test/specs/influx09-querybuilder-specs.js
index 838e1950072..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',
@@ -130,6 +144,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"');
+ });
+
});
});