From 862de3a9dc00c86dcd68806fb8f39a536ba775de Mon Sep 17 00:00:00 2001 From: utkarshcmu Date: Mon, 13 Jun 2016 03:25:50 -0700 Subject: [PATCH 1/5] Added templated dependency in Opentsdb --- .../plugins/datasource/opentsdb/datasource.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/public/app/plugins/datasource/opentsdb/datasource.js b/public/app/plugins/datasource/opentsdb/datasource.js index 1d3db75658c..4a703798e15 100644 --- a/public/app/plugins/datasource/opentsdb/datasource.js +++ b/public/app/plugins/datasource/opentsdb/datasource.js @@ -162,12 +162,21 @@ function (angular, _, dateMath) { }); }; - this._performMetricKeyValueLookup = function(metric, key) { - if(!metric || !key) { + this._performMetricKeyValueLookup = function(metric, keys) { + + if(!metric || !keys) { return $q.when([]); } - var m = metric + "{" + key + "=*}"; + var keysArray = keys.split(","); + var key = keysArray[0]; + var keysQuery = key + "=*"; + + if (keysArray.length > 1) { + keysQuery += "," + keysArray.splice(1).join(","); + } + + var m = metric + "{" + keysQuery + "}"; return this._get('/api/search/lookup', {m: m, limit: 3000}).then(function(result) { result = result.data.results; @@ -225,7 +234,7 @@ function (angular, _, dateMath) { var metrics_regex = /metrics\((.*)\)/; var tag_names_regex = /tag_names\((.*)\)/; - var tag_values_regex = /tag_values\((.*),\s?(.*)\)/; + var tag_values_regex = /tag_values\((.*?),\s?(.*)\)/; var tag_names_suggest_regex = /suggest_tagk\((.*)\)/; var tag_values_suggest_regex = /suggest_tagv\((.*)\)/; From 6550bc97ba4a6e379664aaa3d8b7208fe0d07210 Mon Sep 17 00:00:00 2001 From: utkarshcmu Date: Mon, 13 Jun 2016 04:24:27 -0700 Subject: [PATCH 2/5] Added unit tests --- .../datasource/opentsdb/specs/datasource-specs.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/public/app/plugins/datasource/opentsdb/specs/datasource-specs.ts b/public/app/plugins/datasource/opentsdb/specs/datasource-specs.ts index a1dc9baada9..5fdff3dea3b 100644 --- a/public/app/plugins/datasource/opentsdb/specs/datasource-specs.ts +++ b/public/app/plugins/datasource/opentsdb/specs/datasource-specs.ts @@ -51,6 +51,20 @@ describe('opentsdb', function() { expect(requestOptions.params.m).to.be('cpu{hostname=*}'); }); + it('tag_values(cpu, test) should generate lookup query', function() { + ctx.ds.metricFindQuery('tag_values(cpu, hostname, env=$env)').then(function(data) { results = data; }); + ctx.$rootScope.$apply(); + expect(requestOptions.url).to.be('/api/search/lookup'); + expect(requestOptions.params.m).to.be('cpu{hostname=*, env=$env}'); + }); + + it('tag_values(cpu, test) should generate lookup query', function() { + ctx.ds.metricFindQuery('tag_values(cpu, hostname, env=$env, region=$region)').then(function(data) { results = data; }); + ctx.$rootScope.$apply(); + expect(requestOptions.url).to.be('/api/search/lookup'); + expect(requestOptions.params.m).to.be('cpu{hostname=*, env=$env, region=$region}'); + }); + it('suggest_tagk() should generate api suggest query', function() { ctx.ds.metricFindQuery('suggest_tagk(foo)').then(function(data) { results = data; }); ctx.$rootScope.$apply(); From f3003a97ef73b7eca2bd6cd2fdd97c40503c3824 Mon Sep 17 00:00:00 2001 From: utkarshcmu Date: Mon, 13 Jun 2016 04:34:23 -0700 Subject: [PATCH 3/5] Added required documentation --- docs/sources/datasources/opentsdb.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/sources/datasources/opentsdb.md b/docs/sources/datasources/opentsdb.md index 6ef930c0cc0..9294b6b68ee 100644 --- a/docs/sources/datasources/opentsdb.md +++ b/docs/sources/datasources/opentsdb.md @@ -51,6 +51,13 @@ When using OpenTSDB with a template variable of `query` type you can use followi If you do not see template variables being populated in `Preview of values` section, you need to enable `tsd.core.meta.enable_realtime_ts` in the OpenTSDB server settings. Also, to populate metadata of the existing time series data in OpenTSDB, you need to run `tsdb uid metasync` on the OpenTSDB server. +### Nested Templating + +One template variable can be used to filter tag values for another template varible. Very importantly, the order of the parameters matter in tag_values function. First parameter is the metric name, second parameter is the tag key for which you need to find tag values, and after that all other dependent template variables. Some examples are mentioned below to make nested template queries work successfully. + + tag_values(cpu, hostname, env=$env) // return tag values for cpu metric, selected env tag value and tag key hostname + tag_values(cpu, hostanme, env=$env, region=$region) // return tag values for cpu metric, selected env tag value, selected region tag value and tag key hostname + > Note: This is required for the OpenTSDB `lookup` api to work. For details on opentsdb metric queries checkout the official [OpenTSDB documentation](http://opentsdb.net/docs/build/html/index.html) From e4e042e3899f2de88bb0f802cdec33cc82ebd0ea Mon Sep 17 00:00:00 2001 From: utkarshcmu Date: Mon, 13 Jun 2016 04:53:21 -0700 Subject: [PATCH 4/5] CHANGELOG entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index eb1cb5c55ab..1ad8f717d8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ * **Scripts**: Use restart instead of start for deb package script, closes [#5282](https://github.com/grafana/grafana/pull/5282) * **Logging**: Moved to structured logging lib, and moved to component specific level filters via config file, closes [#4590](https://github.com/grafana/grafana/issues/4590) * **Search**: Add search limit query parameter, closes [#5292](https://github.com/grafana/grafana/pull/5292) +* **OpenTSDB**: Support nested template variables in tag_values function, closes [4398](https://github.com/grafana/grafana/issues/4398) ## Breaking changes * **Logging** : Changed default logging output format (now structured into message, and key value pairs, with logger key acting as component). You can also no change in config to json log ouput. From 33aa3f0fc5ad1722aa5b35b9a1736bb9f53be42f Mon Sep 17 00:00:00 2001 From: utkarshcmu Date: Mon, 13 Jun 2016 14:21:46 -0700 Subject: [PATCH 5/5] Made tag_values query more robust --- public/app/plugins/datasource/opentsdb/datasource.js | 4 +++- .../app/plugins/datasource/opentsdb/specs/datasource-specs.ts | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/public/app/plugins/datasource/opentsdb/datasource.js b/public/app/plugins/datasource/opentsdb/datasource.js index 4a703798e15..e80c811a2a6 100644 --- a/public/app/plugins/datasource/opentsdb/datasource.js +++ b/public/app/plugins/datasource/opentsdb/datasource.js @@ -168,7 +168,9 @@ function (angular, _, dateMath) { return $q.when([]); } - var keysArray = keys.split(","); + var keysArray = keys.split(",").map(function(key) { + return key.trim(); + }); var key = keysArray[0]; var keysQuery = key + "=*"; diff --git a/public/app/plugins/datasource/opentsdb/specs/datasource-specs.ts b/public/app/plugins/datasource/opentsdb/specs/datasource-specs.ts index 5fdff3dea3b..1f63dc88667 100644 --- a/public/app/plugins/datasource/opentsdb/specs/datasource-specs.ts +++ b/public/app/plugins/datasource/opentsdb/specs/datasource-specs.ts @@ -55,14 +55,14 @@ describe('opentsdb', function() { ctx.ds.metricFindQuery('tag_values(cpu, hostname, env=$env)').then(function(data) { results = data; }); ctx.$rootScope.$apply(); expect(requestOptions.url).to.be('/api/search/lookup'); - expect(requestOptions.params.m).to.be('cpu{hostname=*, env=$env}'); + expect(requestOptions.params.m).to.be('cpu{hostname=*,env=$env}'); }); it('tag_values(cpu, test) should generate lookup query', function() { ctx.ds.metricFindQuery('tag_values(cpu, hostname, env=$env, region=$region)').then(function(data) { results = data; }); ctx.$rootScope.$apply(); expect(requestOptions.url).to.be('/api/search/lookup'); - expect(requestOptions.params.m).to.be('cpu{hostname=*, env=$env, region=$region}'); + expect(requestOptions.params.m).to.be('cpu{hostname=*,env=$env,region=$region}'); }); it('suggest_tagk() should generate api suggest query', function() {