kbn.ts 7.7 KB

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