Commit 1d777195 authored by Fatih Acet's avatar Fatih Acet

Merge branch 'jivanvl-remove-feature-flags-monitoring-dashboard' into 'master'

Remove additional_panel_types and use_prometheus_endpoint feature flags

See merge request gitlab-org/gitlab!17151
parents b0732480 20e4a5c5
...@@ -11,7 +11,7 @@ import { ...@@ -11,7 +11,7 @@ import {
GlModalDirective, GlModalDirective,
GlTooltipDirective, GlTooltipDirective,
} from '@gitlab/ui'; } from '@gitlab/ui';
import { __, s__ } from '~/locale'; import { s__ } from '~/locale';
import createFlash from '~/flash'; import createFlash from '~/flash';
import Icon from '~/vue_shared/components/icon.vue'; import Icon from '~/vue_shared/components/icon.vue';
import { getParameterValues, mergeUrlParams, redirectTo } from '~/lib/utils/url_utility'; import { getParameterValues, mergeUrlParams, redirectTo } from '~/lib/utils/url_utility';
...@@ -167,6 +167,7 @@ export default { ...@@ -167,6 +167,7 @@ export default {
formIsValid: null, formIsValid: null,
selectedTimeWindow: {}, selectedTimeWindow: {},
isRearrangingPanels: false, isRearrangingPanels: false,
hasValidDates: true,
}; };
}, },
computed: { computed: {
...@@ -185,7 +186,9 @@ export default { ...@@ -185,7 +186,9 @@ export default {
'additionalPanelTypesEnabled', 'additionalPanelTypesEnabled',
]), ]),
firstDashboard() { firstDashboard() {
return this.allDashboards[0] || {}; return this.environmentsEndpoint.length > 0 && this.allDashboards.length > 0
? this.allDashboards[0]
: {};
}, },
selectedDashboard() { selectedDashboard() {
return this.allDashboards.find(d => d.path === this.currentDashboard) || this.firstDashboard; return this.allDashboards.find(d => d.path === this.currentDashboard) || this.firstDashboard;
...@@ -199,9 +202,6 @@ export default { ...@@ -199,9 +202,6 @@ export default {
addingMetricsAvailable() { addingMetricsAvailable() {
return IS_EE && this.canAddMetrics && !this.showEmptyState; return IS_EE && this.canAddMetrics && !this.showEmptyState;
}, },
alertWidgetAvailable() {
return IS_EE && this.prometheusAlertsAvailable && this.alertsEndpoint;
},
hasHeaderButtons() { hasHeaderButtons() {
return ( return (
this.addingMetricsAvailable || this.addingMetricsAvailable ||
...@@ -237,8 +237,10 @@ export default { ...@@ -237,8 +237,10 @@ export default {
this.selectedTimeWindow = range; this.selectedTimeWindow = range;
if (!isValidDate(start) || !isValidDate(end)) { if (!isValidDate(start) || !isValidDate(end)) {
this.hasValidDates = false;
this.showInvalidDateError(); this.showInvalidDateError();
} else { } else {
this.hasValidDates = true;
this.fetchData(range); this.fetchData(range);
} }
} }
...@@ -248,44 +250,13 @@ export default { ...@@ -248,44 +250,13 @@ export default {
'fetchData', 'fetchData',
'setGettingStartedEmptyState', 'setGettingStartedEmptyState',
'setEndpoints', 'setEndpoints',
'setDashboardEnabled',
'setPanelGroupMetrics', 'setPanelGroupMetrics',
]), ]),
chartsWithData(charts) { chartsWithData(charts) {
if (!this.useDashboardEndpoint) {
return charts;
}
return charts.filter(chart => return charts.filter(chart =>
chart.metrics.some(metric => this.metricsWithData.includes(metric.metric_id)), chart.metrics.some(metric => this.metricsWithData.includes(metric.metric_id)),
); );
}, },
csvText(graphData) {
const chartData = graphData.queries[0].result[0].values;
const yLabel = graphData.y_label;
const header = `timestamp,${yLabel}\r\n`; // eslint-disable-line @gitlab/i18n/no-non-i18n-strings
return chartData.reduce((csv, data) => {
const row = data.join(',');
return `${csv}${row}\r\n`;
}, header);
},
downloadCsv(graphData) {
const data = new Blob([this.csvText(graphData)], { type: 'text/plain' });
return window.URL.createObjectURL(data);
},
// TODO: BEGIN, Duplicated code with panel_type until feature flag is removed
// Issue number: https://gitlab.com/gitlab-org/gitlab-foss/issues/63845
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));
},
showToast() {
this.$toast.show(__('Link copied'));
},
// TODO: END
updateMetrics(key, metrics) { updateMetrics(key, metrics) {
this.setPanelGroupMetrics({ this.setPanelGroupMetrics({
metrics, metrics,
...@@ -298,6 +269,11 @@ export default { ...@@ -298,6 +269,11 @@ export default {
key, key,
}); });
}, },
removeGraph(metrics, graphIndex) {
// At present graphs will not be removed, they should removed using the vuex store
// See https://gitlab.com/gitlab-org/gitlab/issues/27835
metrics.splice(graphIndex, 1);
},
showInvalidDateError() { showInvalidDateError() {
createFlash(s__('Metrics|Link contains an invalid time window.')); createFlash(s__('Metrics|Link contains an invalid time window.'));
}, },
...@@ -387,7 +363,7 @@ export default { ...@@ -387,7 +363,7 @@ export default {
</gl-form-group> </gl-form-group>
<gl-form-group <gl-form-group
v-if="!showEmptyState" v-if="hasValidDates"
:label="s__('Metrics|Show last')" :label="s__('Metrics|Show last')"
label-size="sm" label-size="sm"
label-for="monitor-time-window-dropdown" label-for="monitor-time-window-dropdown"
...@@ -480,109 +456,40 @@ export default { ...@@ -480,109 +456,40 @@ export default {
:show-panels="showPanels" :show-panels="showPanels"
:collapse-group="groupHasData(groupData)" :collapse-group="groupHasData(groupData)"
> >
<template v-if="additionalPanelTypesEnabled"> <vue-draggable
<vue-draggable :value="groupData.metrics"
:value="groupData.metrics" group="metrics-dashboard"
group="metrics-dashboard" :component-data="{ attrs: { class: 'row mx-0 w-100' } }"
:component-data="{ attrs: { class: 'row mx-0 w-100' } }" :disabled="!isRearrangingPanels"
:disabled="!isRearrangingPanels" @input="updateMetrics(groupData.key, $event)"
@input="updateMetrics(groupData.key, $event)" >
<div
v-for="(graphData, graphIndex) in groupData.metrics"
:key="`panel-type-${graphIndex}`"
class="col-12 col-lg-6 px-2 mb-2 draggable"
:class="{ 'draggable-enabled': isRearrangingPanels }"
> >
<div <div class="position-relative draggable-panel js-draggable-panel">
v-for="(graphData, graphIndex) in groupData.metrics" <div
:key="`panel-type-${graphIndex}`" v-if="isRearrangingPanels"
class="col-12 col-lg-6 px-2 mb-2 draggable" class="draggable-remove js-draggable-remove p-2 w-100 position-absolute d-flex justify-content-end"
:class="{ 'draggable-enabled': isRearrangingPanels }" @click="removeGraph(groupData.metrics, graphIndex)"
> >
<div class="position-relative draggable-panel js-draggable-panel"> <a class="mx-2 p-2 draggable-remove-link" :aria-label="__('Remove')"
<div ><icon name="close"
v-if="isRearrangingPanels" /></a>
class="draggable-remove js-draggable-remove p-2 w-100 position-absolute d-flex justify-content-end"
@click="removeMetric(groupData.key, groupData.metrics, graphIndex)"
>
<a class="mx-2 p-2 draggable-remove-link" :aria-label="__('Remove')"
><icon name="close"
/></a>
</div>
<panel-type
:clipboard-text="
generateLink(groupData.group, graphData.title, graphData.y_label)
"
:graph-data="graphData"
:alerts-endpoint="alertsEndpoint"
:prometheus-alerts-available="prometheusAlertsAvailable"
:index="`${index}-${graphIndex}`"
/>
</div> </div>
</div>
</vue-draggable> <panel-type
</template> :clipboard-text="generateLink(groupData.group, graphData.title, graphData.y_label)"
<template v-else> :graph-data="graphData"
<monitor-time-series-chart
v-for="(graphData, graphIndex) in chartsWithData(groupData.metrics)"
:key="graphIndex"
class="col-12 col-lg-6 pb-3"
:graph-data="graphData"
:deployment-data="deploymentData"
:thresholds="getGraphAlertValues(graphData.queries)"
:project-path="projectPath"
group-id="monitor-time-series-chart"
>
<div
class="d-flex align-items-center"
:class="alertWidgetAvailable ? 'justify-content-between' : 'justify-content-end'"
>
<alert-widget
v-if="alertWidgetAvailable && graphData"
:modal-id="`alert-modal-${index}-${graphIndex}`"
:alerts-endpoint="alertsEndpoint" :alerts-endpoint="alertsEndpoint"
:relevant-queries="graphData.queries" :prometheus-alerts-available="prometheusAlertsAvailable"
:alerts-to-manage="getGraphAlerts(graphData.queries)" :index="`${index}-${graphIndex}`"
@setAlerts="setAlerts"
/> />
<gl-dropdown
v-gl-tooltip
class="ml-2 mr-3"
toggle-class="btn btn-transparent border-0"
:right="true"
:no-caret="true"
:title="__('More actions')"
>
<template slot="button-content">
<icon name="ellipsis_v" class="text-secondary" />
</template>
<gl-dropdown-item
v-track-event="downloadCSVOptions(graphData.title)"
:href="downloadCsv(graphData)"
download="chart_metrics.csv"
>
{{ __('Download CSV') }}
</gl-dropdown-item>
<gl-dropdown-item
v-track-event="
generateLinkToChartOptions(
generateLink(groupData.group, graphData.title, graphData.y_label),
)
"
class="js-chart-link"
:data-clipboard-text="
generateLink(groupData.group, graphData.title, graphData.y_label)
"
@click="showToast"
>
{{ __('Generate link to chart') }}
</gl-dropdown-item>
<gl-dropdown-item
v-if="alertWidgetAvailable"
v-gl-modal="`alert-modal-${index}-${graphIndex}`"
>
{{ __('Alerts') }}
</gl-dropdown-item>
</gl-dropdown>
</div> </div>
</monitor-time-series-chart> </div>
</template> </vue-draggable>
</graph-group> </graph-group>
</div> </div>
<empty-state <empty-state
......
...@@ -56,16 +56,10 @@ export default { ...@@ -56,16 +56,10 @@ export default {
}, },
}, },
mounted() { mounted() {
const range = getTimeWindow(this.selectedTimeWindow); this.verifyTimeRange();
if (range) { },
this.selectedTimeWindowText = this.timeWindows[range]; updated() {
} else { this.verifyTimeRange();
this.customTime = {
from: truncateZerosInDateTime(ISODateToString(this.selectedTimeWindow.start)),
to: truncateZerosInDateTime(ISODateToString(this.selectedTimeWindow.end)),
};
this.selectedTimeWindowText = sprintf(s__('%{from} to %{to}'), this.customTime);
}
}, },
methods: { methods: {
activeTimeWindow(key) { activeTimeWindow(key) {
...@@ -87,6 +81,18 @@ export default { ...@@ -87,6 +81,18 @@ export default {
closeDropdown() { closeDropdown() {
this.$refs.dropdown.hide(); this.$refs.dropdown.hide();
}, },
verifyTimeRange() {
const range = getTimeWindow(this.selectedTimeWindow);
if (range) {
this.selectedTimeWindowText = this.timeWindows[range];
} else {
this.customTime = {
from: truncateZerosInDateTime(ISODateToString(this.selectedTimeWindow.start)),
to: truncateZerosInDateTime(ISODateToString(this.selectedTimeWindow.end)),
};
this.selectedTimeWindowText = sprintf(s__('%{from} to %{to}'), this.customTime);
}
},
}, },
}; };
</script> </script>
......
...@@ -78,9 +78,6 @@ export default { ...@@ -78,9 +78,6 @@ export default {
}, sidebarAnimationDuration); }, sidebarAnimationDuration);
}, },
setInitialState() { setInitialState() {
this.setFeatureFlags({
prometheusEndpointEnabled: true,
});
this.setEndpoints({ this.setEndpoints({
dashboardEndpoint: removeParams(['start', 'end'], this.dashboardUrl), dashboardEndpoint: removeParams(['start', 'end'], this.dashboardUrl),
}); });
......
...@@ -11,13 +11,6 @@ export default (props = {}) => { ...@@ -11,13 +11,6 @@ export default (props = {}) => {
const el = document.getElementById('prometheus-graphs'); const el = document.getElementById('prometheus-graphs');
if (el && el.dataset) { if (el && el.dataset) {
if (gon.features) {
store.dispatch('monitoringDashboard/setFeatureFlags', {
prometheusEndpointEnabled: gon.features.environmentMetricsUsePrometheusEndpoint,
additionalPanelTypesEnabled: gon.features.environmentMetricsAdditionalPanelTypes,
});
}
const [currentDashboard] = getParameterValues('dashboard'); const [currentDashboard] = getParameterValues('dashboard');
// eslint-disable-next-line no-new // eslint-disable-next-line no-new
......
...@@ -35,14 +35,6 @@ export const setEndpoints = ({ commit }, endpoints) => { ...@@ -35,14 +35,6 @@ export const setEndpoints = ({ commit }, endpoints) => {
commit(types.SET_ENDPOINTS, endpoints); commit(types.SET_ENDPOINTS, endpoints);
}; };
export const setFeatureFlags = (
{ commit },
{ prometheusEndpointEnabled, additionalPanelTypesEnabled },
) => {
commit(types.SET_DASHBOARD_ENABLED, prometheusEndpointEnabled);
commit(types.SET_ADDITIONAL_PANEL_TYPES_ENABLED, additionalPanelTypesEnabled);
};
export const setShowErrorBanner = ({ commit }, enabled) => { export const setShowErrorBanner = ({ commit }, enabled) => {
commit(types.SET_SHOW_ERROR_BANNER, enabled); commit(types.SET_SHOW_ERROR_BANNER, enabled);
}; };
...@@ -79,29 +71,7 @@ export const fetchData = ({ dispatch }, params) => { ...@@ -79,29 +71,7 @@ export const fetchData = ({ dispatch }, params) => {
dispatch('fetchEnvironmentsData'); dispatch('fetchEnvironmentsData');
}; };
export const fetchMetricsData = ({ state, dispatch }, params) => { export const fetchMetricsData = ({ dispatch }, params) => dispatch('fetchDashboard', params);
if (state.useDashboardEndpoint) {
return dispatch('fetchDashboard', params);
}
dispatch('requestMetricsData');
return backOffRequest(() => axios.get(state.metricsEndpoint, { params }))
.then(resp => resp.data)
.then(response => {
if (!response || !response.data || !response.success) {
dispatch('receiveMetricsDataFailure', null);
createFlash(s__('Metrics|Unexpected metrics data response from prometheus endpoint'));
}
dispatch('receiveMetricsDataSuccess', response.data);
})
.catch(error => {
dispatch('receiveMetricsDataFailure', error);
if (state.setShowErrorBanner) {
createFlash(s__('Metrics|There was an error while retrieving metrics'));
}
});
};
export const fetchDashboard = ({ state, dispatch }, params) => { export const fetchDashboard = ({ state, dispatch }, params) => {
dispatch('requestMetricsDashboard'); dispatch('requestMetricsDashboard');
......
...@@ -9,8 +9,6 @@ export const RECEIVE_ENVIRONMENTS_DATA_SUCCESS = 'RECEIVE_ENVIRONMENTS_DATA_SUCC ...@@ -9,8 +9,6 @@ export const RECEIVE_ENVIRONMENTS_DATA_SUCCESS = 'RECEIVE_ENVIRONMENTS_DATA_SUCC
export const RECEIVE_ENVIRONMENTS_DATA_FAILURE = 'RECEIVE_ENVIRONMENTS_DATA_FAILURE'; export const RECEIVE_ENVIRONMENTS_DATA_FAILURE = 'RECEIVE_ENVIRONMENTS_DATA_FAILURE';
export const SET_QUERY_RESULT = 'SET_QUERY_RESULT'; export const SET_QUERY_RESULT = 'SET_QUERY_RESULT';
export const SET_TIME_WINDOW = 'SET_TIME_WINDOW'; export const SET_TIME_WINDOW = 'SET_TIME_WINDOW';
export const SET_DASHBOARD_ENABLED = 'SET_DASHBOARD_ENABLED';
export const SET_ADDITIONAL_PANEL_TYPES_ENABLED = 'SET_ADDITIONAL_PANEL_TYPES_ENABLED';
export const SET_ALL_DASHBOARDS = 'SET_ALL_DASHBOARDS'; export const SET_ALL_DASHBOARDS = 'SET_ALL_DASHBOARDS';
export const SET_ENDPOINTS = 'SET_ENDPOINTS'; export const SET_ENDPOINTS = 'SET_ENDPOINTS';
export const SET_GETTING_STARTED_EMPTY_STATE = 'SET_GETTING_STARTED_EMPTY_STATE'; export const SET_GETTING_STARTED_EMPTY_STATE = 'SET_GETTING_STARTED_EMPTY_STATE';
......
...@@ -25,12 +25,10 @@ export default { ...@@ -25,12 +25,10 @@ export default {
// for backwards compatibility, and to limit Vue template changes: // for backwards compatibility, and to limit Vue template changes:
// for each group alias panels to metrics // for each group alias panels to metrics
// for each panel alias metrics to queries // for each panel alias metrics to queries
if (state.useDashboardEndpoint) { metrics = panels.map(panel => ({
metrics = panels.map(panel => ({ ...panel,
...panel, queries: panel.metrics,
queries: panel.metrics, }));
}));
}
return { return {
...group, ...group,
...@@ -42,8 +40,6 @@ export default { ...@@ -42,8 +40,6 @@ export default {
if (!state.dashboard.panel_groups.length) { if (!state.dashboard.panel_groups.length) {
state.emptyState = 'noData'; state.emptyState = 'noData';
} else {
state.showEmptyState = false;
} }
}, },
[types.RECEIVE_METRICS_DATA_FAILURE](state, error) { [types.RECEIVE_METRICS_DATA_FAILURE](state, error) {
...@@ -90,9 +86,6 @@ export default { ...@@ -90,9 +86,6 @@ export default {
state.currentDashboard = endpoints.currentDashboard; state.currentDashboard = endpoints.currentDashboard;
state.projectPath = endpoints.projectPath; state.projectPath = endpoints.projectPath;
}, },
[types.SET_DASHBOARD_ENABLED](state, enabled) {
state.useDashboardEndpoint = enabled;
},
[types.SET_GETTING_STARTED_EMPTY_STATE](state) { [types.SET_GETTING_STARTED_EMPTY_STATE](state) {
state.emptyState = 'gettingStarted'; state.emptyState = 'gettingStarted';
}, },
...@@ -103,9 +96,6 @@ export default { ...@@ -103,9 +96,6 @@ export default {
[types.SET_ALL_DASHBOARDS](state, dashboards) { [types.SET_ALL_DASHBOARDS](state, dashboards) {
state.allDashboards = dashboards; state.allDashboards = dashboards;
}, },
[types.SET_ADDITIONAL_PANEL_TYPES_ENABLED](state, enabled) {
state.additionalPanelTypesEnabled = enabled;
},
[types.SET_SHOW_ERROR_BANNER](state, enabled) { [types.SET_SHOW_ERROR_BANNER](state, enabled) {
state.showErrorBanner = enabled; state.showErrorBanner = enabled;
}, },
......
...@@ -7,8 +7,6 @@ export default () => ({ ...@@ -7,8 +7,6 @@ export default () => ({
environmentsEndpoint: null, environmentsEndpoint: null,
deploymentsEndpoint: null, deploymentsEndpoint: null,
dashboardEndpoint: invalidUrl, dashboardEndpoint: invalidUrl,
useDashboardEndpoint: false,
additionalPanelTypesEnabled: false,
emptyState: 'gettingStarted', emptyState: 'gettingStarted',
showEmptyState: true, showEmptyState: true,
showErrorBanner: true, showErrorBanner: true,
......
...@@ -13,8 +13,6 @@ class Projects::EnvironmentsController < Projects::ApplicationController ...@@ -13,8 +13,6 @@ class Projects::EnvironmentsController < Projects::ApplicationController
before_action :verify_api_request!, only: :terminal_websocket_authorize before_action :verify_api_request!, only: :terminal_websocket_authorize
before_action :expire_etag_cache, only: [:index] before_action :expire_etag_cache, only: [:index]
before_action only: [:metrics, :additional_metrics, :metrics_dashboard] do before_action only: [:metrics, :additional_metrics, :metrics_dashboard] do
push_frontend_feature_flag(:environment_metrics_use_prometheus_endpoint, default_enabled: true)
push_frontend_feature_flag(:environment_metrics_additional_panel_types)
push_frontend_feature_flag(:prometheus_computed_alerts) push_frontend_feature_flag(:prometheus_computed_alerts)
end end
......
import { shallowMount, createLocalVue } from '@vue/test-utils'; import { shallowMount, createLocalVue } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter'; import MockAdapter from 'axios-mock-adapter';
import { GlModal, GlDropdown, GlDropdownItem } from '@gitlab/ui'; import { GlModal } from '@gitlab/ui';
import Dashboard from 'ee/monitoring/components/dashboard.vue'; import Dashboard from 'ee/monitoring/components/dashboard.vue';
import { createStore } from '~/monitoring/stores'; import { createStore } from '~/monitoring/stores';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import { metricsGroupsAPIResponse, mockApiEndpoint } from 'spec/monitoring/mock_data'; import {
metricsGroupsAPIResponse,
mockApiEndpoint,
mockedQueryResultPayload,
environmentData,
} from 'spec/monitoring/mock_data';
import propsData from 'spec/monitoring/components/dashboard_spec'; import propsData from 'spec/monitoring/components/dashboard_spec';
import AlertWidget from 'ee/monitoring/components/alert_widget.vue';
import CustomMetricsFormFields from 'ee/custom_metrics/components/custom_metrics_form_fields.vue'; import CustomMetricsFormFields from 'ee/custom_metrics/components/custom_metrics_form_fields.vue';
import * as types from '~/monitoring/stores/mutation_types';
describe('Dashboard', () => { describe('Dashboard', () => {
let Component; let Component;
...@@ -37,76 +42,20 @@ describe('Dashboard', () => { ...@@ -37,76 +42,20 @@ describe('Dashboard', () => {
mock.restore(); mock.restore();
}); });
describe('metrics with alert', () => { function setupComponentStore(component) {
describe('with license', () => { component.vm.$store.commit(
beforeEach(() => { `monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`,
vm = shallowMount(Component, { metricsGroupsAPIResponse,
propsData: { );
...propsData, component.vm.$store.commit(
hasMetrics: true, `monitoringDashboard/${types.SET_QUERY_RESULT}`,
prometheusAlertsAvailable: true, mockedQueryResultPayload,
alertsEndpoint: '/endpoint', );
}, component.vm.$store.commit(
store, `monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`,
}); environmentData,
}); );
}
it('shows alert widget and dropdown item', done => {
setTimeout(() => {
expect(vm.find(AlertWidget).exists()).toBe(true);
expect(
vm
.findAll(GlDropdownItem)
.filter(i => i.text() === 'Alerts')
.exists(),
).toBe(true);
done();
});
});
it('shows More actions dropdown on chart', done => {
setTimeout(() => {
expect(
vm
.findAll(GlDropdown)
.filter(d => d.attributes('data-original-title') === 'More actions')
.exists(),
).toBe(true);
done();
});
});
});
describe('without license', () => {
beforeEach(() => {
vm = shallowMount(Component, {
propsData: {
...propsData,
hasMetrics: true,
prometheusAlertsAvailable: false,
alertsEndpoint: '/endpoint',
},
store,
});
});
it('does not show alert widget', done => {
setTimeout(() => {
expect(vm.find(AlertWidget).exists()).toBe(false);
expect(
vm
.findAll(GlDropdownItem)
.filter(i => i.text() === 'Alerts')
.exists(),
).toBe(false);
done();
});
});
});
});
describe('add custom metrics', () => { describe('add custom metrics', () => {
describe('when not available', () => { describe('when not available', () => {
...@@ -133,7 +82,7 @@ describe('Dashboard', () => { ...@@ -133,7 +82,7 @@ describe('Dashboard', () => {
}); });
describe('when available', () => { describe('when available', () => {
beforeEach(done => { beforeEach(() => {
vm = shallowMount(Component, { vm = shallowMount(Component, {
propsData: { propsData: {
...propsData, ...propsData,
...@@ -146,11 +95,17 @@ describe('Dashboard', () => { ...@@ -146,11 +95,17 @@ describe('Dashboard', () => {
store, store,
}); });
setTimeout(done); setupComponentStore(vm);
}); });
it('renders add button on the dashboard', () => { it('renders add button on the dashboard', done => {
expect(vm.element.querySelector('.js-add-metric-button').innerText).toContain('Add metric'); localVue.nextTick(() => {
expect(vm.element.querySelector('.js-add-metric-button').innerText).toContain(
'Add metric',
);
done();
});
}); });
it('uses modal for custom metrics form', () => { it('uses modal for custom metrics form', () => {
......
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { createStore } from '~/monitoring/stores';
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import PanelType from 'ee/monitoring/components/panel_type.vue';
import { graphDataPrometheusQueryRange } from 'spec/monitoring/mock_data';
import AlertWidget from 'ee/monitoring/components/alert_widget.vue';
describe('Panel Type', () => {
let localVue;
let panelType;
let store;
const dashboardWidth = 100;
const exampleText = 'example_text';
beforeEach(() => {
window.gon = {
...window.gon,
ee: true,
};
});
describe('metrics with alert', () => {
localVue = createLocalVue();
describe('with license', () => {
beforeEach(done => {
store = createStore();
panelType = shallowMount(PanelType, {
localVue,
propsData: {
clipboardText: exampleText,
dashboardWidth,
graphData: graphDataPrometheusQueryRange,
alertsEndpoint: '/endpoint',
prometheusAlertsAvailable: true,
},
store,
sync: false,
});
panelType.vm.$nextTick(done);
});
afterEach(() => {
panelType.destroy();
});
it('shows alert widget and dropdown item', done => {
localVue.nextTick(() => {
expect(panelType.find(AlertWidget).exists()).toBe(true);
expect(
panelType
.findAll(GlDropdownItem)
.filter(i => i.text() === 'Alerts')
.exists(),
).toBe(true);
done();
});
});
it('shows More actions dropdown on chart', done => {
localVue.nextTick(() => {
expect(
panelType
.findAll(GlDropdown)
.filter(d => d.attributes('data-original-title') === 'More actions')
.exists(),
).toBe(true);
done();
});
});
});
describe('without license', () => {
beforeEach(done => {
store = createStore();
panelType = shallowMount(PanelType, {
localVue,
propsData: {
clipboardText: exampleText,
dashboardWidth,
graphData: graphDataPrometheusQueryRange,
alertsEndpoint: '/endpoint',
prometheusAlertsAvailable: false,
},
sync: false,
store,
});
panelType.vm.$nextTick(done);
});
it('does not show alert widget', done => {
setTimeout(() => {
expect(panelType.find(AlertWidget).exists()).toBe(false);
expect(
panelType
.findAll(GlDropdownItem)
.filter(i => i.text() === 'Alerts')
.exists(),
).toBe(false);
done();
});
});
});
});
});
...@@ -10810,9 +10810,6 @@ msgstr "" ...@@ -10810,9 +10810,6 @@ msgstr ""
msgid "Metrics|Unexpected deployment data response from prometheus endpoint" msgid "Metrics|Unexpected deployment data response from prometheus endpoint"
msgstr "" msgstr ""
msgid "Metrics|Unexpected metrics data response from prometheus endpoint"
msgstr ""
msgid "Metrics|Unit label" msgid "Metrics|Unit label"
msgstr "" msgstr ""
......
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import { setTestTimeout } from 'helpers/timeout';
import { createStore } from '~/monitoring/stores'; import { createStore } from '~/monitoring/stores';
import { GlLink } from '@gitlab/ui'; import { GlLink } from '@gitlab/ui';
import { GlAreaChart, GlLineChart, GlChartSeriesLabel } from '@gitlab/ui/dist/charts'; import { GlAreaChart, GlLineChart, GlChartSeriesLabel } from '@gitlab/ui/dist/charts';
import { shallowWrapperContainsSlotText } from 'helpers/vue_test_utils_helper'; import { shallowWrapperContainsSlotText } from 'helpers/vue_test_utils_helper';
import TimeSeries from '~/monitoring/components/charts/time_series.vue'; import TimeSeries from '~/monitoring/components/charts/time_series.vue';
import * as types from '~/monitoring/stores/mutation_types'; import * as types from '~/monitoring/stores/mutation_types';
import { TEST_HOST } from 'spec/test_constants'; import {
import MonitoringMock, {
deploymentData, deploymentData,
mockProjectPath, metricsGroupsAPIResponse,
} from '../../../javascripts/monitoring/mock_data'; mockedQueryResultPayload,
mockProjectDir,
mockHost,
} from '../mock_data';
import * as iconUtils from '~/lib/utils/icon_utils'; import * as iconUtils from '~/lib/utils/icon_utils';
const mockSvgPathContent = 'mockSvgPathContent'; const mockSvgPathContent = 'mockSvgPathContent';
const mockSha = 'mockSha';
const mockWidgets = 'mockWidgets'; const mockWidgets = 'mockWidgets';
const projectPath = `${TEST_HOST}${mockProjectPath}`;
const commitUrl = `${projectPath}/commit/${mockSha}`;
jest.mock('~/lib/utils/icon_utils', () => ({ jest.mock('~/lib/utils/icon_utils', () => ({
getSvgIconPathContent: jest.fn().mockImplementation( getSvgIconPathContent: jest.fn().mockImplementation(
...@@ -33,32 +34,44 @@ describe('Time series component', () => { ...@@ -33,32 +34,44 @@ describe('Time series component', () => {
let store; let store;
beforeEach(() => { beforeEach(() => {
setTestTimeout(1000);
store = createStore(); store = createStore();
store.commit(`monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`, MonitoringMock.data);
store.commit(
`monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`,
metricsGroupsAPIResponse,
);
store.commit(`monitoringDashboard/${types.RECEIVE_DEPLOYMENTS_DATA_SUCCESS}`, deploymentData); store.commit(`monitoringDashboard/${types.RECEIVE_DEPLOYMENTS_DATA_SUCCESS}`, deploymentData);
[, mockGraphData] = store.state.monitoringDashboard.dashboard.panel_groups[0].metrics;
// Mock data contains 2 panels, pick the first one
store.commit(`monitoringDashboard/${types.SET_QUERY_RESULT}`, mockedQueryResultPayload);
[mockGraphData] = store.state.monitoringDashboard.dashboard.panel_groups[0].metrics;
makeTimeSeriesChart = (graphData, type) => makeTimeSeriesChart = (graphData, type) =>
shallowMount(TimeSeries, { shallowMount(TimeSeries, {
attachToDocument: true,
propsData: { propsData: {
graphData: { ...graphData, type }, graphData: { ...graphData, type },
deploymentData: store.state.monitoringDashboard.deploymentData, deploymentData: store.state.monitoringDashboard.deploymentData,
projectPath, projectPath: `${mockHost}${mockProjectDir}`,
}, },
slots: { slots: {
default: mockWidgets, default: mockWidgets,
}, },
sync: false, sync: false,
store, store,
attachToDocument: true,
}); });
}); });
describe('general functions', () => { describe('general functions', () => {
let timeSeriesChart; let timeSeriesChart;
beforeEach(() => { beforeEach(done => {
timeSeriesChart = makeTimeSeriesChart(mockGraphData, 'area-chart'); timeSeriesChart = makeTimeSeriesChart(mockGraphData, 'area-chart');
timeSeriesChart.vm.$nextTick(done);
}); });
it('renders chart title', () => { it('renders chart title', () => {
...@@ -83,18 +96,24 @@ describe('Time series component', () => { ...@@ -83,18 +96,24 @@ describe('Time series component', () => {
describe('methods', () => { describe('methods', () => {
describe('formatTooltipText', () => { describe('formatTooltipText', () => {
const mockDate = deploymentData[0].created_at; let mockDate;
const mockCommitUrl = deploymentData[0].commitUrl; let mockCommitUrl;
const generateSeriesData = type => ({ let generateSeriesData;
seriesData: [
{ beforeEach(() => {
seriesName: timeSeriesChart.vm.chartData[0].name, mockDate = deploymentData[0].created_at;
componentSubType: type, mockCommitUrl = deploymentData[0].commitUrl;
value: [mockDate, 5.55555], generateSeriesData = type => ({
dataIndex: 0, seriesData: [
}, {
], seriesName: timeSeriesChart.vm.chartData[0].name,
value: mockDate, componentSubType: type,
value: [mockDate, 5.55555],
dataIndex: 0,
},
],
value: mockDate,
});
}); });
describe('when series is of line type', () => { describe('when series is of line type', () => {
...@@ -104,11 +123,11 @@ describe('Time series component', () => { ...@@ -104,11 +123,11 @@ describe('Time series component', () => {
}); });
it('formats tooltip title', () => { it('formats tooltip title', () => {
expect(timeSeriesChart.vm.tooltip.title).toBe('31 May 2017, 9:23PM'); expect(timeSeriesChart.vm.tooltip.title).toBe('16 Jul 2019, 10:14AM');
}); });
it('formats tooltip content', () => { it('formats tooltip content', () => {
const name = 'Core Usage'; const name = 'Pod average';
const value = '5.556'; const value = '5.556';
const dataIndex = 0; const dataIndex = 0;
const seriesLabel = timeSeriesChart.find(GlChartSeriesLabel); const seriesLabel = timeSeriesChart.find(GlChartSeriesLabel);
...@@ -129,13 +148,13 @@ describe('Time series component', () => { ...@@ -129,13 +148,13 @@ describe('Time series component', () => {
}); });
}); });
describe('when series is of scatter type', () => { describe('when series is of scatter type, for deployments', () => {
beforeEach(() => { beforeEach(() => {
timeSeriesChart.vm.formatTooltipText(generateSeriesData('scatter')); timeSeriesChart.vm.formatTooltipText(generateSeriesData('scatter'));
}); });
it('formats tooltip title', () => { it('formats tooltip title', () => {
expect(timeSeriesChart.vm.tooltip.title).toBe('31 May 2017, 9:23PM'); expect(timeSeriesChart.vm.tooltip.title).toBe('16 Jul 2019, 10:14AM');
}); });
it('formats tooltip sha', () => { it('formats tooltip sha', () => {
...@@ -274,9 +293,9 @@ describe('Time series component', () => { ...@@ -274,9 +293,9 @@ describe('Time series component', () => {
describe('scatterSeries', () => { describe('scatterSeries', () => {
it('utilizes deployment data', () => { it('utilizes deployment data', () => {
expect(timeSeriesChart.vm.scatterSeries.data).toEqual([ expect(timeSeriesChart.vm.scatterSeries.data).toEqual([
['2017-05-31T21:23:37.881Z', 0], ['2019-07-16T10:14:25.589Z', 0],
['2017-05-30T20:08:04.629Z', 0], ['2019-07-16T11:14:25.589Z', 0],
['2017-05-30T17:42:38.409Z', 0], ['2019-07-16T12:14:25.589Z', 0],
]); ]);
expect(timeSeriesChart.vm.scatterSeries.symbolSize).toBe(14); expect(timeSeriesChart.vm.scatterSeries.symbolSize).toBe(14);
...@@ -285,7 +304,7 @@ describe('Time series component', () => { ...@@ -285,7 +304,7 @@ describe('Time series component', () => {
describe('yAxisLabel', () => { describe('yAxisLabel', () => {
it('constructs a label for the chart y-axis', () => { it('constructs a label for the chart y-axis', () => {
expect(timeSeriesChart.vm.yAxisLabel).toBe('CPU'); expect(timeSeriesChart.vm.yAxisLabel).toBe('Memory Used per Pod');
}); });
}); });
}); });
...@@ -318,6 +337,10 @@ describe('Time series component', () => { ...@@ -318,6 +337,10 @@ describe('Time series component', () => {
timeSeriesAreaChart.vm.$nextTick(done); timeSeriesAreaChart.vm.$nextTick(done);
}); });
afterEach(() => {
timeSeriesAreaChart.destroy();
});
it('is a Vue instance', () => { it('is a Vue instance', () => {
expect(glChart.exists()).toBe(true); expect(glChart.exists()).toBe(true);
expect(glChart.isVueInstance()).toBe(true); expect(glChart.isVueInstance()).toBe(true);
...@@ -343,6 +366,9 @@ describe('Time series component', () => { ...@@ -343,6 +366,9 @@ describe('Time series component', () => {
}); });
describe('when tooltip is showing deployment data', () => { describe('when tooltip is showing deployment data', () => {
const mockSha = 'mockSha';
const commitUrl = `${mockProjectDir}/commit/${mockSha}`;
beforeEach(done => { beforeEach(done => {
timeSeriesAreaChart.vm.tooltip.isDeployment = true; timeSeriesAreaChart.vm.tooltip.isDeployment = true;
timeSeriesAreaChart.vm.$nextTick(done); timeSeriesAreaChart.vm.$nextTick(done);
......
export const mockHost = 'http://test.host';
export const mockProjectDir = '/frontend-fixtures/environments-project'; export const mockProjectDir = '/frontend-fixtures/environments-project';
export const anomalyDeploymentData = [ export const anomalyDeploymentData = [
...@@ -159,3 +160,171 @@ export const anomalyMockGraphData = { ...@@ -159,3 +160,171 @@ export const anomalyMockGraphData = {
}, },
], ],
}; };
export const deploymentData = [
{
id: 111,
iid: 3,
sha: 'f5bcd1d9dac6fa4137e2510b9ccd134ef2e84187',
commitUrl:
'http://test.host/frontend-fixtures/environments-project/commit/f5bcd1d9dac6fa4137e2510b9ccd134ef2e84187',
ref: {
name: 'master',
},
created_at: '2019-07-16T10:14:25.589Z',
tag: false,
tagUrl: 'http://test.host/frontend-fixtures/environments-project/tags/false',
'last?': true,
},
{
id: 110,
iid: 2,
sha: 'f5bcd1d9dac6fa4137e2510b9ccd134ef2e84187',
commitUrl:
'http://test.host/frontend-fixtures/environments-project/commit/f5bcd1d9dac6fa4137e2510b9ccd134ef2e84187',
ref: {
name: 'master',
},
created_at: '2019-07-16T11:14:25.589Z',
tag: false,
tagUrl: 'http://test.host/frontend-fixtures/environments-project/tags/false',
'last?': false,
},
{
id: 109,
iid: 1,
sha: '6511e58faafaa7ad2228990ec57f19d66f7db7c2',
commitUrl:
'http://test.host/frontend-fixtures/environments-project/commit/6511e58faafaa7ad2228990ec57f19d66f7db7c2',
ref: {
name: 'update2-readme',
},
created_at: '2019-07-16T12:14:25.589Z',
tag: false,
tagUrl: 'http://test.host/frontend-fixtures/environments-project/tags/false',
'last?': false,
},
];
export const metricsNewGroupsAPIResponse = [
{
group: 'System metrics (Kubernetes)',
priority: 5,
panels: [
{
title: 'Memory Usage (Pod average)',
type: 'area-chart',
y_label: 'Memory Used per Pod',
weight: 2,
metrics: [
{
id: 'system_metrics_kubernetes_container_memory_average',
query_range:
'avg(sum(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-([^c].*|c([^a]|a([^n]|n([^a]|a([^r]|r[^y])))).*|)-(.*)",namespace="%{kube_namespace}"}) by (job)) without (job) / count(avg(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-([^c].*|c([^a]|a([^n]|n([^a]|a([^r]|r[^y])))).*|)-(.*)",namespace="%{kube_namespace}"}) without (job)) /1024/1024',
label: 'Pod average',
unit: 'MB',
metric_id: 17,
prometheus_endpoint_path:
'/root/autodevops-deploy/environments/32/prometheus/api/v1/query_range?query=avg%28sum%28container_memory_usage_bytes%7Bcontainer_name%21%3D%22POD%22%2Cpod_name%3D~%22%5E%25%7Bci_environment_slug%7D-%28%5B%5Ec%5D.%2A%7Cc%28%5B%5Ea%5D%7Ca%28%5B%5En%5D%7Cn%28%5B%5Ea%5D%7Ca%28%5B%5Er%5D%7Cr%5B%5Ey%5D%29%29%29%29.%2A%7C%29-%28.%2A%29%22%2Cnamespace%3D%22%25%7Bkube_namespace%7D%22%7D%29+by+%28job%29%29+without+%28job%29+%2F+count%28avg%28container_memory_usage_bytes%7Bcontainer_name%21%3D%22POD%22%2Cpod_name%3D~%22%5E%25%7Bci_environment_slug%7D-%28%5B%5Ec%5D.%2A%7Cc%28%5B%5Ea%5D%7Ca%28%5B%5En%5D%7Cn%28%5B%5Ea%5D%7Ca%28%5B%5Er%5D%7Cr%5B%5Ey%5D%29%29%29%29.%2A%7C%29-%28.%2A%29%22%2Cnamespace%3D%22%25%7Bkube_namespace%7D%22%7D%29+without+%28job%29%29+%2F1024%2F1024',
appearance: {
line: {
width: 2,
},
},
},
],
},
],
},
];
export const mockedQueryResultPayload = {
metricId: '17_system_metrics_kubernetes_container_memory_average',
result: [
{
metric: {},
values: [
[1563272065.589, '10.396484375'],
[1563272125.589, '10.333984375'],
[1563272185.589, '10.333984375'],
[1563272245.589, '10.333984375'],
[1563272305.589, '10.333984375'],
[1563272365.589, '10.333984375'],
[1563272425.589, '10.38671875'],
[1563272485.589, '10.333984375'],
[1563272545.589, '10.333984375'],
[1563272605.589, '10.333984375'],
[1563272665.589, '10.333984375'],
[1563272725.589, '10.333984375'],
[1563272785.589, '10.396484375'],
[1563272845.589, '10.333984375'],
[1563272905.589, '10.333984375'],
[1563272965.589, '10.3984375'],
[1563273025.589, '10.337890625'],
[1563273085.589, '10.34765625'],
[1563273145.589, '10.337890625'],
[1563273205.589, '10.337890625'],
[1563273265.589, '10.337890625'],
[1563273325.589, '10.337890625'],
[1563273385.589, '10.337890625'],
[1563273445.589, '10.337890625'],
[1563273505.589, '10.337890625'],
[1563273565.589, '10.337890625'],
[1563273625.589, '10.337890625'],
[1563273685.589, '10.337890625'],
[1563273745.589, '10.337890625'],
[1563273805.589, '10.337890625'],
[1563273865.589, '10.390625'],
[1563273925.589, '10.390625'],
],
},
],
};
export const metricsGroupsAPIResponse = [
{
group: 'System metrics (Kubernetes)',
priority: 5,
panels: [
{
title: 'Memory Usage (Pod average)',
type: 'area-chart',
y_label: 'Memory Used per Pod',
weight: 2,
metrics: [
{
id: 'system_metrics_kubernetes_container_memory_average',
query_range:
'avg(sum(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-([^c].*|c([^a]|a([^n]|n([^a]|a([^r]|r[^y])))).*|)-(.*)",namespace="%{kube_namespace}"}) by (job)) without (job) / count(avg(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-([^c].*|c([^a]|a([^n]|n([^a]|a([^r]|r[^y])))).*|)-(.*)",namespace="%{kube_namespace}"}) without (job)) /1024/1024',
label: 'Pod average',
unit: 'MB',
metric_id: 17,
prometheus_endpoint_path:
'/root/autodevops-deploy/environments/32/prometheus/api/v1/query_range?query=avg%28sum%28container_memory_usage_bytes%7Bcontainer_name%21%3D%22POD%22%2Cpod_name%3D~%22%5E%25%7Bci_environment_slug%7D-%28%5B%5Ec%5D.%2A%7Cc%28%5B%5Ea%5D%7Ca%28%5B%5En%5D%7Cn%28%5B%5Ea%5D%7Ca%28%5B%5Er%5D%7Cr%5B%5Ey%5D%29%29%29%29.%2A%7C%29-%28.%2A%29%22%2Cnamespace%3D%22%25%7Bkube_namespace%7D%22%7D%29+by+%28job%29%29+without+%28job%29+%2F+count%28avg%28container_memory_usage_bytes%7Bcontainer_name%21%3D%22POD%22%2Cpod_name%3D~%22%5E%25%7Bci_environment_slug%7D-%28%5B%5Ec%5D.%2A%7Cc%28%5B%5Ea%5D%7Ca%28%5B%5En%5D%7Cn%28%5B%5Ea%5D%7Ca%28%5B%5Er%5D%7Cr%5B%5Ey%5D%29%29%29%29.%2A%7C%29-%28.%2A%29%22%2Cnamespace%3D%22%25%7Bkube_namespace%7D%22%7D%29+without+%28job%29%29+%2F1024%2F1024',
appearance: {
line: {
width: 2,
},
},
},
],
},
{
title: 'Core Usage (Total)',
type: 'area-chart',
y_label: 'Total Cores',
weight: 3,
metrics: [
{
id: 'system_metrics_kubernetes_container_cores_total',
query_range:
'avg(sum(rate(container_cpu_usage_seconds_total{container_name!="POD",pod_name=~"^%{ci_environment_slug}-(.*)",namespace="%{kube_namespace}"}[15m])) by (job)) without (job)',
label: 'Total',
unit: 'cores',
metric_id: 13,
},
],
},
],
},
];
import { shallowMount } from '@vue/test-utils'; import { shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter'; import AxiosMockAdapter from 'axios-mock-adapter';
import { setTestTimeout } from 'helpers/timeout';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import PanelType from '~/monitoring/components/panel_type.vue'; import PanelType from '~/monitoring/components/panel_type.vue';
import EmptyChart from '~/monitoring/components/charts/empty_chart.vue'; import EmptyChart from '~/monitoring/components/charts/empty_chart.vue';
...@@ -10,15 +11,17 @@ import { anomalyMockGraphData } from '../../frontend/monitoring/mock_data'; ...@@ -10,15 +11,17 @@ import { anomalyMockGraphData } from '../../frontend/monitoring/mock_data';
import { createStore } from '~/monitoring/stores'; import { createStore } from '~/monitoring/stores';
global.IS_EE = true; global.IS_EE = true;
global.URL.createObjectURL = jest.fn(() => {}); global.URL.createObjectURL = jest.fn();
describe('Panel Type component', () => { describe('Panel Type component', () => {
let axiosMock; let axiosMock;
let store; let store;
let panelType; let panelType;
const dashboardWidth = 100; const dashboardWidth = 100;
const exampleText = 'example_text';
beforeEach(() => { beforeEach(() => {
setTestTimeout(1000);
axiosMock = new AxiosMockAdapter(axios); axiosMock = new AxiosMockAdapter(axios);
}); });
...@@ -40,6 +43,7 @@ describe('Panel Type component', () => { ...@@ -40,6 +43,7 @@ describe('Panel Type component', () => {
graphData: graphDataNoResult, graphData: graphDataNoResult,
}, },
sync: false, sync: false,
attachToDocument: true,
}); });
}); });
...@@ -65,14 +69,13 @@ describe('Panel Type component', () => { ...@@ -65,14 +69,13 @@ describe('Panel Type component', () => {
}); });
describe('when Graph data is available', () => { describe('when Graph data is available', () => {
const exampleText = 'example_text';
const propsData = { const propsData = {
clipboardText: exampleText, clipboardText: exampleText,
dashboardWidth, dashboardWidth,
graphData: graphDataPrometheusQueryRange, graphData: graphDataPrometheusQueryRange,
}; };
beforeEach(() => { beforeEach(done => {
store = createStore(); store = createStore();
panelType = shallowMount(PanelType, { panelType = shallowMount(PanelType, {
propsData, propsData,
...@@ -80,6 +83,11 @@ describe('Panel Type component', () => { ...@@ -80,6 +83,11 @@ describe('Panel Type component', () => {
sync: false, sync: false,
attachToDocument: true, attachToDocument: true,
}); });
panelType.vm.$nextTick(done);
});
afterEach(() => {
panelType.destroy();
}); });
describe('Time Series Chart panel type', () => { describe('Time Series Chart panel type', () => {
...@@ -110,4 +118,49 @@ describe('Panel Type component', () => { ...@@ -110,4 +118,49 @@ describe('Panel Type component', () => {
}); });
}); });
}); });
describe('when downloading metrics data as CSV', () => {
beforeEach(done => {
graphDataPrometheusQueryRange.y_label = 'metric';
store = createStore();
panelType = shallowMount(PanelType, {
propsData: {
clipboardText: exampleText,
dashboardWidth,
graphData: graphDataPrometheusQueryRange,
},
store,
sync: false,
attachToDocument: true,
});
panelType.vm.$nextTick(done);
});
afterEach(() => {
panelType.destroy();
});
describe('csvText', () => {
it('converts metrics data from json to csv', () => {
const header = `timestamp,${graphDataPrometheusQueryRange.y_label}`;
const data = graphDataPrometheusQueryRange.queries[0].result[0].values;
const firstRow = `${data[0][0]},${data[0][1]}`;
const secondRow = `${data[1][0]},${data[1][1]}`;
expect(panelType.vm.csvText).toBe(`${header}\r\n${firstRow}\r\n${secondRow}\r\n`);
});
});
describe('downloadCsv', () => {
it('produces a link with a Blob', () => {
expect(global.URL.createObjectURL).toHaveBeenLastCalledWith(expect.any(Blob));
expect(global.URL.createObjectURL).toHaveBeenLastCalledWith(
expect.objectContaining({
size: panelType.vm.csvText.length,
type: 'text/plain',
}),
);
});
});
});
}); });
...@@ -7,11 +7,12 @@ import Dashboard from '~/monitoring/components/dashboard.vue'; ...@@ -7,11 +7,12 @@ import Dashboard from '~/monitoring/components/dashboard.vue';
import * as types from '~/monitoring/stores/mutation_types'; import * as types from '~/monitoring/stores/mutation_types';
import { createStore } from '~/monitoring/stores'; import { createStore } from '~/monitoring/stores';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import MonitoringMock, { import {
metricsGroupsAPIResponse, metricsGroupsAPIResponse,
mockedQueryResultPayload,
mockedQueryResultPayloadCoresTotal,
mockApiEndpoint, mockApiEndpoint,
environmentData, environmentData,
singleGroupResponse,
dashboardGitResponse, dashboardGitResponse,
} from '../mock_data'; } from '../mock_data';
...@@ -44,12 +45,33 @@ const resetSpy = spy => { ...@@ -44,12 +45,33 @@ const resetSpy = spy => {
export default propsData; export default propsData;
function setupComponentStore(component) {
component.$store.commit(
`monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`,
metricsGroupsAPIResponse,
);
// Load 2 panels to the dashboard
component.$store.commit(
`monitoringDashboard/${types.SET_QUERY_RESULT}`,
mockedQueryResultPayload,
);
component.$store.commit(
`monitoringDashboard/${types.SET_QUERY_RESULT}`,
mockedQueryResultPayloadCoresTotal,
);
component.$store.commit(
`monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`,
environmentData,
);
}
describe('Dashboard', () => { describe('Dashboard', () => {
let DashboardComponent; let DashboardComponent;
let mock; let mock;
let store; let store;
let component; let component;
let mockGraphData;
beforeEach(() => { beforeEach(() => {
setFixtures(` setFixtures(`
...@@ -123,25 +145,6 @@ describe('Dashboard', () => { ...@@ -123,25 +145,6 @@ describe('Dashboard', () => {
}); });
}); });
it('hides the legend when showLegend is false', done => {
component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'),
propsData: {
...propsData,
hasMetrics: true,
showLegend: false,
},
store,
});
setTimeout(() => {
expect(component.showEmptyState).toEqual(false);
expect(component.$el.querySelector('.legend-group')).toEqual(null);
expect(component.$el.querySelector('.prometheus-graph-group')).toBeTruthy();
done();
});
});
it('hides the group panels when showPanels is false', done => { it('hides the group panels when showPanels is false', done => {
component = new DashboardComponent({ component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'), el: document.querySelector('.prometheus-graphs'),
...@@ -153,52 +156,66 @@ describe('Dashboard', () => { ...@@ -153,52 +156,66 @@ describe('Dashboard', () => {
store, store,
}); });
setTimeout(() => { setupComponentStore(component);
expect(component.showEmptyState).toEqual(false);
expect(component.$el.querySelector('.prometheus-panel')).toEqual(null); Vue.nextTick()
expect(component.$el.querySelector('.prometheus-graph-group')).toBeTruthy(); .then(() => {
done(); expect(component.showEmptyState).toEqual(false);
}); expect(component.$el.querySelector('.prometheus-panel')).toEqual(null);
expect(component.$el.querySelector('.prometheus-graph-group')).toBeTruthy();
done();
})
.catch(done.fail);
}); });
it('renders the environments dropdown with a number of environments', done => { describe('when all the requests have been commited by the store', () => {
component = new DashboardComponent({ beforeEach(() => {
el: document.querySelector('.prometheus-graphs'), component = new DashboardComponent({
propsData: { el: document.querySelector('.prometheus-graphs'),
...propsData, propsData: {
hasMetrics: true, ...propsData,
showPanels: false, hasMetrics: true,
}, },
store, store,
});
setupComponentStore(component);
}); });
component.$store.commit( it('renders the environments dropdown with a number of environments', done => {
`monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`, Vue.nextTick()
environmentData, .then(() => {
); const dropdownMenuEnvironments = component.$el.querySelectorAll(
component.$store.commit( '.js-environments-dropdown .dropdown-item',
`monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`, );
singleGroupResponse,
);
Vue.nextTick() expect(component.environments.length).toEqual(environmentData.length);
.then(() => { expect(dropdownMenuEnvironments.length).toEqual(component.environments.length);
const dropdownMenuEnvironments = component.$el.querySelectorAll(
'.js-environments-dropdown .dropdown-item',
);
expect(component.environments.length).toEqual(environmentData.length); Array.from(dropdownMenuEnvironments).forEach((value, index) => {
expect(dropdownMenuEnvironments.length).toEqual(component.environments.length); if (environmentData[index].metrics_path) {
expect(value).toHaveAttr('href', environmentData[index].metrics_path);
}
});
Array.from(dropdownMenuEnvironments).forEach((value, index) => { done();
if (environmentData[index].metrics_path) { })
expect(value).toHaveAttr('href', environmentData[index].metrics_path); .catch(done.fail);
} });
});
done(); it('renders the environments dropdown with a single active element', done => {
}) Vue.nextTick()
.catch(done.fail); .then(() => {
const dropdownItems = component.$el.querySelectorAll(
'.js-environments-dropdown .dropdown-item.active',
);
expect(dropdownItems.length).toEqual(1);
done();
})
.catch(done.fail);
});
}); });
it('hides the environments dropdown list when there is no environments', done => { it('hides the environments dropdown list when there is no environments', done => {
...@@ -207,15 +224,17 @@ describe('Dashboard', () => { ...@@ -207,15 +224,17 @@ describe('Dashboard', () => {
propsData: { propsData: {
...propsData, ...propsData,
hasMetrics: true, hasMetrics: true,
showPanels: false,
}, },
store, store,
}); });
component.$store.commit(`monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`, []);
component.$store.commit( component.$store.commit(
`monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`, `monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`,
singleGroupResponse, metricsGroupsAPIResponse,
);
component.$store.commit(
`monitoringDashboard/${types.SET_QUERY_RESULT}`,
mockedQueryResultPayload,
); );
Vue.nextTick() Vue.nextTick()
...@@ -230,7 +249,7 @@ describe('Dashboard', () => { ...@@ -230,7 +249,7 @@ describe('Dashboard', () => {
.catch(done.fail); .catch(done.fail);
}); });
it('renders the environments dropdown with a single active element', done => { it('renders the datetimepicker dropdown', done => {
component = new DashboardComponent({ component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'), el: document.querySelector('.prometheus-graphs'),
propsData: { propsData: {
...@@ -241,64 +260,16 @@ describe('Dashboard', () => { ...@@ -241,64 +260,16 @@ describe('Dashboard', () => {
store, store,
}); });
component.$store.commit( setupComponentStore(component);
`monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`,
environmentData,
);
component.$store.commit(
`monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`,
singleGroupResponse,
);
Vue.nextTick() Vue.nextTick()
.then(() => { .then(() => {
const dropdownItems = component.$el.querySelectorAll( expect(component.$el.querySelector('.js-time-window-dropdown')).not.toBeNull();
'.js-environments-dropdown .dropdown-item.active',
);
expect(dropdownItems.length).toEqual(1);
done(); done();
}) })
.catch(done.fail); .catch(done.fail);
}); });
it('hides the dropdown', done => {
component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'),
propsData: {
...propsData,
hasMetrics: true,
showPanels: false,
environmentsEndpoint: '',
},
store,
});
Vue.nextTick(() => {
const dropdownIsActiveElement = component.$el.querySelectorAll('.environments');
expect(dropdownIsActiveElement.length).toEqual(0);
done();
});
});
it('renders the datetimepicker dropdown', done => {
component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'),
propsData: {
...propsData,
hasMetrics: true,
showPanels: false,
},
store,
});
setTimeout(() => {
expect(component.$el.querySelector('.js-time-window-dropdown')).not.toBeNull();
done();
});
});
it('fetches the metrics data with proper time window', done => { it('fetches the metrics data with proper time window', done => {
component = new DashboardComponent({ component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'), el: document.querySelector('.prometheus-graphs'),
...@@ -347,14 +318,21 @@ describe('Dashboard', () => { ...@@ -347,14 +318,21 @@ describe('Dashboard', () => {
el: document.querySelector('.prometheus-graphs'), el: document.querySelector('.prometheus-graphs'),
propsData: { ...propsData, hasMetrics: true }, propsData: { ...propsData, hasMetrics: true },
store, store,
sync: false,
}); });
setTimeout(() => { setupComponentStore(component);
const selectedTimeWindow = component.$el.querySelector('.js-time-window-dropdown .active');
expect(selectedTimeWindow.textContent.trim()).toEqual('30 minutes'); Vue.nextTick()
done(); .then(() => {
}); const selectedTimeWindow = component.$el.querySelector(
'.js-time-window-dropdown .active',
);
expect(selectedTimeWindow.textContent.trim()).toEqual('30 minutes');
done();
})
.catch(done.fail);
}); });
it('shows an error message if invalid url parameters are passed', done => { it('shows an error message if invalid url parameters are passed', done => {
...@@ -381,29 +359,36 @@ describe('Dashboard', () => { ...@@ -381,29 +359,36 @@ describe('Dashboard', () => {
describe('drag and drop function', () => { describe('drag and drop function', () => {
let wrapper; let wrapper;
let expectedPanelCount; // also called metrics, naming to be improved: https://gitlab.com/gitlab-org/gitlab/issues/31565 let expectedPanelCount; // also called metrics, naming to be improved: https://gitlab.com/gitlab-org/gitlab/issues/31565
const findDraggables = () => wrapper.findAll(VueDraggable); const findDraggables = () => wrapper.findAll(VueDraggable);
const findEnabledDraggables = () => findDraggables().filter(f => !f.attributes('disabled')); const findEnabledDraggables = () => findDraggables().filter(f => !f.attributes('disabled'));
const findDraggablePanels = () => wrapper.findAll('.js-draggable-panel'); const findDraggablePanels = () => wrapper.findAll('.js-draggable-panel');
const findRearrangeButton = () => wrapper.find('.js-rearrange-button'); const findRearrangeButton = () => wrapper.find('.js-rearrange-button');
beforeEach(done => { beforeEach(() => {
mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse); mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse);
expectedPanelCount = metricsGroupsAPIResponse.data.reduce( expectedPanelCount = metricsGroupsAPIResponse.reduce(
(acc, d) => d.metrics.length + acc, (acc, group) => group.panels.length + acc,
0, 0,
); );
store.dispatch('monitoringDashboard/setFeatureFlags', { additionalPanelTypesEnabled: true }); });
beforeEach(done => {
wrapper = shallowMount(DashboardComponent, { wrapper = shallowMount(DashboardComponent, {
localVue, localVue,
sync: false, sync: false,
propsData: { ...propsData, hasMetrics: true }, propsData: { ...propsData, hasMetrics: true },
store, store,
attachToDocument: true,
}); });
// not using $nextTicket becuase we must wait for the dashboard setupComponentStore(wrapper.vm);
// to be populated with the mock data results.
setTimeout(done); wrapper.vm.$nextTick(done);
});
afterEach(() => {
wrapper.destroy();
}); });
it('wraps vuedraggable', () => { it('wraps vuedraggable', () => {
...@@ -444,7 +429,7 @@ describe('Dashboard', () => { ...@@ -444,7 +429,7 @@ describe('Dashboard', () => {
it('metrics can be swapped', done => { it('metrics can be swapped', done => {
const firstDraggable = findDraggables().at(0); const firstDraggable = findDraggables().at(0);
const mockMetrics = [...metricsGroupsAPIResponse.data[0].metrics]; const mockMetrics = [...metricsGroupsAPIResponse[0].panels];
const value = () => firstDraggable.props('value'); const value = () => firstDraggable.props('value');
expect(value().length).toBe(mockMetrics.length); expect(value().length).toBe(mockMetrics.length);
...@@ -486,10 +471,6 @@ describe('Dashboard', () => { ...@@ -486,10 +471,6 @@ describe('Dashboard', () => {
}); });
}); });
}); });
afterEach(() => {
wrapper.destroy();
});
}); });
// https://gitlab.com/gitlab-org/gitlab-ce/issues/66922 // https://gitlab.com/gitlab-org/gitlab-ce/issues/66922
...@@ -577,24 +558,7 @@ describe('Dashboard', () => { ...@@ -577,24 +558,7 @@ describe('Dashboard', () => {
store, store,
}); });
component.$store.dispatch('monitoringDashboard/setFeatureFlags', { setupComponentStore(component);
prometheusEndpoint: false,
});
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,
);
return Vue.nextTick().then(() => { return Vue.nextTick().then(() => {
promPanel = component.$el.querySelector('.prometheus-panel'); promPanel = component.$el.querySelector('.prometheus-panel');
...@@ -707,20 +671,6 @@ describe('Dashboard', () => { ...@@ -707,20 +671,6 @@ describe('Dashboard', () => {
store, store,
}); });
component.$store.dispatch('monitoringDashboard/setFeatureFlags', {
prometheusEndpoint: false,
});
component.$store.commit(
`monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`,
environmentData,
);
component.$store.commit(
`monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`,
singleGroupResponse,
);
component.$store.commit( component.$store.commit(
`monitoringDashboard/${types.SET_ALL_DASHBOARDS}`, `monitoringDashboard/${types.SET_ALL_DASHBOARDS}`,
dashboardGitResponse, dashboardGitResponse,
...@@ -736,38 +686,4 @@ describe('Dashboard', () => { ...@@ -736,38 +686,4 @@ describe('Dashboard', () => {
}); });
}); });
}); });
describe('when downloading metrics data as CSV', () => {
beforeEach(() => {
component = new DashboardComponent({
propsData: {
...propsData,
},
store,
});
store.commit(
`monitoringDashboard/${types.RECEIVE_METRICS_DATA_SUCCESS}`,
MonitoringMock.data,
);
[
mockGraphData,
] = component.$store.state.monitoringDashboard.dashboard.panel_groups[0].metrics;
});
describe('csvText', () => {
it('converts metrics data from json to csv', () => {
const header = `timestamp,${mockGraphData.y_label}`;
const data = mockGraphData.queries[0].result[0].values;
const firstRow = `${data[0][0]},${data[0][1]}`;
expect(component.csvText(mockGraphData)).toMatch(`^${header}\r\n${firstRow}`);
});
});
describe('downloadCsv', () => {
it('produces a link with a Blob', () => {
expect(component.downloadCsv(mockGraphData)).toContain(`blob:`);
});
});
});
}); });
import { anomalyMockGraphData as importedAnomalyMockGraphData } from '../../frontend/monitoring/mock_data'; import {
anomalyMockGraphData as importedAnomalyMockGraphData,
deploymentData as importedDeploymentData,
metricsNewGroupsAPIResponse as importedMetricsNewGroupsAPIResponse,
metricsGroupsAPIResponse as importedMetricsGroupsAPIResponse,
} from '../../frontend/monitoring/mock_data';
// TODO Check if these exports are still needed
export const anomalyMockGraphData = importedAnomalyMockGraphData; export const anomalyMockGraphData = importedAnomalyMockGraphData;
export const deploymentData = importedDeploymentData;
export const metricsNewGroupsAPIResponse = importedMetricsNewGroupsAPIResponse;
export const metricsGroupsAPIResponse = importedMetricsGroupsAPIResponse;
export const mockApiEndpoint = `${gl.TEST_HOST}/monitoring/mock`; export const mockApiEndpoint = `${gl.TEST_HOST}/monitoring/mock`;
export const mockProjectPath = '/frontend-fixtures/environments-project'; export const mockProjectPath = '/frontend-fixtures/environments-project';
export const metricsGroupsAPIResponse = { export const mockedQueryResultPayload = {
success: true, metricId: '17_system_metrics_kubernetes_container_memory_average',
data: [ result: [
{ {
group: 'Kubernetes', metric: {},
priority: 1, values: [
metrics: [ [1563272065.589, '10.396484375'],
{ [1563272125.589, '10.333984375'],
id: 5, [1563272185.589, '10.333984375'],
title: 'Memory usage', [1563272245.589, '10.333984375'],
weight: 1, [1563272305.589, '10.333984375'],
queries: [ [1563272365.589, '10.333984375'],
{ [1563272425.589, '10.38671875'],
query_range: 'avg(container_memory_usage_bytes{%{environment_filter}}) / 2^20', [1563272485.589, '10.333984375'],
label: 'Memory', [1563272545.589, '10.333984375'],
unit: 'MiB', [1563272605.589, '10.333984375'],
result: [ [1563272665.589, '10.333984375'],
{ [1563272725.589, '10.333984375'],
metric: {}, [1563272785.589, '10.396484375'],
values: [ [1563272845.589, '10.333984375'],
[1495700554.925, '8.0390625'], [1563272905.589, '10.333984375'],
[1495700614.925, '8.0390625'], [1563272965.589, '10.3984375'],
[1495700674.925, '8.0390625'], [1563273025.589, '10.337890625'],
[1495700734.925, '8.0390625'], [1563273085.589, '10.34765625'],
[1495700794.925, '8.0390625'], [1563273145.589, '10.337890625'],
[1495700854.925, '8.0390625'], [1563273205.589, '10.337890625'],
[1495700914.925, '8.0390625'], [1563273265.589, '10.337890625'],
[1495700974.925, '8.0390625'], [1563273325.589, '10.337890625'],
[1495701034.925, '8.0390625'], [1563273385.589, '10.337890625'],
[1495701094.925, '8.0390625'], [1563273445.589, '10.337890625'],
[1495701154.925, '8.0390625'], [1563273505.589, '10.337890625'],
[1495701214.925, '8.0390625'], [1563273565.589, '10.337890625'],
[1495701274.925, '8.0390625'], [1563273625.589, '10.337890625'],
[1495701334.925, '8.0390625'], [1563273685.589, '10.337890625'],
[1495701394.925, '8.0390625'], [1563273745.589, '10.337890625'],
[1495701454.925, '8.0390625'], [1563273805.589, '10.337890625'],
[1495701514.925, '8.0390625'], [1563273865.589, '10.390625'],
[1495701574.925, '8.0390625'], [1563273925.589, '10.390625'],
[1495701634.925, '8.0390625'],
[1495701694.925, '8.0390625'],
[1495701754.925, '8.0390625'],
[1495701814.925, '8.0390625'],
[1495701874.925, '8.0390625'],
[1495701934.925, '8.0390625'],
[1495701994.925, '8.0390625'],
[1495702054.925, '8.0390625'],
[1495702114.925, '8.0390625'],
[1495702174.925, '8.0390625'],
[1495702234.925, '8.0390625'],
[1495702294.925, '8.0390625'],
[1495702354.925, '8.0390625'],
[1495702414.925, '8.0390625'],
[1495702474.925, '8.0390625'],
[1495702534.925, '8.0390625'],
[1495702594.925, '8.0390625'],
[1495702654.925, '8.0390625'],
[1495702714.925, '8.0390625'],
[1495702774.925, '8.0390625'],
[1495702834.925, '8.0390625'],
[1495702894.925, '8.0390625'],
[1495702954.925, '8.0390625'],
[1495703014.925, '8.0390625'],
[1495703074.925, '8.0390625'],
[1495703134.925, '8.0390625'],
[1495703194.925, '8.0390625'],
[1495703254.925, '8.03515625'],
[1495703314.925, '8.03515625'],
[1495703374.925, '8.03515625'],
[1495703434.925, '8.03515625'],
[1495703494.925, '8.03515625'],
[1495703554.925, '8.03515625'],
[1495703614.925, '8.03515625'],
[1495703674.925, '8.03515625'],
[1495703734.925, '8.03515625'],
[1495703794.925, '8.03515625'],
[1495703854.925, '8.03515625'],
[1495703914.925, '8.03515625'],
[1495703974.925, '8.03515625'],
[1495704034.925, '8.03515625'],
[1495704094.925, '8.03515625'],
[1495704154.925, '8.03515625'],
[1495704214.925, '7.9296875'],
[1495704274.925, '7.9296875'],
[1495704334.925, '7.9296875'],
[1495704394.925, '7.9296875'],
[1495704454.925, '7.9296875'],
[1495704514.925, '7.9296875'],
[1495704574.925, '7.9296875'],
[1495704634.925, '7.9296875'],
[1495704694.925, '7.9296875'],
[1495704754.925, '7.9296875'],
[1495704814.925, '7.9296875'],
[1495704874.925, '7.9296875'],
[1495704934.925, '7.9296875'],
[1495704994.925, '7.9296875'],
[1495705054.925, '7.9296875'],
[1495705114.925, '7.9296875'],
[1495705174.925, '7.9296875'],
[1495705234.925, '7.9296875'],
[1495705294.925, '7.9296875'],
[1495705354.925, '7.9296875'],
[1495705414.925, '7.9296875'],
[1495705474.925, '7.9296875'],
[1495705534.925, '7.9296875'],
[1495705594.925, '7.9296875'],
[1495705654.925, '7.9296875'],
[1495705714.925, '7.9296875'],
[1495705774.925, '7.9296875'],
[1495705834.925, '7.9296875'],
[1495705894.925, '7.9296875'],
[1495705954.925, '7.9296875'],
[1495706014.925, '7.9296875'],
[1495706074.925, '7.9296875'],
[1495706134.925, '7.9296875'],
[1495706194.925, '7.9296875'],
[1495706254.925, '7.9296875'],
[1495706314.925, '7.9296875'],
[1495706374.925, '7.9296875'],
[1495706434.925, '7.9296875'],
[1495706494.925, '7.9296875'],
[1495706554.925, '7.9296875'],
[1495706614.925, '7.9296875'],
[1495706674.925, '7.9296875'],
[1495706734.925, '7.9296875'],
[1495706794.925, '7.9296875'],
[1495706854.925, '7.9296875'],
[1495706914.925, '7.9296875'],
[1495706974.925, '7.9296875'],
[1495707034.925, '7.9296875'],
[1495707094.925, '7.9296875'],
[1495707154.925, '7.9296875'],
[1495707214.925, '7.9296875'],
[1495707274.925, '7.9296875'],
[1495707334.925, '7.9296875'],
[1495707394.925, '7.9296875'],
[1495707454.925, '7.9296875'],
[1495707514.925, '7.9296875'],
[1495707574.925, '7.9296875'],
[1495707634.925, '7.9296875'],
[1495707694.925, '7.9296875'],
[1495707754.925, '7.9296875'],
[1495707814.925, '7.9296875'],
[1495707874.925, '7.9296875'],
[1495707934.925, '7.9296875'],
[1495707994.925, '7.9296875'],
[1495708054.925, '7.9296875'],
[1495708114.925, '7.9296875'],
[1495708174.925, '7.9296875'],
[1495708234.925, '7.9296875'],
[1495708294.925, '7.9296875'],
[1495708354.925, '7.9296875'],
[1495708414.925, '7.9296875'],
[1495708474.925, '7.9296875'],
[1495708534.925, '7.9296875'],
[1495708594.925, '7.9296875'],
[1495708654.925, '7.9296875'],
[1495708714.925, '7.9296875'],
[1495708774.925, '7.9296875'],
[1495708834.925, '7.9296875'],
[1495708894.925, '7.9296875'],
[1495708954.925, '7.8984375'],
[1495709014.925, '7.8984375'],
[1495709074.925, '7.8984375'],
[1495709134.925, '7.8984375'],
[1495709194.925, '7.8984375'],
[1495709254.925, '7.89453125'],
[1495709314.925, '7.89453125'],
[1495709374.925, '7.89453125'],
[1495709434.925, '7.89453125'],
[1495709494.925, '7.89453125'],
[1495709554.925, '7.89453125'],
[1495709614.925, '7.89453125'],
[1495709674.925, '7.89453125'],
[1495709734.925, '7.89453125'],
[1495709794.925, '7.89453125'],
[1495709854.925, '7.89453125'],
[1495709914.925, '7.89453125'],
[1495709974.925, '7.89453125'],
[1495710034.925, '7.89453125'],
[1495710094.925, '7.89453125'],
[1495710154.925, '7.89453125'],
[1495710214.925, '7.89453125'],
[1495710274.925, '7.89453125'],
[1495710334.925, '7.89453125'],
[1495710394.925, '7.89453125'],
[1495710454.925, '7.89453125'],
[1495710514.925, '7.89453125'],
[1495710574.925, '7.89453125'],
[1495710634.925, '7.89453125'],
[1495710694.925, '7.89453125'],
[1495710754.925, '7.89453125'],
[1495710814.925, '7.89453125'],
[1495710874.925, '7.89453125'],
[1495710934.925, '7.89453125'],
[1495710994.925, '7.89453125'],
[1495711054.925, '7.89453125'],
[1495711114.925, '7.89453125'],
[1495711174.925, '7.8515625'],
[1495711234.925, '7.8515625'],
[1495711294.925, '7.8515625'],
[1495711354.925, '7.8515625'],
[1495711414.925, '7.8515625'],
[1495711474.925, '7.8515625'],
[1495711534.925, '7.8515625'],
[1495711594.925, '7.8515625'],
[1495711654.925, '7.8515625'],
[1495711714.925, '7.8515625'],
[1495711774.925, '7.8515625'],
[1495711834.925, '7.8515625'],
[1495711894.925, '7.8515625'],
[1495711954.925, '7.8515625'],
[1495712014.925, '7.8515625'],
[1495712074.925, '7.8515625'],
[1495712134.925, '7.8515625'],
[1495712194.925, '7.8515625'],
[1495712254.925, '7.8515625'],
[1495712314.925, '7.8515625'],
[1495712374.925, '7.8515625'],
[1495712434.925, '7.83203125'],
[1495712494.925, '7.83203125'],
[1495712554.925, '7.83203125'],
[1495712614.925, '7.83203125'],
[1495712674.925, '7.83203125'],
[1495712734.925, '7.83203125'],
[1495712794.925, '7.83203125'],
[1495712854.925, '7.83203125'],
[1495712914.925, '7.83203125'],
[1495712974.925, '7.83203125'],
[1495713034.925, '7.83203125'],
[1495713094.925, '7.83203125'],
[1495713154.925, '7.83203125'],
[1495713214.925, '7.83203125'],
[1495713274.925, '7.83203125'],
[1495713334.925, '7.83203125'],
[1495713394.925, '7.8125'],
[1495713454.925, '7.8125'],
[1495713514.925, '7.8125'],
[1495713574.925, '7.8125'],
[1495713634.925, '7.8125'],
[1495713694.925, '7.8125'],
[1495713754.925, '7.8125'],
[1495713814.925, '7.8125'],
[1495713874.925, '7.8125'],
[1495713934.925, '7.8125'],
[1495713994.925, '7.8125'],
[1495714054.925, '7.8125'],
[1495714114.925, '7.8125'],
[1495714174.925, '7.8125'],
[1495714234.925, '7.8125'],
[1495714294.925, '7.8125'],
[1495714354.925, '7.80859375'],
[1495714414.925, '7.80859375'],
[1495714474.925, '7.80859375'],
[1495714534.925, '7.80859375'],
[1495714594.925, '7.80859375'],
[1495714654.925, '7.80859375'],
[1495714714.925, '7.80859375'],
[1495714774.925, '7.80859375'],
[1495714834.925, '7.80859375'],
[1495714894.925, '7.80859375'],
[1495714954.925, '7.80859375'],
[1495715014.925, '7.80859375'],
[1495715074.925, '7.80859375'],
[1495715134.925, '7.80859375'],
[1495715194.925, '7.80859375'],
[1495715254.925, '7.80859375'],
[1495715314.925, '7.80859375'],
[1495715374.925, '7.80859375'],
[1495715434.925, '7.80859375'],
[1495715494.925, '7.80859375'],
[1495715554.925, '7.80859375'],
[1495715614.925, '7.80859375'],
[1495715674.925, '7.80859375'],
[1495715734.925, '7.80859375'],
[1495715794.925, '7.80859375'],
[1495715854.925, '7.80859375'],
[1495715914.925, '7.80078125'],
[1495715974.925, '7.80078125'],
[1495716034.925, '7.80078125'],
[1495716094.925, '7.80078125'],
[1495716154.925, '7.80078125'],
[1495716214.925, '7.796875'],
[1495716274.925, '7.796875'],
[1495716334.925, '7.796875'],
[1495716394.925, '7.796875'],
[1495716454.925, '7.796875'],
[1495716514.925, '7.796875'],
[1495716574.925, '7.796875'],
[1495716634.925, '7.796875'],
[1495716694.925, '7.796875'],
[1495716754.925, '7.796875'],
[1495716814.925, '7.796875'],
[1495716874.925, '7.79296875'],
[1495716934.925, '7.79296875'],
[1495716994.925, '7.79296875'],
[1495717054.925, '7.79296875'],
[1495717114.925, '7.79296875'],
[1495717174.925, '7.7890625'],
[1495717234.925, '7.7890625'],
[1495717294.925, '7.7890625'],
[1495717354.925, '7.7890625'],
[1495717414.925, '7.7890625'],
[1495717474.925, '7.7890625'],
[1495717534.925, '7.7890625'],
[1495717594.925, '7.7890625'],
[1495717654.925, '7.7890625'],
[1495717714.925, '7.7890625'],
[1495717774.925, '7.7890625'],
[1495717834.925, '7.77734375'],
[1495717894.925, '7.77734375'],
[1495717954.925, '7.77734375'],
[1495718014.925, '7.77734375'],
[1495718074.925, '7.77734375'],
[1495718134.925, '7.7421875'],
[1495718194.925, '7.7421875'],
[1495718254.925, '7.7421875'],
[1495718314.925, '7.7421875'],
],
},
],
},
],
},
{
id: 6,
title: 'CPU usage',
y_label: 'CPU',
weight: 1,
queries: [
{
appearance: {
line: {
width: 2,
},
},
query_range:
'avg(rate(container_cpu_usage_seconds_total{%{environment_filter}}[2m])) * 100',
label: 'Core Usage',
unit: 'Cores',
result: [
{
metric: {},
values: [
[1495700554.925, '0.0010794445585559514'],
[1495700614.925, '0.003927214935433527'],
[1495700674.925, '0.0053045219047619975'],
[1495700734.925, '0.0048892095238097155'],
[1495700794.925, '0.005827140952381137'],
[1495700854.925, '0.00569846906219937'],
[1495700914.925, '0.004972616802849382'],
[1495700974.925, '0.005117509523809902'],
[1495701034.925, '0.00512389061919564'],
[1495701094.925, '0.005199100501890691'],
[1495701154.925, '0.005415746394885837'],
[1495701214.925, '0.005607682788146286'],
[1495701274.925, '0.005641300000000118'],
[1495701334.925, '0.0071166279368766495'],
[1495701394.925, '0.0063242138095234044'],
[1495701454.925, '0.005793314698235304'],
[1495701514.925, '0.00703934942237556'],
[1495701574.925, '0.006357007076123191'],
[1495701634.925, '0.003753167300126738'],
[1495701694.925, '0.005018469678430698'],
[1495701754.925, '0.0045217153371887'],
[1495701814.925, '0.006140104285714119'],
[1495701874.925, '0.004818684285714102'],
[1495701934.925, '0.005079509718955242'],
[1495701994.925, '0.005059981142498263'],
[1495702054.925, '0.005269098389538773'],
[1495702114.925, '0.005269954285714175'],
[1495702174.925, '0.014199241435795856'],
[1495702234.925, '0.01511936843111017'],
[1495702294.925, '0.0060933692920682875'],
[1495702354.925, '0.004945682380952493'],
[1495702414.925, '0.005641266666666565'],
[1495702474.925, '0.005223752857142996'],
[1495702534.925, '0.005743098505699831'],
[1495702594.925, '0.00538493380952391'],
[1495702654.925, '0.005507793883751339'],
[1495702714.925, '0.005666705714285466'],
[1495702774.925, '0.006231530000000112'],
[1495702834.925, '0.006570768635394899'],
[1495702894.925, '0.005551146666666895'],
[1495702954.925, '0.005602604737098058'],
[1495703014.925, '0.00613993580402159'],
[1495703074.925, '0.004770258764368832'],
[1495703134.925, '0.005512376671364914'],
[1495703194.925, '0.005254436666666674'],
[1495703254.925, '0.0050109839141320505'],
[1495703314.925, '0.0049478019256960016'],
[1495703374.925, '0.0037666860965123463'],
[1495703434.925, '0.004813526061656314'],
[1495703494.925, '0.005047748095238278'],
[1495703554.925, '0.00386494081008772'],
[1495703614.925, '0.004304037408111405'],
[1495703674.925, '0.004999466661587168'],
[1495703734.925, '0.004689140476190834'],
[1495703794.925, '0.004746126153582475'],
[1495703854.925, '0.004482706382572302'],
[1495703914.925, '0.004032808931864524'],
[1495703974.925, '0.005728319047618988'],
[1495704034.925, '0.004436139179627006'],
[1495704094.925, '0.004553455714285617'],
[1495704154.925, '0.003455244285714341'],
[1495704214.925, '0.004742244761904621'],
[1495704274.925, '0.005366978571428422'],
[1495704334.925, '0.004257954837665058'],
[1495704394.925, '0.005431603259831257'],
[1495704454.925, '0.0052009214498621986'],
[1495704514.925, '0.004317201904761618'],
[1495704574.925, '0.004307384285714157'],
[1495704634.925, '0.004789801146644822'],
[1495704694.925, '0.0051429795906706485'],
[1495704754.925, '0.005322495714285479'],
[1495704814.925, '0.004512809333244233'],
[1495704874.925, '0.004953843582568726'],
[1495704934.925, '0.005812690120858119'],
[1495704994.925, '0.004997024285714838'],
[1495705054.925, '0.005246216154439592'],
[1495705114.925, '0.0063494966618726795'],
[1495705174.925, '0.005306004342898225'],
[1495705234.925, '0.005081412857142978'],
[1495705294.925, '0.00511409523809522'],
[1495705354.925, '0.0047861001481192'],
[1495705414.925, '0.005107688228042962'],
[1495705474.925, '0.005271929582294012'],
[1495705534.925, '0.004453254502681249'],
[1495705594.925, '0.005799134293959226'],
[1495705654.925, '0.005340865929502478'],
[1495705714.925, '0.004911654761904942'],
[1495705774.925, '0.005888234873953261'],
[1495705834.925, '0.005565283333332954'],
[1495705894.925, '0.005522869047618869'],
[1495705954.925, '0.005177549737621646'],
[1495706014.925, '0.0053145810232096465'],
[1495706074.925, '0.004751095238095275'],
[1495706134.925, '0.006242077142856976'],
[1495706194.925, '0.00621034406957871'],
[1495706254.925, '0.006887592738978596'],
[1495706314.925, '0.006328128779726213'],
[1495706374.925, '0.007488363809523927'],
[1495706434.925, '0.006193758571428157'],
[1495706494.925, '0.0068798371839706935'],
[1495706554.925, '0.005757034340423128'],
[1495706614.925, '0.004571388497294698'],
[1495706674.925, '0.00620283044923395'],
[1495706734.925, '0.005607562380952455'],
[1495706794.925, '0.005506969933620308'],
[1495706854.925, '0.005621118095238131'],
[1495706914.925, '0.004876606098698849'],
[1495706974.925, '0.0047871205988517206'],
[1495707034.925, '0.00526405939458784'],
[1495707094.925, '0.005716323800605852'],
[1495707154.925, '0.005301459523809575'],
[1495707214.925, '0.0051613042857144905'],
[1495707274.925, '0.005384792857142714'],
[1495707334.925, '0.005259719047619222'],
[1495707394.925, '0.00584101142857182'],
[1495707454.925, '0.0060066121920326326'],
[1495707514.925, '0.006359978571428453'],
[1495707574.925, '0.006315876322151109'],
[1495707634.925, '0.005590012517198831'],
[1495707694.925, '0.005517419877137072'],
[1495707754.925, '0.006089813430348506'],
[1495707814.925, '0.00466754476190479'],
[1495707874.925, '0.006059954380517721'],
[1495707934.925, '0.005085657142856972'],
[1495707994.925, '0.005897665238095296'],
[1495708054.925, '0.0062282023199555885'],
[1495708114.925, '0.00526214553236979'],
[1495708174.925, '0.0044803300000000644'],
[1495708234.925, '0.005421443333333592'],
[1495708294.925, '0.005694326244512144'],
[1495708354.925, '0.005527721904761457'],
[1495708414.925, '0.005988819523809819'],
[1495708474.925, '0.005484704285714448'],
[1495708534.925, '0.005041123649230085'],
[1495708594.925, '0.005717767639612059'],
[1495708654.925, '0.005412954417342863'],
[1495708714.925, '0.005833343333333254'],
[1495708774.925, '0.005448135238094969'],
[1495708834.925, '0.005117341428571432'],
[1495708894.925, '0.005888345825277833'],
[1495708954.925, '0.005398543809524135'],
[1495709014.925, '0.005325611428571416'],
[1495709074.925, '0.005848668571428527'],
[1495709134.925, '0.005135003105145044'],
[1495709194.925, '0.0054551400000003'],
[1495709254.925, '0.005319472937322171'],
[1495709314.925, '0.00585677857142792'],
[1495709374.925, '0.0062146261904759215'],
[1495709434.925, '0.0067105060904182265'],
[1495709494.925, '0.005829691904762108'],
[1495709554.925, '0.005719280952381261'],
[1495709614.925, '0.005682603793416407'],
[1495709674.925, '0.0055272846277326934'],
[1495709734.925, '0.0057123680952386735'],
[1495709794.925, '0.00520597958075818'],
[1495709854.925, '0.005584358957263837'],
[1495709914.925, '0.005601104275197466'],
[1495709974.925, '0.005991657142857066'],
[1495710034.925, '0.00553722238095218'],
[1495710094.925, '0.005127883122696293'],
[1495710154.925, '0.005498111927534584'],
[1495710214.925, '0.005609934069084202'],
[1495710274.925, '0.00459206285714307'],
[1495710334.925, '0.0047910828571428084'],
[1495710394.925, '0.0056014671288845685'],
[1495710454.925, '0.005686936791078528'],
[1495710514.925, '0.00444480476190448'],
[1495710574.925, '0.005780394696738921'],
[1495710634.925, '0.0053107227550210365'],
[1495710694.925, '0.005096031495761817'],
[1495710754.925, '0.005451377979091524'],
[1495710814.925, '0.005328136666667083'],
[1495710874.925, '0.006020612857143043'],
[1495710934.925, '0.0061063585714285365'],
[1495710994.925, '0.006018346015752312'],
[1495711054.925, '0.005069130952381193'],
[1495711114.925, '0.005458406190476052'],
[1495711174.925, '0.00577219190476179'],
[1495711234.925, '0.005760814645658314'],
[1495711294.925, '0.005371875716579101'],
[1495711354.925, '0.0064232666666665834'],
[1495711414.925, '0.009369806836906667'],
[1495711474.925, '0.008956864761904692'],
[1495711534.925, '0.005266849368559271'],
[1495711594.925, '0.005335111364934262'],
[1495711654.925, '0.006461778319586945'],
[1495711714.925, '0.004687939890762393'],
[1495711774.925, '0.004438831245760684'],
[1495711834.925, '0.005142786666666613'],
[1495711894.925, '0.007257734212054963'],
[1495711954.925, '0.005621991904761494'],
[1495712014.925, '0.007868689999999862'],
[1495712074.925, '0.00910970215275738'],
[1495712134.925, '0.006151004285714278'],
[1495712194.925, '0.005447120924961522'],
[1495712254.925, '0.005150705153929503'],
[1495712314.925, '0.006358108714969314'],
[1495712374.925, '0.0057725354795696475'],
[1495712434.925, '0.005232139047619015'],
[1495712494.925, '0.004932809617949037'],
[1495712554.925, '0.004511607508499662'],
[1495712614.925, '0.00440487701522666'],
[1495712674.925, '0.005479113333333174'],
[1495712734.925, '0.004726317619047547'],
[1495712794.925, '0.005582041102958029'],
[1495712854.925, '0.006381481216082099'],
[1495712914.925, '0.005474260014095208'],
[1495712974.925, '0.00567597142857188'],
[1495713034.925, '0.0064741233333332985'],
[1495713094.925, '0.005467475714285271'],
[1495713154.925, '0.004868648393824457'],
[1495713214.925, '0.005254923286444893'],
[1495713274.925, '0.005599217150312865'],
[1495713334.925, '0.005105413720618919'],
[1495713394.925, '0.007246073333333279'],
[1495713454.925, '0.005990312380952272'],
[1495713514.925, '0.005594601853351101'],
[1495713574.925, '0.004739258673727054'],
[1495713634.925, '0.003932121428571783'],
[1495713694.925, '0.005018188268459395'],
[1495713754.925, '0.004538238095237985'],
[1495713814.925, '0.00561816643265435'],
[1495713874.925, '0.0063132584495033586'],
[1495713934.925, '0.00442385238095213'],
[1495713994.925, '0.004181795887658453'],
[1495714054.925, '0.004437759047619037'],
[1495714114.925, '0.006421748157178241'],
[1495714174.925, '0.006525143809523842'],
[1495714234.925, '0.004715904935144247'],
[1495714294.925, '0.005966040152763461'],
[1495714354.925, '0.005614535466921674'],
[1495714414.925, '0.004934375119415906'],
[1495714474.925, '0.0054122933333327385'],
[1495714534.925, '0.004926540699612279'],
[1495714594.925, '0.006124649517134237'],
[1495714654.925, '0.004629427092013995'],
[1495714714.925, '0.005117951257607005'],
[1495714774.925, '0.004868774512685422'],
[1495714834.925, '0.005310093333333399'],
[1495714894.925, '0.0054907752286127345'],
[1495714954.925, '0.004597678117351089'],
[1495715014.925, '0.0059622552380952'],
[1495715074.925, '0.005352457072655368'],
[1495715134.925, '0.005491630952381143'],
[1495715194.925, '0.006391770078379791'],
[1495715254.925, '0.005933472857142518'],
[1495715314.925, '0.005301314285714163'],
[1495715374.925, '0.0058352959724814165'],
[1495715434.925, '0.006154755147867044'],
[1495715494.925, '0.009391935637482038'],
[1495715554.925, '0.007846462857142592'],
[1495715614.925, '0.00477608215316353'],
[1495715674.925, '0.006132865238094998'],
[1495715734.925, '0.006159762457649516'],
[1495715794.925, '0.005957307073265968'],
[1495715854.925, '0.006652319091792501'],
[1495715914.925, '0.005493557402895287'],
[1495715974.925, '0.0058652434829145166'],
[1495716034.925, '0.005627400430468021'],
[1495716094.925, '0.006240656190475609'],
[1495716154.925, '0.006305997676168624'],
[1495716214.925, '0.005388057732783248'],
[1495716274.925, '0.0052814916048421244'],
[1495716334.925, '0.00699498614272497'],
[1495716394.925, '0.00627768693035141'],
[1495716454.925, '0.0042411487048161145'],
[1495716514.925, '0.005348647473627653'],
[1495716574.925, '0.0047176657142853975'],
[1495716634.925, '0.004437898571428686'],
[1495716694.925, '0.004923527366927261'],
[1495716754.925, '0.005131935066048421'],
[1495716814.925, '0.005046949523809611'],
[1495716874.925, '0.00547184095238092'],
[1495716934.925, '0.005224140016380444'],
[1495716994.925, '0.005297991171665292'],
[1495717054.925, '0.005492965995623498'],
[1495717114.925, '0.005754660000000403'],
[1495717174.925, '0.005949557138639285'],
[1495717234.925, '0.006091816112534666'],
[1495717294.925, '0.005554210080192063'],
[1495717354.925, '0.006411504395279871'],
[1495717414.925, '0.006319643996609606'],
[1495717474.925, '0.005539174405717675'],
[1495717534.925, '0.0053157078842772255'],
[1495717594.925, '0.005247480952381066'],
[1495717654.925, '0.004820141620396252'],
[1495717714.925, '0.005906173868322844'],
[1495717774.925, '0.006173117219570961'],
[1495717834.925, '0.005963340952380661'],
[1495717894.925, '0.005698976627681527'],
[1495717954.925, '0.004751279096346378'],
[1495718014.925, '0.005733142379359711'],
[1495718074.925, '0.004831689010348035'],
[1495718134.925, '0.005188370476191092'],
[1495718194.925, '0.004793227554547938'],
[1495718254.925, '0.003997442857142731'],
[1495718314.925, '0.004386040132951264'],
],
},
],
},
],
},
],
},
{
group: 'NGINX',
priority: 2,
metrics: [
{
id: 100,
title: 'Http Error Rate',
weight: 100,
queries: [
{
query_range:
'sum(rate(nginx_upstream_responses_total{status_code="5xx", upstream=~"nginx-test-8691397-production-.*"}[2m])) / sum(rate(nginx_upstream_responses_total{upstream=~"nginx-test-8691397-production-.*"}[2m])) * 100',
label: '5xx errors',
unit: '%',
result: [
{
metric: {},
values: [
[1495700554.925, NaN],
[1495700614.925, NaN],
[1495700674.925, NaN],
[1495700734.925, NaN],
[1495700794.925, NaN],
[1495700854.925, NaN],
[1495700914.925, NaN],
],
},
],
},
],
},
], ],
}, },
], ],
last_update: '2017-05-25T13:18:34.949Z',
}; };
export const singleGroupResponse = [ export const mockedQueryResultPayloadCoresTotal = {
{ metricId: '13_system_metrics_kubernetes_container_cores_total',
group: 'System metrics (Kubernetes)', result: [
priority: 5,
metrics: [
{
title: 'Memory Usage (Total)',
weight: 0,
y_label: 'Total Memory Used',
queries: [
{
query_range:
'avg(sum(container_memory_usage_bytes{container_name!="POD",pod_name=~"^production-(.*)",namespace="autodevops-deploy-33"}) by (job)) without (job) /1024/1024/1024',
unit: 'GB',
label: 'Total',
result: [
{
metric: {},
values: [
[1558453960.079, '0.0357666015625'],
[1558454020.079, '0.035675048828125'],
[1558454080.079, '0.035152435302734375'],
[1558454140.079, '0.035221099853515625'],
[1558454200.079, '0.0352325439453125'],
[1558454260.079, '0.03479766845703125'],
[1558454320.079, '0.034793853759765625'],
[1558454380.079, '0.034931182861328125'],
[1558454440.079, '0.034816741943359375'],
[1558454500.079, '0.034816741943359375'],
[1558454560.079, '0.034816741943359375'],
],
},
],
},
],
id: 15,
},
],
},
];
export default metricsGroupsAPIResponse;
export const deploymentData = [
{
id: 111,
iid: 3,
sha: 'f5bcd1d9dac6fa4137e2510b9ccd134ef2e84187',
commitUrl:
'http://test.host/frontend-fixtures/environments-project/commit/f5bcd1d9dac6fa4137e2510b9ccd134ef2e84187',
ref: {
name: 'master',
},
created_at: '2017-05-31T21:23:37.881Z',
tag: false,
tagUrl: 'http://test.host/frontend-fixtures/environments-project/tags/false',
'last?': true,
},
{
id: 110,
iid: 2,
sha: 'f5bcd1d9dac6fa4137e2510b9ccd134ef2e84187',
commitUrl:
'http://test.host/frontend-fixtures/environments-project/commit/f5bcd1d9dac6fa4137e2510b9ccd134ef2e84187',
ref: {
name: 'master',
},
created_at: '2017-05-30T20:08:04.629Z',
tag: false,
tagUrl: 'http://test.host/frontend-fixtures/environments-project/tags/false',
'last?': false,
},
{
id: 109,
iid: 1,
sha: '6511e58faafaa7ad2228990ec57f19d66f7db7c2',
commitUrl:
'http://test.host/frontend-fixtures/environments-project/commit/6511e58faafaa7ad2228990ec57f19d66f7db7c2',
ref: {
name: 'update2-readme',
},
created_at: '2017-05-30T17:42:38.409Z',
tag: false,
tagUrl: 'http://test.host/frontend-fixtures/environments-project/tags/false',
'last?': false,
},
];
export const statePaths = {
settingsPath: '/root/hello-prometheus/services/prometheus/edit',
clustersPath: '/root/hello-prometheus/clusters',
documentationPath: '/help/administration/monitoring/prometheus/index.md',
};
export const queryWithoutData = {
title: 'HTTP Error rate',
weight: 10,
y_label: 'Http Error Rate',
queries: [
{ {
query_range: metric: {},
'sum(rate(nginx_upstream_responses_total{status_code="5xx", upstream=~"nginx-test-8691397-production-.*"}[2m])) / sum(rate(nginx_upstream_responses_total{upstream=~"nginx-test-8691397-production-.*"}[2m])) * 100', values: [
label: '5xx errors', [1563272065.589, '9.396484375'],
unit: '%', [1563272125.589, '9.333984375'],
result: [], [1563272185.589, '9.333984375'],
[1563272245.589, '9.333984375'],
[1563272305.589, '9.333984375'],
[1563272365.589, '9.333984375'],
[1563272425.589, '9.38671875'],
[1563272485.589, '9.333984375'],
[1563272545.589, '9.333984375'],
[1563272605.589, '9.333984375'],
[1563272665.589, '9.333984375'],
[1563272725.589, '9.333984375'],
[1563272785.589, '9.396484375'],
[1563272845.589, '9.333984375'],
[1563272905.589, '9.333984375'],
[1563272965.589, '9.3984375'],
[1563273025.589, '9.337890625'],
[1563273085.589, '9.34765625'],
[1563273145.589, '9.337890625'],
[1563273205.589, '9.337890625'],
[1563273265.589, '9.337890625'],
[1563273325.589, '9.337890625'],
[1563273385.589, '9.337890625'],
[1563273445.589, '9.337890625'],
[1563273505.589, '9.337890625'],
[1563273565.589, '9.337890625'],
[1563273625.589, '9.337890625'],
[1563273685.589, '9.337890625'],
[1563273745.589, '9.337890625'],
[1563273805.589, '9.337890625'],
[1563273865.589, '9.390625'],
[1563273925.589, '9.390625'],
],
}, },
], ],
}; };
export function convertDatesMultipleSeries(multipleSeries) {
const convertedMultiple = multipleSeries;
multipleSeries.forEach((column, index) => {
let convertedResult = [];
convertedResult = column.queries[0].result.map(resultObj => {
const convertedMetrics = {};
convertedMetrics.values = resultObj.values.map(val => ({
time: new Date(val.time),
value: val.value,
}));
convertedMetrics.metric = resultObj.metric;
return convertedMetrics;
});
convertedMultiple[index].queries[0].result = convertedResult;
});
return convertedMultiple;
}
export const environmentData = [ export const environmentData = [
{ {
id: 34, id: 34,
...@@ -1006,7 +289,7 @@ export const graphDataPrometheusQueryRange = { ...@@ -1006,7 +289,7 @@ export const graphDataPrometheusQueryRange = {
], ],
queries: [ queries: [
{ {
metricId: null, metricId: '10',
id: 'metric_a1', id: 'metric_a1',
metric_id: 2, metric_id: 2,
query_range: query_range:
......
...@@ -317,7 +317,7 @@ describe('Monitoring store actions', () => { ...@@ -317,7 +317,7 @@ describe('Monitoring store actions', () => {
const metric = metricsDashboardResponse.dashboard.panel_groups[0].panels[0].metrics[0]; const metric = metricsDashboardResponse.dashboard.panel_groups[0].panels[0].metrics[0];
const state = storeState(); const state = storeState();
const data = metricsGroupsAPIResponse.data[0].metrics[0].queries[0]; const data = metricsGroupsAPIResponse[0].panels[0].metrics[0];
const response = { data }; const response = { data };
mock.onGet('http://test').reply(200, response); mock.onGet('http://test').reply(200, response);
......
...@@ -21,79 +21,46 @@ describe('Monitoring mutations', () => { ...@@ -21,79 +21,46 @@ describe('Monitoring mutations', () => {
beforeEach(() => { beforeEach(() => {
stateCopy.dashboard.panel_groups = []; stateCopy.dashboard.panel_groups = [];
groups = metricsGroupsAPIResponse.data; groups = metricsGroupsAPIResponse;
}); });
it('adds a key to the group', () => { it('adds a key to the group', () => {
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, groups); mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, groups);
expect(stateCopy.dashboard.panel_groups[0].key).toBe('kubernetes-0'); expect(stateCopy.dashboard.panel_groups[0].key).toBe('system-metrics-kubernetes--0');
expect(stateCopy.dashboard.panel_groups[1].key).toBe('nginx-1');
}); });
it('normalizes values', () => { it('normalizes values', () => {
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, groups); mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, groups);
const expectedTimestamp = '2017-05-25T08:22:34.925Z'; const expectedLabel = 'Pod average';
const expectedValue = 8.0390625; const { label, query_range } = stateCopy.dashboard.panel_groups[0].metrics[0].metrics[0];
const [
timestamp,
value,
] = stateCopy.dashboard.panel_groups[0].metrics[0].queries[0].result[0].values[0];
expect(timestamp).toEqual(expectedTimestamp); expect(label).toEqual(expectedLabel);
expect(value).toEqual(expectedValue); expect(query_range.length).toBeGreaterThan(0);
}); });
it('contains two groups that contains, one of which has two queries sorted by priority', () => { it('contains one group, which it has two panels and one metrics property', () => {
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, groups); mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, groups);
expect(stateCopy.dashboard.panel_groups).toBeDefined(); expect(stateCopy.dashboard.panel_groups).toBeDefined();
expect(stateCopy.dashboard.panel_groups.length).toEqual(2); expect(stateCopy.dashboard.panel_groups.length).toEqual(1);
expect(stateCopy.dashboard.panel_groups[0].metrics.length).toEqual(2); expect(stateCopy.dashboard.panel_groups[0].panels.length).toEqual(2);
expect(stateCopy.dashboard.panel_groups[0].panels[0].metrics.length).toEqual(1);
expect(stateCopy.dashboard.panel_groups[0].panels[1].metrics.length).toEqual(1);
}); });
it('assigns queries a metric id', () => { it('assigns queries a metric id', () => {
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, groups); mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, groups);
expect(stateCopy.dashboard.panel_groups[1].metrics[0].queries[0].metricId).toEqual('100'); expect(stateCopy.dashboard.panel_groups[0].metrics[0].queries[0].metricId).toEqual(
'17_system_metrics_kubernetes_container_memory_average',
);
}); });
it('removes the data if all the values from a query are not defined', () => { describe('dashboard endpoint', () => {
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, groups);
expect(stateCopy.dashboard.panel_groups[1].metrics[0].queries[0].result.length).toEqual(0);
});
it('assigns metric id of null if metric has no id', () => {
stateCopy.dashboard.panel_groups = [];
const noId = groups.map(group => ({
...group,
...{
metrics: group.metrics.map(metric => {
const { id, ...metricWithoutId } = metric;
return metricWithoutId;
}),
},
}));
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, noId);
stateCopy.dashboard.panel_groups.forEach(group => {
group.metrics.forEach(metric => {
expect(metric.queries.every(query => query.metricId === null)).toBe(true);
});
});
});
describe('dashboard endpoint enabled', () => {
const dashboardGroups = metricsDashboardResponse.dashboard.panel_groups; const dashboardGroups = metricsDashboardResponse.dashboard.panel_groups;
beforeEach(() => {
stateCopy.useDashboardEndpoint = true;
});
it('aliases group panels to metrics for backwards compatibility', () => { it('aliases group panels to metrics for backwards compatibility', () => {
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, dashboardGroups); mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, dashboardGroups);
...@@ -143,7 +110,6 @@ describe('Monitoring mutations', () => { ...@@ -143,7 +110,6 @@ describe('Monitoring mutations', () => {
const result = [{ values: [[0, 1], [1, 1], [1, 3]] }]; const result = [{ values: [[0, 1], [1, 1], [1, 3]] }];
beforeEach(() => { beforeEach(() => {
stateCopy.useDashboardEndpoint = true;
const dashboardGroups = metricsDashboardResponse.dashboard.panel_groups; const dashboardGroups = metricsDashboardResponse.dashboard.panel_groups;
mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, dashboardGroups); mutations[types.RECEIVE_METRICS_DATA_SUCCESS](stateCopy, dashboardGroups);
}); });
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment