diff options
author | Simon Knox <simon@gitlab.com> | 2019-06-26 22:14:41 +0000 |
---|---|---|
committer | Fatih Acet <acetfatih@gmail.com> | 2019-06-26 22:14:41 +0000 |
commit | 27afe5496db343962c573ce4e48a87af74235e4c (patch) | |
tree | 23710882fd4f3be902fd518b931184ef71e3712c | |
parent | 871d06993edba9220c10ef2ca5c64f412ee5f984 (diff) | |
download | gitlab-ce-27afe5496db343962c573ce4e48a87af74235e4c.tar.gz |
Add feature flag and dashboard endpoint
First part of FE for Prometheus API
Dashboard endpoint fetches all info except for chart results
Renders empty groups after loading
10 files changed, 160 insertions, 15 deletions
diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue index 973fa346a4f..23687c54fd3 100644 --- a/app/assets/javascripts/monitoring/components/dashboard.vue +++ b/app/assets/javascripts/monitoring/components/dashboard.vue @@ -106,17 +106,24 @@ export default { }, customMetricsPath: { type: String, - required: true, + required: false, + default: invalidUrl, }, validateQueryPath: { type: String, - required: true, + required: false, + default: invalidUrl, }, dashboardEndpoint: { type: String, required: false, default: invalidUrl, }, + currentDashboard: { + type: String, + required: false, + default: '', + }, }, data() { return { @@ -139,10 +146,15 @@ export default { 'deploymentData', 'metricsWithData', 'useDashboardEndpoint', + 'allDashboards', + 'multipleDashboardsEnabled', ]), groupsWithData() { return this.groups.filter(group => this.chartsWithData(group.metrics).length > 0); }, + selectedDashboardText() { + return this.currentDashboard || (this.allDashboards[0] && this.allDashboards[0].display_name); + }, }, created() { this.setEndpoints({ @@ -150,6 +162,7 @@ export default { environmentsEndpoint: this.environmentsEndpoint, deploymentsEndpoint: this.deploymentsEndpoint, dashboardEndpoint: this.dashboardEndpoint, + currentDashboard: this.currentDashboard, }); this.timeWindows = timeWindows; @@ -240,6 +253,24 @@ export default { v-if="environmentsEndpoint" class="dropdowns d-flex align-items-center justify-content-between" > + <div v-if="multipleDashboardsEnabled" class="d-flex align-items-center"> + <label class="mb-0">{{ __('Dashboard') }}</label> + <gl-dropdown + class="ml-2 mr-3 js-dashboards-dropdown" + toggle-class="dropdown-menu-toggle" + :text="selectedDashboardText" + > + <gl-dropdown-item + v-for="dashboard in allDashboards" + :key="dashboard.path" + :active="dashboard.path === currentDashboard" + active-class="is-active" + :href="`?dashboard=${dashboard.path}`" + > + {{ dashboard.display_name || dashboard.path }} + </gl-dropdown-item> + </gl-dropdown> + </div> <div class="d-flex align-items-center"> <strong>{{ s__('Metrics|Environment') }}</strong> <gl-dropdown diff --git a/app/assets/javascripts/monitoring/monitoring_bundle.js b/app/assets/javascripts/monitoring/monitoring_bundle.js index 1d33537b3b2..edbcf84b342 100644 --- a/app/assets/javascripts/monitoring/monitoring_bundle.js +++ b/app/assets/javascripts/monitoring/monitoring_bundle.js @@ -1,5 +1,6 @@ import Vue from 'vue'; import { parseBoolean } from '~/lib/utils/common_utils'; +import { getParameterValues } from '~/lib/utils/url_utility'; import Dashboard from 'ee_else_ce/monitoring/components/dashboard.vue'; import store from './stores'; @@ -7,10 +8,12 @@ export default (props = {}) => { const el = document.getElementById('prometheus-graphs'); if (el && el.dataset) { - store.dispatch( - 'monitoringDashboard/setDashboardEnabled', - gon.features.environmentMetricsUsePrometheusEndpoint, - ); + store.dispatch('monitoringDashboard/setFeatureFlags', { + prometheusEndpointEnabled: gon.features.environmentMetricsUsePrometheusEndpoint, + multipleDashboardsEnabled: gon.features.environmentMetricsShowMultipleDashboards, + }); + + const [currentDashboard] = getParameterValues('dashboard'); // eslint-disable-next-line no-new new Vue({ @@ -20,6 +23,7 @@ export default (props = {}) => { return createElement(Dashboard, { props: { ...el.dataset, + currentDashboard, hasMetrics: parseBoolean(el.dataset.hasMetrics), ...props, }, diff --git a/app/assets/javascripts/monitoring/stores/actions.js b/app/assets/javascripts/monitoring/stores/actions.js index f41e215cb5d..0fa2a5d6370 100644 --- a/app/assets/javascripts/monitoring/stores/actions.js +++ b/app/assets/javascripts/monitoring/stores/actions.js @@ -35,14 +35,24 @@ export const setEndpoints = ({ commit }, endpoints) => { commit(types.SET_ENDPOINTS, endpoints); }; -export const setDashboardEnabled = ({ commit }, enabled) => { - commit(types.SET_DASHBOARD_ENABLED, enabled); +export const setFeatureFlags = ( + { commit }, + { prometheusEndpointEnabled, multipleDashboardsEnabled }, +) => { + commit(types.SET_DASHBOARD_ENABLED, prometheusEndpointEnabled); + commit(types.SET_MULTIPLE_DASHBOARDS_ENABLED, multipleDashboardsEnabled); }; export const requestMetricsDashboard = ({ commit }) => { commit(types.REQUEST_METRICS_DATA); }; -export const receiveMetricsDashboardSuccess = ({ commit, dispatch }, { response, params }) => { +export const receiveMetricsDashboardSuccess = ( + { state, commit, dispatch }, + { response, params }, +) => { + if (state.multipleDashboardsEnabled) { + commit(types.SET_ALL_DASHBOARDS, response.all_dashboards); + } commit(types.RECEIVE_METRICS_DATA_SUCCESS, response.dashboard.panel_groups); dispatch('fetchPrometheusMetrics', params); }; @@ -95,6 +105,11 @@ export const fetchMetricsData = ({ state, dispatch }, params) => { export const fetchDashboard = ({ state, dispatch }, params) => { dispatch('requestMetricsDashboard'); + if (state.currentDashboard) { + // eslint-disable-next-line no-param-reassign + params.dashboard = state.currentDashboard; + } + return axios .get(state.dashboardEndpoint, { params }) .then(resp => resp.data) diff --git a/app/assets/javascripts/monitoring/stores/mutation_types.js b/app/assets/javascripts/monitoring/stores/mutation_types.js index 63894e83362..2c78a0b9315 100644 --- a/app/assets/javascripts/monitoring/stores/mutation_types.js +++ b/app/assets/javascripts/monitoring/stores/mutation_types.js @@ -10,6 +10,8 @@ export const RECEIVE_ENVIRONMENTS_DATA_FAILURE = 'RECEIVE_ENVIRONMENTS_DATA_FAIL export const SET_QUERY_RESULT = 'SET_QUERY_RESULT'; export const SET_TIME_WINDOW = 'SET_TIME_WINDOW'; export const SET_DASHBOARD_ENABLED = 'SET_DASHBOARD_ENABLED'; +export const SET_MULTIPLE_DASHBOARDS_ENABLED = 'SET_MULTIPLE_DASHBOARDS_ENABLED'; +export const SET_ALL_DASHBOARDS = 'SET_ALL_DASHBOARDS'; export const SET_ENDPOINTS = 'SET_ENDPOINTS'; export const SET_GETTING_STARTED_EMPTY_STATE = 'SET_GETTING_STARTED_EMPTY_STATE'; export const SET_NO_DATA_EMPTY_STATE = 'SET_NO_DATA_EMPTY_STATE'; diff --git a/app/assets/javascripts/monitoring/stores/mutations.js b/app/assets/javascripts/monitoring/stores/mutations.js index d4b816e2717..a85a7723c1f 100644 --- a/app/assets/javascripts/monitoring/stores/mutations.js +++ b/app/assets/javascripts/monitoring/stores/mutations.js @@ -74,10 +74,14 @@ export default { state.environmentsEndpoint = endpoints.environmentsEndpoint; state.deploymentsEndpoint = endpoints.deploymentsEndpoint; state.dashboardEndpoint = endpoints.dashboardEndpoint; + state.currentDashboard = endpoints.currentDashboard; }, [types.SET_DASHBOARD_ENABLED](state, enabled) { state.useDashboardEndpoint = enabled; }, + [types.SET_MULTIPLE_DASHBOARDS_ENABLED](state, enabled) { + state.multipleDashboardsEnabled = enabled; + }, [types.SET_GETTING_STARTED_EMPTY_STATE](state) { state.emptyState = 'gettingStarted'; }, @@ -85,4 +89,7 @@ export default { state.showEmptyState = true; state.emptyState = 'noData'; }, + [types.SET_ALL_DASHBOARDS](state, dashboards) { + state.allDashboards = dashboards; + }, }; diff --git a/app/assets/javascripts/monitoring/stores/state.js b/app/assets/javascripts/monitoring/stores/state.js index c33529cd588..de711d6ccae 100644 --- a/app/assets/javascripts/monitoring/stores/state.js +++ b/app/assets/javascripts/monitoring/stores/state.js @@ -8,10 +8,13 @@ export default () => ({ deploymentsEndpoint: null, dashboardEndpoint: invalidUrl, useDashboardEndpoint: false, + multipleDashboardsEnabled: false, emptyState: 'gettingStarted', showEmptyState: true, groups: [], deploymentData: [], environments: [], metricsWithData: [], + allDashboards: [], + currentDashboard: null, }); diff --git a/spec/javascripts/monitoring/dashboard_spec.js b/spec/javascripts/monitoring/dashboard_spec.js index cf72cce1781..ab8360193be 100644 --- a/spec/javascripts/monitoring/dashboard_spec.js +++ b/spec/javascripts/monitoring/dashboard_spec.js @@ -10,6 +10,7 @@ import { mockApiEndpoint, environmentData, singleGroupResponse, + dashboardGitResponse, } from './mock_data'; const propsData = { @@ -309,10 +310,6 @@ describe('Dashboard', () => { const getTimeDiffSpy = spyOnDependency(Dashboard, 'getTimeDiff'); component.$store.commit( - `monitoringDashboard/${types.SET_ENVIRONMENTS_ENDPOINT}`, - '/environments', - ); - component.$store.commit( `monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`, environmentData, ); @@ -430,4 +427,49 @@ describe('Dashboard', () => { }); }); }); + + describe('Dashboard dropdown', () => { + beforeEach(() => { + mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse); + + component = new DashboardComponent({ + el: document.querySelector('.prometheus-graphs'), + propsData: { + ...propsData, + hasMetrics: true, + showPanels: false, + }, + store, + }); + + component.$store.dispatch('monitoringDashboard/setFeatureFlags', { + prometheusEndpoint: false, + multipleDashboardsEnabled: true, + }); + + component.$store.commit( + `monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`, + environmentData, + ); + + component.$store.commit( + `monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`, + singleGroupResponse, + ); + + component.$store.commit( + `monitoringDashboard/${types.SET_ALL_DASHBOARDS}`, + dashboardGitResponse, + ); + }); + + it('shows the dashboard dropdown', done => { + setTimeout(() => { + const dashboardDropdown = component.$el.querySelector('.js-dashboards-dropdown'); + + expect(dashboardDropdown).not.toEqual(null); + done(); + }); + }); + }); }); diff --git a/spec/javascripts/monitoring/mock_data.js b/spec/javascripts/monitoring/mock_data.js index 82e42fe9ade..7bbb215475a 100644 --- a/spec/javascripts/monitoring/mock_data.js +++ b/spec/javascripts/monitoring/mock_data.js @@ -922,3 +922,16 @@ export const metricsDashboardResponse = { }, status: 'success', }; + +export const dashboardGitResponse = [ + { + path: 'config/prometheus/common_metrics.yml', + display_name: 'Common Metrics', + default: true, + }, + { + path: '.gitlab/dashboards/super.yml', + display_name: 'Custom Dashboard 1', + default: false, + }, +]; diff --git a/spec/javascripts/monitoring/store/actions_spec.js b/spec/javascripts/monitoring/store/actions_spec.js index 083a01c4d74..677455275de 100644 --- a/spec/javascripts/monitoring/store/actions_spec.js +++ b/spec/javascripts/monitoring/store/actions_spec.js @@ -22,6 +22,7 @@ import { environmentData, metricsDashboardResponse, metricsGroupsAPIResponse, + dashboardGitResponse, } from '../mock_data'; describe('Monitoring store actions', () => { @@ -212,17 +213,19 @@ describe('Monitoring store actions', () => { describe('receiveMetricsDashboardSuccess', () => { let commit; let dispatch; + let state; beforeEach(() => { commit = jasmine.createSpy(); dispatch = jasmine.createSpy(); + state = storeState(); }); it('stores groups ', () => { const params = {}; const response = metricsDashboardResponse; - receiveMetricsDashboardSuccess({ commit, dispatch }, { response, params }); + receiveMetricsDashboardSuccess({ state, commit, dispatch }, { response, params }); expect(commit).toHaveBeenCalledWith( types.RECEIVE_METRICS_DATA_SUCCESS, @@ -231,6 +234,18 @@ describe('Monitoring store actions', () => { expect(dispatch).toHaveBeenCalledWith('fetchPrometheusMetrics', params); }); + + it('sets the dashboards loaded from the repository', () => { + const params = {}; + const response = metricsDashboardResponse; + + response.all_dashboards = dashboardGitResponse; + state.multipleDashboardsEnabled = true; + + receiveMetricsDashboardSuccess({ state, commit, dispatch }, { response, params }); + + expect(commit).toHaveBeenCalledWith(types.SET_ALL_DASHBOARDS, dashboardGitResponse); + }); }); describe('receiveMetricsDashboardFailure', () => { diff --git a/spec/javascripts/monitoring/store/mutations_spec.js b/spec/javascripts/monitoring/store/mutations_spec.js index 02ff5847b34..91580366531 100644 --- a/spec/javascripts/monitoring/store/mutations_spec.js +++ b/spec/javascripts/monitoring/store/mutations_spec.js @@ -1,7 +1,12 @@ import mutations from '~/monitoring/stores/mutations'; import * as types from '~/monitoring/stores/mutation_types'; import state from '~/monitoring/stores/state'; -import { metricsGroupsAPIResponse, deploymentData, metricsDashboardResponse } from '../mock_data'; +import { + metricsGroupsAPIResponse, + deploymentData, + metricsDashboardResponse, + dashboardGitResponse, +} from '../mock_data'; describe('Monitoring mutations', () => { let stateCopy; @@ -156,4 +161,12 @@ describe('Monitoring mutations', () => { expect(stateCopy.metricsWithData).toEqual([]); }); }); + + describe('SET_ALL_DASHBOARDS', () => { + it('stores the dashboards loaded from the git repository', () => { + mutations[types.SET_ALL_DASHBOARDS](stateCopy, dashboardGitResponse); + + expect(stateCopy.allDashboards).toEqual(dashboardGitResponse); + }); + }); }); |