Add ability to embed metrics
See https://gitlab.com/gitlab-org/gitlab-ce/issues/30423
This commit is contained in:
parent
86e002147c
commit
97b325a4a2
15 changed files with 410 additions and 50 deletions
|
@ -2,6 +2,7 @@ import $ from 'jquery';
|
||||||
import syntaxHighlight from '~/syntax_highlight';
|
import syntaxHighlight from '~/syntax_highlight';
|
||||||
import renderMath from './render_math';
|
import renderMath from './render_math';
|
||||||
import renderMermaid from './render_mermaid';
|
import renderMermaid from './render_mermaid';
|
||||||
|
import renderMetrics from './render_metrics';
|
||||||
import highlightCurrentUser from './highlight_current_user';
|
import highlightCurrentUser from './highlight_current_user';
|
||||||
import initUserPopovers from '../../user_popovers';
|
import initUserPopovers from '../../user_popovers';
|
||||||
import initMRPopovers from '../../mr_popover';
|
import initMRPopovers from '../../mr_popover';
|
||||||
|
@ -17,6 +18,9 @@ $.fn.renderGFM = function renderGFM() {
|
||||||
highlightCurrentUser(this.find('.gfm-project_member').get());
|
highlightCurrentUser(this.find('.gfm-project_member').get());
|
||||||
initUserPopovers(this.find('.gfm-project_member').get());
|
initUserPopovers(this.find('.gfm-project_member').get());
|
||||||
initMRPopovers(this.find('.gfm-merge_request').get());
|
initMRPopovers(this.find('.gfm-merge_request').get());
|
||||||
|
if (gon.features && gon.features.gfmEmbeddedMetrics) {
|
||||||
|
renderMetrics(this.find('.js-render-metrics').get());
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
24
app/assets/javascripts/behaviors/markdown/render_metrics.js
Normal file
24
app/assets/javascripts/behaviors/markdown/render_metrics.js
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import Vue from 'vue';
|
||||||
|
import Metrics from '~/monitoring/components/embed.vue';
|
||||||
|
import { createStore } from '~/monitoring/stores';
|
||||||
|
|
||||||
|
// TODO: Handle copy-pasting - https://gitlab.com/gitlab-org/gitlab-ce/issues/64369.
|
||||||
|
export default function renderMetrics(elements) {
|
||||||
|
if (!elements.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
elements.forEach(element => {
|
||||||
|
const { dashboardUrl } = element.dataset;
|
||||||
|
const MetricsComponent = Vue.extend(Metrics);
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-new
|
||||||
|
new MetricsComponent({
|
||||||
|
el: element,
|
||||||
|
store: createStore(),
|
||||||
|
propsData: {
|
||||||
|
dashboardUrl,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
|
@ -37,7 +37,13 @@ export default {
|
||||||
},
|
},
|
||||||
projectPath: {
|
projectPath: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: false,
|
||||||
|
default: () => '',
|
||||||
|
},
|
||||||
|
showBorder: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: () => false,
|
||||||
},
|
},
|
||||||
thresholds: {
|
thresholds: {
|
||||||
type: Array,
|
type: Array,
|
||||||
|
@ -234,52 +240,54 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="prometheus-graph col-12 col-lg-6">
|
<div class="col-12 col-lg-6" :class="[showBorder ? 'p-2' : 'p-0']">
|
||||||
<div class="prometheus-graph-header">
|
<div class="prometheus-graph" :class="{ 'prometheus-graph-embed w-100 p-3': showBorder }">
|
||||||
<h5 ref="graphTitle" class="prometheus-graph-title">{{ graphData.title }}</h5>
|
<div class="prometheus-graph-header">
|
||||||
<div ref="graphWidgets" class="prometheus-graph-widgets"><slot></slot></div>
|
<h5 ref="graphTitle" class="prometheus-graph-title">{{ graphData.title }}</h5>
|
||||||
</div>
|
<div ref="graphWidgets" class="prometheus-graph-widgets"><slot></slot></div>
|
||||||
<gl-area-chart
|
</div>
|
||||||
ref="areaChart"
|
<gl-area-chart
|
||||||
v-bind="$attrs"
|
ref="areaChart"
|
||||||
:data="chartData"
|
v-bind="$attrs"
|
||||||
:option="chartOptions"
|
:data="chartData"
|
||||||
:format-tooltip-text="formatTooltipText"
|
:option="chartOptions"
|
||||||
:thresholds="thresholds"
|
:format-tooltip-text="formatTooltipText"
|
||||||
:width="width"
|
:thresholds="thresholds"
|
||||||
:height="height"
|
:width="width"
|
||||||
@updated="onChartUpdated"
|
:height="height"
|
||||||
>
|
@updated="onChartUpdated"
|
||||||
<template v-if="tooltip.isDeployment">
|
>
|
||||||
<template slot="tooltipTitle">
|
<template v-if="tooltip.isDeployment">
|
||||||
{{ __('Deployed') }}
|
<template slot="tooltipTitle">
|
||||||
</template>
|
{{ __('Deployed') }}
|
||||||
<div slot="tooltipContent" class="d-flex align-items-center">
|
</template>
|
||||||
<icon name="commit" class="mr-2" />
|
<div slot="tooltipContent" class="d-flex align-items-center">
|
||||||
<gl-link :href="tooltip.commitUrl">{{ tooltip.sha }}</gl-link>
|
<icon name="commit" class="mr-2" />
|
||||||
</div>
|
<gl-link :href="tooltip.commitUrl">{{ tooltip.sha }}</gl-link>
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<template slot="tooltipTitle">
|
|
||||||
<div class="text-nowrap">
|
|
||||||
{{ tooltip.title }}
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template slot="tooltipContent">
|
<template v-else>
|
||||||
<div
|
<template slot="tooltipTitle">
|
||||||
v-for="(content, key) in tooltip.content"
|
<div class="text-nowrap">
|
||||||
:key="key"
|
{{ tooltip.title }}
|
||||||
class="d-flex justify-content-between"
|
|
||||||
>
|
|
||||||
<gl-chart-series-label :color="isMultiSeries ? content.color : ''">
|
|
||||||
{{ content.name }}
|
|
||||||
</gl-chart-series-label>
|
|
||||||
<div class="prepend-left-32">
|
|
||||||
{{ content.value }}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</template>
|
||||||
|
<template slot="tooltipContent">
|
||||||
|
<div
|
||||||
|
v-for="(content, key) in tooltip.content"
|
||||||
|
:key="key"
|
||||||
|
class="d-flex justify-content-between"
|
||||||
|
>
|
||||||
|
<gl-chart-series-label :color="isMultiSeries ? content.color : ''">
|
||||||
|
{{ content.name }}
|
||||||
|
</gl-chart-series-label>
|
||||||
|
<div class="prepend-left-32">
|
||||||
|
{{ content.value }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</gl-area-chart>
|
||||||
</gl-area-chart>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -11,10 +11,9 @@ import MonitorSingleStatChart from './charts/single_stat.vue';
|
||||||
import PanelType from './panel_type.vue';
|
import PanelType from './panel_type.vue';
|
||||||
import GraphGroup from './graph_group.vue';
|
import GraphGroup from './graph_group.vue';
|
||||||
import EmptyState from './empty_state.vue';
|
import EmptyState from './empty_state.vue';
|
||||||
import { timeWindows, timeWindowsKeyNames } from '../constants';
|
import { sidebarAnimationDuration, timeWindows, timeWindowsKeyNames } from '../constants';
|
||||||
import { getTimeDiff } from '../utils';
|
import { getTimeDiff } from '../utils';
|
||||||
|
|
||||||
const sidebarAnimationDuration = 150;
|
|
||||||
let sidebarMutationObserver;
|
let sidebarMutationObserver;
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -370,8 +369,8 @@ export default {
|
||||||
</div>
|
</div>
|
||||||
<div v-if="!showEmptyState">
|
<div v-if="!showEmptyState">
|
||||||
<graph-group
|
<graph-group
|
||||||
v-for="(groupData, index) in groupsWithData"
|
v-for="groupData in groupsWithData"
|
||||||
:key="index"
|
:key="`${groupData.group}.${groupData.priority}`"
|
||||||
:name="groupData.group"
|
:name="groupData.group"
|
||||||
:show-panels="showPanels"
|
:show-panels="showPanels"
|
||||||
>
|
>
|
||||||
|
|
97
app/assets/javascripts/monitoring/components/embed.vue
Normal file
97
app/assets/javascripts/monitoring/components/embed.vue
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
<script>
|
||||||
|
import { mapActions, mapState } from 'vuex';
|
||||||
|
import GraphGroup from './graph_group.vue';
|
||||||
|
import MonitorAreaChart from './charts/area.vue';
|
||||||
|
import { sidebarAnimationDuration, timeWindowsKeyNames, timeWindows } from '../constants';
|
||||||
|
import { getTimeDiff } from '../utils';
|
||||||
|
|
||||||
|
let sidebarMutationObserver;
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
GraphGroup,
|
||||||
|
MonitorAreaChart,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
dashboardUrl: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
params: {
|
||||||
|
...getTimeDiff(timeWindows[timeWindowsKeyNames.eightHours]),
|
||||||
|
},
|
||||||
|
elWidth: 0,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState('monitoringDashboard', ['groups', 'metricsWithData']),
|
||||||
|
groupData() {
|
||||||
|
const groupsWithData = this.groups.filter(group => this.chartsWithData(group.metrics).length);
|
||||||
|
if (groupsWithData.length) {
|
||||||
|
return groupsWithData[0];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.setInitialState();
|
||||||
|
this.fetchMetricsData(this.params);
|
||||||
|
sidebarMutationObserver = new MutationObserver(this.onSidebarMutation);
|
||||||
|
sidebarMutationObserver.observe(document.querySelector('.layout-page'), {
|
||||||
|
attributes: true,
|
||||||
|
childList: false,
|
||||||
|
subtree: false,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
if (sidebarMutationObserver) {
|
||||||
|
sidebarMutationObserver.disconnect();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions('monitoringDashboard', [
|
||||||
|
'fetchMetricsData',
|
||||||
|
'setEndpoints',
|
||||||
|
'setFeatureFlags',
|
||||||
|
'setShowErrorBanner',
|
||||||
|
]),
|
||||||
|
chartsWithData(charts) {
|
||||||
|
return charts.filter(chart =>
|
||||||
|
chart.metrics.some(metric => this.metricsWithData.includes(metric.metric_id)),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onSidebarMutation() {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.elWidth = this.$el.clientWidth;
|
||||||
|
}, sidebarAnimationDuration);
|
||||||
|
},
|
||||||
|
setInitialState() {
|
||||||
|
this.setFeatureFlags({
|
||||||
|
prometheusEndpointEnabled: true,
|
||||||
|
});
|
||||||
|
this.setEndpoints({
|
||||||
|
dashboardEndpoint: this.dashboardUrl,
|
||||||
|
});
|
||||||
|
this.setShowErrorBanner(false);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<div class="metrics-embed">
|
||||||
|
<div v-if="groupData" class="row w-100 m-n2 pb-4">
|
||||||
|
<monitor-area-chart
|
||||||
|
v-for="graphData in chartsWithData(groupData.metrics)"
|
||||||
|
:key="graphData.title"
|
||||||
|
:graph-data="graphData"
|
||||||
|
:container-width="elWidth"
|
||||||
|
group-id="monitor-area-chart"
|
||||||
|
:project-path="null"
|
||||||
|
:show-border="true"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
|
@ -1,5 +1,7 @@
|
||||||
import { __ } from '~/locale';
|
import { __ } from '~/locale';
|
||||||
|
|
||||||
|
export const sidebarAnimationDuration = 300; // milliseconds.
|
||||||
|
|
||||||
export const chartHeight = 300;
|
export const chartHeight = 300;
|
||||||
|
|
||||||
export const graphTypes = {
|
export const graphTypes = {
|
||||||
|
|
|
@ -44,6 +44,10 @@ export const setFeatureFlags = (
|
||||||
commit(types.SET_ADDITIONAL_PANEL_TYPES_ENABLED, additionalPanelTypesEnabled);
|
commit(types.SET_ADDITIONAL_PANEL_TYPES_ENABLED, additionalPanelTypesEnabled);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const setShowErrorBanner = ({ commit }, enabled) => {
|
||||||
|
commit(types.SET_SHOW_ERROR_BANNER, enabled);
|
||||||
|
};
|
||||||
|
|
||||||
export const requestMetricsDashboard = ({ commit }) => {
|
export const requestMetricsDashboard = ({ commit }) => {
|
||||||
commit(types.REQUEST_METRICS_DATA);
|
commit(types.REQUEST_METRICS_DATA);
|
||||||
};
|
};
|
||||||
|
@ -99,7 +103,9 @@ export const fetchMetricsData = ({ state, dispatch }, params) => {
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
dispatch('receiveMetricsDataFailure', error);
|
dispatch('receiveMetricsDataFailure', error);
|
||||||
createFlash(s__('Metrics|There was an error while retrieving metrics'));
|
if (state.setShowErrorBanner) {
|
||||||
|
createFlash(s__('Metrics|There was an error while retrieving metrics'));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -119,7 +125,9 @@ export const fetchDashboard = ({ state, dispatch }, params) => {
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
dispatch('receiveMetricsDashboardFailure', error);
|
dispatch('receiveMetricsDashboardFailure', error);
|
||||||
createFlash(s__('Metrics|There was an error while retrieving metrics'));
|
if (state.setShowErrorBanner) {
|
||||||
|
createFlash(s__('Metrics|There was an error while retrieving metrics'));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -16,3 +16,4 @@ 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';
|
||||||
export const SET_NO_DATA_EMPTY_STATE = 'SET_NO_DATA_EMPTY_STATE';
|
export const SET_NO_DATA_EMPTY_STATE = 'SET_NO_DATA_EMPTY_STATE';
|
||||||
|
export const SET_SHOW_ERROR_BANNER = 'SET_SHOW_ERROR_BANNER';
|
||||||
|
|
|
@ -96,4 +96,7 @@ export default {
|
||||||
[types.SET_ADDITIONAL_PANEL_TYPES_ENABLED](state, enabled) {
|
[types.SET_ADDITIONAL_PANEL_TYPES_ENABLED](state, enabled) {
|
||||||
state.additionalPanelTypesEnabled = enabled;
|
state.additionalPanelTypesEnabled = enabled;
|
||||||
},
|
},
|
||||||
|
[types.SET_SHOW_ERROR_BANNER](state, enabled) {
|
||||||
|
state.showErrorBanner = enabled;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,6 +12,7 @@ export default () => ({
|
||||||
additionalPanelTypesEnabled: false,
|
additionalPanelTypesEnabled: false,
|
||||||
emptyState: 'gettingStarted',
|
emptyState: 'gettingStarted',
|
||||||
showEmptyState: true,
|
showEmptyState: true,
|
||||||
|
showErrorBanner: true,
|
||||||
groups: [],
|
groups: [],
|
||||||
deploymentData: [],
|
deploymentData: [],
|
||||||
environments: [],
|
environments: [],
|
||||||
|
|
|
@ -29,6 +29,11 @@
|
||||||
padding: $gl-padding / 2;
|
padding: $gl-padding / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.prometheus-graph-embed {
|
||||||
|
border: 1px solid $border-color;
|
||||||
|
border-radius: $border-radius-default;
|
||||||
|
}
|
||||||
|
|
||||||
.prometheus-graph-header {
|
.prometheus-graph-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
37
spec/frontend/behaviors/markdown/render_metrics_spec.js
Normal file
37
spec/frontend/behaviors/markdown/render_metrics_spec.js
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import Vue from 'vue';
|
||||||
|
import renderMetrics from '~/behaviors/markdown/render_metrics';
|
||||||
|
import { TEST_HOST } from 'helpers/test_constants';
|
||||||
|
|
||||||
|
const originalExtend = Vue.extend;
|
||||||
|
|
||||||
|
describe('Render metrics for Gitlab Flavoured Markdown', () => {
|
||||||
|
const container = {
|
||||||
|
Metrics() {},
|
||||||
|
};
|
||||||
|
|
||||||
|
let spyExtend;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
Vue.extend = () => container.Metrics;
|
||||||
|
spyExtend = jest.spyOn(Vue, 'extend');
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
Vue.extend = originalExtend;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does nothing when no elements are found', () => {
|
||||||
|
renderMetrics([]);
|
||||||
|
|
||||||
|
expect(spyExtend).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders a vue component when elements are found', () => {
|
||||||
|
const element = document.createElement('div');
|
||||||
|
element.setAttribute('data-dashboard-url', TEST_HOST);
|
||||||
|
|
||||||
|
renderMetrics([element]);
|
||||||
|
|
||||||
|
expect(spyExtend).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
78
spec/frontend/monitoring/embed/embed_spec.js
Normal file
78
spec/frontend/monitoring/embed/embed_spec.js
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
import { createLocalVue, shallowMount } from '@vue/test-utils';
|
||||||
|
import Vuex from 'vuex';
|
||||||
|
import Embed from '~/monitoring/components/embed.vue';
|
||||||
|
import MonitorAreaChart from '~/monitoring/components/charts/area.vue';
|
||||||
|
import { TEST_HOST } from 'helpers/test_constants';
|
||||||
|
import { groups, initialState, metricsData, metricsWithData } from './mock_data';
|
||||||
|
|
||||||
|
const localVue = createLocalVue();
|
||||||
|
localVue.use(Vuex);
|
||||||
|
|
||||||
|
describe('Embed', () => {
|
||||||
|
let wrapper;
|
||||||
|
let store;
|
||||||
|
let actions;
|
||||||
|
|
||||||
|
function mountComponent() {
|
||||||
|
wrapper = shallowMount(Embed, {
|
||||||
|
localVue,
|
||||||
|
store,
|
||||||
|
propsData: {
|
||||||
|
dashboardUrl: TEST_HOST,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
actions = {
|
||||||
|
setFeatureFlags: () => {},
|
||||||
|
setShowErrorBanner: () => {},
|
||||||
|
setEndpoints: () => {},
|
||||||
|
fetchMetricsData: () => {},
|
||||||
|
};
|
||||||
|
|
||||||
|
store = new Vuex.Store({
|
||||||
|
modules: {
|
||||||
|
monitoringDashboard: {
|
||||||
|
namespaced: true,
|
||||||
|
actions,
|
||||||
|
state: initialState,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
if (wrapper) {
|
||||||
|
wrapper.destroy();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('no metrics are available yet', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
mountComponent();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows an empty state when no metrics are present', () => {
|
||||||
|
expect(wrapper.find('.metrics-embed').exists()).toBe(true);
|
||||||
|
expect(wrapper.find(MonitorAreaChart).exists()).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('metrics are available', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
store.state.monitoringDashboard.groups = groups;
|
||||||
|
store.state.monitoringDashboard.groups[0].metrics = metricsData;
|
||||||
|
store.state.monitoringDashboard.metricsWithData = metricsWithData;
|
||||||
|
|
||||||
|
mountComponent();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows a chart when metrics are present', () => {
|
||||||
|
wrapper.setProps({});
|
||||||
|
expect(wrapper.find('.metrics-embed').exists()).toBe(true);
|
||||||
|
expect(wrapper.find(MonitorAreaChart).exists()).toBe(true);
|
||||||
|
expect(wrapper.findAll(MonitorAreaChart).length).toBe(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
87
spec/frontend/monitoring/embed/mock_data.js
Normal file
87
spec/frontend/monitoring/embed/mock_data.js
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
export const metricsWithData = [15, 16];
|
||||||
|
|
||||||
|
export const groups = [
|
||||||
|
{
|
||||||
|
panels: [
|
||||||
|
{
|
||||||
|
title: 'Memory Usage (Total)',
|
||||||
|
type: 'area-chart',
|
||||||
|
y_label: 'Total Memory Used',
|
||||||
|
weight: 4,
|
||||||
|
metrics: [
|
||||||
|
{
|
||||||
|
id: 'system_metrics_kubernetes_container_memory_total',
|
||||||
|
metric_id: 15,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Core Usage (Total)',
|
||||||
|
type: 'area-chart',
|
||||||
|
y_label: 'Total Cores',
|
||||||
|
weight: 3,
|
||||||
|
metrics: [
|
||||||
|
{
|
||||||
|
id: 'system_metrics_kubernetes_container_cores_total',
|
||||||
|
metric_id: 16,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const metrics = [
|
||||||
|
{
|
||||||
|
id: 'system_metrics_kubernetes_container_memory_total',
|
||||||
|
metric_id: 15,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'system_metrics_kubernetes_container_cores_total',
|
||||||
|
metric_id: 16,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const queries = [
|
||||||
|
{
|
||||||
|
result: [
|
||||||
|
{
|
||||||
|
values: [
|
||||||
|
['Mon', 1220],
|
||||||
|
['Tue', 932],
|
||||||
|
['Wed', 901],
|
||||||
|
['Thu', 934],
|
||||||
|
['Fri', 1290],
|
||||||
|
['Sat', 1330],
|
||||||
|
['Sun', 1320],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const metricsData = [
|
||||||
|
{
|
||||||
|
queries,
|
||||||
|
metrics: [
|
||||||
|
{
|
||||||
|
metric_id: 15,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
queries,
|
||||||
|
metrics: [
|
||||||
|
{
|
||||||
|
metric_id: 16,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const initialState = {
|
||||||
|
monitoringDashboard: {},
|
||||||
|
groups: [],
|
||||||
|
metricsWithData: [],
|
||||||
|
useDashboardEndpoint: true,
|
||||||
|
};
|
|
@ -69,3 +69,9 @@ Object.entries(jqueryMatchers).forEach(([matcherName, matcherFactory]) => {
|
||||||
|
|
||||||
// Tech debt issue TBD
|
// Tech debt issue TBD
|
||||||
testUtilsConfig.logModifiedComponents = false;
|
testUtilsConfig.logModifiedComponents = false;
|
||||||
|
|
||||||
|
// Basic stub for MutationObserver
|
||||||
|
global.MutationObserver = () => ({
|
||||||
|
disconnect: () => {},
|
||||||
|
observe: () => {},
|
||||||
|
});
|
||||||
|
|
Loading…
Reference in a new issue