summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhil Hughes <me@iamphill.com>2018-03-06 18:13:33 +0000
committerPhil Hughes <me@iamphill.com>2018-03-06 18:13:33 +0000
commit2d00d6d459164f9c51f9e04fe56aecdca5edfe24 (patch)
tree97d5d477c23e2ab9eeb0b4e9b364a7ca76adec83
parentd12f60a5c07f942d187ef840ef0a65784bb3b119 (diff)
parent226d43b31733f4c61b2f2c54cf7a5c4374c801a6 (diff)
downloadgitlab-ce-2d00d6d459164f9c51f9e04fe56aecdca5edfe24.tar.gz
Merge branch 'cluster-monitoring-changes-ce-backport' into 'master'
Cluster monitoring changes CE backport See merge request gitlab-org/gitlab-ce!17547
-rw-r--r--app/assets/javascripts/clusters/components/applications.vue5
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard.vue86
-rw-r--r--app/assets/javascripts/monitoring/components/graph.vue17
-rw-r--r--app/assets/javascripts/monitoring/components/graph/legend.vue78
-rw-r--r--app/assets/javascripts/monitoring/components/graph_group.vue16
-rw-r--r--app/assets/javascripts/monitoring/monitoring_bundle.js23
-rw-r--r--app/assets/javascripts/monitoring/services/monitoring_service.js3
-rw-r--r--app/assets/javascripts/pages/projects/environments/index/index.js (renamed from app/assets/javascripts/pages/projects/environments/index.js)0
-rw-r--r--app/assets/stylesheets/pages/environments.scss3
-rw-r--r--app/views/projects/environments/metrics.html.haml5
-rw-r--r--spec/javascripts/fixtures/environments.rb30
-rw-r--r--spec/javascripts/monitoring/dashboard_spec.js67
12 files changed, 225 insertions, 108 deletions
diff --git a/app/assets/javascripts/clusters/components/applications.vue b/app/assets/javascripts/clusters/components/applications.vue
index 1325a268214..27136c7289f 100644
--- a/app/assets/javascripts/clusters/components/applications.vue
+++ b/app/assets/javascripts/clusters/components/applications.vue
@@ -117,7 +117,10 @@
</script>
<template>
- <section class="settings no-animate expanded">
+ <section
+ id="cluster-applications"
+ class="settings no-animate expanded"
+ >
<div class="settings-header">
<h4>
{{ s__('ClusterIntegration|Applications') }}
diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue
index 031badc7026..8ca94ef3e2a 100644
--- a/app/assets/javascripts/monitoring/components/dashboard.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard.vue
@@ -7,34 +7,82 @@
import EmptyState from './empty_state.vue';
import MonitoringStore from '../stores/monitoring_store';
import eventHub from '../event_hub';
- import { convertPermissionToBoolean } from '../../lib/utils/common_utils';
export default {
-
components: {
Graph,
GraphGroup,
EmptyState,
},
- data() {
- const metricsData = document.querySelector('#prometheus-graphs').dataset;
- const store = new MonitoringStore();
+ props: {
+ hasMetrics: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ showLegend: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ showPanels: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ forceSmallGraph: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ documentationPath: {
+ type: String,
+ required: true,
+ },
+ settingsPath: {
+ type: String,
+ required: true,
+ },
+ clustersPath: {
+ type: String,
+ required: true,
+ },
+ tagsPath: {
+ type: String,
+ required: true,
+ },
+ projectPath: {
+ type: String,
+ required: true,
+ },
+ metricsEndpoint: {
+ type: String,
+ required: true,
+ },
+ deploymentEndpoint: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ emptyGettingStartedSvgPath: {
+ type: String,
+ required: true,
+ },
+ emptyLoadingSvgPath: {
+ type: String,
+ required: true,
+ },
+ emptyUnableToConnectSvgPath: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
return {
- store,
+ store: new MonitoringStore(),
state: 'gettingStarted',
- hasMetrics: convertPermissionToBoolean(metricsData.hasMetrics),
- documentationPath: metricsData.documentationPath,
- settingsPath: metricsData.settingsPath,
- clustersPath: metricsData.clustersPath,
- tagsPath: metricsData.tagsPath,
- projectPath: metricsData.projectPath,
- metricsEndpoint: metricsData.additionalMetrics,
- deploymentEndpoint: metricsData.deploymentEndpoint,
- emptyGettingStartedSvgPath: metricsData.emptyGettingStartedSvgPath,
- emptyLoadingSvgPath: metricsData.emptyLoadingSvgPath,
- emptyUnableToConnectSvgPath: metricsData.emptyUnableToConnectSvgPath,
showEmptyState: true,
updateAspectRatio: false,
updatedAspectRatios: 0,
@@ -67,6 +115,7 @@
window.addEventListener('resize', this.resizeThrottled, false);
}
},
+
methods: {
getGraphsData() {
this.state = 'loading';
@@ -115,6 +164,7 @@
v-for="(groupData, index) in store.groups"
:key="index"
:name="groupData.group"
+ :show-panels="showPanels"
>
<graph
v-for="(graphData, index) in groupData.metrics"
@@ -125,6 +175,8 @@
:deployment-data="store.deploymentData"
:project-path="projectPath"
:tags-path="tagsPath"
+ :show-legend="showLegend"
+ :small-graph="forceSmallGraph"
/>
</graph-group>
</div>
diff --git a/app/assets/javascripts/monitoring/components/graph.vue b/app/assets/javascripts/monitoring/components/graph.vue
index ea5c24efaf9..9e67a6f2146 100644
--- a/app/assets/javascripts/monitoring/components/graph.vue
+++ b/app/assets/javascripts/monitoring/components/graph.vue
@@ -52,6 +52,16 @@
type: String,
required: true,
},
+ showLegend: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ smallGraph: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
@@ -130,7 +140,7 @@
const breakpointSize = bp.getBreakpointSize();
const query = this.graphData.queries[0];
this.margin = measurements.large.margin;
- if (breakpointSize === 'xs' || breakpointSize === 'sm') {
+ if (this.smallGraph || breakpointSize === 'xs' || breakpointSize === 'sm') {
this.graphHeight = 300;
this.margin = measurements.small.margin;
this.measurements = measurements.small;
@@ -182,7 +192,9 @@
this.graphHeightOffset,
);
- if (this.timeSeries.length > 3) {
+ if (!this.showLegend) {
+ this.baseGraphHeight -= 50;
+ } else if (this.timeSeries.length > 3) {
this.baseGraphHeight = this.baseGraphHeight += (this.timeSeries.length - 3) * 20;
}
@@ -255,6 +267,7 @@
:time-series="timeSeries"
:unit-of-display="unitOfDisplay"
:current-data-index="currentDataIndex"
+ :show-legend-group="showLegend"
/>
<svg
class="graph-data"
diff --git a/app/assets/javascripts/monitoring/components/graph/legend.vue b/app/assets/javascripts/monitoring/components/graph/legend.vue
index c6e8d726ffc..3149397b61f 100644
--- a/app/assets/javascripts/monitoring/components/graph/legend.vue
+++ b/app/assets/javascripts/monitoring/components/graph/legend.vue
@@ -39,6 +39,11 @@
type: Number,
required: true,
},
+ showLegendGroup: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
},
data() {
return {
@@ -57,8 +62,9 @@
},
rectTransform() {
- const yCoordinate = ((this.graphHeight - this.margin.top) / 2)
- + (this.yLabelWidth / 2) + 10 || 0;
+ const yCoordinate = (((this.graphHeight - this.margin.top)
+ + this.measurements.axisLabelLineOffset) / 2)
+ + (this.yLabelWidth / 2) || 0;
return `translate(0, ${yCoordinate}) rotate(-90)`;
},
@@ -166,39 +172,41 @@
>
Time
</text>
- <g
- class="legend-group"
- v-for="(series, index) in timeSeries"
- :key="index"
- :transform="translateLegendGroup(index)"
- >
- <line
- :stroke="series.lineColor"
- :stroke-width="measurements.legends.height"
- :stroke-dasharray="strokeDashArray(series.lineStyle)"
- :x1="measurements.legends.offsetX"
- :x2="measurements.legends.offsetX + measurements.legends.width"
- :y1="graphHeight - measurements.legends.offsetY"
- :y2="graphHeight - measurements.legends.offsetY"
- />
- <text
- v-if="timeSeries.length > 1"
- class="legend-metric-title"
- ref="legendTitleSvg"
- x="38"
- :y="graphHeight - 30"
- >
- {{ createSeriesString(index, series) }}
- </text>
- <text
- v-else
- class="legend-metric-title"
- ref="legendTitleSvg"
- x="38"
- :y="graphHeight - 30"
+ <template v-if="showLegendGroup">
+ <g
+ class="legend-group"
+ v-for="(series, index) in timeSeries"
+ :key="index"
+ :transform="translateLegendGroup(index)"
>
- {{ legendTitle }} {{ formatMetricUsage(series) }}
- </text>
- </g>
+ <line
+ :stroke="series.lineColor"
+ :stroke-width="measurements.legends.height"
+ :stroke-dasharray="strokeDashArray(series.lineStyle)"
+ :x1="measurements.legends.offsetX"
+ :x2="measurements.legends.offsetX + measurements.legends.width"
+ :y1="graphHeight - measurements.legends.offsetY"
+ :y2="graphHeight - measurements.legends.offsetY"
+ />
+ <text
+ v-if="timeSeries.length > 1"
+ class="legend-metric-title"
+ ref="legendTitleSvg"
+ x="38"
+ :y="graphHeight - 30"
+ >
+ {{ createSeriesString(index, series) }}
+ </text>
+ <text
+ v-else
+ class="legend-metric-title"
+ ref="legendTitleSvg"
+ x="38"
+ :y="graphHeight - 30"
+ >
+ {{ legendTitle }} {{ formatMetricUsage(series) }}
+ </text>
+ </g>
+ </template>
</g>
</template>
diff --git a/app/assets/javascripts/monitoring/components/graph_group.vue b/app/assets/javascripts/monitoring/components/graph_group.vue
index 079351a69af..f71cf614552 100644
--- a/app/assets/javascripts/monitoring/components/graph_group.vue
+++ b/app/assets/javascripts/monitoring/components/graph_group.vue
@@ -5,12 +5,20 @@
type: String,
required: true,
},
+ showPanels: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
},
};
</script>
<template>
- <div class="panel panel-default prometheus-panel">
+ <div
+ v-if="showPanels"
+ class="panel panel-default prometheus-panel"
+ >
<div class="panel-heading">
<h4>{{ name }}</h4>
</div>
@@ -18,4 +26,10 @@
<slot></slot>
</div>
</div>
+ <div
+ v-else
+ class="prometheus-graph-group"
+ >
+ <slot></slot>
+ </div>
</template>
diff --git a/app/assets/javascripts/monitoring/monitoring_bundle.js b/app/assets/javascripts/monitoring/monitoring_bundle.js
index c3b0ef7e9ca..41270e015d4 100644
--- a/app/assets/javascripts/monitoring/monitoring_bundle.js
+++ b/app/assets/javascripts/monitoring/monitoring_bundle.js
@@ -1,7 +1,22 @@
import Vue from 'vue';
+import { convertPermissionToBoolean } from '~/lib/utils/common_utils';
import Dashboard from './components/dashboard.vue';
-export default () => new Vue({
- el: '#prometheus-graphs',
- render: createElement => createElement(Dashboard),
-});
+export default () => {
+ const el = document.getElementById('prometheus-graphs');
+
+ if (el && el.dataset) {
+ // eslint-disable-next-line no-new
+ new Vue({
+ el,
+ render(createElement) {
+ return createElement(Dashboard, {
+ props: {
+ ...el.dataset,
+ hasMetrics: convertPermissionToBoolean(el.dataset.hasMetrics),
+ },
+ });
+ },
+ });
+ }
+};
diff --git a/app/assets/javascripts/monitoring/services/monitoring_service.js b/app/assets/javascripts/monitoring/services/monitoring_service.js
index e230a06cd8c..6fcca36d2fa 100644
--- a/app/assets/javascripts/monitoring/services/monitoring_service.js
+++ b/app/assets/javascripts/monitoring/services/monitoring_service.js
@@ -40,6 +40,9 @@ export default class MonitoringService {
}
getDeploymentData() {
+ if (!this.deploymentEndpoint) {
+ return Promise.resolve([]);
+ }
return backOffRequest(() => axios.get(this.deploymentEndpoint))
.then(resp => resp.data)
.then((response) => {
diff --git a/app/assets/javascripts/pages/projects/environments/index.js b/app/assets/javascripts/pages/projects/environments/index/index.js
index ace8af00ece..ace8af00ece 100644
--- a/app/assets/javascripts/pages/projects/environments/index.js
+++ b/app/assets/javascripts/pages/projects/environments/index/index.js
diff --git a/app/assets/stylesheets/pages/environments.scss b/app/assets/stylesheets/pages/environments.scss
index 884665d35c7..58700661142 100644
--- a/app/assets/stylesheets/pages/environments.scss
+++ b/app/assets/stylesheets/pages/environments.scss
@@ -369,7 +369,8 @@
}
> text {
- font-size: 12px;
+ fill: $theme-gray-600;
+ font-size: 10px;
}
}
diff --git a/app/views/projects/environments/metrics.html.haml b/app/views/projects/environments/metrics.html.haml
index 9d9759ebc5f..c151b5acdf7 100644
--- a/app/views/projects/environments/metrics.html.haml
+++ b/app/views/projects/environments/metrics.html.haml
@@ -15,7 +15,8 @@
"empty-getting-started-svg-path": image_path('illustrations/monitoring/getting_started.svg'),
"empty-loading-svg-path": image_path('illustrations/monitoring/loading.svg'),
"empty-unable-to-connect-svg-path": image_path('illustrations/monitoring/unable_to_connect.svg'),
- "additional-metrics": additional_metrics_project_environment_path(@project, @environment, format: :json),
+ "metrics-endpoint": additional_metrics_project_environment_path(@project, @environment, format: :json),
+ "deployment-endpoint": project_environment_deployments_path(@project, @environment, format: :json),
"project-path": project_path(@project),
"tags-path": project_tags_path(@project),
- "has-metrics": "#{@environment.has_metrics?}", deployment_endpoint: project_environment_deployments_path(@project, @environment, format: :json) } }
+ "has-metrics": "#{@environment.has_metrics?}" } }
diff --git a/spec/javascripts/fixtures/environments.rb b/spec/javascripts/fixtures/environments.rb
deleted file mode 100644
index d2457d75419..00000000000
--- a/spec/javascripts/fixtures/environments.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-require 'spec_helper'
-
-describe Projects::EnvironmentsController, '(JavaScript fixtures)', type: :controller do
- include JavaScriptFixturesHelpers
-
- let(:admin) { create(:admin) }
- let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
- let(:project) { create(:project_empty_repo, namespace: namespace, path: 'environments-project') }
- let(:environment) { create(:environment, name: 'production', project: project) }
-
- render_views
-
- before(:all) do
- clean_frontend_fixtures('environments/metrics')
- end
-
- before do
- sign_in(admin)
- end
-
- it 'environments/metrics/metrics.html.raw' do |example|
- get :metrics,
- namespace_id: project.namespace,
- project_id: project,
- id: environment.id
-
- expect(response).to be_success
- store_frontend_fixture(response, example.description)
- end
-end
diff --git a/spec/javascripts/monitoring/dashboard_spec.js b/spec/javascripts/monitoring/dashboard_spec.js
index eb8f6bbe50d..29b355307ef 100644
--- a/spec/javascripts/monitoring/dashboard_spec.js
+++ b/spec/javascripts/monitoring/dashboard_spec.js
@@ -5,24 +5,35 @@ import axios from '~/lib/utils/axios_utils';
import { metricsGroupsAPIResponse, mockApiEndpoint } from './mock_data';
describe('Dashboard', () => {
- const fixtureName = 'environments/metrics/metrics.html.raw';
let DashboardComponent;
- let component;
- preloadFixtures(fixtureName);
+
+ const propsData = {
+ hasMetrics: false,
+ documentationPath: '/path/to/docs',
+ settingsPath: '/path/to/settings',
+ clustersPath: '/path/to/clusters',
+ tagsPath: '/path/to/tags',
+ projectPath: '/path/to/project',
+ metricsEndpoint: mockApiEndpoint,
+ deploymentEndpoint: null,
+ emptyGettingStartedSvgPath: '/path/to/getting-started.svg',
+ emptyLoadingSvgPath: '/path/to/loading.svg',
+ emptyUnableToConnectSvgPath: '/path/to/unable-to-connect.svg',
+ };
beforeEach(() => {
- loadFixtures(fixtureName);
+ setFixtures('<div class="prometheus-graphs"></div>');
DashboardComponent = Vue.extend(Dashboard);
});
describe('no metrics are available yet', () => {
it('shows a getting started empty state when no metrics are present', () => {
- component = new DashboardComponent({
- el: document.querySelector('#prometheus-graphs'),
+ const component = new DashboardComponent({
+ el: document.querySelector('.prometheus-graphs'),
+ propsData,
});
- component.$mount();
- expect(component.$el.querySelector('#prometheus-graphs')).toBe(null);
+ expect(component.$el.querySelector('.prometheus-graphs')).toBe(null);
expect(component.state).toEqual('gettingStarted');
});
});
@@ -30,11 +41,8 @@ describe('Dashboard', () => {
describe('requests information to the server', () => {
let mock;
beforeEach(() => {
- document.querySelector('#prometheus-graphs').setAttribute('data-has-metrics', 'true');
mock = new MockAdapter(axios);
- mock.onGet(mockApiEndpoint).reply(200, {
- metricsGroupsAPIResponse,
- });
+ mock.onGet(mockApiEndpoint).reply(200, metricsGroupsAPIResponse);
});
afterEach(() => {
@@ -42,14 +50,43 @@ describe('Dashboard', () => {
});
it('shows up a loading state', (done) => {
- component = new DashboardComponent({
- el: document.querySelector('#prometheus-graphs'),
+ const component = new DashboardComponent({
+ el: document.querySelector('.prometheus-graphs'),
+ propsData: { ...propsData, hasMetrics: true },
});
- component.$mount();
+
Vue.nextTick(() => {
expect(component.state).toEqual('loading');
done();
});
});
+
+ it('hides the legend when showLegend is false', (done) => {
+ const component = new DashboardComponent({
+ el: document.querySelector('.prometheus-graphs'),
+ propsData: { ...propsData, hasMetrics: true, showLegend: false },
+ });
+
+ 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) => {
+ const component = new DashboardComponent({
+ el: document.querySelector('.prometheus-graphs'),
+ propsData: { ...propsData, hasMetrics: true, showPanels: false },
+ });
+
+ setTimeout(() => {
+ expect(component.showEmptyState).toEqual(false);
+ expect(component.$el.querySelector('.prometheus-panel')).toEqual(null);
+ expect(component.$el.querySelector('.prometheus-graph-group')).toBeTruthy();
+ done();
+ });
+ });
});
});