kbn.ts 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. import _ from 'lodash';
  2. import { getValueFormat, getValueFormatterIndex, getValueFormats } from '@grafana/ui';
  3. const kbn: any = {};
  4. kbn.valueFormats = {};
  5. kbn.regexEscape = value => {
  6. return value.replace(/[\\^$*+?.()|[\]{}\/]/g, '\\$&');
  7. };
  8. ///// HELPER FUNCTIONS /////
  9. kbn.round_interval = interval => {
  10. switch (true) {
  11. // 0.015s
  12. case interval < 15:
  13. return 10; // 0.01s
  14. // 0.035s
  15. case interval < 35:
  16. return 20; // 0.02s
  17. // 0.075s
  18. case interval < 75:
  19. return 50; // 0.05s
  20. // 0.15s
  21. case interval < 150:
  22. return 100; // 0.1s
  23. // 0.35s
  24. case interval < 350:
  25. return 200; // 0.2s
  26. // 0.75s
  27. case interval < 750:
  28. return 500; // 0.5s
  29. // 1.5s
  30. case interval < 1500:
  31. return 1000; // 1s
  32. // 3.5s
  33. case interval < 3500:
  34. return 2000; // 2s
  35. // 7.5s
  36. case interval < 7500:
  37. return 5000; // 5s
  38. // 12.5s
  39. case interval < 12500:
  40. return 10000; // 10s
  41. // 17.5s
  42. case interval < 17500:
  43. return 15000; // 15s
  44. // 25s
  45. case interval < 25000:
  46. return 20000; // 20s
  47. // 45s
  48. case interval < 45000:
  49. return 30000; // 30s
  50. // 1.5m
  51. case interval < 90000:
  52. return 60000; // 1m
  53. // 3.5m
  54. case interval < 210000:
  55. return 120000; // 2m
  56. // 7.5m
  57. case interval < 450000:
  58. return 300000; // 5m
  59. // 12.5m
  60. case interval < 750000:
  61. return 600000; // 10m
  62. // 12.5m
  63. case interval < 1050000:
  64. return 900000; // 15m
  65. // 25m
  66. case interval < 1500000:
  67. return 1200000; // 20m
  68. // 45m
  69. case interval < 2700000:
  70. return 1800000; // 30m
  71. // 1.5h
  72. case interval < 5400000:
  73. return 3600000; // 1h
  74. // 2.5h
  75. case interval < 9000000:
  76. return 7200000; // 2h
  77. // 4.5h
  78. case interval < 16200000:
  79. return 10800000; // 3h
  80. // 9h
  81. case interval < 32400000:
  82. return 21600000; // 6h
  83. // 1d
  84. case interval < 86400000:
  85. return 43200000; // 12h
  86. // 1w
  87. case interval < 604800000:
  88. return 86400000; // 1d
  89. // 3w
  90. case interval < 1814400000:
  91. return 604800000; // 1w
  92. // 6w
  93. case interval < 3628800000:
  94. return 2592000000; // 30d
  95. default:
  96. return 31536000000; // 1y
  97. }
  98. };
  99. kbn.secondsToHms = seconds => {
  100. const numyears = Math.floor(seconds / 31536000);
  101. if (numyears) {
  102. return numyears + 'y';
  103. }
  104. const numdays = Math.floor((seconds % 31536000) / 86400);
  105. if (numdays) {
  106. return numdays + 'd';
  107. }
  108. const numhours = Math.floor(((seconds % 31536000) % 86400) / 3600);
  109. if (numhours) {
  110. return numhours + 'h';
  111. }
  112. const numminutes = Math.floor((((seconds % 31536000) % 86400) % 3600) / 60);
  113. if (numminutes) {
  114. return numminutes + 'm';
  115. }
  116. const numseconds = Math.floor((((seconds % 31536000) % 86400) % 3600) % 60);
  117. if (numseconds) {
  118. return numseconds + 's';
  119. }
  120. const nummilliseconds = Math.floor(seconds * 1000.0);
  121. if (nummilliseconds) {
  122. return nummilliseconds + 'ms';
  123. }
  124. return 'less than a millisecond'; //'just now' //or other string you like;
  125. };
  126. kbn.secondsToHhmmss = seconds => {
  127. const strings = [];
  128. const numhours = Math.floor(seconds / 3600);
  129. const numminutes = Math.floor((seconds % 3600) / 60);
  130. const numseconds = Math.floor((seconds % 3600) % 60);
  131. numhours > 9 ? strings.push('' + numhours) : strings.push('0' + numhours);
  132. numminutes > 9 ? strings.push('' + numminutes) : strings.push('0' + numminutes);
  133. numseconds > 9 ? strings.push('' + numseconds) : strings.push('0' + numseconds);
  134. return strings.join(':');
  135. };
  136. kbn.to_percent = (nr, outof) => {
  137. return Math.floor((nr / outof) * 10000) / 100 + '%';
  138. };
  139. kbn.addslashes = str => {
  140. str = str.replace(/\\/g, '\\\\');
  141. str = str.replace(/\'/g, "\\'");
  142. str = str.replace(/\"/g, '\\"');
  143. str = str.replace(/\0/g, '\\0');
  144. return str;
  145. };
  146. kbn.interval_regex = /(\d+(?:\.\d+)?)(ms|[Mwdhmsy])/;
  147. // histogram & trends
  148. kbn.intervals_in_seconds = {
  149. y: 31536000,
  150. M: 2592000,
  151. w: 604800,
  152. d: 86400,
  153. h: 3600,
  154. m: 60,
  155. s: 1,
  156. ms: 0.001,
  157. };
  158. kbn.calculateInterval = (range, resolution, lowLimitInterval) => {
  159. let lowLimitMs = 1; // 1 millisecond default low limit
  160. let intervalMs;
  161. if (lowLimitInterval) {
  162. if (lowLimitInterval[0] === '>') {
  163. lowLimitInterval = lowLimitInterval.slice(1);
  164. }
  165. lowLimitMs = kbn.interval_to_ms(lowLimitInterval);
  166. }
  167. intervalMs = kbn.round_interval((range.to.valueOf() - range.from.valueOf()) / resolution);
  168. if (lowLimitMs > intervalMs) {
  169. intervalMs = lowLimitMs;
  170. }
  171. return {
  172. intervalMs: intervalMs,
  173. interval: kbn.secondsToHms(intervalMs / 1000),
  174. };
  175. };
  176. kbn.describe_interval = str => {
  177. const matches = str.match(kbn.interval_regex);
  178. if (!matches || !_.has(kbn.intervals_in_seconds, matches[2])) {
  179. throw new Error('Invalid interval string, expecting a number followed by one of "Mwdhmsy"');
  180. } else {
  181. return {
  182. sec: kbn.intervals_in_seconds[matches[2]],
  183. type: matches[2],
  184. count: parseInt(matches[1], 10),
  185. };
  186. }
  187. };
  188. kbn.interval_to_ms = str => {
  189. const info = kbn.describe_interval(str);
  190. return info.sec * 1000 * info.count;
  191. };
  192. kbn.interval_to_seconds = str => {
  193. const info = kbn.describe_interval(str);
  194. return info.sec * info.count;
  195. };
  196. kbn.query_color_dot = (color, diameter) => {
  197. return (
  198. '<div class="icon-circle" style="' +
  199. ['display:inline-block', 'color:' + color, 'font-size:' + diameter + 'px'].join(';') +
  200. '"></div>'
  201. );
  202. };
  203. kbn.slugifyForUrl = str => {
  204. return str
  205. .toLowerCase()
  206. .replace(/[^\w ]+/g, '')
  207. .replace(/ +/g, '-');
  208. };
  209. kbn.stringToJsRegex = str => {
  210. if (str[0] !== '/') {
  211. return new RegExp('^' + str + '$');
  212. }
  213. const match = str.match(new RegExp('^/(.*?)/(g?i?m?y?)$'));
  214. if (!match) {
  215. throw new Error(`'${str}' is not a valid regular expression.`);
  216. }
  217. return new RegExp(match[1], match[2]);
  218. };
  219. kbn.toFixed = (value, decimals) => {
  220. if (value === null) {
  221. return '';
  222. }
  223. const factor = decimals ? Math.pow(10, Math.max(0, decimals)) : 1;
  224. const formatted = String(Math.round(value * factor) / factor);
  225. // if exponent return directly
  226. if (formatted.indexOf('e') !== -1 || value === 0) {
  227. return formatted;
  228. }
  229. // If tickDecimals was specified, ensure that we have exactly that
  230. // much precision; otherwise default to the value's own precision.
  231. if (decimals != null) {
  232. const decimalPos = formatted.indexOf('.');
  233. const precision = decimalPos === -1 ? 0 : formatted.length - decimalPos - 1;
  234. if (precision < decimals) {
  235. return (precision ? formatted : formatted + '.') + String(factor).substr(1, decimals - precision);
  236. }
  237. }
  238. return formatted;
  239. };
  240. kbn.toFixedScaled = (value, decimals, scaledDecimals, additionalDecimals, ext) => {
  241. if (scaledDecimals === null) {
  242. return kbn.toFixed(value, decimals) + ext;
  243. } else {
  244. return kbn.toFixed(value, scaledDecimals + additionalDecimals) + ext;
  245. }
  246. };
  247. kbn.roundValue = (num, decimals) => {
  248. if (num === null) {
  249. return null;
  250. }
  251. const n = Math.pow(10, decimals);
  252. const formatted = (n * num).toFixed(decimals);
  253. return Math.round(parseFloat(formatted)) / n;
  254. };
  255. ///// FORMAT MENU /////
  256. kbn.getUnitFormats = () => {
  257. return getValueFormats();
  258. };
  259. //
  260. // Backward compatible layer for value formats to support old plugins
  261. //
  262. if (typeof Proxy !== 'undefined') {
  263. kbn.valueFormats = new Proxy(kbn.valueFormats, {
  264. get(target, name, receiver) {
  265. if (typeof name !== 'string') {
  266. throw { message: `Value format ${String(name)} is not a string` };
  267. }
  268. const formatter = getValueFormat(name);
  269. if (formatter) {
  270. return formatter;
  271. }
  272. // default to look here
  273. return Reflect.get(target, name, receiver);
  274. },
  275. });
  276. } else {
  277. kbn.valueFormats = getValueFormatterIndex();
  278. }
  279. export default kbn;