2019-09-04 21:01:54 +05:30
|
|
|
import Vue from 'vue';
|
2020-03-13 15:44:24 +05:30
|
|
|
import pick from 'lodash/pick';
|
2019-09-04 21:01:54 +05:30
|
|
|
import * as types from './mutation_types';
|
2020-04-08 14:13:33 +05:30
|
|
|
import { mapToDashboardViewModel, normalizeQueryResult } from './utils';
|
2020-01-01 13:55:28 +05:30
|
|
|
import { BACKOFF_TIMEOUT } from '../../lib/utils/common_utils';
|
|
|
|
import { metricStates } from '../constants';
|
|
|
|
import httpStatusCodes from '~/lib/utils/http_status';
|
2019-12-21 20:55:43 +05:30
|
|
|
|
2020-01-01 13:55:28 +05:30
|
|
|
/**
|
|
|
|
* Locate and return a metric in the dashboard by its id
|
|
|
|
* as generated by `uniqMetricsId()`.
|
|
|
|
* @param {String} metricId Unique id in the dashboard
|
|
|
|
* @param {Object} dashboard Full dashboard object
|
|
|
|
*/
|
|
|
|
const findMetricInDashboard = (metricId, dashboard) => {
|
|
|
|
let res = null;
|
2020-04-08 14:13:33 +05:30
|
|
|
dashboard.panelGroups.forEach(group => {
|
2020-01-01 13:55:28 +05:30
|
|
|
group.panels.forEach(panel => {
|
|
|
|
panel.metrics.forEach(metric => {
|
2020-04-08 14:13:33 +05:30
|
|
|
if (metric.metricId === metricId) {
|
2020-01-01 13:55:28 +05:30
|
|
|
res = metric;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
return res;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set a new state for a metric.
|
|
|
|
*
|
|
|
|
* Initally metric data is not populated, so `Vue.set` is
|
|
|
|
* used to add new properties to the metric.
|
|
|
|
*
|
|
|
|
* @param {Object} metric - Metric object as defined in the dashboard
|
|
|
|
* @param {Object} state - New state
|
|
|
|
* @param {Array|null} state.result - Array of results
|
|
|
|
* @param {String} state.error - Error code from metricStates
|
|
|
|
* @param {Boolean} state.loading - True if the metric is loading
|
|
|
|
*/
|
|
|
|
const setMetricState = (metric, { result = null, loading = false, state = null }) => {
|
|
|
|
Vue.set(metric, 'result', result);
|
|
|
|
Vue.set(metric, 'loading', loading);
|
|
|
|
Vue.set(metric, 'state', state);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Maps a backened error state to a `metricStates` constant
|
|
|
|
* @param {Object} error - Error from backend response
|
|
|
|
*/
|
|
|
|
const emptyStateFromError = error => {
|
|
|
|
if (!error) {
|
|
|
|
return metricStates.UNKNOWN_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Special error responses
|
|
|
|
if (error.message === BACKOFF_TIMEOUT) {
|
|
|
|
return metricStates.TIMEOUT;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Axios error responses
|
|
|
|
const { response } = error;
|
|
|
|
if (response && response.status === httpStatusCodes.SERVICE_UNAVAILABLE) {
|
|
|
|
return metricStates.CONNECTION_FAILED;
|
|
|
|
} else if (response && response.status === httpStatusCodes.BAD_REQUEST) {
|
|
|
|
// Note: "error.response.data.error" may contain Prometheus error information
|
|
|
|
return metricStates.BAD_QUERY;
|
|
|
|
}
|
|
|
|
|
|
|
|
return metricStates.UNKNOWN_ERROR;
|
|
|
|
};
|
2019-09-04 21:01:54 +05:30
|
|
|
|
|
|
|
export default {
|
2020-01-01 13:55:28 +05:30
|
|
|
/**
|
|
|
|
* Dashboard panels structure and global state
|
|
|
|
*/
|
2019-09-04 21:01:54 +05:30
|
|
|
[types.REQUEST_METRICS_DATA](state) {
|
|
|
|
state.emptyState = 'loading';
|
|
|
|
state.showEmptyState = true;
|
|
|
|
},
|
2020-03-13 15:44:24 +05:30
|
|
|
[types.RECEIVE_METRICS_DATA_SUCCESS](state, dashboard) {
|
2020-04-08 14:13:33 +05:30
|
|
|
state.dashboard = mapToDashboardViewModel(dashboard);
|
2019-09-04 21:01:54 +05:30
|
|
|
|
2020-04-08 14:13:33 +05:30
|
|
|
if (!state.dashboard.panelGroups.length) {
|
2019-09-04 21:01:54 +05:30
|
|
|
state.emptyState = 'noData';
|
|
|
|
}
|
|
|
|
},
|
|
|
|
[types.RECEIVE_METRICS_DATA_FAILURE](state, error) {
|
|
|
|
state.emptyState = error ? 'unableToConnect' : 'noData';
|
|
|
|
state.showEmptyState = true;
|
|
|
|
},
|
2020-01-01 13:55:28 +05:30
|
|
|
|
|
|
|
/**
|
|
|
|
* Deployments and environments
|
|
|
|
*/
|
2019-09-04 21:01:54 +05:30
|
|
|
[types.RECEIVE_DEPLOYMENTS_DATA_SUCCESS](state, deployments) {
|
|
|
|
state.deploymentData = deployments;
|
|
|
|
},
|
|
|
|
[types.RECEIVE_DEPLOYMENTS_DATA_FAILURE](state) {
|
|
|
|
state.deploymentData = [];
|
|
|
|
},
|
2020-03-13 15:44:24 +05:30
|
|
|
[types.REQUEST_ENVIRONMENTS_DATA](state) {
|
|
|
|
state.environmentsLoading = true;
|
|
|
|
},
|
2019-09-04 21:01:54 +05:30
|
|
|
[types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS](state, environments) {
|
2020-03-13 15:44:24 +05:30
|
|
|
state.environmentsLoading = false;
|
2019-09-04 21:01:54 +05:30
|
|
|
state.environments = environments;
|
|
|
|
},
|
|
|
|
[types.RECEIVE_ENVIRONMENTS_DATA_FAILURE](state) {
|
2020-03-13 15:44:24 +05:30
|
|
|
state.environmentsLoading = false;
|
2019-09-04 21:01:54 +05:30
|
|
|
state.environments = [];
|
|
|
|
},
|
2020-01-01 13:55:28 +05:30
|
|
|
|
|
|
|
/**
|
|
|
|
* Individual panel/metric results
|
|
|
|
*/
|
|
|
|
[types.REQUEST_METRIC_RESULT](state, { metricId }) {
|
|
|
|
const metric = findMetricInDashboard(metricId, state.dashboard);
|
|
|
|
setMetricState(metric, {
|
|
|
|
loading: true,
|
|
|
|
state: metricStates.LOADING,
|
|
|
|
});
|
|
|
|
},
|
|
|
|
[types.RECEIVE_METRIC_RESULT_SUCCESS](state, { metricId, result }) {
|
|
|
|
if (!metricId) {
|
2019-09-04 21:01:54 +05:30
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
state.showEmptyState = false;
|
|
|
|
|
2020-01-01 13:55:28 +05:30
|
|
|
const metric = findMetricInDashboard(metricId, state.dashboard);
|
|
|
|
if (!result || result.length === 0) {
|
|
|
|
setMetricState(metric, {
|
|
|
|
state: metricStates.NO_DATA,
|
2019-09-04 21:01:54 +05:30
|
|
|
});
|
2020-01-01 13:55:28 +05:30
|
|
|
} else {
|
|
|
|
const normalizedResults = result.map(normalizeQueryResult);
|
|
|
|
setMetricState(metric, {
|
|
|
|
result: Object.freeze(normalizedResults),
|
|
|
|
state: metricStates.OK,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
},
|
|
|
|
[types.RECEIVE_METRIC_RESULT_FAILURE](state, { metricId, error }) {
|
|
|
|
if (!metricId) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const metric = findMetricInDashboard(metricId, state.dashboard);
|
|
|
|
setMetricState(metric, {
|
|
|
|
state: emptyStateFromError(error),
|
2019-09-04 21:01:54 +05:30
|
|
|
});
|
|
|
|
},
|
2020-03-13 15:44:24 +05:30
|
|
|
[types.SET_ENDPOINTS](state, endpoints = {}) {
|
|
|
|
const endpointKeys = [
|
|
|
|
'metricsEndpoint',
|
|
|
|
'deploymentsEndpoint',
|
|
|
|
'dashboardEndpoint',
|
|
|
|
'dashboardsEndpoint',
|
|
|
|
'currentDashboard',
|
|
|
|
'projectPath',
|
|
|
|
'logsPath',
|
|
|
|
];
|
|
|
|
Object.entries(pick(endpoints, endpointKeys)).forEach(([key, value]) => {
|
|
|
|
state[key] = value;
|
|
|
|
});
|
|
|
|
},
|
|
|
|
[types.SET_TIME_RANGE](state, timeRange) {
|
|
|
|
state.timeRange = timeRange;
|
2019-09-04 21:01:54 +05:30
|
|
|
},
|
|
|
|
[types.SET_GETTING_STARTED_EMPTY_STATE](state) {
|
|
|
|
state.emptyState = 'gettingStarted';
|
|
|
|
},
|
|
|
|
[types.SET_NO_DATA_EMPTY_STATE](state) {
|
|
|
|
state.showEmptyState = true;
|
|
|
|
state.emptyState = 'noData';
|
|
|
|
},
|
2019-09-30 21:07:59 +05:30
|
|
|
[types.SET_ALL_DASHBOARDS](state, dashboards) {
|
2019-12-26 22:10:19 +05:30
|
|
|
state.allDashboards = dashboards || [];
|
2019-09-30 21:07:59 +05:30
|
|
|
},
|
2019-10-12 21:52:04 +05:30
|
|
|
[types.SET_SHOW_ERROR_BANNER](state, enabled) {
|
|
|
|
state.showErrorBanner = enabled;
|
|
|
|
},
|
2019-12-26 22:10:19 +05:30
|
|
|
[types.SET_PANEL_GROUP_METRICS](state, payload) {
|
2020-04-08 14:13:33 +05:30
|
|
|
const panelGroup = state.dashboard.panelGroups.find(pg => payload.key === pg.key);
|
2020-01-01 13:55:28 +05:30
|
|
|
panelGroup.panels = payload.panels;
|
2019-12-26 22:10:19 +05:30
|
|
|
},
|
2020-03-13 15:44:24 +05:30
|
|
|
[types.SET_ENVIRONMENTS_FILTER](state, searchTerm) {
|
|
|
|
state.environmentsSearchTerm = searchTerm;
|
|
|
|
},
|
2019-09-04 21:01:54 +05:30
|
|
|
};
|