All files / app/assets/javascripts/monitoring/components/charts options.js

100% Statements 48/48
91.18% Branches 31/34
100% Functions 12/12
100% Lines 45/45

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176            16x       16x   16x   16x 16x   16x 16x     16x 16x 16x               16x                             16x 232x 232x         5x                 16x         232x                         16x     283x       2123x                       226x             16x       10x 10x                             16x 73x 73x           73x 25x     48x   93x   48x     72x 8x 64x 64x     72x     48x     46x 2x   44x     46x     48x     48x       48x    
import { isFinite, uniq, sortBy, includes } from 'lodash';
import { SUPPORTED_FORMATS, getFormatter } from '~/lib/utils/unit_format';
import { __, s__ } from '~/locale';
import { thresholdModeTypes } from '../../constants';
import { formatDate, timezones, formats } from '../../format_date';
 
const yAxisBoundaryGap = [0.1, 0.1];
/**
 * Max string length of formatted axis tick
 */
const maxDataAxisTickLength = 8;
//  Defaults
const defaultFormat = SUPPORTED_FORMATS.engineering;
 
const defaultYAxisFormat = defaultFormat;
const defaultYAxisPrecision = 2;
 
const defaultTooltipFormat = defaultFormat;
const defaultTooltipPrecision = 3;
 
// Give enough space for y-axis with units and name.
const chartGridLeft = 63; // larger gap than gitlab-ui's default to fit formatted numbers
const chartGridRight = 10; // half of the scroll-handle icon for data zoom
const yAxisNameGap = chartGridLeft - 12; // offset the axis label line-height
 
// Axis options
 
/**
 * Axis types
 * @see https://echarts.apache.org/en/option.html#xAxis.type
 */
export const axisTypes = {
  /**
   * Category axis, suitable for discrete category data.
   */
  category: 'category',
  /**
   *  Time axis, suitable for continuous time series data.
   */
  time: 'time',
};
 
/**
 * Converts .yml parameters to echarts axis options for data axis
 * @param {Object} param - Dashboard .yml definition options
 */
const getDataAxisOptions = ({ format, precision, name }) => {
  const formatter = getFormatter(format); // default to engineeringNotation, same as gitlab-ui
  return {
    name,
    nameLocation: 'center', // same as gitlab-ui's default
    scale: true,
    axisLabel: {
      formatter: (val) => formatter(val, precision, maxDataAxisTickLength),
    },
  };
};
 
/**
 * Converts .yml parameters to echarts y-axis options
 * @param {Object} param - Dashboard .yml definition options
 */
export const getYAxisOptions = ({
  name = s__('Metrics|Values'),
  format = defaultYAxisFormat,
  precision = defaultYAxisPrecision,
} = {}) => {
  return {
    nameGap: yAxisNameGap,
    scale: true,
    boundaryGap: yAxisBoundaryGap,
 
    ...getDataAxisOptions({
      name,
      format,
      precision,
    }),
  };
};
 
export const getTimeAxisOptions = ({
  timezone = timezones.LOCAL,
  format = formats.shortDateTime,
} = {}) => ({
  name: __('Time'),
  type: axisTypes.time,
  axisLabel: {
    formatter: (date) => formatDate(date, { format, timezone }),
  },
  axisPointer: {
    snap: false,
  },
});
 
// Chart grid
 
/**
 * Grid with enough room to display chart.
 */
export const getChartGrid = ({ left = chartGridLeft, right = chartGridRight } = {}) => ({
  left,
  right,
});
 
// Tooltip options
 
export const getTooltipFormatter = ({
  format = defaultTooltipFormat,
  precision = defaultTooltipPrecision,
} = {}) => {
  const formatter = getFormatter(format);
  return (num) => formatter(num, precision);
};
 
// Thresholds
 
/**
 *
 * Used to find valid thresholds for the gauge chart
 *
 * An array of thresholds values is
 * - duplicate values are removed;
 * - filtered for invalid values;
 * - sorted in ascending order;
 * - only first two values are used.
 */
export const getValidThresholds = ({ mode, range = {}, values = [] } = {}) => {
  const supportedModes = [thresholdModeTypes.ABSOLUTE, thresholdModeTypes.PERCENTAGE];
  const { min, max } = range;
 
  /**
   * return early if min and max have invalid values
   * or mode has invalid value
   */
  if (!isFinite(min) || !isFinite(max) || min >= max || !includes(supportedModes, mode)) {
    return [];
  }
 
  const uniqueThresholds = uniq(values);
 
  const numberThresholds = uniqueThresholds.filter((threshold) => isFinite(threshold));
 
  const validThresholds = numberThresholds.filter((threshold) => {
    let isValid;
 
    if (mode === thresholdModeTypes.PERCENTAGE) {
      isValid = threshold > 0 && threshold < 100;
    } else Eif (mode === thresholdModeTypes.ABSOLUTE) {
      isValid = threshold > min && threshold < max;
    }
 
    return isValid;
  });
 
  const transformedThresholds = validThresholds.map((threshold) => {
    let transformedThreshold;
 
    if (mode === 'percentage') {
      transformedThreshold = (threshold / 100) * (max - min);
    } else {
      transformedThreshold = threshold;
    }
 
    return transformedThreshold;
  });
 
  const sortedThresholds = sortBy(transformedThresholds);
 
  const reducedThresholdsArray =
    sortedThresholds.length > 2
      ? [sortedThresholds[0], sortedThresholds[1]]
      : [...sortedThresholds];
 
  return reducedThresholdsArray;
};