Commit 2dc4434a by Torkel Ödegaard

Progress on influxdb and templated queries/variables, #613

parent 39c068bd
...@@ -652,5 +652,14 @@ function($, _, moment) { ...@@ -652,5 +652,14 @@ function($, _, moment) {
} }
}; };
kbn.stringToJsRegex = function(str) {
if (str[0] !== '/') {
return new RegExp(str);
}
var match = str.match(new RegExp('^/(.*?)/(g?i?m?y?)$'));
return new RegExp(match[1], match[2]);
};
return kbn; return kbn;
}); });
...@@ -15,8 +15,7 @@ function (_, kbn) { ...@@ -15,8 +15,7 @@ function (_, kbn) {
if (!aliasOrRegex) { return false; } if (!aliasOrRegex) { return false; }
if (aliasOrRegex[0] === '/') { if (aliasOrRegex[0] === '/') {
var match = aliasOrRegex.match(new RegExp('^/(.*?)/(g?i?m?y?)$')); var regex = kbn.stringToJsRegex(aliasOrRegex);
var regex = new RegExp(match[1], match[2]);
return seriesAlias.match(regex) != null; return seriesAlias.match(regex) != null;
} }
......
...@@ -7,7 +7,7 @@ function (angular, _) { ...@@ -7,7 +7,7 @@ function (angular, _) {
var module = angular.module('grafana.controllers'); var module = angular.module('grafana.controllers');
module.controller('TemplateEditorCtrl', function($scope, datasourceSrv, templateSrv, templateValuesSrv) { module.controller('TemplateEditorCtrl', function($scope, datasourceSrv, templateSrv, templateValuesSrv, alertSrv) {
var replacementDefaults = { var replacementDefaults = {
type: 'query', type: 'query',
...@@ -38,7 +38,10 @@ function (angular, _) { ...@@ -38,7 +38,10 @@ function (angular, _) {
}; };
$scope.runQuery = function() { $scope.runQuery = function() {
templateValuesSrv.updateOptions($scope.current); return templateValuesSrv.updateOptions($scope.current).then(function() {
}, function(err) {
alertSrv.set('Templating', 'Failed to run query for variable values: ' + err.message, 'error');
});
}; };
$scope.edit = function(variable) { $scope.edit = function(variable) {
...@@ -54,9 +57,10 @@ function (angular, _) { ...@@ -54,9 +57,10 @@ function (angular, _) {
}; };
$scope.update = function() { $scope.update = function() {
templateValuesSrv.updateOptions($scope.current); $scope.runQuery().then(function() {
$scope.reset(); $scope.reset();
$scope.editor.index = 0; $scope.editor.index = 0;
});
}; };
$scope.reset = function() { $scope.reset = function() {
...@@ -68,9 +72,6 @@ function (angular, _) { ...@@ -68,9 +72,6 @@ function (angular, _) {
if ($scope.current.type === 'time period') { if ($scope.current.type === 'time period') {
$scope.current.query = '1m,10m,30m,1h,6h,12h,1d,7d,14d,30d'; $scope.current.query = '1m,10m,30m,1h,6h,12h,1d,7d,14d,30d';
} }
else {
$scope.current.query = '';
}
}; };
$scope.removeVariable = function(variable) { $scope.removeVariable = function(variable) {
......
...@@ -113,7 +113,7 @@ ...@@ -113,7 +113,7 @@
<div class="editor-option"> <div class="editor-option">
<div class="editor-row"> <div class="editor-row">
<div class="editor-option" > <div class="editor-option" >
<label class="small">Variable values (first 20)</label> <label class="small">Variable values (showing 20/{{current.options.length}})</label>
<ul class="grafana-options-list"> <ul class="grafana-options-list">
<li ng-repeat="option in current.options | limitTo: 20"> <li ng-repeat="option in current.options | limitTo: 20">
{{option.text}} {{option.text}}
......
...@@ -214,6 +214,7 @@ function (angular, $, kbn, _, moment) { ...@@ -214,6 +214,7 @@ function (angular, $, kbn, _, moment) {
for (i = 0 ; i < this.templating.list.length; i++) { for (i = 0 ; i < this.templating.list.length; i++) {
var variable = this.templating.list[i]; var variable = this.templating.list[i];
if (variable.datasource === void 0) { variable.datasource = null; } if (variable.datasource === void 0) { variable.datasource = null; }
if (variable.type === 'filter') { variable.type = 'query'; }
if (variable.type === void 0) { variable.type = 'query'; } if (variable.type === void 0) { variable.type = 'query'; }
if (variable.allFormat === void 0) { variable.allFormat = 'Glob'; } if (variable.allFormat === void 0) { variable.allFormat = 'Glob'; }
} }
......
...@@ -161,7 +161,7 @@ function (angular, _, kbn, InfluxSeries) { ...@@ -161,7 +161,7 @@ function (angular, _, kbn, InfluxSeries) {
}); });
}; };
InfluxDatasource.prototype.metricFindQuery = function (filterSrv, query) { InfluxDatasource.prototype.metricFindQuery = function (query) {
var interpolated; var interpolated;
try { try {
interpolated = templateSrv.replace(query); interpolated = templateSrv.replace(query);
......
...@@ -2,9 +2,8 @@ define([ ...@@ -2,9 +2,8 @@ define([
'angular', 'angular',
'lodash', 'lodash',
'kbn', 'kbn',
'store'
], ],
function (angular, _) { function (angular, _, kbn) {
'use strict'; 'use strict';
var module = angular.module('grafana.services'); var module = angular.module('grafana.services');
...@@ -30,7 +29,7 @@ function (angular, _) { ...@@ -30,7 +29,7 @@ function (angular, _) {
templateSrv.updateTemplateData(); templateSrv.updateTemplateData();
return this.applyFilterToOtherFilters(variable) return this.updateOptionsInChildVariables(variable)
.then(function() { .then(function() {
if (!recursive) { if (!recursive) {
$rootScope.$broadcast('refresh'); $rootScope.$broadcast('refresh');
...@@ -38,7 +37,7 @@ function (angular, _) { ...@@ -38,7 +37,7 @@ function (angular, _) {
}); });
}; };
this.applyFilterToOtherFilters = function(updatedVariable) { this.updateOptionsInChildVariables = function(updatedVariable) {
var promises = _.map(self.variables, function(otherVariable) { var promises = _.map(self.variables, function(otherVariable) {
if (otherVariable === updatedVariable) { if (otherVariable === updatedVariable) {
return; return;
...@@ -63,9 +62,8 @@ function (angular, _) { ...@@ -63,9 +62,8 @@ function (angular, _) {
var datasource = datasourceSrv.get(variable.datasource); var datasource = datasourceSrv.get(variable.datasource);
return datasource.metricFindQuery(variable.query) return datasource.metricFindQuery(variable.query)
.then(function (results) { .then(function (results) {
variable.options = _.map(results, function(node) {
return { text: node.text, value: node.text }; variable.options = self.metricNamesToVariableValues(variable, results);
});
if (variable.includeAll) { if (variable.includeAll) {
self.addAllOption(variable); self.addAllOption(variable);
...@@ -84,6 +82,31 @@ function (angular, _) { ...@@ -84,6 +82,31 @@ function (angular, _) {
}); });
}; };
this.metricNamesToVariableValues = function(variable, metricNames) {
var regex, options, i, matches;
options = [];
if (variable.regex) {
regex = kbn.stringToJsRegex(variable.regex);
}
for (i = 0; i < metricNames.length; i++) {
var value = metricNames[i].text;
if (regex) {
matches = regex.exec(value);
if (!matches) { continue; }
if (matches.length > 1) {
value = matches[1];
}
}
options.push({text: value, value: value});
}
return options;
};
this.addAllOption = function(variable) { this.addAllOption = function(variable) {
var allValue = ''; var allValue = '';
switch(variable.allFormat) { switch(variable.allFormat) {
......
...@@ -8,26 +8,27 @@ define([ ...@@ -8,26 +8,27 @@ define([
describe('templateValuesSrv', function() { describe('templateValuesSrv', function() {
var _templateValuesSrv; var _templateValuesSrv;
var _dashboard; var _dashboard;
var _datasourceSrv = {};
var _q;
var _rootScope;
beforeEach(module('grafana.services')); beforeEach(module('grafana.services'));
beforeEach(module(function($provide) { beforeEach(module(function($provide) {
$provide.value('datasourceSrv', {}); $provide.value('datasourceSrv', _datasourceSrv);
$provide.value('templateSrv', { $provide.value('templateSrv', {
updateTemplateData: function() {} updateTemplateData: function() {}
}); });
_dashboard = dashboardMock.create(); _dashboard = dashboardMock.create();
})); }));
beforeEach(inject(function(templateValuesSrv) { beforeEach(inject(function(templateValuesSrv, $rootScope, $q) {
_templateValuesSrv = templateValuesSrv; _templateValuesSrv = templateValuesSrv;
_rootScope = $rootScope;
_q = $q;
})); }));
describe('update time period variable options', function() { describe('update time period variable options', function() {
var variable = { var variable = { type: 'time period', query: 'auto,1s,2h,5h,1d', name: 'test' };
type: 'time period',
query: 'auto,1s,2h,5h,1d',
name: 'test'
};
beforeEach(function() { beforeEach(function() {
_templateValuesSrv.updateOptions(variable); _templateValuesSrv.updateOptions(variable);
...@@ -40,6 +41,128 @@ define([ ...@@ -40,6 +41,128 @@ define([
}); });
}); });
function describeUpdateVariable(desc, fn) {
describe(desc, function() {
var ctx = {};
ctx.setup = function(setupFn) {
ctx.setupFn = setupFn;
};
beforeEach(function() {
ctx.setupFn();
var ds = {};
ds.metricFindQuery = sinon.stub().returns(_q.when(ctx.queryResult));
_datasourceSrv.get = sinon.stub().returns(ds);
_templateValuesSrv.updateOptions(ctx.variable);
_rootScope.$digest();
});
fn(ctx);
});
}
describeUpdateVariable('time period variable ', function(ctx) {
ctx.setup(function() {
ctx.variable = { type: 'time period', query: 'auto,1s,2h,5h,1d', name: 'test' };
});
it('should update options array', function() {
expect(ctx.variable.options.length).to.be(5);
expect(ctx.variable.options[1].text).to.be('1s');
expect(ctx.variable.options[1].value).to.be('1s');
});
});
describeUpdateVariable('basic query variable', function(ctx) {
ctx.setup(function() {
ctx.variable = { type: 'query', query: 'apps.*', name: 'test' };
ctx.queryResult = [{text: 'backend1'}, {text: 'backend2'}];
});
it('should update options array', function() {
expect(ctx.variable.options.length).to.be(2);
expect(ctx.variable.options[0].text).to.be('backend1');
expect(ctx.variable.options[0].value).to.be('backend1');
expect(ctx.variable.options[1].value).to.be('backend2');
});
it('should select first option as value', function() {
expect(ctx.variable.current.value).to.be('backend1');
});
});
describeUpdateVariable('and existing value still exists in options', function(ctx) {
ctx.setup(function() {
ctx.variable = { type: 'query', query: 'apps.*', name: 'test' };
ctx.variable.current = { value: 'backend2'};
ctx.queryResult = [{text: 'backend1'}, {text: 'backend2'}];
});
it('should keep variable value', function() {
expect(ctx.variable.current.value).to.be('backend2');
});
});
describeUpdateVariable('and regex pattern exists', function(ctx) {
ctx.setup(function() {
ctx.variable = { type: 'query', query: 'apps.*', name: 'test' };
ctx.variable.regex = '/apps.*(backend_[0-9]+)/';
ctx.queryResult = [{text: 'apps.backend.backend_01.counters.req'}, {text: 'apps.backend.backend_02.counters.req'}];
});
it('should extract and use match group', function() {
expect(ctx.variable.options[0].value).to.be('backend_01');
});
});
describeUpdateVariable('and regex pattern exists and no match', function(ctx) {
ctx.setup(function() {
ctx.variable = { type: 'query', query: 'apps.*', name: 'test' };
ctx.variable.regex = '/apps.*(backendasd[0-9]+)/';
ctx.queryResult = [{text: 'apps.backend.backend_01.counters.req'}, {text: 'apps.backend.backend_02.counters.req'}];
});
it('should not add non matching items', function() {
expect(ctx.variable.options.length).to.be(0);
});
});
describeUpdateVariable('regex pattern without slashes', function(ctx) {
ctx.setup(function() {
ctx.variable = { type: 'query', query: 'apps.*', name: 'test' };
ctx.variable.regex = 'backend_01';
ctx.queryResult = [{text: 'apps.backend.backend_01.counters.req'}, {text: 'apps.backend.backend_02.counters.req'}];
});
it('should return matches options', function() {
expect(ctx.variable.options.length).to.be(1);
});
});
describeUpdateVariable('and existing value still exists in options', function(ctx) {
ctx.setup(function() {
ctx.variable = { type: 'query', query: 'apps.*', name: 'test' };
ctx.variable.current = { value: 'backend2'};
ctx.queryResult = [{text: 'backend1'}, {text: 'backend2'}];
});
it('should keep variable value', function() {
expect(ctx.variable.current.value).to.be('backend2');
});
});
describeUpdateVariable('with include All glob syntax', function(ctx) {
ctx.setup(function() {
ctx.variable = { type: 'query', query: 'apps.*', name: 'test', includeAll: true, allFormat: 'Glob' };
ctx.queryResult = [{text: 'backend1'}, {text: 'backend2'}, { text: 'backend3'}];
});
it('should add All Glob option', function() {
expect(ctx.variable.options[0].value).to.be('{backend1,backend2,backend3}');
});
});
}); });
}); });
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment