Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-08-07 00:10:15 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-08-07 00:10:15 +0300
commit0790cf032c70b3df250e1953a3a11b71d835c5a1 (patch)
treeca31b07a5623da26df1fa0323832c7896b5e3386 /app/assets/javascripts/monitoring
parent37419c44f04cd802ac89fe2d54b8501a0718a5e3 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/monitoring')
-rw-r--r--app/assets/javascripts/monitoring/components/charts/gauge.vue123
-rw-r--r--app/assets/javascripts/monitoring/components/charts/options.js64
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard_panel.vue7
-rw-r--r--app/assets/javascripts/monitoring/constants.js9
-rw-r--r--app/assets/javascripts/monitoring/stores/utils.js8
5 files changed, 210 insertions, 1 deletions
diff --git a/app/assets/javascripts/monitoring/components/charts/gauge.vue b/app/assets/javascripts/monitoring/components/charts/gauge.vue
new file mode 100644
index 00000000000..32834a1cb45
--- /dev/null
+++ b/app/assets/javascripts/monitoring/components/charts/gauge.vue
@@ -0,0 +1,123 @@
+<script>
+import { GlResizeObserverDirective } from '@gitlab/ui';
+import { GlGaugeChart } from '@gitlab/ui/dist/charts';
+import { graphDataValidatorForValues } from '../../utils';
+import { getValidThresholds } from './options';
+import { getFormatter, SUPPORTED_FORMATS } from '~/lib/utils/unit_format';
+
+import { isFinite, isArray, isInteger } from 'lodash';
+
+export default {
+ components: {
+ GlGaugeChart,
+ },
+ directives: {
+ GlResizeObserverDirective,
+ },
+ props: {
+ graphData: {
+ type: Object,
+ required: true,
+ validator: graphDataValidatorForValues.bind(null, true),
+ },
+ },
+ data() {
+ return {
+ width: 0,
+ };
+ },
+ computed: {
+ rangeValues() {
+ let min = 0;
+ let max = 100;
+
+ const { minValue, maxValue } = this.graphData;
+
+ const isValidMinMax = () => {
+ return isFinite(minValue) && isFinite(maxValue) && minValue < maxValue;
+ };
+
+ if (isValidMinMax()) {
+ min = minValue;
+ max = maxValue;
+ }
+
+ return {
+ min,
+ max,
+ };
+ },
+ validThresholds() {
+ const { mode, values } = this.graphData?.thresholds || {};
+ const range = this.rangeValues;
+
+ if (!isArray(values)) {
+ return [];
+ }
+
+ return getValidThresholds({ mode, range, values });
+ },
+ queryResult() {
+ return this.graphData?.metrics[0]?.result[0]?.value[1];
+ },
+ splitValue() {
+ const { split } = this.graphData;
+ const defaultValue = 10;
+
+ return isInteger(split) && split > 0 ? split : defaultValue;
+ },
+ textValue() {
+ const formatFromPanel = this.graphData.format;
+ const defaultFormat = SUPPORTED_FORMATS.engineering;
+ const format = SUPPORTED_FORMATS[formatFromPanel] ?? defaultFormat;
+ const { queryResult } = this;
+
+ const formatter = getFormatter(format);
+
+ return isFinite(queryResult) ? formatter(queryResult) : '--';
+ },
+ thresholdsValue() {
+ /**
+ * If there are no valid thresholds, a default threshold
+ * will be set at 90% of the gauge arcs' max value
+ */
+ const { min, max } = this.rangeValues;
+
+ const defaultThresholdValue = [(max - min) * 0.95];
+ return this.validThresholds.length ? this.validThresholds : defaultThresholdValue;
+ },
+ value() {
+ /**
+ * The gauge chart gitlab-ui component expects a value
+ * of type number.
+ *
+ * So, if the query result is undefined,
+ * we pass the gauge chart a value of NaN.
+ */
+ return this.queryResult || NaN;
+ },
+ },
+ methods: {
+ onResize() {
+ if (!this.$refs.gaugeChart) return;
+ const { width } = this.$refs.gaugeChart.$el.getBoundingClientRect();
+ this.width = width;
+ },
+ },
+};
+</script>
+<template>
+ <div v-gl-resize-observer-directive="onResize">
+ <gl-gauge-chart
+ ref="gaugeChart"
+ v-bind="$attrs"
+ :value="value"
+ :min="rangeValues.min"
+ :max="rangeValues.max"
+ :thresholds="thresholdsValue"
+ :text="textValue"
+ :split-number="splitValue"
+ :width="width"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/monitoring/components/charts/options.js b/app/assets/javascripts/monitoring/components/charts/options.js
index 42252dd5897..5cb16ddaf17 100644
--- a/app/assets/javascripts/monitoring/components/charts/options.js
+++ b/app/assets/javascripts/monitoring/components/charts/options.js
@@ -1,6 +1,8 @@
import { SUPPORTED_FORMATS, getFormatter } from '~/lib/utils/unit_format';
import { __, s__ } from '~/locale';
+import { isFinite, uniq, sortBy, includes } from 'lodash';
import { formatDate, timezones, formats } from '../../format_date';
+import { thresholdModeTypes } from '../../constants';
const yAxisBoundaryGap = [0.1, 0.1];
/**
@@ -109,3 +111,65 @@ export const getTooltipFormatter = ({
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 if (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;
+};
diff --git a/app/assets/javascripts/monitoring/components/dashboard_panel.vue b/app/assets/javascripts/monitoring/components/dashboard_panel.vue
index 610bef37fdb..a75f01c12df 100644
--- a/app/assets/javascripts/monitoring/components/dashboard_panel.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard_panel.vue
@@ -22,6 +22,7 @@ import MonitorEmptyChart from './charts/empty_chart.vue';
import MonitorTimeSeriesChart from './charts/time_series.vue';
import MonitorAnomalyChart from './charts/anomaly.vue';
import MonitorSingleStatChart from './charts/single_stat.vue';
+import MonitorGaugeChart from './charts/gauge.vue';
import MonitorHeatmapChart from './charts/heatmap.vue';
import MonitorColumnChart from './charts/column.vue';
import MonitorBarChart from './charts/bar.vue';
@@ -170,6 +171,9 @@ export default {
if (this.isPanelType(panelTypes.SINGLE_STAT)) {
return MonitorSingleStatChart;
}
+ if (this.isPanelType(panelTypes.GAUGE_CHART)) {
+ return MonitorGaugeChart;
+ }
if (this.isPanelType(panelTypes.HEATMAP)) {
return MonitorHeatmapChart;
}
@@ -215,7 +219,8 @@ export default {
return (
this.isPanelType(panelTypes.AREA_CHART) ||
this.isPanelType(panelTypes.LINE_CHART) ||
- this.isPanelType(panelTypes.SINGLE_STAT)
+ this.isPanelType(panelTypes.SINGLE_STAT) ||
+ this.isPanelType(panelTypes.GAUGE_CHART)
);
},
editCustomMetricLink() {
diff --git a/app/assets/javascripts/monitoring/constants.js b/app/assets/javascripts/monitoring/constants.js
index 2ddee67db8c..7835050d033 100644
--- a/app/assets/javascripts/monitoring/constants.js
+++ b/app/assets/javascripts/monitoring/constants.js
@@ -87,6 +87,10 @@ export const panelTypes = {
*/
SINGLE_STAT: 'single-stat',
/**
+ * Gauge
+ */
+ GAUGE_CHART: 'gauge-chart',
+ /**
* Heatmap
*/
HEATMAP: 'heatmap',
@@ -272,3 +276,8 @@ export const keyboardShortcutKeys = {
DOWNLOAD_CSV: 'd',
CHART_COPY: 'c',
};
+
+export const thresholdModeTypes = {
+ ABSOLUTE: 'absolute',
+ PERCENTAGE: 'percentage',
+};
diff --git a/app/assets/javascripts/monitoring/stores/utils.js b/app/assets/javascripts/monitoring/stores/utils.js
index 29c477c2c41..df7f22e622f 100644
--- a/app/assets/javascripts/monitoring/stores/utils.js
+++ b/app/assets/javascripts/monitoring/stores/utils.js
@@ -176,7 +176,11 @@ export const mapPanelToViewModel = ({
field,
metrics = [],
links = [],
+ min_value,
max_value,
+ split,
+ thresholds,
+ format,
}) => {
// Both `x_axis.name` and `x_label` are supported for now
// https://gitlab.com/gitlab-org/gitlab/issues/210521
@@ -195,7 +199,11 @@ export const mapPanelToViewModel = ({
yAxis,
xAxis,
field,
+ minValue: min_value,
maxValue: max_value,
+ split,
+ thresholds,
+ format,
links: links.map(mapLinksToViewModel),
metrics: mapToMetricsViewModel(metrics),
};