From 9f60745e5749b5c24f85fd5ded28c666edf55d36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 2 Sep 2014 20:59:54 +0200 Subject: [PATCH] Graphite: Graphite query builder can now handle functions that multiple series as arguments! #117 --- CHANGELOG.md | 1 + src/app/controllers/graphiteTarget.js | 25 ++++-- src/app/directives/graphiteFuncEditor.js | 4 +- src/app/directives/graphiteSegment.js | 5 +- src/app/partials/graphite/editor.html | 7 +- src/app/services/graphite/gfunc.js | 16 +++- .../services/graphite/graphiteDatasource.js | 53 ++++++++---- src/app/services/graphite/lexer.js | 1 + src/app/services/graphite/parser.js | 19 +++++ src/css/less/grafana.less | 4 +- src/test/specs/graphiteDatasource-specs.js | 84 +++++++++++++++++++ src/test/specs/graphiteTargetCtrl-specs.js | 53 ++++++++++++ src/test/specs/parser-specs.js | 10 +++ src/test/test-main.js | 1 + 14 files changed, 246 insertions(+), 37 deletions(-) create mode 100644 src/test/specs/graphiteDatasource-specs.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 9102807b6e1..2fafde3aebe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - [Issue #219](https://github.com/grafana/grafana/issues/219). Templating: Template variable value selection is now a typeahead autocomplete dropdown **New features and improvements** +- [Issue #117](https://github.com/grafana/grafana/issues/117). Graphite: Graphite query builder can now handle functions that multiple series as arguments! - [Issue #281](https://github.com/grafana/grafana/issues/281). Graphite: Metric node/segment selection is now a textbox with autocomplete dropdown, allow for custom glob expression for single node segment without entering text editor mode. - [Issue #578](https://github.com/grafana/grafana/issues/578). Dashboard: Row option to display row title even when the row is visible - [Issue #672](https://github.com/grafana/grafana/issues/672). Dashboard: panel fullscreen & edit state is present in url, can now link to graph in edit & fullscreen mode. diff --git a/src/app/controllers/graphiteTarget.js b/src/app/controllers/graphiteTarget.js index 493f01eb562..5671dd0dd04 100644 --- a/src/app/controllers/graphiteTarget.js +++ b/src/app/controllers/graphiteTarget.js @@ -9,11 +9,13 @@ function (angular, _, config, gfunc, Parser) { 'use strict'; var module = angular.module('grafana.controllers'); + var targetLetters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O']; module.controller('GraphiteTargetCtrl', function($scope, $sce, templateSrv) { $scope.init = function() { $scope.target.target = $scope.target.target || ''; + $scope.targetLetter = targetLetters[$scope.$index]; parseTarget(); }; @@ -69,6 +71,14 @@ function (angular, _, config, gfunc, Parser) { $scope.functions.push(innerFunc); break; + case 'series-ref': + if ($scope.segments.length === 0) { + func.params[index] = astNode.value; + } + else { + func.params[index - 1] = astNode.value; + } + break; case 'string': case 'number': if ((index-1) >= func.def.params.length) { @@ -81,9 +91,7 @@ function (angular, _, config, gfunc, Parser) { else { func.params[index - 1] = astNode.value; } - break; - case 'metric': if ($scope.segments.length > 0) { throw { message: 'Multiple metric params not supported, use text editor.' }; @@ -113,8 +121,10 @@ function (angular, _, config, gfunc, Parser) { return $scope.datasource.metricFindQuery(path) .then(function(segments) { if (segments.length === 0) { - $scope.segments = $scope.segments.splice(0, fromIndex); - $scope.segments.push(new MetricSegment('select metric')); + if (path !== '') { + $scope.segments = $scope.segments.splice(0, fromIndex); + $scope.segments.push(new MetricSegment('select metric')); + } return; } if (segments[0].expandable) { @@ -144,8 +154,7 @@ function (angular, _, config, gfunc, Parser) { $scope.getAltSegments = function (index) { $scope.altSegments = []; - var query = index === 0 ? - '*' : getSegmentPathUpTo(index) + '.*'; + var query = index === 0 ? '*' : getSegmentPathUpTo(index) + '.*'; return $scope.datasource.metricFindQuery(query) .then(function(segments) { @@ -226,6 +235,10 @@ function (angular, _, config, gfunc, Parser) { if (!newFunc.params.length && newFunc.added) { $scope.targetChanged(); } + + if ($scope.segments.length === 1 && $scope.segments[0].value === 'select metric') { + $scope.segments = []; + } }; $scope.moveAliasFuncLast = function() { diff --git a/src/app/directives/graphiteFuncEditor.js b/src/app/directives/graphiteFuncEditor.js index 57f1294a2df..db92240bb40 100644 --- a/src/app/directives/graphiteFuncEditor.js +++ b/src/app/directives/graphiteFuncEditor.js @@ -69,7 +69,6 @@ function (angular, _, $) { function inputBlur(paramIndex) { /*jshint validthis:true */ - var $input = $(this); var $link = $input.prev(); @@ -88,7 +87,6 @@ function (angular, _, $) { function inputKeyPress(paramIndex, e) { /*jshint validthis:true */ - if(e.which === 13) { inputBlur.call(this, paramIndex); } @@ -147,7 +145,7 @@ function (angular, _, $) { $funcLink.appendTo(elem); _.each(funcDef.params, function(param, index) { - if (param.optional && func.params.length !== index + 1) { + if (param.optional && func.params.length <= index) { return; } diff --git a/src/app/directives/graphiteSegment.js b/src/app/directives/graphiteSegment.js index 0f1e4397d25..032ea99c39a 100644 --- a/src/app/directives/graphiteSegment.js +++ b/src/app/directives/graphiteSegment.js @@ -64,10 +64,7 @@ function (angular, app, _, $) { }; $scope.source = function(query, callback) { - console.log("source!", callback); - if (options) { - return options; - } + if (options) { return options; } $scope.$apply(function() { $scope.getAltSegments($scope.$index).then(function() { diff --git a/src/app/partials/graphite/editor.html b/src/app/partials/graphite/editor.html index 2a314615963..9b93297ef75 100755 --- a/src/app/partials/graphite/editor.html +++ b/src/app/partials/graphite/editor.html @@ -47,6 +47,9 @@