utils.ts 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. import { valid, gte } from 'semver';
  2. import {
  3. isMetricAggregationWithField,
  4. MetricAggregation,
  5. MetricAggregationWithInlineScript,
  6. } from './components/QueryEditor/MetricAggregationsEditor/aggregations';
  7. import { metricAggregationConfig } from './components/QueryEditor/MetricAggregationsEditor/utils';
  8. export const describeMetric = (metric: MetricAggregation) => {
  9. if (!isMetricAggregationWithField(metric)) {
  10. return metricAggregationConfig[metric.type].label;
  11. }
  12. // TODO: field might be undefined
  13. return `${metricAggregationConfig[metric.type].label} ${metric.field}`;
  14. };
  15. /**
  16. * Utility function to clean up aggregations settings objects.
  17. * It removes nullish values and empty strings, array and objects
  18. * recursing over nested objects (not arrays).
  19. * @param obj
  20. */
  21. export const removeEmpty = <T>(obj: T): Partial<T> =>
  22. Object.entries(obj).reduce((acc, [key, value]) => {
  23. // Removing nullish values (null & undefined)
  24. if (value == null) {
  25. return { ...acc };
  26. }
  27. // Removing empty arrays (This won't recurse the array)
  28. if (Array.isArray(value) && value.length === 0) {
  29. return { ...acc };
  30. }
  31. // Removing empty strings
  32. if (value?.length === 0) {
  33. return { ...acc };
  34. }
  35. // Recursing over nested objects
  36. if (!Array.isArray(value) && typeof value === 'object') {
  37. const cleanObj = removeEmpty(value);
  38. if (Object.keys(cleanObj).length === 0) {
  39. return { ...acc };
  40. }
  41. return { ...acc, [key]: cleanObj };
  42. }
  43. return {
  44. ...acc,
  45. [key]: value,
  46. };
  47. }, {});
  48. /**
  49. * This function converts an order by string to the correct metric id For example,
  50. * if the user uses the standard deviation extended stat for the order by,
  51. * the value would be "1[std_deviation]" and this would return "1"
  52. */
  53. export const convertOrderByToMetricId = (orderBy: string): string | undefined => {
  54. const metricIdMatches = orderBy.match(/^(\d+)/);
  55. return metricIdMatches ? metricIdMatches[1] : void 0;
  56. };
  57. /** Gets the actual script value for metrics that support inline scripts.
  58. *
  59. * This is needed because the `script` is a bit polymorphic.
  60. * when creating a query with Grafana < 7.4 it was stored as:
  61. * ```json
  62. * {
  63. * "settings": {
  64. * "script": {
  65. * "inline": "value"
  66. * }
  67. * }
  68. * }
  69. * ```
  70. *
  71. * while from 7.4 it's stored as
  72. * ```json
  73. * {
  74. * "settings": {
  75. * "script": "value"
  76. * }
  77. * }
  78. * ```
  79. *
  80. * This allows us to access both formats and support both queries created before 7.4 and after.
  81. */
  82. export const getScriptValue = (metric: MetricAggregationWithInlineScript) =>
  83. (typeof metric.settings?.script === 'object' ? metric.settings?.script?.inline : metric.settings?.script) || '';
  84. /**
  85. * Coerces the a version string/number to a valid semver string.
  86. * It takes care of also converting from the legacy format (numeric) to the new one.
  87. * @param version
  88. */
  89. export const coerceESVersion = (version: string | number): string => {
  90. if (typeof version === 'string') {
  91. return valid(version) || '5.0.0';
  92. }
  93. switch (version) {
  94. case 2:
  95. return '2.0.0';
  96. case 56:
  97. return '5.6.0';
  98. case 60:
  99. return '6.0.0';
  100. case 70:
  101. return '7.0.0';
  102. case 5:
  103. default:
  104. return '5.0.0';
  105. }
  106. };
  107. export const isSupportedVersion = (version: string): boolean => {
  108. if (gte(version, '7.10.0')) {
  109. return true;
  110. }
  111. return false;
  112. };