kbn.ts 7.6 KB

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