diff --git a/public/app/plugins/datasource/influxdb/datasource.js b/public/app/plugins/datasource/influxdb/datasource.js
index 56b01772c55..de7379d6367 100644
--- a/public/app/plugins/datasource/influxdb/datasource.js
+++ b/public/app/plugins/datasource/influxdb/datasource.js
@@ -69,8 +69,11 @@ function (angular, _, kbn, InfluxSeries, InfluxQueryBuilder) {
var query = annotation.query.replace('$timeFilter', timeFilter);
query = templateSrv.replace(query);
- return this._seriesQuery(query).then(function(results) {
- return new InfluxSeries({ seriesList: results, annotation: annotation }).getAnnotations();
+ return this._seriesQuery(query).then(function(data) {
+ if (!data || !data.results || !data.results[0]) {
+ throw { message: 'No results in response from InfluxDB' };
+ }
+ return new InfluxSeries({ series: data.results[0].series, annotation: annotation }).getAnnotations();
});
};
@@ -168,9 +171,11 @@ function (angular, _, kbn, InfluxSeries, InfluxQueryBuilder) {
return deferred.promise;
};
- function handleInfluxQueryResponse(alias, seriesList) {
- var influxSeries = new InfluxSeries({ seriesList: seriesList, alias: alias });
- return influxSeries.getTimeSeries();
+ function handleInfluxQueryResponse(alias, data) {
+ if (!data || !data.results || !data.results[0]) {
+ throw { message: 'No results in response from InfluxDB' };
+ }
+ return new InfluxSeries({ series: data.results[0].series, alias: alias }).getTimeSeries();
}
function getTimeFilter(options) {
diff --git a/public/app/plugins/datasource/influxdb/influxSeries.js b/public/app/plugins/datasource/influxdb/influxSeries.js
index cca01459fc4..45e4325c016 100644
--- a/public/app/plugins/datasource/influxdb/influxSeries.js
+++ b/public/app/plugins/datasource/influxdb/influxSeries.js
@@ -5,8 +5,7 @@ function (_) {
'use strict';
function InfluxSeries(options) {
- this.seriesList = options.seriesList && options.seriesList.results && options.seriesList.results.length > 0
- ? options.seriesList.results[0].series || [] : [];
+ this.series = options.series;
this.alias = options.alias;
this.annotation = options.annotation;
}
@@ -17,23 +16,25 @@ function (_) {
var output = [];
var self = this;
- console.log(self.seriesList);
- if (self.seriesList.length === 0) {
+ if (self.series.length === 0) {
return output;
}
- _.each(self.seriesList, function(series) {
+ _.each(self.series, function(series) {
var datapoints = [];
for (var i = 0; i < series.values.length; i++) {
datapoints[i] = [series.values[i][1], new Date(series.values[i][0]).getTime()];
}
var seriesName = series.name;
- var tags = _.map(series.tags, function(value, key) {
- return key + ': ' + value;
- });
- if (tags.length > 0) {
+ if (self.alias) {
+ seriesName = self.alias;
+ } else if (series.tags) {
+ var tags = _.map(series.tags, function(value, key) {
+ return key + ': ' + value;
+ });
+
seriesName = seriesName + ' {' + tags.join(', ') + '}';
}
diff --git a/public/app/plugins/datasource/influxdb/partials/query.editor.html b/public/app/plugins/datasource/influxdb/partials/query.editor.html
index 0881921078d..9a9fca802ea 100644
--- a/public/app/plugins/datasource/influxdb/partials/query.editor.html
+++ b/public/app/plugins/datasource/influxdb/partials/query.editor.html
@@ -141,14 +141,103 @@
+
+
+
+
+
+
Alias patterns
+
+ - $m = replaced with measurement name
+ - $measurement = replaced with measurement name
+ - $tag_hostname = replaced with the value of the hostname tag
+ - You can also use [[tag_hostname]] pattern replacement syntax
+
+
+
+
+
Stacking and fill
+
+ - When stacking is enabled it important that points align
+ - If there are missing points for one series it can cause gaps or missing bars
+ - You must use fill(0), and select a group by time low limit
+ - Use the group by time option below your queries and specify for example >10s if your metrics are written every 10 seconds
+ - This will insert zeros for series that are missing measurements and will make stacking work properly
+
+
+
+
+
Group by time
+
+ - Group by time is important, otherwise the query could return many thousands of datapoints that will slow down Grafana
+ - Leave the group by time field empty for each query and it will be calculated based on time range and pixel width of the graph
+ - If you use fill(0) or fill(null) set a low limit for the auto group by time interval
+ - The low limit can only be set in the group by time option below your queries
+ - You set a low limit by adding a greater sign before the interval
+ - Example: >60s if you write metrics to InfluxDB every 60 seconds
+
+
+
+
+
diff --git a/public/css/less/tightform.less b/public/css/less/tightform.less
index 41630400cf7..5bd9cda8f43 100644
--- a/public/css/less/tightform.less
+++ b/public/css/less/tightform.less
@@ -23,7 +23,7 @@
.tight-form-container-no-item-borders {
border: 1px solid @grafanaTargetBorder;
- .tight-form, .tight-form-item {
+ .tight-form, .tight-form-item, [type=text].tight-form-input {
border: none;
}
}
diff --git a/public/test/specs/influxSeries-specs.js b/public/test/specs/influxSeries-specs.js
index 47fb77b67b3..b68a3a95e8c 100644
--- a/public/test/specs/influxSeries-specs.js
+++ b/public/test/specs/influxSeries-specs.js
@@ -1,218 +1,57 @@
define([
- 'plugins/datasource/influxdb_08/influxSeries'
+ 'plugins/datasource/influxdb/influxSeries'
], function(InfluxSeries) {
'use strict';
describe('when generating timeseries from influxdb response', function() {
describe('given two series', function() {
- var series = new InfluxSeries({
- seriesList: [
- {
- columns: ['time', 'mean', 'sequence_number'],
- name: 'prod.server1.cpu',
- points: [[1402596000, 10, 1], [1402596001, 12, 2]]
- },
- {
- columns: ['time', 'mean', 'sequence_number'],
- name: 'prod.server2.cpu',
- points: [[1402596000, 15, 1], [1402596001, 16, 2]]
- }
- ]
- });
-
- var result = series.getTimeSeries();
-
- it('should generate two time series', function() {
- expect(result.length).to.be(2);
- expect(result[0].target).to.be('prod.server1.cpu.mean');
- expect(result[0].datapoints[0][0]).to.be(10);
- expect(result[0].datapoints[0][1]).to.be(1402596000);
- expect(result[0].datapoints[1][0]).to.be(12);
- expect(result[0].datapoints[1][1]).to.be(1402596001);
-
- expect(result[1].target).to.be('prod.server2.cpu.mean');
- expect(result[1].datapoints[0][0]).to.be(15);
- expect(result[1].datapoints[0][1]).to.be(1402596000);
- expect(result[1].datapoints[1][0]).to.be(16);
- expect(result[1].datapoints[1][1]).to.be(1402596001);
- });
-
- });
-
- describe('given an alias format', function() {
- var series = new InfluxSeries({
- seriesList: [
- {
- columns: ['time', 'mean', 'sequence_number'],
- name: 'prod.server1.cpu',
- points: [[1402596000, 10, 1], [1402596001, 12, 2]]
- }
- ],
- alias: '$s.testing'
- });
-
- var result = series.getTimeSeries();
-
- it('should generate correct series name', function() {
- expect(result[0].target).to.be('prod.server1.cpu.testing');
- });
-
- });
-
- describe('given an alias format with segment numbers', function() {
- var series = new InfluxSeries({
- seriesList: [
- {
- columns: ['time', 'mean', 'sequence_number'],
- name: 'prod.server1.cpu',
- points: [[1402596000, 10, 1], [1402596001, 12, 2]]
- }
- ],
- alias: '$1.mean'
- });
-
- var result = series.getTimeSeries();
-
- it('should generate correct series name', function() {
- expect(result[0].target).to.be('server1.mean');
- });
-
- });
-
- describe('given an alias format and many segments', function() {
- var series = new InfluxSeries({
- seriesList: [
- {
- columns: ['time', 'mean', 'sequence_number'],
- name: 'a0.a1.a2.a3.a4.a5.a6.a7.a8.a9.a10.a11.a12',
- points: [[1402596000, 10, 1], [1402596001, 12, 2]]
- }
- ],
- alias: '$5.$11.mean'
- });
-
- var result = series.getTimeSeries();
-
- it('should generate correct series name', function() {
- expect(result[0].target).to.be('a5.a11.mean');
- });
-
- });
-
-
- describe('given an alias format with group by field', function() {
- var series = new InfluxSeries({
- seriesList: [
- {
- columns: ['time', 'mean', 'host'],
- name: 'prod.cpu',
- points: [[1402596000, 10, 'A']]
- }
- ],
- groupByField: 'host',
- alias: '$g.$1'
- });
-
- var result = series.getTimeSeries();
-
- it('should generate correct series name', function() {
- expect(result[0].target).to.be('A.cpu');
- });
-
- });
-
- describe('given group by column', function() {
- var series = new InfluxSeries({
- seriesList: [
- {
- columns: ['time', 'mean', 'host'],
- name: 'prod.cpu',
- points: [
- [1402596000, 10, 'A'],
- [1402596001, 11, 'A'],
- [1402596000, 5, 'B'],
- [1402596001, 6, 'B'],
- ]
- }
- ],
- groupByField: 'host'
- });
-
- var result = series.getTimeSeries();
-
- it('should generate two time series', function() {
- expect(result.length).to.be(2);
- expect(result[0].target).to.be('prod.cpu.A');
- expect(result[0].datapoints[0][0]).to.be(10);
- expect(result[0].datapoints[0][1]).to.be(1402596000);
- expect(result[0].datapoints[1][0]).to.be(11);
- expect(result[0].datapoints[1][1]).to.be(1402596001);
-
- expect(result[1].target).to.be('prod.cpu.B');
- expect(result[1].datapoints[0][0]).to.be(5);
- expect(result[1].datapoints[0][1]).to.be(1402596000);
- expect(result[1].datapoints[1][0]).to.be(6);
- expect(result[1].datapoints[1][1]).to.be(1402596001);
- });
-
- });
-
- });
-
- describe("when creating annotations from influxdb response", function() {
- describe('given column mapping for all columns', function() {
- var series = new InfluxSeries({
- seriesList: [
- {
- columns: ['time', 'text', 'sequence_number', 'title', 'tags'],
- name: 'events1',
- points: [[1402596000000, 'some text', 1, 'Hello', 'B'], [1402596001000, 'asd', 2, 'Hello2', 'B']]
- }
- ],
- annotation: {
- query: 'select',
- titleColumn: 'title',
- tagsColumn: 'tags',
- textColumn: 'text',
+ var options = { series: [
+ {
+ name: 'cpu',
+ tags: {app: 'test'},
+ columns: ['time', 'mean'],
+ values: [["2015-05-18T10:57:05Z", 10], ["2015-05-18T10:57:06Z", 12]]
+ },
+ {
+ name: 'cpu',
+ tags: {app: 'test2'},
+ columns: ['time', 'mean'],
+ values: [["2015-05-18T10:57:05Z", 15], ["2015-05-18T10:57:06Z", 16]]
}
+ ]};
+
+ describe('and no alias', function() {
+
+ it('should generate two time series', function() {
+ var series = new InfluxSeries(options);
+ var result = series.getTimeSeries();
+
+ expect(result.length).to.be(2);
+ expect(result[0].target).to.be('cpu {app: test}');
+ expect(result[0].datapoints[0][0]).to.be(10);
+ expect(result[0].datapoints[0][1]).to.be(1431946625000);
+ expect(result[0].datapoints[1][0]).to.be(12);
+ expect(result[0].datapoints[1][1]).to.be(1431946626000);
+
+ expect(result[1].target).to.be('cpu {app: test2}');
+ expect(result[1].datapoints[0][0]).to.be(15);
+ expect(result[1].datapoints[0][1]).to.be(1431946625000);
+ expect(result[1].datapoints[1][0]).to.be(16);
+ expect(result[1].datapoints[1][1]).to.be(1431946626000);
+ });
});
- var result = series.getAnnotations();
+ describe('and simple alias', function() {
+ it('should use alias', function() {
+ options.alias = 'new series';
+ var series = new InfluxSeries(options);
+ var result = series.getTimeSeries();
+
+ expect(result[0].target).to.be('new series');
+ });
- it(' should generate 2 annnotations ', function() {
- expect(result.length).to.be(2);
- expect(result[0].annotation.query).to.be('select');
- expect(result[0].title).to.be('Hello');
- expect(result[0].time).to.be(1402596000000);
- expect(result[0].tags).to.be('B');
- expect(result[0].text).to.be('some text');
});
-
- });
-
- describe('given no column mapping', function() {
- var series = new InfluxSeries({
- seriesList: [
- {
- columns: ['time', 'text', 'sequence_number'],
- name: 'events1',
- points: [[1402596000000, 'some text', 1]]
- }
- ],
- annotation: { query: 'select' }
- });
-
- var result = series.getAnnotations();
-
- it('should generate 1 annnotation', function() {
- expect(result.length).to.be(1);
- expect(result[0].title).to.be('some text');
- expect(result[0].time).to.be(1402596000000);
- expect(result[0].tags).to.be(undefined);
- expect(result[0].text).to.be(undefined);
- });
-
});
});
diff --git a/public/test/specs/influxSeries08-specs.js b/public/test/specs/influxSeries08-specs.js
new file mode 100644
index 00000000000..47fb77b67b3
--- /dev/null
+++ b/public/test/specs/influxSeries08-specs.js
@@ -0,0 +1,220 @@
+define([
+ 'plugins/datasource/influxdb_08/influxSeries'
+], function(InfluxSeries) {
+ 'use strict';
+
+ describe('when generating timeseries from influxdb response', function() {
+
+ describe('given two series', function() {
+ var series = new InfluxSeries({
+ seriesList: [
+ {
+ columns: ['time', 'mean', 'sequence_number'],
+ name: 'prod.server1.cpu',
+ points: [[1402596000, 10, 1], [1402596001, 12, 2]]
+ },
+ {
+ columns: ['time', 'mean', 'sequence_number'],
+ name: 'prod.server2.cpu',
+ points: [[1402596000, 15, 1], [1402596001, 16, 2]]
+ }
+ ]
+ });
+
+ var result = series.getTimeSeries();
+
+ it('should generate two time series', function() {
+ expect(result.length).to.be(2);
+ expect(result[0].target).to.be('prod.server1.cpu.mean');
+ expect(result[0].datapoints[0][0]).to.be(10);
+ expect(result[0].datapoints[0][1]).to.be(1402596000);
+ expect(result[0].datapoints[1][0]).to.be(12);
+ expect(result[0].datapoints[1][1]).to.be(1402596001);
+
+ expect(result[1].target).to.be('prod.server2.cpu.mean');
+ expect(result[1].datapoints[0][0]).to.be(15);
+ expect(result[1].datapoints[0][1]).to.be(1402596000);
+ expect(result[1].datapoints[1][0]).to.be(16);
+ expect(result[1].datapoints[1][1]).to.be(1402596001);
+ });
+
+ });
+
+ describe('given an alias format', function() {
+ var series = new InfluxSeries({
+ seriesList: [
+ {
+ columns: ['time', 'mean', 'sequence_number'],
+ name: 'prod.server1.cpu',
+ points: [[1402596000, 10, 1], [1402596001, 12, 2]]
+ }
+ ],
+ alias: '$s.testing'
+ });
+
+ var result = series.getTimeSeries();
+
+ it('should generate correct series name', function() {
+ expect(result[0].target).to.be('prod.server1.cpu.testing');
+ });
+
+ });
+
+ describe('given an alias format with segment numbers', function() {
+ var series = new InfluxSeries({
+ seriesList: [
+ {
+ columns: ['time', 'mean', 'sequence_number'],
+ name: 'prod.server1.cpu',
+ points: [[1402596000, 10, 1], [1402596001, 12, 2]]
+ }
+ ],
+ alias: '$1.mean'
+ });
+
+ var result = series.getTimeSeries();
+
+ it('should generate correct series name', function() {
+ expect(result[0].target).to.be('server1.mean');
+ });
+
+ });
+
+ describe('given an alias format and many segments', function() {
+ var series = new InfluxSeries({
+ seriesList: [
+ {
+ columns: ['time', 'mean', 'sequence_number'],
+ name: 'a0.a1.a2.a3.a4.a5.a6.a7.a8.a9.a10.a11.a12',
+ points: [[1402596000, 10, 1], [1402596001, 12, 2]]
+ }
+ ],
+ alias: '$5.$11.mean'
+ });
+
+ var result = series.getTimeSeries();
+
+ it('should generate correct series name', function() {
+ expect(result[0].target).to.be('a5.a11.mean');
+ });
+
+ });
+
+
+ describe('given an alias format with group by field', function() {
+ var series = new InfluxSeries({
+ seriesList: [
+ {
+ columns: ['time', 'mean', 'host'],
+ name: 'prod.cpu',
+ points: [[1402596000, 10, 'A']]
+ }
+ ],
+ groupByField: 'host',
+ alias: '$g.$1'
+ });
+
+ var result = series.getTimeSeries();
+
+ it('should generate correct series name', function() {
+ expect(result[0].target).to.be('A.cpu');
+ });
+
+ });
+
+ describe('given group by column', function() {
+ var series = new InfluxSeries({
+ seriesList: [
+ {
+ columns: ['time', 'mean', 'host'],
+ name: 'prod.cpu',
+ points: [
+ [1402596000, 10, 'A'],
+ [1402596001, 11, 'A'],
+ [1402596000, 5, 'B'],
+ [1402596001, 6, 'B'],
+ ]
+ }
+ ],
+ groupByField: 'host'
+ });
+
+ var result = series.getTimeSeries();
+
+ it('should generate two time series', function() {
+ expect(result.length).to.be(2);
+ expect(result[0].target).to.be('prod.cpu.A');
+ expect(result[0].datapoints[0][0]).to.be(10);
+ expect(result[0].datapoints[0][1]).to.be(1402596000);
+ expect(result[0].datapoints[1][0]).to.be(11);
+ expect(result[0].datapoints[1][1]).to.be(1402596001);
+
+ expect(result[1].target).to.be('prod.cpu.B');
+ expect(result[1].datapoints[0][0]).to.be(5);
+ expect(result[1].datapoints[0][1]).to.be(1402596000);
+ expect(result[1].datapoints[1][0]).to.be(6);
+ expect(result[1].datapoints[1][1]).to.be(1402596001);
+ });
+
+ });
+
+ });
+
+ describe("when creating annotations from influxdb response", function() {
+ describe('given column mapping for all columns', function() {
+ var series = new InfluxSeries({
+ seriesList: [
+ {
+ columns: ['time', 'text', 'sequence_number', 'title', 'tags'],
+ name: 'events1',
+ points: [[1402596000000, 'some text', 1, 'Hello', 'B'], [1402596001000, 'asd', 2, 'Hello2', 'B']]
+ }
+ ],
+ annotation: {
+ query: 'select',
+ titleColumn: 'title',
+ tagsColumn: 'tags',
+ textColumn: 'text',
+ }
+ });
+
+ var result = series.getAnnotations();
+
+ it(' should generate 2 annnotations ', function() {
+ expect(result.length).to.be(2);
+ expect(result[0].annotation.query).to.be('select');
+ expect(result[0].title).to.be('Hello');
+ expect(result[0].time).to.be(1402596000000);
+ expect(result[0].tags).to.be('B');
+ expect(result[0].text).to.be('some text');
+ });
+
+ });
+
+ describe('given no column mapping', function() {
+ var series = new InfluxSeries({
+ seriesList: [
+ {
+ columns: ['time', 'text', 'sequence_number'],
+ name: 'events1',
+ points: [[1402596000000, 'some text', 1]]
+ }
+ ],
+ annotation: { query: 'select' }
+ });
+
+ var result = series.getAnnotations();
+
+ it('should generate 1 annnotation', function() {
+ expect(result.length).to.be(1);
+ expect(result[0].title).to.be('some text');
+ expect(result[0].time).to.be(1402596000000);
+ expect(result[0].tags).to.be(undefined);
+ expect(result[0].text).to.be(undefined);
+ });
+
+ });
+
+ });
+
+});
diff --git a/public/test/test-main.js b/public/test/test-main.js
index 86196069265..f064b81bab2 100644
--- a/public/test/test-main.js
+++ b/public/test/test-main.js
@@ -125,6 +125,7 @@ require([
'specs/graphiteTargetCtrl-specs',
'specs/graphiteDatasource-specs',
'specs/influxSeries-specs',
+ 'specs/influxSeries08-specs',
'specs/influxQueryBuilder-specs',
'specs/influx09-querybuilder-specs',
'specs/influxdb-datasource-specs',