From 4fe79edd405540570c68d2fb83ded08e79fa7089 Mon Sep 17 00:00:00 2001 From: Alexander Zobnin Date: Mon, 7 Aug 2017 16:10:59 +0300 Subject: [PATCH] Graphite 1.0 functions (#8987) * graphite-ds: add graphite version to config editor * graphite-ds: modify add-graphite-function to show only version-related functions * graphite-ds: refactor, move func filtering to gfunc.js * graphite-ds: add new functions for graphite 1.0.x * graphite-ds: fix unit tests (add jsonData) --- .../datasource/graphite/add_graphite_func.js | 19 +- .../datasource/graphite/config_ctrl.ts | 20 ++ .../plugins/datasource/graphite/datasource.ts | 1 + .../app/plugins/datasource/graphite/gfunc.js | 327 ++++++++++++++---- .../app/plugins/datasource/graphite/module.ts | 5 +- .../datasource/graphite/partials/config.html | 8 + .../graphite/specs/datasource_specs.ts | 2 +- 7 files changed, 297 insertions(+), 85 deletions(-) create mode 100644 public/app/plugins/datasource/graphite/config_ctrl.ts diff --git a/public/app/plugins/datasource/graphite/add_graphite_func.js b/public/app/plugins/datasource/graphite/add_graphite_func.js index bb4558b154b..52246fa1ff6 100644 --- a/public/app/plugins/datasource/graphite/add_graphite_func.js +++ b/public/app/plugins/datasource/graphite/add_graphite_func.js @@ -20,9 +20,10 @@ function (angular, _, $, gfunc) { return { link: function($scope, elem) { - var categories = gfunc.getCategories(); - var allFunctions = getAllFunctionNames(categories); var ctrl = $scope.ctrl; + var graphiteVersion = ctrl.datasource.graphiteVersion; + var categories = gfunc.getCategories(graphiteVersion); + var allFunctions = getAllFunctionNames(categories); $scope.functionMenu = createFunctionDropDownMenu(categories); @@ -94,14 +95,16 @@ function (angular, _, $, gfunc) { function createFunctionDropDownMenu(categories) { return _.map(categories, function(list, category) { + var submenu = _.map(list, function(value) { + return { + text: value.name, + click: "ctrl.addFunction('" + value.name + "')", + }; + }); + return { text: category, - submenu: _.map(list, function(value) { - return { - text: value.name, - click: "ctrl.addFunction('" + value.name + "')", - }; - }) + submenu: submenu }; }); } diff --git a/public/app/plugins/datasource/graphite/config_ctrl.ts b/public/app/plugins/datasource/graphite/config_ctrl.ts new file mode 100644 index 00000000000..a27ea01b0d6 --- /dev/null +++ b/public/app/plugins/datasource/graphite/config_ctrl.ts @@ -0,0 +1,20 @@ +/// + +import angular from 'angular'; +import _ from 'lodash'; + +export class GraphiteConfigCtrl { + static templateUrl = 'public/app/plugins/datasource/graphite/partials/config.html'; + current: any; + + /** @ngInject */ + constructor($scope) { + this.current.jsonData.graphiteVersion = this.current.jsonData.graphiteVersion || '0.9'; + } + + graphiteVersions = [ + {name: '0.9.x', value: '0.9'}, + {name: '1.0.x', value: '1.0'}, + ]; +} + diff --git a/public/app/plugins/datasource/graphite/datasource.ts b/public/app/plugins/datasource/graphite/datasource.ts index 40573db4234..6b2c8d166f4 100644 --- a/public/app/plugins/datasource/graphite/datasource.ts +++ b/public/app/plugins/datasource/graphite/datasource.ts @@ -11,6 +11,7 @@ export function GraphiteDatasource(instanceSettings, $q, backendSrv, templateSrv this.basicAuth = instanceSettings.basicAuth; this.url = instanceSettings.url; this.name = instanceSettings.name; + this.graphiteVersion = instanceSettings.jsonData.graphiteVersion || '0.9'; this.cacheTimeout = instanceSettings.cacheTimeout; this.withCredentials = instanceSettings.withCredentials; this.render_method = instanceSettings.render_method || 'POST'; diff --git a/public/app/plugins/datasource/graphite/gfunc.js b/public/app/plugins/datasource/graphite/gfunc.js index 17fd2d3ce08..bbf3c034310 100644 --- a/public/app/plugins/datasource/graphite/gfunc.js +++ b/public/app/plugins/datasource/graphite/gfunc.js @@ -115,27 +115,6 @@ function (_, $) { category: categories.Combine, }); - addFuncDef({ - name: 'mapSeries', - shortName: 'map', - params: [{ name: "node", type: 'int' }], - defaultParams: [3], - category: categories.Combine, - }); - - addFuncDef({ - name: 'reduceSeries', - shortName: 'reduce', - params: [ - { name: "function", type: 'string', options: ['asPercent', 'diffSeries', 'divideSeries'] }, - { name: "reduceNode", type: 'int', options: [0,1,2,3,4,5,6,7,8,9,10,11,12,13] }, - { name: "reduceMatchers", type: 'string' }, - { name: "reduceMatchers", type: 'string' }, - ], - defaultParams: ['asPercent', 2, 'used_bytes', 'total_bytes'], - category: categories.Combine, - }); - addFuncDef({ name: 'sumSeries', shortName: 'sum', @@ -152,11 +131,6 @@ function (_, $) { defaultParams: [''], }); - addFuncDef({ - name: 'isNonNull', - category: categories.Combine, - }); - addFuncDef({ name: 'rangeOfSeries', category: categories.Combine @@ -262,23 +236,6 @@ function (_, $) { defaultParams: [3, "sum"] }); - addFuncDef({ - name: "groupByNodes", - category: categories.Special, - params: [ - { - name: "function", - type: "string", - options: ['sum', 'avg', 'maxSeries'] - }, - { name: "node", type: "int", options: [0,1,2,3,4,5,6,7,8,9,10,12] }, - { name: "node", type: "int", options: [0,-1,-2,-3,-4,-5,-6,-7], optional: true }, - { name: "node", type: "int", options: [0,-1,-2,-3,-4,-5,-6,-7], optional: true }, - { name: "node", type: "int", options: [0,-1,-2,-3,-4,-5,-6,-7], optional: true }, - ], - defaultParams: ["sum", 3] - }); - addFuncDef({ name: 'aliasByNode', category: categories.Special, @@ -381,11 +338,6 @@ function (_, $) { defaultParams: [10] }); - addFuncDef({ - name: 'offsetToZero', - category: categories.Transform, - }); - addFuncDef({ name: 'transformNull', category: categories.Transform, @@ -542,13 +494,6 @@ function (_, $) { defaultParams: ['exclude'] }); - addFuncDef({ - name: "grep", - category: categories.Filter, - params: [{ name: "grep", type: 'string' }], - defaultParams: ['grep'] - }); - addFuncDef({ name: 'highestCurrent', category: categories.Filter, @@ -577,16 +522,6 @@ function (_, $) { defaultParams: [10] }); - addFuncDef({ - name: 'weightedAverage', - category: categories.Filter, - params: [ - { name: 'other', type: 'value_or_series', optional: true }, - { name: "node", type: "int", options: [0,1,2,3,4,5,6,7,8,9,10,12] }, - ], - defaultParams: ['#A', 4] - }); - addFuncDef({ name: 'movingMedian', category: categories.Filter, @@ -643,11 +578,6 @@ function (_, $) { defaultParams: [5] }); - addFuncDef({ - name: 'removeEmptySeries', - category: categories.Filter - }); - addFuncDef({ name: 'useSeriesAbove', category: categories.Filter, @@ -659,6 +589,239 @@ function (_, $) { defaultParams: [0, 'search', 'replace'] }); + //////////////////// + // Graphite 1.0.x // + //////////////////// + + addFuncDef({ + name: 'aggregateLine', + category: categories.Combine, + params: [{ name: "func", type: "select", options: ['sum', 'avg', 'min', 'max', 'last']}], + defaultParams: ['avg'], + version: '1.0' + }); + + addFuncDef({ + name: 'averageOutsidePercentile', + category: categories.Filter, + params: [{ name: "n", type: "int", }], + defaultParams: [95], + version: '1.0' + }); + + addFuncDef({ + name: 'delay', + category: categories.Transform, + params: [{ name: 'steps', type: 'int', }], + defaultParams: [1], + version: '1.0' + }); + + addFuncDef({ + name: 'exponentialMovingAverage', + category: categories.Calculate, + params: [{ name: 'windowSize', type: 'int_or_interval', options: ['5', '7', '10', '5min', '10min', '30min', '1hour'] }], + defaultParams: [10], + version: '1.0' + }); + + addFuncDef({ + name: 'fallbackSeries', + category: categories.Special, + params: [{ name: 'fallback', type: 'string' }], + defaultParams: ['constantLine(0)'], + version: '1.0' + }); + + addFuncDef({ + name: "grep", + category: categories.Filter, + params: [{ name: "grep", type: 'string' }], + defaultParams: ['grep'], + version: '1.0' + }); + + addFuncDef({ + name: "groupByNodes", + category: categories.Special, + params: [ + { + name: "function", + type: "string", + options: ['sum', 'avg', 'maxSeries'] + }, + { name: "node", type: "int", options: [0,1,2,3,4,5,6,7,8,9,10,12] }, + { name: "node", type: "int", options: [0,-1,-2,-3,-4,-5,-6,-7], optional: true }, + { name: "node", type: "int", options: [0,-1,-2,-3,-4,-5,-6,-7], optional: true }, + { name: "node", type: "int", options: [0,-1,-2,-3,-4,-5,-6,-7], optional: true }, + ], + defaultParams: ["sum", 3], + version: '1.0' + }); + + addFuncDef({ + name: 'integralByInterval', + category: categories.Transform, + params: [{ name: "intervalUnit", type: "select", options: ['1h', '6h', '12h', '1d', '2d', '7d', '14d', '30d'] }], + defaultParams: ['1d'], + version: '1.0' + }); + + addFuncDef({ + name: 'interpolate', + category: categories.Transform, + params: [{ name: 'limit', type: 'int', optional: true}], + defaultParams: [], + version: '1.0' + }); + + addFuncDef({ + name: 'invert', + category: categories.Transform, + version: '1.0' + }); + + addFuncDef({ + name: 'isNonNull', + category: categories.Combine, + version: '1.0' + }); + + addFuncDef({ + name: 'linearRegression', + category: categories.Calculate, + params: [ + { name: "startSourceAt", type: "select", options: ['-1h', '-6h', '-12h', '-1d', '-2d', '-7d', '-14d', '-30d'], optional: true }, + { name: "endSourceAt", type: "select", options: ['-1h', '-6h', '-12h', '-1d', '-2d', '-7d', '-14d', '-30d'], optional: true } + ], + defaultParams: [], + version: '1.0' + }); + + addFuncDef({ + name: 'mapSeries', + shortName: 'map', + params: [{ name: "node", type: 'int' }], + defaultParams: [3], + category: categories.Combine, + version: '1.0' + }); + + addFuncDef({ + name: 'movingMin', + category: categories.Calculate, + params: [{ name: 'windowSize', type: 'int_or_interval', options: ['5', '7', '10', '5min', '10min', '30min', '1hour'] }], + defaultParams: [10], + version: '1.0' + }); + + addFuncDef({ + name: 'movingMax', + category: categories.Calculate, + params: [{ name: 'windowSize', type: 'int_or_interval', options: ['5', '7', '10', '5min', '10min', '30min', '1hour'] }], + defaultParams: [10], + version: '1.0' + }); + + addFuncDef({ + name: 'movingSum', + category: categories.Calculate, + params: [{ name: 'windowSize', type: 'int_or_interval', options: ['5', '7', '10', '5min', '10min', '30min', '1hour'] }], + defaultParams: [10], + version: '1.0' + }); + + addFuncDef({ + name: "multiplySeriesWithWildcards", + category: categories.Calculate, + params: [ + { name: "position", type: "int", options: [0,1,2,3,4,5,6,7,8,9,10,12] }, + { name: "position", type: "int", options: [0,-1,-2,-3,-4,-5,-6,-7], optional: true }, + { name: "position", type: "int", options: [0,-1,-2,-3,-4,-5,-6,-7], optional: true }, + { name: "position", type: "int", options: [0,-1,-2,-3,-4,-5,-6,-7], optional: true }, + ], + defaultParams: [2], + version: '1.0' + }); + + addFuncDef({ + name: 'offsetToZero', + category: categories.Transform, + version: '1.0' + }); + + addFuncDef({ + name: 'pow', + category: categories.Transform, + params: [{ name: 'factor', type: 'int' }], + defaultParams: [10], + version: '1.0' + }); + + addFuncDef({ + name: 'powSeries', + category: categories.Transform, + params: optionalSeriesRefArgs, + defaultParams: [''], + version: '1.0' + }); + + addFuncDef({ + name: 'reduceSeries', + shortName: 'reduce', + params: [ + { name: "function", type: 'string', options: ['asPercent', 'diffSeries', 'divideSeries'] }, + { name: "reduceNode", type: 'int', options: [0,1,2,3,4,5,6,7,8,9,10,11,12,13] }, + { name: "reduceMatchers", type: 'string' }, + { name: "reduceMatchers", type: 'string' }, + ], + defaultParams: ['asPercent', 2, 'used_bytes', 'total_bytes'], + category: categories.Combine, + version: '1.0' + }); + + addFuncDef({ + name: 'removeBetweenPercentile', + category: categories.Filter, + params: [{ name: "n", type: "int", }], + defaultParams: [95], + version: '1.0' + }); + + addFuncDef({ + name: 'removeEmptySeries', + category: categories.Filter, + version: '1.0' + }); + + addFuncDef({ + name: 'squareRoot', + category: categories.Transform, + version: '1.0' + }); + + addFuncDef({ + name: 'timeSlice', + category: categories.Transform, + params: [ + { name: "startSliceAt", type: "select", options: ['-1h', '-6h', '-12h', '-1d', '-2d', '-7d', '-14d', '-30d']}, + { name: "endSliceAt", type: "select", options: ['-1h', '-6h', '-12h', '-1d', '-2d', '-7d', '-14d', '-30d'], optional: true } + ], + defaultParams: ['-1h'], + version: '1.0' + }); + + addFuncDef({ + name: 'weightedAverage', + category: categories.Filter, + params: [ + { name: 'other', type: 'value_or_series', optional: true }, + { name: "node", type: "int", options: [0,1,2,3,4,5,6,7,8,9,10,12] }, + ], + defaultParams: ['#A', 4], + version: '1.0' + }); + _.each(categories, function(funcList, catName) { categories[catName] = _.sortBy(funcList, 'name'); }); @@ -737,6 +900,16 @@ function (_, $) { this.text = text; }; + function isVersionRelatedFunction(func, graphiteVersion) { + return isVersionGreaterOrEqual(graphiteVersion, func.version) || !func.version; + } + + function isVersionGreaterOrEqual(a, b) { + var a_num = Number(a); + var b_num = Number(b); + return a_num >= b_num; + } + return { createFuncInstance: function(funcDef, options) { if (_.isString(funcDef)) { @@ -752,8 +925,18 @@ function (_, $) { return index[name]; }, - getCategories: function() { - return categories; + getCategories: function(graphiteVersion) { + var filteredCategories = {}; + _.each(categories, function(functions, category) { + var filteredFuncs = _.filter(functions, function(func) { + return isVersionRelatedFunction(func, graphiteVersion); + }); + if (filteredFuncs.length) { + filteredCategories[category] = filteredFuncs; + } + }); + + return filteredCategories; } }; diff --git a/public/app/plugins/datasource/graphite/module.ts b/public/app/plugins/datasource/graphite/module.ts index b06df4c9254..8a0965b6619 100644 --- a/public/app/plugins/datasource/graphite/module.ts +++ b/public/app/plugins/datasource/graphite/module.ts @@ -1,9 +1,6 @@ import {GraphiteDatasource} from './datasource'; import {GraphiteQueryCtrl} from './query_ctrl'; - -class GraphiteConfigCtrl { - static templateUrl = 'partials/config.html'; -} +import {GraphiteConfigCtrl} from './config_ctrl'; class GraphiteQueryOptionsCtrl { static templateUrl = 'partials/query.options.html'; diff --git a/public/app/plugins/datasource/graphite/partials/config.html b/public/app/plugins/datasource/graphite/partials/config.html index 7356c8948e4..8f71b339121 100644 --- a/public/app/plugins/datasource/graphite/partials/config.html +++ b/public/app/plugins/datasource/graphite/partials/config.html @@ -3,3 +3,11 @@ suggest-url="http://localhost:8080"> +

Graphite details

+ +
+
+ Version + +
+
diff --git a/public/app/plugins/datasource/graphite/specs/datasource_specs.ts b/public/app/plugins/datasource/graphite/specs/datasource_specs.ts index df7300d65eb..0fd6f7b118a 100644 --- a/public/app/plugins/datasource/graphite/specs/datasource_specs.ts +++ b/public/app/plugins/datasource/graphite/specs/datasource_specs.ts @@ -5,7 +5,7 @@ import {GraphiteDatasource} from "../datasource"; describe('graphiteDatasource', function() { var ctx = new helpers.ServiceTestContext(); - var instanceSettings: any = {url: [''], name: 'graphiteProd'}; + var instanceSettings: any = {url: [''], name: 'graphiteProd', jsonData: {}}; beforeEach(angularMocks.module('grafana.core')); beforeEach(angularMocks.module('grafana.services'));