summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/monitoring/stores/actions.js
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/monitoring/stores/actions.js')
-rw-r--r--app/assets/javascripts/monitoring/stores/actions.js124
1 files changed, 105 insertions, 19 deletions
diff --git a/app/assets/javascripts/monitoring/stores/actions.js b/app/assets/javascripts/monitoring/stores/actions.js
index 3a9cccec438..a441882a47d 100644
--- a/app/assets/javascripts/monitoring/stores/actions.js
+++ b/app/assets/javascripts/monitoring/stores/actions.js
@@ -12,6 +12,7 @@ import {
import trackDashboardLoad from '../monitoring_tracking_helper';
import getEnvironments from '../queries/getEnvironments.query.graphql';
import getAnnotations from '../queries/getAnnotations.query.graphql';
+import getDashboardValidationWarnings from '../queries/getDashboardValidationWarnings.query.graphql';
import statusCodes from '../../lib/utils/http_status';
import { backOff, convertObjectPropsToCamelCase } from '../../lib/utils/common_utils';
import { s__, sprintf } from '../../locale';
@@ -20,6 +21,7 @@ import {
PROMETHEUS_TIMEOUT,
ENVIRONMENT_AVAILABLE_STATE,
DEFAULT_DASHBOARD_PATH,
+ VARIABLE_TYPES,
} from '../constants';
function prometheusMetricQueryParams(timeRange) {
@@ -50,15 +52,14 @@ function backOffRequest(makeRequestCallback) {
}, PROMETHEUS_TIMEOUT);
}
-function getPrometheusMetricResult(prometheusEndpoint, params) {
+function getPrometheusQueryData(prometheusEndpoint, params) {
return backOffRequest(() => axios.get(prometheusEndpoint, { params }))
.then(res => res.data)
.then(response => {
if (response.status === 'error') {
throw new Error(response.error);
}
-
- return response.data.result;
+ return response.data;
});
}
@@ -76,10 +77,6 @@ export const setTimeRange = ({ commit }, timeRange) => {
commit(types.SET_TIME_RANGE, timeRange);
};
-export const setVariables = ({ commit }, variables) => {
- commit(types.SET_VARIABLES, variables);
-};
-
export const filterEnvironments = ({ commit, dispatch }, searchTerm) => {
commit(types.SET_ENVIRONMENTS_FILTER, searchTerm);
dispatch('fetchEnvironmentsData');
@@ -100,6 +97,10 @@ export const clearExpandedPanel = ({ commit }) => {
});
};
+export const setCurrentDashboard = ({ commit }, { currentDashboard }) => {
+ commit(types.SET_CURRENT_DASHBOARD, currentDashboard);
+};
+
// All Data
/**
@@ -117,17 +118,27 @@ export const fetchData = ({ dispatch }) => {
// Metrics dashboard
-export const fetchDashboard = ({ state, commit, dispatch }) => {
+export const fetchDashboard = ({ state, commit, dispatch, getters }) => {
dispatch('requestMetricsDashboard');
const params = {};
- if (state.currentDashboard) {
- params.dashboard = state.currentDashboard;
+ if (getters.fullDashboardPath) {
+ params.dashboard = getters.fullDashboardPath;
}
return backOffRequest(() => axios.get(state.dashboardEndpoint, { params }))
.then(resp => resp.data)
- .then(response => dispatch('receiveMetricsDashboardSuccess', { response }))
+ .then(response => {
+ dispatch('receiveMetricsDashboardSuccess', { response });
+ /**
+ * After the dashboard is fetched, there can be non-blocking invalid syntax
+ * in the dashboard file. This call will fetch such syntax warnings
+ * and surface a warning on the UI. If the invalid syntax is blocking,
+ * the `fetchDashboard` returns a 404 with error messages that are displayed
+ * on the UI.
+ */
+ dispatch('fetchDashboardValidationWarnings');
+ })
.catch(error => {
Sentry.captureException(error);
@@ -181,8 +192,12 @@ export const fetchDashboardData = ({ state, dispatch, getters }) => {
return Promise.reject();
}
+ // Time range params must be pre-calculated once for all metrics and options
+ // A subsequent call, may calculate a different time range
const defaultQueryParams = prometheusMetricQueryParams(state.timeRange);
+ dispatch('fetchVariableMetricLabelValues', { defaultQueryParams });
+
const promises = [];
state.dashboard.panelGroups.forEach(group => {
group.panels.forEach(panel => {
@@ -194,7 +209,7 @@ export const fetchDashboardData = ({ state, dispatch, getters }) => {
return Promise.all(promises)
.then(() => {
- const dashboardType = state.currentDashboard === '' ? 'default' : 'custom';
+ const dashboardType = getters.fullDashboardPath === '' ? 'default' : 'custom';
trackDashboardLoad({
label: `${dashboardType}_metrics_dashboard`,
value: getters.metricsWithData().length,
@@ -220,7 +235,7 @@ export const fetchPrometheusMetric = (
queryParams.step = metric.step;
}
- if (Object.keys(state.variables).length > 0) {
+ if (state.variables.length > 0) {
queryParams = {
...queryParams,
...getters.getCustomVariablesParams,
@@ -229,9 +244,9 @@ export const fetchPrometheusMetric = (
commit(types.REQUEST_METRIC_RESULT, { metricId: metric.metricId });
- return getPrometheusMetricResult(metric.prometheusEndpointPath, queryParams)
- .then(result => {
- commit(types.RECEIVE_METRIC_RESULT_SUCCESS, { metricId: metric.metricId, result });
+ return getPrometheusQueryData(metric.prometheusEndpointPath, queryParams)
+ .then(data => {
+ commit(types.RECEIVE_METRIC_RESULT_SUCCESS, { metricId: metric.metricId, data });
})
.catch(error => {
Sentry.captureException(error);
@@ -312,9 +327,9 @@ export const receiveEnvironmentsDataFailure = ({ commit }) => {
commit(types.RECEIVE_ENVIRONMENTS_DATA_FAILURE);
};
-export const fetchAnnotations = ({ state, dispatch }) => {
+export const fetchAnnotations = ({ state, dispatch, getters }) => {
const { start } = convertToFixedRange(state.timeRange);
- const dashboardPath = state.currentDashboard || DEFAULT_DASHBOARD_PATH;
+ const dashboardPath = getters.fullDashboardPath || DEFAULT_DASHBOARD_PATH;
return gqClient
.mutate({
mutation: getAnnotations,
@@ -345,6 +360,46 @@ export const receiveAnnotationsSuccess = ({ commit }, data) =>
commit(types.RECEIVE_ANNOTATIONS_SUCCESS, data);
export const receiveAnnotationsFailure = ({ commit }) => commit(types.RECEIVE_ANNOTATIONS_FAILURE);
+export const fetchDashboardValidationWarnings = ({ state, dispatch, getters }) => {
+ /**
+ * Normally, the default dashboard won't throw any validation warnings.
+ *
+ * However, if a bug sneaks into the default dashboard making it invalid,
+ * this might come handy for our clients
+ */
+ const dashboardPath = getters.fullDashboardPath || DEFAULT_DASHBOARD_PATH;
+ return gqClient
+ .mutate({
+ mutation: getDashboardValidationWarnings,
+ variables: {
+ projectPath: removeLeadingSlash(state.projectPath),
+ environmentName: state.currentEnvironmentName,
+ dashboardPath,
+ },
+ })
+ .then(resp => resp.data?.project?.environments?.nodes?.[0]?.metricsDashboard)
+ .then(({ schemaValidationWarnings } = {}) => {
+ const hasWarnings = schemaValidationWarnings && schemaValidationWarnings.length !== 0;
+ /**
+ * The payload of the dispatch is a boolean, because at the moment a standard
+ * warning message is shown instead of the warnings the BE returns
+ */
+ dispatch('receiveDashboardValidationWarningsSuccess', hasWarnings || false);
+ })
+ .catch(err => {
+ Sentry.captureException(err);
+ dispatch('receiveDashboardValidationWarningsFailure');
+ createFlash(
+ s__('Metrics|There was an error getting dashboard validation warnings information.'),
+ );
+ });
+};
+
+export const receiveDashboardValidationWarningsSuccess = ({ commit }, hasWarnings) =>
+ commit(types.RECEIVE_DASHBOARD_VALIDATION_WARNINGS_SUCCESS, hasWarnings);
+export const receiveDashboardValidationWarningsFailure = ({ commit }) =>
+ commit(types.RECEIVE_DASHBOARD_VALIDATION_WARNINGS_FAILURE);
+
// Dashboard manipulation
export const toggleStarredValue = ({ commit, state, getters }) => {
@@ -416,10 +471,41 @@ export const duplicateSystemDashboard = ({ state }, payload) => {
// Variables manipulation
export const updateVariablesAndFetchData = ({ commit, dispatch }, updatedVariable) => {
- commit(types.UPDATE_VARIABLES, updatedVariable);
+ commit(types.UPDATE_VARIABLE_VALUE, updatedVariable);
return dispatch('fetchDashboardData');
};
+export const fetchVariableMetricLabelValues = ({ state, commit }, { defaultQueryParams }) => {
+ const { start_time, end_time } = defaultQueryParams;
+ const optionsRequests = [];
+
+ state.variables.forEach(variable => {
+ if (variable.type === VARIABLE_TYPES.metric_label_values) {
+ const { prometheusEndpointPath, label } = variable.options;
+
+ const optionsRequest = backOffRequest(() =>
+ axios.get(prometheusEndpointPath, {
+ params: { start_time, end_time },
+ }),
+ )
+ .then(({ data }) => data.data)
+ .then(data => {
+ commit(types.UPDATE_VARIABLE_METRIC_LABEL_VALUES, { variable, label, data });
+ })
+ .catch(() => {
+ createFlash(
+ sprintf(s__('Metrics|There was an error getting options for variable "%{name}".'), {
+ name: variable.name,
+ }),
+ );
+ });
+ optionsRequests.push(optionsRequest);
+ }
+ });
+
+ return Promise.all(optionsRequests);
+};
+
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};