gfunc.ts 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239
  1. import { assign, each, filter, forEach, get, includes, isString, last, map, toString, isFinite } from 'lodash';
  2. import { InterpolateFunction } from '@grafana/data';
  3. import { isVersionGtOrEq } from 'app/core/utils/version';
  4. export type ParamDef = {
  5. name: string;
  6. type: string;
  7. options?: Array<string | number>;
  8. multiple?: boolean;
  9. optional?: boolean;
  10. version?: string;
  11. };
  12. export interface FuncDef {
  13. name: string;
  14. params: ParamDef[];
  15. defaultParams: Array<string | number>;
  16. category?: string;
  17. shortName?: any;
  18. fake?: boolean;
  19. version?: string;
  20. description?: string;
  21. /**
  22. * True if the function was not found on the list of available function descriptions.
  23. */
  24. unknown?: boolean;
  25. }
  26. export type FuncDefs = {
  27. [functionName in string]: FuncDef;
  28. };
  29. const index: FuncDefs = {};
  30. function addFuncDef(funcDef: Partial<FuncDef> & { name: string; category: string }) {
  31. funcDef.params = funcDef.params || [];
  32. funcDef.defaultParams = funcDef.defaultParams || [];
  33. index[funcDef.name] = funcDef as FuncDef;
  34. if (funcDef.shortName) {
  35. index[funcDef.shortName] = funcDef as FuncDef;
  36. }
  37. }
  38. const optionalSeriesRefArgs = [{ name: 'other', type: 'value_or_series', optional: true, multiple: true }];
  39. addFuncDef({
  40. name: 'scaleToSeconds',
  41. category: 'Transform',
  42. params: [{ name: 'seconds', type: 'int' }],
  43. defaultParams: [1],
  44. });
  45. addFuncDef({
  46. name: 'perSecond',
  47. category: 'Transform',
  48. params: [{ name: 'max value', type: 'int', optional: true }],
  49. defaultParams: [],
  50. });
  51. addFuncDef({
  52. name: 'holtWintersForecast',
  53. category: 'Calculate',
  54. });
  55. addFuncDef({
  56. name: 'holtWintersConfidenceBands',
  57. category: 'Calculate',
  58. params: [{ name: 'delta', type: 'int' }],
  59. defaultParams: [3],
  60. });
  61. addFuncDef({
  62. name: 'holtWintersAberration',
  63. category: 'Calculate',
  64. params: [{ name: 'delta', type: 'int' }],
  65. defaultParams: [3],
  66. });
  67. addFuncDef({
  68. name: 'nPercentile',
  69. category: 'Calculate',
  70. params: [{ name: 'Nth percentile', type: 'int' }],
  71. defaultParams: [95],
  72. });
  73. addFuncDef({
  74. name: 'diffSeries',
  75. params: optionalSeriesRefArgs,
  76. defaultParams: ['#A'],
  77. category: 'Combine',
  78. });
  79. addFuncDef({
  80. name: 'stddevSeries',
  81. params: optionalSeriesRefArgs,
  82. defaultParams: [''],
  83. category: 'Combine',
  84. });
  85. addFuncDef({
  86. name: 'divideSeries',
  87. params: optionalSeriesRefArgs,
  88. defaultParams: ['#A'],
  89. category: 'Combine',
  90. });
  91. addFuncDef({
  92. name: 'multiplySeries',
  93. params: optionalSeriesRefArgs,
  94. defaultParams: ['#A'],
  95. category: 'Combine',
  96. });
  97. addFuncDef({
  98. name: 'asPercent',
  99. params: optionalSeriesRefArgs,
  100. defaultParams: ['#A'],
  101. category: 'Combine',
  102. });
  103. addFuncDef({
  104. name: 'group',
  105. params: optionalSeriesRefArgs,
  106. defaultParams: ['#A', '#B'],
  107. category: 'Combine',
  108. });
  109. addFuncDef({
  110. name: 'sumSeries',
  111. shortName: 'sum',
  112. category: 'Combine',
  113. params: optionalSeriesRefArgs,
  114. defaultParams: [''],
  115. });
  116. addFuncDef({
  117. name: 'averageSeries',
  118. shortName: 'avg',
  119. category: 'Combine',
  120. params: optionalSeriesRefArgs,
  121. defaultParams: [''],
  122. });
  123. addFuncDef({
  124. name: 'rangeOfSeries',
  125. category: 'Combine',
  126. });
  127. addFuncDef({
  128. name: 'percentileOfSeries',
  129. category: 'Combine',
  130. params: [
  131. { name: 'n', type: 'int' },
  132. { name: 'interpolate', type: 'boolean', options: ['true', 'false'] },
  133. ],
  134. defaultParams: [95, 'false'],
  135. });
  136. addFuncDef({
  137. name: 'sumSeriesWithWildcards',
  138. category: 'Combine',
  139. params: [{ name: 'node', type: 'int', multiple: true }],
  140. defaultParams: [3],
  141. });
  142. addFuncDef({
  143. name: 'maxSeries',
  144. shortName: 'max',
  145. category: 'Combine',
  146. });
  147. addFuncDef({
  148. name: 'minSeries',
  149. shortName: 'min',
  150. category: 'Combine',
  151. });
  152. addFuncDef({
  153. name: 'averageSeriesWithWildcards',
  154. category: 'Combine',
  155. params: [{ name: 'node', type: 'int', multiple: true }],
  156. defaultParams: [3],
  157. });
  158. addFuncDef({
  159. name: 'alias',
  160. category: 'Alias',
  161. params: [{ name: 'alias', type: 'string' }],
  162. defaultParams: ['alias'],
  163. });
  164. addFuncDef({
  165. name: 'aliasSub',
  166. category: 'Alias',
  167. params: [
  168. { name: 'search', type: 'string' },
  169. { name: 'replace', type: 'string' },
  170. ],
  171. defaultParams: ['', '\\1'],
  172. });
  173. addFuncDef({
  174. name: 'consolidateBy',
  175. category: 'Special',
  176. params: [
  177. {
  178. name: 'function',
  179. type: 'string',
  180. options: ['sum', 'average', 'min', 'max'],
  181. },
  182. ],
  183. defaultParams: ['max'],
  184. });
  185. addFuncDef({
  186. name: 'cumulative',
  187. category: 'Special',
  188. params: [],
  189. defaultParams: [],
  190. });
  191. addFuncDef({
  192. name: 'groupByNode',
  193. category: 'Combine',
  194. params: [
  195. {
  196. name: 'node',
  197. type: 'int',
  198. options: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12],
  199. },
  200. {
  201. name: 'function',
  202. type: 'string',
  203. options: ['sum', 'avg', 'maxSeries'],
  204. },
  205. ],
  206. defaultParams: [3, 'sum'],
  207. });
  208. addFuncDef({
  209. name: 'aliasByNode',
  210. category: 'Alias',
  211. params: [
  212. {
  213. name: 'node',
  214. type: 'int',
  215. options: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12],
  216. multiple: true,
  217. },
  218. ],
  219. defaultParams: [3],
  220. });
  221. addFuncDef({
  222. name: 'substr',
  223. category: 'Special',
  224. params: [
  225. {
  226. name: 'start',
  227. type: 'int',
  228. options: [-6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12],
  229. },
  230. {
  231. name: 'stop',
  232. type: 'int',
  233. options: [-6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12],
  234. },
  235. ],
  236. defaultParams: [0, 0],
  237. });
  238. addFuncDef({
  239. name: 'sortByName',
  240. category: 'Sorting',
  241. params: [
  242. {
  243. name: 'natural',
  244. type: 'boolean',
  245. options: ['true', 'false'],
  246. optional: true,
  247. },
  248. ],
  249. defaultParams: ['false'],
  250. });
  251. addFuncDef({
  252. name: 'sortByMaxima',
  253. category: 'Sorting',
  254. });
  255. addFuncDef({
  256. name: 'sortByMinima',
  257. category: 'Sorting',
  258. });
  259. addFuncDef({
  260. name: 'sortByTotal',
  261. category: 'Sorting',
  262. });
  263. addFuncDef({
  264. name: 'aliasByMetric',
  265. category: 'Alias',
  266. });
  267. addFuncDef({
  268. name: 'randomWalk',
  269. fake: true,
  270. category: 'Special',
  271. params: [{ name: 'name', type: 'string' }],
  272. defaultParams: ['randomWalk'],
  273. });
  274. addFuncDef({
  275. name: 'countSeries',
  276. category: 'Combine',
  277. });
  278. addFuncDef({
  279. name: 'constantLine',
  280. category: 'Special',
  281. params: [{ name: 'value', type: 'int' }],
  282. defaultParams: [10],
  283. });
  284. addFuncDef({
  285. name: 'cactiStyle',
  286. category: 'Special',
  287. });
  288. addFuncDef({
  289. name: 'keepLastValue',
  290. category: 'Transform',
  291. params: [{ name: 'n', type: 'int' }],
  292. defaultParams: [100],
  293. });
  294. addFuncDef({
  295. name: 'changed',
  296. category: 'Special',
  297. params: [],
  298. defaultParams: [],
  299. });
  300. addFuncDef({
  301. name: 'scale',
  302. category: 'Transform',
  303. params: [{ name: 'factor', type: 'int' }],
  304. defaultParams: [1],
  305. });
  306. addFuncDef({
  307. name: 'offset',
  308. category: 'Transform',
  309. params: [{ name: 'amount', type: 'int' }],
  310. defaultParams: [10],
  311. });
  312. addFuncDef({
  313. name: 'transformNull',
  314. category: 'Transform',
  315. params: [{ name: 'amount', type: 'int' }],
  316. defaultParams: [0],
  317. });
  318. addFuncDef({
  319. name: 'integral',
  320. category: 'Transform',
  321. });
  322. addFuncDef({
  323. name: 'derivative',
  324. category: 'Transform',
  325. });
  326. addFuncDef({
  327. name: 'nonNegativeDerivative',
  328. category: 'Transform',
  329. params: [{ name: 'max value or 0', type: 'int', optional: true }],
  330. defaultParams: [''],
  331. });
  332. addFuncDef({
  333. name: 'timeShift',
  334. category: 'Transform',
  335. params: [
  336. {
  337. name: 'amount',
  338. type: 'select',
  339. options: ['1h', '6h', '12h', '1d', '2d', '7d', '14d', '30d'],
  340. },
  341. ],
  342. defaultParams: ['1d'],
  343. });
  344. addFuncDef({
  345. name: 'timeStack',
  346. category: 'Transform',
  347. params: [
  348. {
  349. name: 'timeShiftUnit',
  350. type: 'select',
  351. options: ['1h', '6h', '12h', '1d', '2d', '7d', '14d', '30d'],
  352. },
  353. { name: 'timeShiftStart', type: 'int' },
  354. { name: 'timeShiftEnd', type: 'int' },
  355. ],
  356. defaultParams: ['1d', 0, 7],
  357. });
  358. addFuncDef({
  359. name: 'summarize',
  360. category: 'Transform',
  361. params: [
  362. { name: 'interval', type: 'string' },
  363. {
  364. name: 'func',
  365. type: 'select',
  366. options: ['sum', 'avg', 'min', 'max', 'last'],
  367. },
  368. {
  369. name: 'alignToFrom',
  370. type: 'boolean',
  371. optional: true,
  372. options: ['false', 'true'],
  373. },
  374. ],
  375. defaultParams: ['1h', 'sum', 'false'],
  376. });
  377. addFuncDef({
  378. name: 'smartSummarize',
  379. category: 'Transform',
  380. params: [
  381. { name: 'interval', type: 'string' },
  382. {
  383. name: 'func',
  384. type: 'select',
  385. options: ['sum', 'avg', 'min', 'max', 'last'],
  386. },
  387. ],
  388. defaultParams: ['1h', 'sum'],
  389. });
  390. addFuncDef({
  391. name: 'absolute',
  392. category: 'Transform',
  393. });
  394. addFuncDef({
  395. name: 'hitcount',
  396. category: 'Transform',
  397. params: [{ name: 'interval', type: 'string' }],
  398. defaultParams: ['10s'],
  399. });
  400. addFuncDef({
  401. name: 'log',
  402. category: 'Transform',
  403. params: [{ name: 'base', type: 'int' }],
  404. defaultParams: ['10'],
  405. });
  406. addFuncDef({
  407. name: 'averageAbove',
  408. category: 'Filter Series',
  409. params: [{ name: 'n', type: 'int' }],
  410. defaultParams: [25],
  411. });
  412. addFuncDef({
  413. name: 'averageBelow',
  414. category: 'Filter Series',
  415. params: [{ name: 'n', type: 'int' }],
  416. defaultParams: [25],
  417. });
  418. addFuncDef({
  419. name: 'currentAbove',
  420. category: 'Filter Series',
  421. params: [{ name: 'n', type: 'int' }],
  422. defaultParams: [25],
  423. });
  424. addFuncDef({
  425. name: 'currentBelow',
  426. category: 'Filter Series',
  427. params: [{ name: 'n', type: 'int' }],
  428. defaultParams: [25],
  429. });
  430. addFuncDef({
  431. name: 'maximumAbove',
  432. category: 'Filter Series',
  433. params: [{ name: 'value', type: 'int' }],
  434. defaultParams: [0],
  435. });
  436. addFuncDef({
  437. name: 'maximumBelow',
  438. category: 'Filter Series',
  439. params: [{ name: 'value', type: 'int' }],
  440. defaultParams: [0],
  441. });
  442. addFuncDef({
  443. name: 'minimumAbove',
  444. category: 'Filter Series',
  445. params: [{ name: 'value', type: 'int' }],
  446. defaultParams: [0],
  447. });
  448. addFuncDef({
  449. name: 'minimumBelow',
  450. category: 'Filter Series',
  451. params: [{ name: 'value', type: 'int' }],
  452. defaultParams: [0],
  453. });
  454. addFuncDef({
  455. name: 'limit',
  456. category: 'Filter Series',
  457. params: [{ name: 'n', type: 'int' }],
  458. defaultParams: [5],
  459. });
  460. addFuncDef({
  461. name: 'mostDeviant',
  462. category: 'Filter Series',
  463. params: [{ name: 'n', type: 'int' }],
  464. defaultParams: [10],
  465. });
  466. addFuncDef({
  467. name: 'exclude',
  468. category: 'Filter Series',
  469. params: [{ name: 'exclude', type: 'string' }],
  470. defaultParams: ['exclude'],
  471. });
  472. addFuncDef({
  473. name: 'highestCurrent',
  474. category: 'Filter Series',
  475. params: [{ name: 'count', type: 'int' }],
  476. defaultParams: [5],
  477. });
  478. addFuncDef({
  479. name: 'highestMax',
  480. category: 'Filter Series',
  481. params: [{ name: 'count', type: 'int' }],
  482. defaultParams: [5],
  483. });
  484. addFuncDef({
  485. name: 'lowestCurrent',
  486. category: 'Filter Series',
  487. params: [{ name: 'count', type: 'int' }],
  488. defaultParams: [5],
  489. });
  490. addFuncDef({
  491. name: 'movingAverage',
  492. category: 'Calculate',
  493. params: [
  494. {
  495. name: 'windowSize',
  496. type: 'int_or_interval',
  497. options: ['5', '7', '10', '5min', '10min', '30min', '1hour'],
  498. },
  499. ],
  500. defaultParams: [10],
  501. });
  502. addFuncDef({
  503. name: 'movingMedian',
  504. category: 'Calculate',
  505. params: [
  506. {
  507. name: 'windowSize',
  508. type: 'int_or_interval',
  509. options: ['5', '7', '10', '5min', '10min', '30min', '1hour'],
  510. },
  511. ],
  512. defaultParams: ['5'],
  513. });
  514. addFuncDef({
  515. name: 'stdev',
  516. category: 'Calculate',
  517. params: [
  518. { name: 'n', type: 'int' },
  519. { name: 'tolerance', type: 'int' },
  520. ],
  521. defaultParams: [5, 0.1],
  522. });
  523. addFuncDef({
  524. name: 'highestAverage',
  525. category: 'Filter Series',
  526. params: [{ name: 'count', type: 'int' }],
  527. defaultParams: [5],
  528. });
  529. addFuncDef({
  530. name: 'lowestAverage',
  531. category: 'Filter Series',
  532. params: [{ name: 'count', type: 'int' }],
  533. defaultParams: [5],
  534. });
  535. addFuncDef({
  536. name: 'removeAbovePercentile',
  537. category: 'Filter Data',
  538. params: [{ name: 'n', type: 'int' }],
  539. defaultParams: [5],
  540. });
  541. addFuncDef({
  542. name: 'removeAboveValue',
  543. category: 'Filter Data',
  544. params: [{ name: 'n', type: 'int' }],
  545. defaultParams: [5],
  546. });
  547. addFuncDef({
  548. name: 'removeBelowPercentile',
  549. category: 'Filter Data',
  550. params: [{ name: 'n', type: 'int' }],
  551. defaultParams: [5],
  552. });
  553. addFuncDef({
  554. name: 'removeBelowValue',
  555. category: 'Filter Data',
  556. params: [{ name: 'n', type: 'int' }],
  557. defaultParams: [5],
  558. });
  559. addFuncDef({
  560. name: 'useSeriesAbove',
  561. category: 'Filter Series',
  562. params: [
  563. { name: 'value', type: 'int' },
  564. { name: 'search', type: 'string' },
  565. { name: 'replace', type: 'string' },
  566. ],
  567. defaultParams: [0, 'search', 'replace'],
  568. });
  569. ////////////////////
  570. // Graphite 1.0.x //
  571. ////////////////////
  572. addFuncDef({
  573. name: 'aggregateLine',
  574. category: 'Calculate',
  575. params: [
  576. {
  577. name: 'func',
  578. type: 'select',
  579. options: ['sum', 'avg', 'min', 'max', 'last'],
  580. },
  581. ],
  582. defaultParams: ['avg'],
  583. version: '1.0',
  584. });
  585. addFuncDef({
  586. name: 'averageOutsidePercentile',
  587. category: 'Filter Series',
  588. params: [{ name: 'n', type: 'int' }],
  589. defaultParams: [95],
  590. version: '1.0',
  591. });
  592. addFuncDef({
  593. name: 'delay',
  594. category: 'Transform',
  595. params: [{ name: 'steps', type: 'int' }],
  596. defaultParams: [1],
  597. version: '1.0',
  598. });
  599. addFuncDef({
  600. name: 'exponentialMovingAverage',
  601. category: 'Calculate',
  602. params: [
  603. {
  604. name: 'windowSize',
  605. type: 'int_or_interval',
  606. options: ['5', '7', '10', '5min', '10min', '30min', '1hour'],
  607. },
  608. ],
  609. defaultParams: [10],
  610. version: '1.0',
  611. });
  612. addFuncDef({
  613. name: 'fallbackSeries',
  614. category: 'Special',
  615. params: [{ name: 'fallback', type: 'string' }],
  616. defaultParams: ['constantLine(0)'],
  617. version: '1.0',
  618. });
  619. addFuncDef({
  620. name: 'grep',
  621. category: 'Filter Series',
  622. params: [{ name: 'grep', type: 'string' }],
  623. defaultParams: ['grep'],
  624. version: '1.0',
  625. });
  626. addFuncDef({
  627. name: 'groupByNodes',
  628. category: 'Combine',
  629. params: [
  630. {
  631. name: 'function',
  632. type: 'string',
  633. options: ['sum', 'avg', 'maxSeries'],
  634. },
  635. {
  636. name: 'node',
  637. type: 'int',
  638. options: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12],
  639. multiple: true,
  640. },
  641. ],
  642. defaultParams: ['sum', 3],
  643. version: '1.0',
  644. });
  645. addFuncDef({
  646. name: 'integralByInterval',
  647. category: 'Transform',
  648. params: [
  649. {
  650. name: 'intervalUnit',
  651. type: 'select',
  652. options: ['1h', '6h', '12h', '1d', '2d', '7d', '14d', '30d'],
  653. },
  654. ],
  655. defaultParams: ['1d'],
  656. version: '1.0',
  657. });
  658. addFuncDef({
  659. name: 'interpolate',
  660. category: 'Transform',
  661. params: [{ name: 'limit', type: 'int', optional: true }],
  662. defaultParams: [],
  663. version: '1.0',
  664. });
  665. addFuncDef({
  666. name: 'invert',
  667. category: 'Transform',
  668. version: '1.0',
  669. });
  670. addFuncDef({
  671. name: 'isNonNull',
  672. category: 'Combine',
  673. version: '1.0',
  674. });
  675. addFuncDef({
  676. name: 'linearRegression',
  677. category: 'Calculate',
  678. params: [
  679. {
  680. name: 'startSourceAt',
  681. type: 'select',
  682. options: ['-1h', '-6h', '-12h', '-1d', '-2d', '-7d', '-14d', '-30d'],
  683. optional: true,
  684. },
  685. {
  686. name: 'endSourceAt',
  687. type: 'select',
  688. options: ['-1h', '-6h', '-12h', '-1d', '-2d', '-7d', '-14d', '-30d'],
  689. optional: true,
  690. },
  691. ],
  692. defaultParams: [],
  693. version: '1.0',
  694. });
  695. addFuncDef({
  696. name: 'mapSeries',
  697. shortName: 'map',
  698. params: [{ name: 'node', type: 'int' }],
  699. defaultParams: [3],
  700. category: 'Combine',
  701. version: '1.0',
  702. });
  703. addFuncDef({
  704. name: 'movingMin',
  705. category: 'Calculate',
  706. params: [
  707. {
  708. name: 'windowSize',
  709. type: 'int_or_interval',
  710. options: ['5', '7', '10', '5min', '10min', '30min', '1hour'],
  711. },
  712. ],
  713. defaultParams: [10],
  714. version: '1.0',
  715. });
  716. addFuncDef({
  717. name: 'movingMax',
  718. category: 'Calculate',
  719. params: [
  720. {
  721. name: 'windowSize',
  722. type: 'int_or_interval',
  723. options: ['5', '7', '10', '5min', '10min', '30min', '1hour'],
  724. },
  725. ],
  726. defaultParams: [10],
  727. version: '1.0',
  728. });
  729. addFuncDef({
  730. name: 'movingSum',
  731. category: 'Calculate',
  732. params: [
  733. {
  734. name: 'windowSize',
  735. type: 'int_or_interval',
  736. options: ['5', '7', '10', '5min', '10min', '30min', '1hour'],
  737. },
  738. ],
  739. defaultParams: [10],
  740. version: '1.0',
  741. });
  742. addFuncDef({
  743. name: 'multiplySeriesWithWildcards',
  744. category: 'Combine',
  745. params: [
  746. {
  747. name: 'position',
  748. type: 'int',
  749. options: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12],
  750. multiple: true,
  751. },
  752. ],
  753. defaultParams: [2],
  754. version: '1.0',
  755. });
  756. addFuncDef({
  757. name: 'offsetToZero',
  758. category: 'Transform',
  759. version: '1.0',
  760. });
  761. addFuncDef({
  762. name: 'pow',
  763. category: 'Transform',
  764. params: [{ name: 'factor', type: 'int' }],
  765. defaultParams: [10],
  766. version: '1.0',
  767. });
  768. addFuncDef({
  769. name: 'powSeries',
  770. category: 'Transform',
  771. params: optionalSeriesRefArgs,
  772. defaultParams: [''],
  773. version: '1.0',
  774. });
  775. addFuncDef({
  776. name: 'reduceSeries',
  777. shortName: 'reduce',
  778. params: [
  779. {
  780. name: 'function',
  781. type: 'string',
  782. options: ['asPercent', 'diffSeries', 'divideSeries'],
  783. },
  784. {
  785. name: 'reduceNode',
  786. type: 'int',
  787. options: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],
  788. },
  789. { name: 'reduceMatchers', type: 'string', multiple: true },
  790. ],
  791. defaultParams: ['asPercent', 2, 'used_bytes'],
  792. category: 'Combine',
  793. version: '1.0',
  794. });
  795. addFuncDef({
  796. name: 'removeBetweenPercentile',
  797. category: 'Filter Series',
  798. params: [{ name: 'n', type: 'int' }],
  799. defaultParams: [95],
  800. version: '1.0',
  801. });
  802. addFuncDef({
  803. name: 'removeEmptySeries',
  804. category: 'Filter Series',
  805. version: '1.0',
  806. });
  807. addFuncDef({
  808. name: 'squareRoot',
  809. category: 'Transform',
  810. version: '1.0',
  811. });
  812. addFuncDef({
  813. name: 'timeSlice',
  814. category: 'Transform',
  815. params: [
  816. {
  817. name: 'startSliceAt',
  818. type: 'select',
  819. options: ['-1h', '-6h', '-12h', '-1d', '-2d', '-7d', '-14d', '-30d'],
  820. },
  821. {
  822. name: 'endSliceAt',
  823. type: 'select',
  824. options: ['-1h', '-6h', '-12h', '-1d', '-2d', '-7d', '-14d', '-30d'],
  825. optional: true,
  826. },
  827. ],
  828. defaultParams: ['-1h'],
  829. version: '1.0',
  830. });
  831. addFuncDef({
  832. name: 'weightedAverage',
  833. category: 'Combine',
  834. params: [
  835. { name: 'other', type: 'value_or_series', optional: true },
  836. {
  837. name: 'node',
  838. type: 'int',
  839. options: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12],
  840. },
  841. ],
  842. defaultParams: ['#A', 4],
  843. version: '1.0',
  844. });
  845. addFuncDef({
  846. name: 'seriesByTag',
  847. category: 'Special',
  848. params: [{ name: 'tagExpression', type: 'string', multiple: true }],
  849. version: '1.1',
  850. });
  851. addFuncDef({
  852. name: 'groupByTags',
  853. category: 'Combine',
  854. params: [
  855. {
  856. name: 'function',
  857. type: 'string',
  858. options: ['sum', 'avg', 'maxSeries'],
  859. },
  860. { name: 'tag', type: 'string', multiple: true },
  861. ],
  862. defaultParams: ['sum', 'tag'],
  863. version: '1.1',
  864. });
  865. addFuncDef({
  866. name: 'aliasByTags',
  867. category: 'Alias',
  868. params: [{ name: 'tag', type: 'string', multiple: true }],
  869. defaultParams: ['tag'],
  870. version: '1.1',
  871. });
  872. function isVersionRelatedFunction(obj: { version?: string }, graphiteVersion: string) {
  873. return !obj.version || isVersionGtOrEq(graphiteVersion, obj.version);
  874. }
  875. export class FuncInstance {
  876. def: FuncDef;
  877. params: Array<string | number>;
  878. text: any;
  879. /**
  880. * True if this function was just added and not edited yet. It's used to focus on first
  881. * function param to edit it straight away after adding a function.
  882. */
  883. declare added: boolean;
  884. /**
  885. * Hidden functions are not displayed in UI but available in text editor
  886. * This is used for seriesByTagUsed function which when used switches
  887. * the editor to tag-only mode. Defined tags are provided to seriesByTagUsed
  888. * as parameters.
  889. */
  890. hidden?: boolean;
  891. constructor(funcDef: FuncDef, options?: { withDefaultParams: any }) {
  892. this.def = funcDef;
  893. this.params = [];
  894. if (options && options.withDefaultParams && funcDef.defaultParams) {
  895. this.params = funcDef.defaultParams.slice(0);
  896. }
  897. this.updateText();
  898. }
  899. render(metricExp: string, replaceVariables: InterpolateFunction): string {
  900. const str = this.def.name + '(';
  901. const parameters = map(this.params, (value, index) => {
  902. let paramType;
  903. if (index < this.def.params.length) {
  904. paramType = this.def.params[index].type;
  905. } else if (get(last(this.def.params), 'multiple')) {
  906. paramType = get(last(this.def.params), 'type');
  907. }
  908. // param types that should never be quoted
  909. if (includes(['value_or_series', 'boolean', 'int', 'float', 'node', 'int_or_infinity'], paramType)) {
  910. return value;
  911. }
  912. const valueInterpolated = isString(value) ? replaceVariables(value) : value;
  913. // param types that might be quoted
  914. // To quote variables correctly we need to interpolate it to check if it contains a numeric or string value
  915. if (includes(['int_or_interval', 'node_or_tag'], paramType) && isFinite(+valueInterpolated)) {
  916. return toString(value);
  917. }
  918. return "'" + value + "'";
  919. });
  920. // don't send any blank parameters to graphite
  921. while (parameters[parameters.length - 1] === '') {
  922. parameters.pop();
  923. }
  924. if (metricExp) {
  925. parameters.unshift(metricExp);
  926. }
  927. return str + parameters.join(', ') + ')';
  928. }
  929. _hasMultipleParamsInString(strValue: any, index: number) {
  930. if (strValue.indexOf(',') === -1) {
  931. return false;
  932. }
  933. if (this.def.params[index + 1] && this.def.params[index + 1].optional) {
  934. return true;
  935. }
  936. if (index + 1 >= this.def.params.length && get(last(this.def.params), 'multiple')) {
  937. return true;
  938. }
  939. return false;
  940. }
  941. updateParam(strValue: any, index: any) {
  942. // handle optional parameters
  943. // if string contains ',' and next param is optional, split and update both
  944. if (this._hasMultipleParamsInString(strValue, index)) {
  945. each(strValue.split(','), (partVal, idx) => {
  946. this.updateParam(partVal.trim(), index + idx);
  947. });
  948. return;
  949. }
  950. if (strValue === '' && (index >= this.def.params.length || this.def.params[index].optional)) {
  951. this.params.splice(index, 1);
  952. } else {
  953. this.params[index] = strValue;
  954. }
  955. this.updateText();
  956. }
  957. updateText() {
  958. if (this.params.length === 0) {
  959. this.text = this.def.name + '()';
  960. return;
  961. }
  962. let text = this.def.name + '(';
  963. text += this.params.join(', ');
  964. text += ')';
  965. this.text = text;
  966. }
  967. }
  968. function createFuncInstance(funcDef: any, options?: { withDefaultParams: any }, idx?: any): FuncInstance {
  969. if (isString(funcDef)) {
  970. funcDef = getFuncDef(funcDef, idx);
  971. }
  972. return new FuncInstance(funcDef, options);
  973. }
  974. function getFuncDef(name: string, idx?: any): FuncDef {
  975. if (!(idx || index)[name]) {
  976. return { name: name, params: [{ name: '', type: '', multiple: true }], defaultParams: [''], unknown: true };
  977. }
  978. return (idx || index)[name];
  979. }
  980. function getFuncDefs(graphiteVersion: string, idx?: any): FuncDefs {
  981. const funcs: FuncDefs = {};
  982. forEach(idx || index, (funcDef: FuncDef) => {
  983. if (isVersionRelatedFunction(funcDef, graphiteVersion)) {
  984. funcs[funcDef.name] = assign({}, funcDef, {
  985. params: filter(funcDef.params, (param) => {
  986. return isVersionRelatedFunction(param, graphiteVersion);
  987. }),
  988. });
  989. }
  990. });
  991. return funcs;
  992. }
  993. // parse response from graphite /functions endpoint into internal format
  994. function parseFuncDefs(rawDefs: any): FuncDefs {
  995. const funcDefs: FuncDefs = {};
  996. forEach(rawDefs || {}, (funcDef, funcName) => {
  997. // skip graphite graph functions
  998. if (funcDef.group === 'Graph') {
  999. return;
  1000. }
  1001. let description = funcDef.description;
  1002. if (description) {
  1003. // tidy up some pydoc syntax that rst2html can't handle
  1004. description = description
  1005. .replace(/:py:func:`(.+)( <[^>]*>)?`/g, '``$1``')
  1006. .replace(/.. seealso:: /g, 'See also: ')
  1007. .replace(/.. code-block *:: *none/g, '.. code-block::');
  1008. }
  1009. const func: FuncDef = {
  1010. name: funcDef.name,
  1011. description,
  1012. category: funcDef.group,
  1013. params: [],
  1014. defaultParams: [],
  1015. fake: false,
  1016. };
  1017. // get rid of the first "seriesList" param
  1018. if (/^seriesLists?$/.test(get(funcDef, 'params[0].type', ''))) {
  1019. // handle functions that accept multiple seriesLists
  1020. // we leave the param in place but mark it optional, so users can add more series if they wish
  1021. if (funcDef.params[0].multiple) {
  1022. funcDef.params[0].required = false;
  1023. // otherwise chop off the first param, it'll be handled separately
  1024. } else {
  1025. funcDef.params.shift();
  1026. }
  1027. // tag function as fake
  1028. } else {
  1029. func.fake = true;
  1030. }
  1031. forEach(funcDef.params, (rawParam) => {
  1032. const param: any = {
  1033. name: rawParam.name,
  1034. type: 'string',
  1035. optional: !rawParam.required,
  1036. multiple: !!rawParam.multiple,
  1037. options: undefined,
  1038. };
  1039. if (rawParam.default !== undefined) {
  1040. if (rawParam.default === Infinity) {
  1041. func.defaultParams.push('inf');
  1042. } else {
  1043. func.defaultParams.push(toString(rawParam.default));
  1044. }
  1045. } else if (rawParam.suggestions) {
  1046. func.defaultParams.push(toString(rawParam.suggestions[0]));
  1047. } else {
  1048. func.defaultParams.push('');
  1049. }
  1050. if (rawParam.type === 'boolean') {
  1051. param.type = 'boolean';
  1052. param.options = ['true', 'false'];
  1053. } else if (rawParam.type === 'integer') {
  1054. param.type = 'int';
  1055. } else if (rawParam.type === 'float') {
  1056. param.type = 'float';
  1057. } else if (rawParam.type === 'node') {
  1058. param.type = 'node';
  1059. param.options = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'];
  1060. } else if (rawParam.type === 'nodeOrTag') {
  1061. param.type = 'node_or_tag';
  1062. param.options = ['name', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'];
  1063. } else if (rawParam.type === 'intOrInterval') {
  1064. param.type = 'int_or_interval';
  1065. } else if (rawParam.type === 'seriesList') {
  1066. param.type = 'value_or_series';
  1067. } else if (rawParam.type === 'intOrInf') {
  1068. param.type = 'int_or_infinity';
  1069. }
  1070. if (rawParam.options) {
  1071. param.options = map(rawParam.options, toString);
  1072. } else if (rawParam.suggestions) {
  1073. param.options = map(rawParam.suggestions, toString);
  1074. }
  1075. func.params.push(param);
  1076. });
  1077. funcDefs[funcName] = func;
  1078. });
  1079. return funcDefs;
  1080. }
  1081. export default {
  1082. createFuncInstance: createFuncInstance,
  1083. getFuncDef: getFuncDef,
  1084. getFuncDefs: getFuncDefs,
  1085. parseFuncDefs: parseFuncDefs,
  1086. };