The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/public/app/plugins/datasource/graphite/gfunc.ts

1245 lines
26 KiB

import { assign, each, filter, forEach, get, includes, isString, last, map, toString, isFinite } from 'lodash';
import { InterpolateFunction } from '@grafana/data';
import { isVersionGtOrEq } from 'app/core/utils/version';
export type ParamDef = {
name: string;
type: string;
options?: Array<string | number>;
multiple?: boolean;
optional?: boolean;
version?: string;
};
export interface FuncDef {
name: string;
params: ParamDef[];
defaultParams: Array<string | number>;
category?: string;
shortName?: any;
fake?: boolean;
version?: string;
description?: string;
/**
* True if the function was not found on the list of available function descriptions.
*/
unknown?: boolean;
}
export type FuncDefs = {
[functionName in string]: FuncDef;
};
const index: FuncDefs = {};
function addFuncDef(funcDef: Partial<FuncDef> & { name: string; category: string }) {
funcDef.params = funcDef.params || [];
funcDef.defaultParams = funcDef.defaultParams || [];
index[funcDef.name] = funcDef as FuncDef;
if (funcDef.shortName) {
index[funcDef.shortName] = funcDef as FuncDef;
}
}
const optionalSeriesRefArgs = [{ name: 'other', type: 'value_or_series', optional: true, multiple: true }];
addFuncDef({
name: 'scaleToSeconds',
category: 'Transform',
params: [{ name: 'seconds', type: 'int' }],
defaultParams: [1],
});
addFuncDef({
name: 'perSecond',
category: 'Transform',
params: [{ name: 'max value', type: 'int', optional: true }],
defaultParams: [],
});
addFuncDef({
name: 'holtWintersForecast',
category: 'Calculate',
});
addFuncDef({
name: 'holtWintersConfidenceBands',
category: 'Calculate',
params: [{ name: 'delta', type: 'int' }],
defaultParams: [3],
});
addFuncDef({
name: 'holtWintersAberration',
category: 'Calculate',
params: [{ name: 'delta', type: 'int' }],
defaultParams: [3],
});
addFuncDef({
name: 'nPercentile',
category: 'Calculate',
params: [{ name: 'Nth percentile', type: 'int' }],
defaultParams: [95],
});
addFuncDef({
name: 'diffSeries',
params: optionalSeriesRefArgs,
defaultParams: ['#A'],
category: 'Combine',
});
addFuncDef({
name: 'stddevSeries',
params: optionalSeriesRefArgs,
defaultParams: [''],
category: 'Combine',
});
addFuncDef({
name: 'divideSeries',
params: optionalSeriesRefArgs,
defaultParams: ['#A'],
category: 'Combine',
});
addFuncDef({
name: 'multiplySeries',
params: optionalSeriesRefArgs,
defaultParams: ['#A'],
category: 'Combine',
});
addFuncDef({
name: 'asPercent',
params: optionalSeriesRefArgs,
defaultParams: ['#A'],
category: 'Combine',
});
addFuncDef({
name: 'group',
params: optionalSeriesRefArgs,
defaultParams: ['#A', '#B'],
category: 'Combine',
});
addFuncDef({
name: 'sumSeries',
shortName: 'sum',
category: 'Combine',
params: optionalSeriesRefArgs,
defaultParams: [''],
});
addFuncDef({
name: 'averageSeries',
shortName: 'avg',
category: 'Combine',
params: optionalSeriesRefArgs,
defaultParams: [''],
});
addFuncDef({
name: 'rangeOfSeries',
category: 'Combine',
});
addFuncDef({
name: 'percentileOfSeries',
category: 'Combine',
params: [
{ name: 'n', type: 'int' },
{ name: 'interpolate', type: 'boolean', options: ['true', 'false'] },
],
defaultParams: [95, 'false'],
});
addFuncDef({
name: 'sumSeriesWithWildcards',
category: 'Combine',
params: [{ name: 'node', type: 'int', multiple: true }],
defaultParams: [3],
});
addFuncDef({
name: 'maxSeries',
shortName: 'max',
category: 'Combine',
});
addFuncDef({
name: 'minSeries',
shortName: 'min',
category: 'Combine',
});
addFuncDef({
name: 'averageSeriesWithWildcards',
category: 'Combine',
params: [{ name: 'node', type: 'int', multiple: true }],
defaultParams: [3],
});
addFuncDef({
name: 'alias',
category: 'Alias',
params: [{ name: 'alias', type: 'string' }],
defaultParams: ['alias'],
});
addFuncDef({
name: 'aliasSub',
category: 'Alias',
params: [
{ name: 'search', type: 'string' },
{ name: 'replace', type: 'string' },
],
defaultParams: ['', '\\1'],
});
addFuncDef({
name: 'consolidateBy',
category: 'Special',
params: [
{
name: 'function',
type: 'string',
options: ['sum', 'average', 'min', 'max'],
},
],
defaultParams: ['max'],
});
addFuncDef({
name: 'cumulative',
category: 'Special',
params: [],
defaultParams: [],
});
addFuncDef({
name: 'groupByNode',
category: 'Combine',
params: [
{
name: 'node',
type: 'int',
options: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12],
},
{
name: 'function',
type: 'string',
options: ['sum', 'avg', 'maxSeries'],
},
],
defaultParams: [3, 'sum'],
});
addFuncDef({
name: 'aliasByNode',
category: 'Alias',
params: [
{
name: 'node',
type: 'int',
options: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12],
multiple: true,
},
],
defaultParams: [3],
});
addFuncDef({
name: 'substr',
category: 'Special',
params: [
{
name: 'start',
type: 'int',
options: [-6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12],
},
{
name: 'stop',
type: 'int',
options: [-6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12],
},
],
defaultParams: [0, 0],
});
addFuncDef({
name: 'sortByName',
category: 'Sorting',
params: [
{
name: 'natural',
type: 'boolean',
options: ['true', 'false'],
optional: true,
},
],
defaultParams: ['false'],
});
addFuncDef({
name: 'sortByMaxima',
category: 'Sorting',
});
addFuncDef({
name: 'sortByMinima',
category: 'Sorting',
});
addFuncDef({
name: 'sortByTotal',
category: 'Sorting',
});
addFuncDef({
name: 'aliasByMetric',
category: 'Alias',
});
addFuncDef({
name: 'randomWalk',
fake: true,
category: 'Special',
params: [{ name: 'name', type: 'string' }],
defaultParams: ['randomWalk'],
});
addFuncDef({
name: 'countSeries',
category: 'Combine',
});
addFuncDef({
name: 'constantLine',
category: 'Special',
params: [{ name: 'value', type: 'int' }],
defaultParams: [10],
});
addFuncDef({
name: 'cactiStyle',
category: 'Special',
});
addFuncDef({
name: 'keepLastValue',
category: 'Transform',
params: [{ name: 'n', type: 'int' }],
defaultParams: [100],
});
addFuncDef({
name: 'changed',
category: 'Special',
params: [],
defaultParams: [],
});
addFuncDef({
name: 'scale',
category: 'Transform',
params: [{ name: 'factor', type: 'int' }],
defaultParams: [1],
});
addFuncDef({
name: 'offset',
category: 'Transform',
params: [{ name: 'amount', type: 'int' }],
defaultParams: [10],
});
addFuncDef({
name: 'transformNull',
category: 'Transform',
params: [{ name: 'amount', type: 'int' }],
defaultParams: [0],
});
addFuncDef({
name: 'integral',
category: 'Transform',
});
addFuncDef({
name: 'derivative',
category: 'Transform',
});
addFuncDef({
name: 'nonNegativeDerivative',
category: 'Transform',
params: [{ name: 'max value or 0', type: 'int', optional: true }],
defaultParams: [''],
});
addFuncDef({
name: 'timeShift',
category: 'Transform',
params: [
{
name: 'amount',
type: 'select',
options: ['1h', '6h', '12h', '1d', '2d', '7d', '14d', '30d'],
},
],
defaultParams: ['1d'],
});
addFuncDef({
name: 'timeStack',
category: 'Transform',
params: [
{
name: 'timeShiftUnit',
type: 'select',
options: ['1h', '6h', '12h', '1d', '2d', '7d', '14d', '30d'],
},
{ name: 'timeShiftStart', type: 'int' },
{ name: 'timeShiftEnd', type: 'int' },
],
defaultParams: ['1d', 0, 7],
});
addFuncDef({
name: 'summarize',
category: 'Transform',
params: [
{ name: 'interval', type: 'string' },
{
name: 'func',
type: 'select',
options: ['sum', 'avg', 'min', 'max', 'last'],
},
{
name: 'alignToFrom',
type: 'boolean',
optional: true,
options: ['false', 'true'],
},
],
defaultParams: ['1h', 'sum', 'false'],
});
addFuncDef({
name: 'smartSummarize',
category: 'Transform',
params: [
{ name: 'interval', type: 'string' },
{
name: 'func',
type: 'select',
options: ['sum', 'avg', 'min', 'max', 'last'],
},
],
defaultParams: ['1h', 'sum'],
});
addFuncDef({
name: 'absolute',
category: 'Transform',
});
addFuncDef({
name: 'hitcount',
category: 'Transform',
params: [{ name: 'interval', type: 'string' }],
defaultParams: ['10s'],
});
addFuncDef({
name: 'log',
category: 'Transform',
params: [{ name: 'base', type: 'int' }],
defaultParams: ['10'],
});
addFuncDef({
name: 'averageAbove',
category: 'Filter Series',
params: [{ name: 'n', type: 'int' }],
defaultParams: [25],
});
addFuncDef({
name: 'averageBelow',
category: 'Filter Series',
params: [{ name: 'n', type: 'int' }],
defaultParams: [25],
});
addFuncDef({
name: 'currentAbove',
category: 'Filter Series',
params: [{ name: 'n', type: 'int' }],
defaultParams: [25],
});
addFuncDef({
name: 'currentBelow',
category: 'Filter Series',
params: [{ name: 'n', type: 'int' }],
defaultParams: [25],
});
addFuncDef({
name: 'maximumAbove',
category: 'Filter Series',
params: [{ name: 'value', type: 'int' }],
defaultParams: [0],
});
addFuncDef({
name: 'maximumBelow',
category: 'Filter Series',
params: [{ name: 'value', type: 'int' }],
defaultParams: [0],
});
addFuncDef({
name: 'minimumAbove',
category: 'Filter Series',
params: [{ name: 'value', type: 'int' }],
defaultParams: [0],
});
addFuncDef({
name: 'minimumBelow',
category: 'Filter Series',
params: [{ name: 'value', type: 'int' }],
defaultParams: [0],
});
addFuncDef({
name: 'limit',
category: 'Filter Series',
params: [{ name: 'n', type: 'int' }],
defaultParams: [5],
});
addFuncDef({
name: 'mostDeviant',
category: 'Filter Series',
params: [{ name: 'n', type: 'int' }],
defaultParams: [10],
});
addFuncDef({
name: 'exclude',
category: 'Filter Series',
params: [{ name: 'exclude', type: 'string' }],
defaultParams: ['exclude'],
});
addFuncDef({
name: 'highestCurrent',
category: 'Filter Series',
params: [{ name: 'count', type: 'int' }],
defaultParams: [5],
});
addFuncDef({
name: 'highestMax',
category: 'Filter Series',
params: [{ name: 'count', type: 'int' }],
defaultParams: [5],
});
addFuncDef({
name: 'lowestCurrent',
category: 'Filter Series',
params: [{ name: 'count', type: 'int' }],
defaultParams: [5],
});
addFuncDef({
name: 'movingAverage',
category: 'Calculate',
params: [
{
name: 'windowSize',
type: 'int_or_interval',
options: ['5', '7', '10', '5min', '10min', '30min', '1hour'],
},
],
defaultParams: [10],
});
addFuncDef({
name: 'movingMedian',
category: 'Calculate',
params: [
{
name: 'windowSize',
type: 'int_or_interval',
options: ['5', '7', '10', '5min', '10min', '30min', '1hour'],
},
],
defaultParams: ['5'],
});
addFuncDef({
name: 'stdev',
category: 'Calculate',
params: [
{ name: 'n', type: 'int' },
{ name: 'tolerance', type: 'int' },
],
defaultParams: [5, 0.1],
});
addFuncDef({
name: 'highestAverage',
category: 'Filter Series',
params: [{ name: 'count', type: 'int' }],
defaultParams: [5],
});
addFuncDef({
name: 'lowestAverage',
category: 'Filter Series',
params: [{ name: 'count', type: 'int' }],
defaultParams: [5],
});
addFuncDef({
name: 'removeAbovePercentile',
category: 'Filter Data',
params: [{ name: 'n', type: 'int' }],
defaultParams: [5],
});
addFuncDef({
name: 'removeAboveValue',
category: 'Filter Data',
params: [{ name: 'n', type: 'int' }],
defaultParams: [5],
});
addFuncDef({
name: 'removeBelowPercentile',
category: 'Filter Data',
params: [{ name: 'n', type: 'int' }],
defaultParams: [5],
});
addFuncDef({
name: 'removeBelowValue',
category: 'Filter Data',
params: [{ name: 'n', type: 'int' }],
defaultParams: [5],
});
addFuncDef({
name: 'useSeriesAbove',
category: 'Filter Series',
params: [
{ name: 'value', type: 'int' },
{ name: 'search', type: 'string' },
{ name: 'replace', type: 'string' },
],
defaultParams: [0, 'search', 'replace'],
});
////////////////////
// Graphite 1.0.x //
////////////////////
addFuncDef({
name: 'aggregateLine',
category: 'Calculate',
params: [
{
name: 'func',
type: 'select',
options: ['sum', 'avg', 'min', 'max', 'last'],
},
],
defaultParams: ['avg'],
version: '1.0',
});
addFuncDef({
name: 'averageOutsidePercentile',
category: 'Filter Series',
params: [{ name: 'n', type: 'int' }],
defaultParams: [95],
version: '1.0',
});
addFuncDef({
name: 'delay',
category: 'Transform',
params: [{ name: 'steps', type: 'int' }],
defaultParams: [1],
version: '1.0',
});
addFuncDef({
name: 'exponentialMovingAverage',
category: '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: 'Special',
params: [{ name: 'fallback', type: 'string' }],
defaultParams: ['constantLine(0)'],
version: '1.0',
});
addFuncDef({
name: 'grep',
category: 'Filter Series',
params: [{ name: 'grep', type: 'string' }],
defaultParams: ['grep'],
version: '1.0',
});
addFuncDef({
name: 'groupByNodes',
category: 'Combine',
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],
multiple: true,
},
],
defaultParams: ['sum', 3],
version: '1.0',
});
addFuncDef({
name: 'integralByInterval',
category: 'Transform',
params: [
{
name: 'intervalUnit',
type: 'select',
options: ['1h', '6h', '12h', '1d', '2d', '7d', '14d', '30d'],
},
],
defaultParams: ['1d'],
version: '1.0',
});
addFuncDef({
name: 'interpolate',
category: 'Transform',
params: [{ name: 'limit', type: 'int', optional: true }],
defaultParams: [],
version: '1.0',
});
addFuncDef({
name: 'invert',
category: 'Transform',
version: '1.0',
});
addFuncDef({
name: 'isNonNull',
category: 'Combine',
version: '1.0',
});
addFuncDef({
name: 'linearRegression',
category: '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: 'Combine',
version: '1.0',
});
addFuncDef({
name: 'movingMin',
category: '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: '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: '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: 'Combine',
params: [
{
name: 'position',
type: 'int',
options: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12],
multiple: true,
},
],
defaultParams: [2],
version: '1.0',
});
addFuncDef({
name: 'offsetToZero',
category: 'Transform',
version: '1.0',
});
addFuncDef({
name: 'pow',
category: 'Transform',
params: [{ name: 'factor', type: 'int' }],
defaultParams: [10],
version: '1.0',
});
addFuncDef({
name: 'powSeries',
category: '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', multiple: true },
],
defaultParams: ['asPercent', 2, 'used_bytes'],
category: 'Combine',
version: '1.0',
});
addFuncDef({
name: 'removeBetweenPercentile',
category: 'Filter Series',
params: [{ name: 'n', type: 'int' }],
defaultParams: [95],
version: '1.0',
});
addFuncDef({
name: 'removeEmptySeries',
category: 'Filter Series',
version: '1.0',
});
addFuncDef({
name: 'squareRoot',
category: 'Transform',
version: '1.0',
});
addFuncDef({
name: 'timeSlice',
category: '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: 'Combine',
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',
});
addFuncDef({
name: 'seriesByTag',
category: 'Special',
params: [{ name: 'tagExpression', type: 'string', multiple: true }],
version: '1.1',
});
addFuncDef({
name: 'groupByTags',
category: 'Combine',
params: [
{
name: 'function',
type: 'string',
options: ['sum', 'avg', 'maxSeries'],
},
{ name: 'tag', type: 'string', multiple: true },
],
defaultParams: ['sum', 'tag'],
version: '1.1',
});
addFuncDef({
name: 'aliasByTags',
category: 'Alias',
params: [{ name: 'tag', type: 'string', multiple: true }],
defaultParams: ['tag'],
version: '1.1',
});
function isVersionRelatedFunction(obj: { version?: string }, graphiteVersion: string) {
return !obj.version || isVersionGtOrEq(graphiteVersion, obj.version);
}
export class FuncInstance {
def: FuncDef;
params: Array<string | number>;
text: any;
/**
* True if this function was just added and not edited yet. It's used to focus on first
* function param to edit it straight away after adding a function.
*/
declare added: boolean;
/**
* Hidden functions are not displayed in UI but available in text editor
* This is used for seriesByTagUsed function which when used switches
* the editor to tag-only mode. Defined tags are provided to seriesByTagUsed
* as parameters.
*/
hidden?: boolean;
constructor(funcDef: FuncDef, options?: { withDefaultParams: any }) {
this.def = funcDef;
this.params = [];
if (options && options.withDefaultParams && funcDef.defaultParams) {
this.params = funcDef.defaultParams.slice(0);
}
this.updateText();
}
render(metricExp: string, replaceVariables: InterpolateFunction): string {
const str = this.def.name + '(';
const parameters = map(this.params, (value, index) => {
let paramType;
if (index < this.def.params.length) {
paramType = this.def.params[index].type;
} else if (get(last(this.def.params), 'multiple')) {
paramType = get(last(this.def.params), 'type');
}
// param types that should never be quoted
const neverQuotedParams = ['value_or_series', 'boolean', 'int', 'float', 'node', 'int_or_infinity'];
// functions that should not have param types quoted
// https://github.com/grafana/grafana/issues/54924
const neverQuotedFunctions = ['asPercent'];
// params or functions that should never be quoted
if (includes(neverQuotedParams, paramType) || includes(neverQuotedFunctions, this.def.name)) {
return value;
}
const valueInterpolated = isString(value) ? replaceVariables(value) : value;
// param types that might be quoted
// To quote variables correctly we need to interpolate it to check if it contains a numeric or string value
if (includes(['int_or_interval', 'node_or_tag'], paramType) && isFinite(+valueInterpolated)) {
return toString(value);
}
return "'" + value + "'";
});
// don't send any blank parameters to graphite
while (parameters[parameters.length - 1] === '') {
parameters.pop();
}
if (metricExp) {
parameters.unshift(metricExp);
}
return str + parameters.join(', ') + ')';
}
_hasMultipleParamsInString(strValue: string, index: number) {
if (strValue.indexOf(',') === -1) {
return false;
}
if (this.def.params[index + 1] && this.def.params[index + 1].optional) {
return true;
}
if (index + 1 >= this.def.params.length && get(last(this.def.params), 'multiple')) {
return true;
}
return false;
}
updateParam(strValue: string, index: number) {
// handle optional parameters
// if string contains ',' and next param is optional, split and update both
if (this._hasMultipleParamsInString(strValue, index)) {
each(strValue.split(','), (partVal, idx) => {
this.updateParam(partVal.trim(), index + idx);
});
return;
}
if (strValue === '' && (index >= this.def.params.length || this.def.params[index].optional)) {
this.params.splice(index, 1);
} else {
this.params[index] = strValue;
}
this.updateText();
}
updateText() {
if (this.params.length === 0) {
this.text = this.def.name + '()';
return;
}
let text = this.def.name + '(';
text += this.params.join(', ');
text += ')';
this.text = text;
}
}
function createFuncInstance(funcDef: FuncDef | string, options?: { withDefaultParams: any }, idx?: any): FuncInstance {
if (isString(funcDef)) {
funcDef = getFuncDef(funcDef, idx);
}
return new FuncInstance(funcDef, options);
}
function getFuncDef(name: string, idx?: any): FuncDef {
if (!(idx || index)[name]) {
return { name: name, params: [{ name: '', type: '', multiple: true }], defaultParams: [''], unknown: true };
}
return (idx || index)[name];
}
function getFuncDefs(graphiteVersion: string, idx?: any): FuncDefs {
const funcs: FuncDefs = {};
forEach(idx || index, (funcDef: FuncDef) => {
if (isVersionRelatedFunction(funcDef, graphiteVersion)) {
funcs[funcDef.name] = assign({}, funcDef, {
params: filter(funcDef.params, (param) => {
return isVersionRelatedFunction(param, graphiteVersion);
}),
});
}
});
return funcs;
}
// parse response from graphite /functions endpoint into internal format
function parseFuncDefs(rawDefs: any): FuncDefs {
const funcDefs: FuncDefs = {};
forEach(rawDefs || {}, (funcDef, funcName) => {
// skip graphite graph functions
if (funcDef.group === 'Graph') {
return;
}
let description = funcDef.description;
if (description) {
// tidy up some pydoc syntax that rst2html can't handle
description = description
.replace(/:py:func:`(.+)( <[^>]*>)?`/g, '``$1``')
.replace(/.. seealso:: /g, 'See also: ')
.replace(/.. code-block *:: *none/g, '.. code-block::');
}
const func: FuncDef = {
name: funcDef.name,
description,
category: funcDef.group,
params: [],
defaultParams: [],
fake: false,
};
// get rid of the first "seriesList" param
if (/^seriesLists?$/.test(get(funcDef, 'params[0].type', ''))) {
// handle functions that accept multiple seriesLists
// we leave the param in place but mark it optional, so users can add more series if they wish
if (funcDef.params[0].multiple) {
funcDef.params[0].required = false;
// otherwise chop off the first param, it'll be handled separately
} else {
funcDef.params.shift();
}
// tag function as fake
} else {
func.fake = true;
}
forEach(funcDef.params, (rawParam) => {
const param: any = {
name: rawParam.name,
type: 'string',
optional: !rawParam.required,
multiple: !!rawParam.multiple,
options: undefined,
};
if (rawParam.default !== undefined) {
if (rawParam.default === Infinity) {
func.defaultParams.push('inf');
} else {
func.defaultParams.push(toString(rawParam.default));
}
} else if (rawParam.suggestions) {
func.defaultParams.push(toString(rawParam.suggestions[0]));
} else {
func.defaultParams.push('');
}
if (rawParam.type === 'boolean') {
param.type = 'boolean';
param.options = ['true', 'false'];
} else if (rawParam.type === 'integer') {
param.type = 'int';
} else if (rawParam.type === 'float') {
param.type = 'float';
} else if (rawParam.type === 'node') {
param.type = 'node';
param.options = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'];
} else if (rawParam.type === 'nodeOrTag') {
param.type = 'node_or_tag';
param.options = ['name', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'];
} else if (rawParam.type === 'intOrInterval') {
param.type = 'int_or_interval';
} else if (rawParam.type === 'seriesList') {
param.type = 'value_or_series';
} else if (rawParam.type === 'intOrInf') {
param.type = 'int_or_infinity';
}
if (rawParam.options) {
param.options = map(rawParam.options, toString);
} else if (rawParam.suggestions) {
param.options = map(rawParam.suggestions, toString);
}
func.params.push(param);
});
funcDefs[funcName] = func;
});
return funcDefs;
}
export default {
createFuncInstance: createFuncInstance,
getFuncDef: getFuncDef,
getFuncDefs: getFuncDefs,
parseFuncDefs: parseFuncDefs,
};