summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJose Ivan Vargas <jvargas@gitlab.com>2019-07-10 21:12:46 +0000
committerFatih Acet <acetfatih@gmail.com>2019-07-10 21:12:46 +0000
commit202a150f72cdf2793f66d80f892ee6d68d7f26ad (patch)
treed11278d89da180e0c6a669f6a2aa1b1a32cf35f1
parentef348618c5105a97ae257bc683c85ef1c01a969b (diff)
downloadgitlab-ce-202a150f72cdf2793f66d80f892ee6d68d7f26ad.tar.gz
Add support for additional panel types
This introduces the single stat chart component aside from the area chart component
-rw-r--r--app/assets/javascripts/monitoring/components/charts/area.vue15
-rw-r--r--app/assets/javascripts/monitoring/components/charts/column.vue23
-rw-r--r--app/assets/javascripts/monitoring/components/charts/single_stat.vue29
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard.vue53
-rw-r--r--app/assets/javascripts/monitoring/components/panel_type.vue62
-rw-r--r--app/assets/javascripts/monitoring/monitoring_bundle.js1
-rw-r--r--app/assets/javascripts/monitoring/stores/actions.js3
-rw-r--r--app/assets/javascripts/monitoring/stores/mutation_types.js1
-rw-r--r--app/assets/javascripts/monitoring/stores/mutations.js4
-rw-r--r--app/assets/javascripts/monitoring/stores/state.js2
-rw-r--r--app/assets/javascripts/monitoring/stores/utils.js27
-rw-r--r--app/assets/javascripts/monitoring/utils.js24
-rw-r--r--app/controllers/projects/environments_controller.rb1
-rw-r--r--spec/javascripts/monitoring/charts/single_stat_spec.js9
-rw-r--r--spec/javascripts/monitoring/mock_data.js72
-rw-r--r--spec/javascripts/monitoring/store/mutations_spec.js2
-rw-r--r--spec/javascripts/monitoring/utils_spec.js27
17 files changed, 280 insertions, 75 deletions
diff --git a/app/assets/javascripts/monitoring/components/charts/area.vue b/app/assets/javascripts/monitoring/components/charts/area.vue
index 81773bd140e..454ff4f284e 100644
--- a/app/assets/javascripts/monitoring/components/charts/area.vue
+++ b/app/assets/javascripts/monitoring/components/charts/area.vue
@@ -8,6 +8,7 @@ import { getSvgIconPathContent } from '~/lib/utils/icon_utils';
import Icon from '~/vue_shared/components/icon.vue';
import { chartHeight, graphTypes, lineTypes } from '../../constants';
import { makeDataSeries } from '~/helpers/monitor_helper';
+import { graphDataValidatorForValues } from '../../utils';
let debouncedResize;
@@ -23,19 +24,7 @@ export default {
graphData: {
type: Object,
required: true,
- validator(data) {
- return (
- Array.isArray(data.queries) &&
- data.queries.filter(query => {
- if (Array.isArray(query.result)) {
- return (
- query.result.filter(res => Array.isArray(res.values)).length === query.result.length
- );
- }
- return false;
- }).length === data.queries.length
- );
- },
+ validator: graphDataValidatorForValues.bind(null, false),
},
containerWidth: {
type: Number,
diff --git a/app/assets/javascripts/monitoring/components/charts/column.vue b/app/assets/javascripts/monitoring/components/charts/column.vue
index 05a2036f4c3..83136d43479 100644
--- a/app/assets/javascripts/monitoring/components/charts/column.vue
+++ b/app/assets/javascripts/monitoring/components/charts/column.vue
@@ -4,6 +4,7 @@ import { debounceByAnimationFrame } from '~/lib/utils/common_utils';
import { getSvgIconPathContent } from '~/lib/utils/icon_utils';
import { chartHeight } from '../../constants';
import { makeDataSeries } from '~/helpers/monitor_helper';
+import { graphDataValidatorForValues } from '../../utils';
export default {
components: {
@@ -14,23 +15,11 @@ export default {
graphData: {
type: Object,
required: true,
- validator(data) {
- return (
- Array.isArray(data.queries) &&
- data.queries.filter(query => {
- if (Array.isArray(query.result)) {
- return (
- query.result.filter(res => Array.isArray(res.values)).length === query.result.length
- );
- }
- return false;
- }).length === data.queries.length
- );
- },
- containerWidth: {
- type: Number,
- required: true,
- },
+ validator: graphDataValidatorForValues.bind(null, false),
+ },
+ containerWidth: {
+ type: Number,
+ required: true,
},
},
data() {
diff --git a/app/assets/javascripts/monitoring/components/charts/single_stat.vue b/app/assets/javascripts/monitoring/components/charts/single_stat.vue
index b03a6ca1806..7428b27a9c3 100644
--- a/app/assets/javascripts/monitoring/components/charts/single_stat.vue
+++ b/app/assets/javascripts/monitoring/components/charts/single_stat.vue
@@ -1,5 +1,7 @@
<script>
import { GlSingleStat } from '@gitlab/ui/dist/charts';
+import { roundOffFloat } from '~/lib/utils/common_utils';
+import { graphDataValidatorForValues } from '../../utils';
export default {
components: {
@@ -7,22 +9,21 @@ export default {
},
inheritAttrs: false,
props: {
- title: {
- type: String,
- required: true,
- },
- value: {
- type: Number,
- required: true,
- },
- unit: {
- type: String,
+ graphData: {
+ type: Object,
required: true,
+ validator: graphDataValidatorForValues.bind(null, true),
},
},
computed: {
- valueWithUnit() {
- return `${this.value}${this.unit}`;
+ queryInfo() {
+ return this.graphData.queries[0];
+ },
+ engineeringNotation() {
+ return `${roundOffFloat(this.queryInfo.result[0].value[1], 1)}${this.queryInfo.unit}`;
+ },
+ graphTitle() {
+ return this.queryInfo.label;
},
},
};
@@ -30,8 +31,8 @@ export default {
<template>
<div class="prometheus-graph col-12 col-lg-6">
<div class="prometheus-graph-header">
- <h5 ref="graphTitle" class="prometheus-graph-title">{{ title }}</h5>
+ <h5 ref="graphTitle" class="prometheus-graph-title">{{ graphTitle }}</h5>
</div>
- <gl-single-stat :value="valueWithUnit" :title="title" variant="success" />
+ <gl-single-stat :value="engineeringNotation" :title="graphTitle" variant="success" />
</div>
</template>
diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue
index ba79a697df2..6eaced0c108 100644
--- a/app/assets/javascripts/monitoring/components/dashboard.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard.vue
@@ -7,6 +7,8 @@ import Icon from '~/vue_shared/components/icon.vue';
import { getParameterValues } from '~/lib/utils/url_utility';
import invalidUrl from '~/lib/utils/invalid_url';
import MonitorAreaChart from './charts/area.vue';
+import MonitorSingleStatChart from './charts/single_stat.vue';
+import PanelType from './panel_type.vue';
import GraphGroup from './graph_group.vue';
import EmptyState from './empty_state.vue';
import { timeWindows, timeWindowsKeyNames } from '../constants';
@@ -18,6 +20,8 @@ let sidebarMutationObserver;
export default {
components: {
MonitorAreaChart,
+ MonitorSingleStatChart,
+ PanelType,
GraphGroup,
EmptyState,
Icon,
@@ -152,6 +156,7 @@ export default {
'useDashboardEndpoint',
'allDashboards',
'multipleDashboardsEnabled',
+ 'additionalPanelTypesEnabled',
]),
groupsWithData() {
return this.groups.filter(group => this.chartsWithData(group.metrics).length > 0);
@@ -173,6 +178,7 @@ export default {
deploymentsEndpoint: this.deploymentsEndpoint,
dashboardEndpoint: this.dashboardEndpoint,
currentDashboard: this.currentDashboard,
+ projectPath: this.projectPath,
});
this.timeWindows = timeWindows;
@@ -220,6 +226,8 @@ export default {
chart.metrics.some(metric => this.metricsWithData.includes(metric.metric_id)),
);
},
+ // TODO: BEGIN, Duplicated code with panel_type until feature flag is removed
+ // Issue number: https://gitlab.com/gitlab-org/gitlab-ce/issues/63845
getGraphAlerts(queries) {
if (!this.allAlerts) return {};
const metricIdsForChart = queries.map(q => q.metricId);
@@ -228,6 +236,7 @@ export default {
getGraphAlertValues(queries) {
return Object.values(this.getGraphAlerts(queries));
},
+ // TODO: END
hideAddMetricModal() {
this.$refs.addMetricModal.hide();
},
@@ -366,24 +375,34 @@ export default {
:name="groupData.group"
:show-panels="showPanels"
>
- <monitor-area-chart
- v-for="(graphData, graphIndex) in chartsWithData(groupData.metrics)"
- :key="graphIndex"
- :project-path="projectPath"
- :graph-data="graphData"
- :deployment-data="deploymentData"
- :thresholds="getGraphAlertValues(graphData.queries)"
- :container-width="elWidth"
- group-id="monitor-area-chart"
- >
- <alert-widget
- v-if="alertWidgetAvailable && graphData"
- :alerts-endpoint="alertsEndpoint"
- :relevant-queries="graphData.queries"
- :alerts-to-manage="getGraphAlerts(graphData.queries)"
- @setAlerts="setAlerts"
+ <template v-if="additionalPanelTypesEnabled">
+ <panel-type
+ v-for="(graphData, graphIndex) in chartsWithData(groupData.metrics)"
+ :key="`panel-type-${graphIndex}`"
+ :graph-data="graphData"
+ :dashboard-width="elWidth"
/>
- </monitor-area-chart>
+ </template>
+ <template v-else>
+ <monitor-area-chart
+ v-for="(graphData, graphIndex) in chartsWithData(groupData.metrics)"
+ :key="graphIndex"
+ :graph-data="graphData"
+ :deployment-data="deploymentData"
+ :thresholds="getGraphAlertValues(graphData.queries)"
+ :container-width="elWidth"
+ :project-path="projectPath"
+ group-id="monitor-area-chart"
+ >
+ <alert-widget
+ v-if="alertWidgetAvailable && graphData"
+ :alerts-endpoint="alertsEndpoint"
+ :relevant-queries="graphData.queries"
+ :alerts-to-manage="getGraphAlerts(graphData.queries)"
+ @setAlerts="setAlerts"
+ />
+ </monitor-area-chart>
+ </template>
</graph-group>
</div>
<empty-state
diff --git a/app/assets/javascripts/monitoring/components/panel_type.vue b/app/assets/javascripts/monitoring/components/panel_type.vue
new file mode 100644
index 00000000000..45ee067de83
--- /dev/null
+++ b/app/assets/javascripts/monitoring/components/panel_type.vue
@@ -0,0 +1,62 @@
+<script>
+import { mapState } from 'vuex';
+import _ from 'underscore';
+import MonitorAreaChart from './charts/area.vue';
+import MonitorSingleStatChart from './charts/single_stat.vue';
+
+export default {
+ components: {
+ MonitorAreaChart,
+ MonitorSingleStatChart,
+ },
+ props: {
+ graphData: {
+ type: Object,
+ required: true,
+ },
+ dashboardWidth: {
+ type: Number,
+ required: true,
+ },
+ },
+ computed: {
+ ...mapState('monitoringDashboard', ['deploymentData', 'projectPath']),
+ alertWidgetAvailable() {
+ return IS_EE && this.prometheusAlertsAvailable && this.alertsEndpoint && this.graphData;
+ },
+ },
+ methods: {
+ 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));
+ },
+ isPanelType(type) {
+ return this.graphData.type && this.graphData.type === type;
+ },
+ },
+};
+</script>
+<template>
+ <monitor-single-stat-chart v-if="isPanelType('single-stat')" :graph-data="graphData" />
+ <monitor-area-chart
+ v-else
+ :graph-data="graphData"
+ :deployment-data="deploymentData"
+ :project-path="projectPath"
+ :thresholds="getGraphAlertValues(graphData.queries)"
+ :container-width="dashboardWidth"
+ group-id="monitor-area-chart"
+ >
+ <alert-widget
+ v-if="alertWidgetAvailable"
+ :alerts-endpoint="alertsEndpoint"
+ :relevant-queries="graphData.queries"
+ :alerts-to-manage="getGraphAlerts(graphData.queries)"
+ @setAlerts="setAlerts"
+ />
+ </monitor-area-chart>
+</template>
diff --git a/app/assets/javascripts/monitoring/monitoring_bundle.js b/app/assets/javascripts/monitoring/monitoring_bundle.js
index 97d149e9ad5..c0fee1ebb99 100644
--- a/app/assets/javascripts/monitoring/monitoring_bundle.js
+++ b/app/assets/javascripts/monitoring/monitoring_bundle.js
@@ -12,6 +12,7 @@ export default (props = {}) => {
store.dispatch('monitoringDashboard/setFeatureFlags', {
prometheusEndpointEnabled: gon.features.environmentMetricsUsePrometheusEndpoint,
multipleDashboardsEnabled: gon.features.environmentMetricsShowMultipleDashboards,
+ additionalPanelTypesEnabled: gon.features.environmentMetricsAdditionalPanelTypes,
});
}
diff --git a/app/assets/javascripts/monitoring/stores/actions.js b/app/assets/javascripts/monitoring/stores/actions.js
index 0fa2a5d6370..5b3da51e9a6 100644
--- a/app/assets/javascripts/monitoring/stores/actions.js
+++ b/app/assets/javascripts/monitoring/stores/actions.js
@@ -37,10 +37,11 @@ export const setEndpoints = ({ commit }, endpoints) => {
export const setFeatureFlags = (
{ commit },
- { prometheusEndpointEnabled, multipleDashboardsEnabled },
+ { prometheusEndpointEnabled, multipleDashboardsEnabled, additionalPanelTypesEnabled },
) => {
commit(types.SET_DASHBOARD_ENABLED, prometheusEndpointEnabled);
commit(types.SET_MULTIPLE_DASHBOARDS_ENABLED, multipleDashboardsEnabled);
+ commit(types.SET_ADDITIONAL_PANEL_TYPES_ENABLED, additionalPanelTypesEnabled);
};
export const requestMetricsDashboard = ({ commit }) => {
diff --git a/app/assets/javascripts/monitoring/stores/mutation_types.js b/app/assets/javascripts/monitoring/stores/mutation_types.js
index 2c78a0b9315..c89daba3df7 100644
--- a/app/assets/javascripts/monitoring/stores/mutation_types.js
+++ b/app/assets/javascripts/monitoring/stores/mutation_types.js
@@ -11,6 +11,7 @@ export const SET_QUERY_RESULT = 'SET_QUERY_RESULT';
export const SET_TIME_WINDOW = 'SET_TIME_WINDOW';
export const SET_DASHBOARD_ENABLED = 'SET_DASHBOARD_ENABLED';
export const SET_MULTIPLE_DASHBOARDS_ENABLED = 'SET_MULTIPLE_DASHBOARDS_ENABLED';
+export const SET_ADDITIONAL_PANEL_TYPES_ENABLED = 'SET_ADDITIONAL_PANEL_TYPES_ENABLED';
export const SET_ALL_DASHBOARDS = 'SET_ALL_DASHBOARDS';
export const SET_ENDPOINTS = 'SET_ENDPOINTS';
export const SET_GETTING_STARTED_EMPTY_STATE = 'SET_GETTING_STARTED_EMPTY_STATE';
diff --git a/app/assets/javascripts/monitoring/stores/mutations.js b/app/assets/javascripts/monitoring/stores/mutations.js
index a85a7723c1f..0104dcb867d 100644
--- a/app/assets/javascripts/monitoring/stores/mutations.js
+++ b/app/assets/javascripts/monitoring/stores/mutations.js
@@ -75,6 +75,7 @@ export default {
state.deploymentsEndpoint = endpoints.deploymentsEndpoint;
state.dashboardEndpoint = endpoints.dashboardEndpoint;
state.currentDashboard = endpoints.currentDashboard;
+ state.projectPath = endpoints.projectPath;
},
[types.SET_DASHBOARD_ENABLED](state, enabled) {
state.useDashboardEndpoint = enabled;
@@ -92,4 +93,7 @@ export default {
[types.SET_ALL_DASHBOARDS](state, dashboards) {
state.allDashboards = dashboards;
},
+ [types.SET_ADDITIONAL_PANEL_TYPES_ENABLED](state, enabled) {
+ state.additionalPanelTypesEnabled = enabled;
+ },
};
diff --git a/app/assets/javascripts/monitoring/stores/state.js b/app/assets/javascripts/monitoring/stores/state.js
index de711d6ccae..e54bb712695 100644
--- a/app/assets/javascripts/monitoring/stores/state.js
+++ b/app/assets/javascripts/monitoring/stores/state.js
@@ -9,6 +9,7 @@ export default () => ({
dashboardEndpoint: invalidUrl,
useDashboardEndpoint: false,
multipleDashboardsEnabled: false,
+ additionalPanelTypesEnabled: false,
emptyState: 'gettingStarted',
showEmptyState: true,
groups: [],
@@ -17,4 +18,5 @@ export default () => ({
metricsWithData: [],
allDashboards: [],
currentDashboard: null,
+ projectPath: null,
});
diff --git a/app/assets/javascripts/monitoring/stores/utils.js b/app/assets/javascripts/monitoring/stores/utils.js
index 721942f9d3b..938ee2f0a9a 100644
--- a/app/assets/javascripts/monitoring/stores/utils.js
+++ b/app/assets/javascripts/monitoring/stores/utils.js
@@ -69,13 +69,26 @@ export const sortMetrics = metrics =>
.sortBy('weight')
.value();
-export const normalizeQueryResult = timeSeries => ({
- ...timeSeries,
- values: timeSeries.values.map(([timestamp, value]) => [
- new Date(timestamp * 1000).toISOString(),
- Number(value),
- ]),
-});
+export const normalizeQueryResult = timeSeries => {
+ let normalizedResult = {};
+
+ if (timeSeries.values) {
+ normalizedResult = {
+ ...timeSeries,
+ values: timeSeries.values.map(([timestamp, value]) => [
+ new Date(timestamp * 1000).toISOString(),
+ Number(value),
+ ]),
+ };
+ } else if (timeSeries.value) {
+ normalizedResult = {
+ ...timeSeries,
+ value: [new Date(timeSeries.value[0] * 1000).toISOString(), Number(timeSeries.value[1])],
+ };
+ }
+
+ return normalizedResult;
+};
export const normalizeMetrics = metrics => {
const groupedMetrics = groupQueriesByChartInfo(metrics);
diff --git a/app/assets/javascripts/monitoring/utils.js b/app/assets/javascripts/monitoring/utils.js
index ef309c8a398..478e2b3d06c 100644
--- a/app/assets/javascripts/monitoring/utils.js
+++ b/app/assets/javascripts/monitoring/utils.js
@@ -30,4 +30,28 @@ export const getTimeDiff = selectedTimeWindow => {
return { start, end };
};
+/**
+ * This method is used to validate if the graph data format for a chart component
+ * that needs a time series as a response from a prometheus query (query_range) is
+ * of a valid format or not.
+ * @param {Object} graphData the graph data response from a prometheus request
+ * @returns {boolean} whether the graphData format is correct
+ */
+export const graphDataValidatorForValues = (isValues, graphData) => {
+ const responseValueKeyName = isValues ? 'value' : 'values';
+
+ return (
+ Array.isArray(graphData.queries) &&
+ graphData.queries.filter(query => {
+ if (Array.isArray(query.result)) {
+ return (
+ query.result.filter(res => Array.isArray(res[responseValueKeyName])).length ===
+ query.result.length
+ );
+ }
+ return false;
+ }).length === graphData.queries.length
+ );
+};
+
export default {};
diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb
index ecf05e6ea64..1bca52106fa 100644
--- a/app/controllers/projects/environments_controller.rb
+++ b/app/controllers/projects/environments_controller.rb
@@ -13,6 +13,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController
before_action only: [:metrics, :additional_metrics, :metrics_dashboard] do
push_frontend_feature_flag(:environment_metrics_use_prometheus_endpoint)
push_frontend_feature_flag(:environment_metrics_show_multiple_dashboards)
+ push_frontend_feature_flag(:environment_metrics_additional_panel_types)
push_frontend_feature_flag(:prometheus_computed_alerts)
end
diff --git a/spec/javascripts/monitoring/charts/single_stat_spec.js b/spec/javascripts/monitoring/charts/single_stat_spec.js
index 12b73002f97..127a4a7955a 100644
--- a/spec/javascripts/monitoring/charts/single_stat_spec.js
+++ b/spec/javascripts/monitoring/charts/single_stat_spec.js
@@ -1,5 +1,6 @@
import { shallowMount } from '@vue/test-utils';
import SingleStatChart from '~/monitoring/components/charts/single_stat.vue';
+import { graphDataPrometheusQuery } from '../mock_data';
describe('Single Stat Chart component', () => {
let singleStatChart;
@@ -7,9 +8,7 @@ describe('Single Stat Chart component', () => {
beforeEach(() => {
singleStatChart = shallowMount(SingleStatChart, {
propsData: {
- title: 'Time to render',
- value: 1,
- unit: 'sec',
+ graphData: graphDataPrometheusQuery,
},
});
});
@@ -19,9 +18,9 @@ describe('Single Stat Chart component', () => {
});
describe('computed', () => {
- describe('valueWithUnit', () => {
+ describe('engineeringNotation', () => {
it('should interpolate the value and unit props', () => {
- expect(singleStatChart.vm.valueWithUnit).toBe('1sec');
+ expect(singleStatChart.vm.engineeringNotation).toBe('91MB');
});
});
});
diff --git a/spec/javascripts/monitoring/mock_data.js b/spec/javascripts/monitoring/mock_data.js
index 7bbb215475a..85e660d3925 100644
--- a/spec/javascripts/monitoring/mock_data.js
+++ b/spec/javascripts/monitoring/mock_data.js
@@ -935,3 +935,75 @@ export const dashboardGitResponse = [
default: false,
},
];
+
+export const graphDataPrometheusQuery = {
+ title: 'Super Chart A2',
+ type: 'single-stat',
+ weight: 2,
+ metrics: [
+ {
+ id: 'metric_a1',
+ metric_id: 2,
+ query: 'max(go_memstats_alloc_bytes{job="prometheus"}) by (job) /1024/1024',
+ unit: 'MB',
+ label: 'Total Consumption',
+ prometheus_endpoint_path:
+ '/root/kubernetes-gke-project/environments/35/prometheus/api/v1/query?query=max%28go_memstats_alloc_bytes%7Bjob%3D%22prometheus%22%7D%29+by+%28job%29+%2F1024%2F1024',
+ },
+ ],
+ queries: [
+ {
+ metricId: null,
+ id: 'metric_a1',
+ metric_id: 2,
+ query: 'max(go_memstats_alloc_bytes{job="prometheus"}) by (job) /1024/1024',
+ unit: 'MB',
+ label: 'Total Consumption',
+ prometheus_endpoint_path:
+ '/root/kubernetes-gke-project/environments/35/prometheus/api/v1/query?query=max%28go_memstats_alloc_bytes%7Bjob%3D%22prometheus%22%7D%29+by+%28job%29+%2F1024%2F1024',
+ result: [
+ {
+ metric: { job: 'prometheus' },
+ value: ['2019-06-26T21:03:20.881Z', 91],
+ },
+ ],
+ },
+ ],
+};
+
+export const graphDataPrometheusQueryRange = {
+ title: 'Super Chart A1',
+ type: 'area',
+ weight: 2,
+ metrics: [
+ {
+ id: 'metric_a1',
+ metric_id: 2,
+ query_range:
+ 'avg(sum(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-(.*)",namespace="%{kube_namespace}"}) by (job)) without (job) /1024/1024/1024',
+ unit: 'MB',
+ label: 'Total Consumption',
+ prometheus_endpoint_path:
+ '/root/kubernetes-gke-project/environments/35/prometheus/api/v1/query?query=max%28go_memstats_alloc_bytes%7Bjob%3D%22prometheus%22%7D%29+by+%28job%29+%2F1024%2F1024',
+ },
+ ],
+ queries: [
+ {
+ metricId: null,
+ id: 'metric_a1',
+ metric_id: 2,
+ query_range:
+ 'avg(sum(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-(.*)",namespace="%{kube_namespace}"}) by (job)) without (job) /1024/1024/1024',
+ unit: 'MB',
+ label: 'Total Consumption',
+ prometheus_endpoint_path:
+ '/root/kubernetes-gke-project/environments/35/prometheus/api/v1/query?query=max%28go_memstats_alloc_bytes%7Bjob%3D%22prometheus%22%7D%29+by+%28job%29+%2F1024%2F1024',
+ result: [
+ {
+ metric: {},
+ values: [[1495700554.925, '8.0390625'], [1495700614.925, '8.0390625']],
+ },
+ ],
+ },
+ ],
+};
diff --git a/spec/javascripts/monitoring/store/mutations_spec.js b/spec/javascripts/monitoring/store/mutations_spec.js
index 91580366531..43776b1b7f2 100644
--- a/spec/javascripts/monitoring/store/mutations_spec.js
+++ b/spec/javascripts/monitoring/store/mutations_spec.js
@@ -115,12 +115,14 @@ describe('Monitoring mutations', () => {
environmentsEndpoint: 'environments.json',
deploymentsEndpoint: 'deployments.json',
dashboardEndpoint: 'dashboard.json',
+ projectPath: '/gitlab-org/gitlab-ce',
});
expect(stateCopy.metricsEndpoint).toEqual('additional_metrics.json');
expect(stateCopy.environmentsEndpoint).toEqual('environments.json');
expect(stateCopy.deploymentsEndpoint).toEqual('deployments.json');
expect(stateCopy.dashboardEndpoint).toEqual('dashboard.json');
+ expect(stateCopy.projectPath).toEqual('/gitlab-org/gitlab-ce');
});
});
diff --git a/spec/javascripts/monitoring/utils_spec.js b/spec/javascripts/monitoring/utils_spec.js
index e3c455d1686..5570d57b8b2 100644
--- a/spec/javascripts/monitoring/utils_spec.js
+++ b/spec/javascripts/monitoring/utils_spec.js
@@ -1,5 +1,6 @@
-import { getTimeDiff } from '~/monitoring/utils';
+import { getTimeDiff, graphDataValidatorForValues } from '~/monitoring/utils';
import { timeWindows } from '~/monitoring/constants';
+import { graphDataPrometheusQuery, graphDataPrometheusQueryRange } from './mock_data';
describe('getTimeDiff', () => {
it('defaults to an 8 hour (28800s) difference', () => {
@@ -27,3 +28,27 @@ describe('getTimeDiff', () => {
});
});
});
+
+describe('graphDataValidatorForValues', () => {
+ /*
+ * When dealing with a metric using the query format, e.g.
+ * query: 'max(go_memstats_alloc_bytes{job="prometheus"}) by (job) /1024/1024'
+ * the validator will look for the `value` key instead of `values`
+ */
+ it('validates data with the query format', () => {
+ const validGraphData = graphDataValidatorForValues(true, graphDataPrometheusQuery);
+
+ expect(validGraphData).toBe(true);
+ });
+
+ /*
+ * When dealing with a metric using the query?range format, e.g.
+ * query_range: 'avg(sum(container_memory_usage_bytes{container_name!="POD",pod_name=~"^%{ci_environment_slug}-(.*)",namespace="%{kube_namespace}"}) by (job)) without (job) /1024/1024/1024',
+ * the validator will look for the `values` key instead of `value`
+ */
+ it('validates data with the query_range format', () => {
+ const validGraphData = graphDataValidatorForValues(false, graphDataPrometheusQueryRange);
+
+ expect(validGraphData).toBe(true);
+ });
+});