summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Knox <psimyn@gmail.com>2019-05-02 12:15:24 +1000
committerSimon Knox <psimyn@gmail.com>2019-05-02 12:16:55 +1000
commit3b8c905cf314d451dadcc68b0104dd1b2384c2af (patch)
treed3847e5d1e613ba9f61f7a572ce07e11ae83dcc0
parent257805f1fee423be2a9ea46635ee956ae33e3def (diff)
downloadgitlab-ce-psimyn-science.tar.gz
Remove other chart types for now so area-chart displayspsimyn-science
When there is a v-if inside a v-for things do not go well
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard.vue22
-rw-r--r--app/assets/javascripts/monitoring/stores/actions.js19
-rw-r--r--app/assets/javascripts/monitoring/stores/getters.js106
-rw-r--r--app/assets/javascripts/monitoring/stores/mutations.js10
4 files changed, 111 insertions, 46 deletions
diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue
index 0a33fab99e5..294df5dc311 100644
--- a/app/assets/javascripts/monitoring/components/dashboard.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard.vue
@@ -198,7 +198,8 @@ export default {
this.showEmptyState = false;
})
- .catch(() => {
+ .catch((e) => {
+ console.error(e)
this.state = 'unableToConnect';
});
},
@@ -279,7 +280,6 @@ export default {
>
<template v-for="(graphData, graphIndex) in groupData.metrics">
<monitor-area-chart
- v-if="graphData.type === undefined || graphData.type === 'area'"
:key="`area-${graphIndex}`"
:graph-data="graphData"
:deployment-data="store.deploymentData"
@@ -295,24 +295,6 @@ export default {
@setAlerts="setAlerts"
/>
</monitor-area-chart>
- <single-stat-chart
- v-else-if="graphData.type === 'single_stat'"
- :key="`single-stat-${graphIndex}`"
- value="100"
- unit="ms"
- title="latency"
- />
- <line-chart
- v-else-if="graphData.type === 'line_chart'"
- :key="`line-${graphIndex}`"
- :graph-data="graphData"
- :container-width="elWidth"
- />
- <heatmap-chart
- v-else-if="graphData.type === 'heatmap_chart'"
- :key="`heatmap-${graphIndex}`"
- :graph-data="graphData"
- />
</template>
</graph-group>
</div>
diff --git a/app/assets/javascripts/monitoring/stores/actions.js b/app/assets/javascripts/monitoring/stores/actions.js
index 29a7cbca669..32c86c32d5d 100644
--- a/app/assets/javascripts/monitoring/stores/actions.js
+++ b/app/assets/javascripts/monitoring/stores/actions.js
@@ -94,7 +94,7 @@ export const fetchPrometheusMetrics = ({ state, dispatch }) => {
*
* @param {metric} metric
*/
-export const fetchPrometheusMetric = ({ commit }, metric) => {
+export const fetchPrometheusMetric = ({ commit, getters }, metric) => {
const queryType = Object.keys(metric).find(key => ['query', 'query_range'].includes(key));
const query = metric[queryType];
// TODO don't hardcode
@@ -116,6 +116,12 @@ export const fetchPrometheusMetric = ({ commit }, metric) => {
step,
};
+ prom(prometheusEndpoint, params).then(result => {
+ commit(types.SET_QUERY_RESULT, { metricId: metric.metric_id, result });
+ })
+}
+
+function prom(prometheusEndpoint, params) {
return backOffRequest(() => axios.get(prometheusEndpoint, { params }))
.then(res => res.data)
.then(response => {
@@ -124,18 +130,11 @@ export const fetchPrometheusMetric = ({ commit }, metric) => {
}
const { resultType, result } = response.data;
-
+
if (resultType === 'matrix') {
if (result.length > 0) {
- // TODO: maybe use Object.freeze here since results don't need to be reactive
- commit(types.SET_QUERY_RESULT, { metricId: metric.metric_id, result });
+ return result
}
}
- // .then(res => {
- // if (res.resultType === 'matrix') {
- // if (res.result.length > 0) {
- // panel.queries[0].result = res.result;
- // panel.queries[0].metricId = panel.queries[0].metric_id;
-
});
}
diff --git a/app/assets/javascripts/monitoring/stores/getters.js b/app/assets/javascripts/monitoring/stores/getters.js
index 045356adc44..c106d5fe6b3 100644
--- a/app/assets/javascripts/monitoring/stores/getters.js
+++ b/app/assets/javascripts/monitoring/stores/getters.js
@@ -1,20 +1,104 @@
+import _ from 'underscore';
+
+function sortMetrics(metrics) {
+ return _.chain(metrics)
+ .sortBy('title')
+ .sortBy('weight')
+ .value();
+}
+
+function checkQueryEmptyData(query) {
+ return {
+ ...query,
+ result: query.result.filter(timeSeries => {
+ const newTimeSeries = timeSeries;
+ const hasValue = series =>
+ !Number.isNaN(series[1]) && (series[1] !== null || series[1] !== undefined);
+ const hasNonNullValue = timeSeries.values.find(hasValue);
+
+ newTimeSeries.values = hasNonNullValue ? newTimeSeries.values : [];
+
+ return newTimeSeries.values.length > 0;
+ }),
+ };
+}
+
+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 { queries, ...chart } = metric;
+ const metricId = chart.id ? chart.id.toString() : null;
+
+ const chartKey = `${chart.title}|${chart.y_label}`;
+ accumulator[chartKey] = accumulator[chartKey] || { ...chart, queries: [] };
+
+ queries.forEach(queryAttrs => accumulator[chartKey].queries.push({ metricId, ...queryAttrs }));
+
+ return accumulator;
+ }, {});
+
+ return Object.values(metricsByChart);
+}
+
+function normalizeMetrics(metrics) {
+ 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]) => [
+ new Date(timestamp * 1000).toISOString(),
+ Number(value),
+ ]),
+ })),
+ }));
+
+ return {
+ ...metric,
+ queries: removeTimeSeriesNoData(queries),
+ };
+ });
+}
+
export const groups = state => {
- return state.groups.map(group => {
+ return state.groups.reduce((acc, group) => {
group.panels.forEach(panel => {
panel.queries = panel.metrics;
panel.queries.forEach(metric => {
const metricId = metric.metric_id;
const result = state.queryResults[metricId];
- metric.result = result;
+ metric.result = result || [];
});
});
- return group;
- })
-
- // panel.queries[0].result
-
- // queryResults: {
- // metricId
- // result
- // }
+
+ const metrics = normalizeMetrics(sortMetrics(group.panels));
+
+ return acc.concat({
+ ...group,
+ metrics,
+ });
+ }, []);
}
diff --git a/app/assets/javascripts/monitoring/stores/mutations.js b/app/assets/javascripts/monitoring/stores/mutations.js
index 05f273355f1..3cb370dda6a 100644
--- a/app/assets/javascripts/monitoring/stores/mutations.js
+++ b/app/assets/javascripts/monitoring/stores/mutations.js
@@ -110,12 +110,12 @@ export default {
state.metricsEndpoint = endpoint;
},
[types.SET_QUERY_RESULT](state, { metricId, result }) {
- Vue.set(state.queryResults, metricId, result)
+ if (!metricId || !result) {
+ return;
+ }
+ Vue.set(state.queryResults, metricId, Object.freeze(result));
},
[types.SET_GROUPS](state, groups) {
- state.groups = groups.map(group => ({
- ...group,
- // metrics: normalizeMetrics(sortMetrics(group.metrics)),
- }));
+ state.groups = groups;
}
};