summaryrefslogtreecommitdiff
path: root/app
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 /app
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.
Diffstat (limited to 'app')
-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
3 files changed, 60 insertions, 13 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]) => [