summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSarah Yasonik <syasonik@gitlab.com>2019-04-05 20:41:31 +0000
committerClement Ho <clemmakesapps@gmail.com>2019-04-05 20:41:31 +0000
commitf44737e453a35ef7361cd90af2b5a5ae09473992 (patch)
tree53a3489b547a4d605a59890e9e9fdd74e809e77a
parenta5eb29c16045f5ae96ad107474f8fde974c3197e (diff)
downloadgitlab-ce-f44737e453a35ef7361cd90af2b5a5ae09473992.tar.gz
Support multiple queries per chart on metrics dash
Adding support for metrics alerts disabled multiple query support. To avoid a data model refactor, this enables the visual of multiple queries per chart on the front end, combining queries based on metric group, title, and y-axis label. This also adds support for adding and editing alerts based on the query selected rather than the single metric associated with the chart.
-rw-r--r--app/assets/javascripts/monitoring/components/charts/area.vue14
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard.vue20
-rw-r--r--app/assets/javascripts/monitoring/stores/monitoring_store.js39
-rw-r--r--changelogs/unreleased/minimized-multiple-queries-ce.yml5
-rw-r--r--package.json2
-rw-r--r--spec/javascripts/monitoring/charts/area_spec.js7
-rw-r--r--yarn.lock8
7 files changed, 74 insertions, 21 deletions
diff --git a/app/assets/javascripts/monitoring/components/charts/area.vue b/app/assets/javascripts/monitoring/components/charts/area.vue
index b0bbe272d1f..eb2ab3e135e 100644
--- a/app/assets/javascripts/monitoring/components/charts/area.vue
+++ b/app/assets/javascripts/monitoring/components/charts/area.vue
@@ -42,10 +42,10 @@ export default {
required: false,
default: () => [],
},
- alertData: {
- type: Object,
+ thresholds: {
+ type: Array,
required: false,
- default: () => ({}),
+ default: () => [],
},
},
data() {
@@ -64,6 +64,9 @@ export default {
},
computed: {
chartData() {
+ // Transforms & supplements query data to render appropriate labels & styles
+ // Input: [{ queryAttributes1 }, { queryAttributes2 }]
+ // Output: [{ seriesAttributes1 }, { seriesAttributes2 }]
return this.graphData.queries.reduce((acc, query) => {
const { appearance } = query;
const lineType =
@@ -121,6 +124,9 @@ export default {
},
earliestDatapoint() {
return this.chartData.reduce((acc, series) => {
+ if (!series.data.length) {
+ return acc;
+ }
const [[timestamp]] = series.data.sort(([a], [b]) => {
if (a < b) {
return -1;
@@ -235,7 +241,7 @@ export default {
:data="chartData"
:option="chartOptions"
:format-tooltip-text="formatTooltipText"
- :thresholds="alertData"
+ :thresholds="thresholds"
:width="width"
:height="height"
@updated="onChartUpdated"
diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue
index ba6a17827f7..f5019bc627e 100644
--- a/app/assets/javascripts/monitoring/components/dashboard.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard.vue
@@ -1,5 +1,6 @@
<script>
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import _ from 'underscore';
import { s__ } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
import '~/vue_shared/mixins/is_ee';
@@ -142,8 +143,13 @@ export default {
}
},
methods: {
- getGraphAlerts(graphId) {
- return this.alertData ? this.alertData[graphId] || {} : {};
+ getGraphAlerts(queries) {
+ if (!this.allAlerts) return {};
+ const metricIdsForChart = queries.map(q => q.metricId);
+ return _.pick(this.allAlerts, alert => metricIdsForChart.includes(alert.metricId));
+ },
+ getGraphAlertValues(queries) {
+ return Object.values(this.getGraphAlerts(queries));
},
getGraphsData() {
this.state = 'loading';
@@ -199,17 +205,15 @@ export default {
:key="graphIndex"
:graph-data="graphData"
:deployment-data="store.deploymentData"
- :alert-data="getGraphAlerts(graphData.id)"
+ :thresholds="getGraphAlertValues(graphData.queries)"
:container-width="elWidth"
group-id="monitor-area-chart"
>
<alert-widget
- v-if="isEE && prometheusAlertsAvailable && alertsEndpoint && graphData.id"
+ v-if="isEE && prometheusAlertsAvailable && alertsEndpoint && graphData"
:alerts-endpoint="alertsEndpoint"
- :label="getGraphLabel(graphData)"
- :current-alerts="getQueryAlerts(graphData)"
- :custom-metric-id="graphData.id"
- :alert-data="alertData[graphData.id]"
+ :relevant-queries="graphData.queries"
+ :alerts-to-manage="getGraphAlerts(graphData.queries)"
@setAlerts="setAlerts"
/>
</monitor-area-chart>
diff --git a/app/assets/javascripts/monitoring/stores/monitoring_store.js b/app/assets/javascripts/monitoring/stores/monitoring_store.js
index 70635059bd9..9761fe168be 100644
--- a/app/assets/javascripts/monitoring/stores/monitoring_store.js
+++ b/app/assets/javascripts/monitoring/stores/monitoring_store.js
@@ -27,10 +27,47 @@ function removeTimeSeriesNoData(queries) {
return queries.reduce((series, query) => series.concat(checkQueryEmptyData(query)), []);
}
+// Metrics and queries are currently stored 1:1, so `queries` is an array of length one.
+// We want to group queries onto a single chart by title & y-axis label.
+// This function will no longer be required when metrics:queries are 1:many,
+// though there is no consequence if the function stays in use.
+// @param metrics [Array<Object>]
+// Ex) [
+// { id: 1, title: 'title', y_label: 'MB', queries: [{ ...query1Attrs }] },
+// { id: 2, title: 'title', y_label: 'MB', queries: [{ ...query2Attrs }] },
+// { id: 3, title: 'new title', y_label: 'MB', queries: [{ ...query3Attrs }] }
+// ]
+// @return [Array<Object>]
+// Ex) [
+// { title: 'title', y_label: 'MB', queries: [{ metricId: 1, ...query1Attrs },
+// { metricId: 2, ...query2Attrs }] },
+// { title: 'new title', y_label: 'MB', queries: [{ metricId: 3, ...query3Attrs }]}
+// ]
+function groupQueriesByChartInfo(metrics) {
+ const metricsByChart = metrics.reduce((accumulator, metric) => {
+ const { id, queries, ...chart } = metric;
+
+ const chartKey = `${chart.title}|${chart.y_label}`;
+ accumulator[chartKey] = accumulator[chartKey] || { ...chart, queries: [] };
+
+ queries.forEach(queryAttrs =>
+ accumulator[chartKey].queries.push({ metricId: id.toString(), ...queryAttrs }),
+ );
+
+ return accumulator;
+ }, {});
+
+ return Object.values(metricsByChart);
+}
+
function normalizeMetrics(metrics) {
- return metrics.map(metric => {
+ const groupedMetrics = groupQueriesByChartInfo(metrics);
+
+ return groupedMetrics.map(metric => {
const queries = metric.queries.map(query => ({
...query,
+ // custom metrics do not require a label, so we should ensure this attribute is defined
+ label: query.label || metric.y_label,
result: query.result.map(result => ({
...result,
values: result.values.map(([timestamp, value]) => [
diff --git a/changelogs/unreleased/minimized-multiple-queries-ce.yml b/changelogs/unreleased/minimized-multiple-queries-ce.yml
new file mode 100644
index 00000000000..d8c20d492d6
--- /dev/null
+++ b/changelogs/unreleased/minimized-multiple-queries-ce.yml
@@ -0,0 +1,5 @@
+---
+title: Support multiple queries per chart on metrics dash
+merge_request: 25758
+author:
+type: added
diff --git a/package.json b/package.json
index 74de09010d4..ac8f6bd0db5 100644
--- a/package.json
+++ b/package.json
@@ -34,7 +34,7 @@
"@babel/preset-env": "^7.3.1",
"@gitlab/csslab": "^1.9.0",
"@gitlab/svgs": "^1.58.0",
- "@gitlab/ui": "^3.0.0",
+ "@gitlab/ui": "^3.0.1",
"apollo-cache-inmemory": "^1.5.1",
"apollo-client": "^2.5.1",
"apollo-upload-client": "^10.0.0",
diff --git a/spec/javascripts/monitoring/charts/area_spec.js b/spec/javascripts/monitoring/charts/area_spec.js
index 549a7935c0f..4ff519ae0e7 100644
--- a/spec/javascripts/monitoring/charts/area_spec.js
+++ b/spec/javascripts/monitoring/charts/area_spec.js
@@ -65,7 +65,7 @@ describe('Area component', () => {
expect(props.data).toBe(areaChart.vm.chartData);
expect(props.option).toBe(areaChart.vm.chartOptions);
expect(props.formatTooltipText).toBe(areaChart.vm.formatTooltipText);
- expect(props.thresholds).toBe(areaChart.props('alertData'));
+ expect(props.thresholds).toBe(areaChart.vm.thresholds);
});
it('recieves a tooltip title', () => {
@@ -105,12 +105,13 @@ describe('Area component', () => {
seriesName: areaChart.vm.chartData[0].name,
componentSubType: type,
value: [mockDate, 5.55555],
+ seriesIndex: 0,
},
],
value: mockDate,
});
- describe('series is of line type', () => {
+ describe('when series is of line type', () => {
beforeEach(() => {
areaChart.vm.formatTooltipText(generateSeriesData('line'));
});
@@ -131,7 +132,7 @@ describe('Area component', () => {
});
});
- describe('series is of scatter type', () => {
+ describe('when series is of scatter type', () => {
beforeEach(() => {
areaChart.vm.formatTooltipText(generateSeriesData('scatter'));
});
diff --git a/yarn.lock b/yarn.lock
index cd420b81ad6..80f25897670 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -663,10 +663,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.58.0.tgz#bb05263ff2eb7ca09a25cd14d0b1a932d2ea9c2f"
integrity sha512-RlWSjjBT4lMIFuNC1ziCO1nws9zqZtxCjhrqK2DxDDTgp2W0At9M/BFkHp8RHyMCrO3g1fHTrLPUgzr5oR3Epg==
-"@gitlab/ui@^3.0.0":
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-3.0.0.tgz#33ca2808dbd4395e69a366a219d1edc1f3dbccd5"
- integrity sha512-pDEa2k6ln5GE/N2z0V7dNEeFtSTW0p9ipO2/N9q6QMxO7fhhOhpMC0QVbdIljKTbglspDWI5v6BcqUjzYri5Pg==
+"@gitlab/ui@^3.0.1":
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-3.0.2.tgz#29a17699751261657487b939c651c0f93264df2a"
+ integrity sha512-JZhcS5cDxtpxopTc55UWvUbZAwKvxygYHT9I01QmUtKgaKIJlnjBj8zkcg1xHazX7raSjjtjqfDEla39a+luuQ==
dependencies:
"@babel/standalone" "^7.0.0"
bootstrap-vue "^2.0.0-rc.11"