Commit a43b7d4a authored by Phil Hughes's avatar Phil Hughes

Merge branch '45738-add-environment-drop-down-to-metrics-dashboard' into 'master'

Add `environment` drop down to Metrics dashboard

Closes #45738

See merge request gitlab-org/gitlab-ce!19833
parents 5c847f1a 786edcb4
<script>
import _ from 'underscore';
import { s__ } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue';
import Flash from '../../flash';
import MonitoringService from '../services/monitoring_service';
import GraphGroup from './graph_group.vue';
......@@ -13,6 +15,7 @@ export default {
Graph,
GraphGroup,
EmptyState,
Icon,
},
props: {
hasMetrics: {
......@@ -80,6 +83,14 @@ export default {
type: String,
required: true,
},
environmentsEndpoint: {
type: String,
required: true,
},
currentEnvironmentName: {
type: String,
required: true,
},
},
data() {
return {
......@@ -96,6 +107,7 @@ export default {
this.service = new MonitoringService({
metricsEndpoint: this.metricsEndpoint,
deploymentEndpoint: this.deploymentEndpoint,
environmentsEndpoint: this.environmentsEndpoint,
});
eventHub.$on('toggleAspectRatio', this.toggleAspectRatio);
eventHub.$on('hoverChanged', this.hoverChanged);
......@@ -122,7 +134,11 @@ export default {
this.service
.getDeploymentData()
.then(data => this.store.storeDeploymentData(data))
.catch(() => new Flash('Error getting deployment information.')),
.catch(() => Flash(s__('Metrics|There was an error getting deployment information.'))),
this.service
.getEnvironmentsData()
.then((data) => this.store.storeEnvironmentsData(data))
.catch(() => Flash(s__('Metrics|There was an error getting environments information.'))),
])
.then(() => {
if (this.store.groups.length < 1) {
......@@ -155,8 +171,41 @@ export default {
<template>
<div
v-if="!showEmptyState"
class="prometheus-graphs"
class="prometheus-graphs prepend-top-10"
>
<div class="environments d-flex align-items-center">
{{ s__('Metrics|Environment') }}
<div class="dropdown prepend-left-10">
<button
class="dropdown-menu-toggle"
data-toggle="dropdown"
type="button"
>
<span>
{{ currentEnvironmentName }}
</span>
<icon
name="chevron-down"
/>
</button>
<div class="dropdown-menu dropdown-menu-selectable dropdown-menu-drop-up">
<ul>
<li
v-for="environment in store.environmentsData"
:key="environment.latest.id"
>
<a
:href="environment.latest.metrics_path"
:class="{ 'is-active': environment.latest.name == currentEnvironmentName }"
class="dropdown-item"
>
{{ environment.latest.name }}
</a>
</li>
</ul>
</div>
</div>
</div>
<graph-group
v-for="(groupData, index) in store.groups"
:key="index"
......
import axios from '../../lib/utils/axios_utils';
import statusCodes from '../../lib/utils/http_status';
import { backOff } from '../../lib/utils/common_utils';
import { s__ } from '../../locale';
const MAX_REQUESTS = 3;
......@@ -23,9 +24,10 @@ function backOffRequest(makeRequestCallback) {
}
export default class MonitoringService {
constructor({ metricsEndpoint, deploymentEndpoint }) {
constructor({ metricsEndpoint, deploymentEndpoint, environmentsEndpoint }) {
this.metricsEndpoint = metricsEndpoint;
this.deploymentEndpoint = deploymentEndpoint;
this.environmentsEndpoint = environmentsEndpoint;
}
getGraphsData() {
......@@ -33,7 +35,7 @@ export default class MonitoringService {
.then(resp => resp.data)
.then((response) => {
if (!response || !response.data) {
throw new Error('Unexpected metrics data response from prometheus endpoint');
throw new Error(s__('Metrics|Unexpected metrics data response from prometheus endpoint'));
}
return response.data;
});
......@@ -47,9 +49,20 @@ export default class MonitoringService {
.then(resp => resp.data)
.then((response) => {
if (!response || !response.deployments) {
throw new Error('Unexpected deployment data response from prometheus endpoint');
throw new Error(s__('Metrics|Unexpected deployment data response from prometheus endpoint'));
}
return response.deployments;
});
}
getEnvironmentsData() {
return axios.get(this.environmentsEndpoint)
.then(resp => resp.data)
.then((response) => {
if (!response || !response.environments) {
throw new Error(s__('Metrics|There was an error fetching the environments data, please try again'));
}
return response.environments;
});
}
}
......@@ -24,6 +24,7 @@ export default class MonitoringStore {
constructor() {
this.groups = [];
this.deploymentData = [];
this.environmentsData = [];
}
storeMetrics(groups = []) {
......@@ -37,6 +38,10 @@ export default class MonitoringStore {
this.deploymentData = deploymentData;
}
storeEnvironmentsData(environmentsData = []) {
this.environmentsData = environmentsData;
}
getMetricsCount() {
return this.groups.reduce((count, group) => count + group.metrics.length, 0);
}
......
......@@ -222,6 +222,23 @@
}
}
.prometheus-graphs {
.environments {
.dropdown-menu-toggle {
svg {
position: absolute;
right: 5%;
top: 25%;
}
}
.dropdown-menu-toggle,
.dropdown-menu {
width: 240px;
}
}
}
.environments-actions {
.external-url,
.monitoring-url,
......
......@@ -2,15 +2,9 @@
- page_title "Metrics for environment", @environment.name
.prometheus-container{ class: container_class }
.top-area
.row
.col-sm-6
%h3
Environment:
= link_to @environment.name, environment_path(@environment)
#prometheus-graphs{ data: { "settings-path": edit_project_service_path(@project, 'prometheus'),
"clusters-path": project_clusters_path(@project),
"current-environment-name": @environment.name,
"documentation-path": help_page_path('administration/monitoring/prometheus/index.md'),
"empty-getting-started-svg-path": image_path('illustrations/monitoring/getting_started.svg'),
"empty-loading-svg-path": image_path('illustrations/monitoring/loading.svg'),
......@@ -18,6 +12,7 @@
"empty-unable-to-connect-svg-path": image_path('illustrations/monitoring/unable_to_connect.svg'),
"metrics-endpoint": additional_metrics_project_environment_path(@project, @environment, format: :json),
"deployment-endpoint": project_environment_deployments_path(@project, @environment, format: :json),
"environments-endpoint": project_environments_path(@project, format: :json),
"project-path": project_path(@project),
"tags-path": project_tags_path(@project),
"has-metrics": "#{@environment.has_metrics?}" } }
---
title: Add environment dropdown for the metrics page
merge_request: 19833
author:
type: changed
......@@ -2,7 +2,7 @@ import Vue from 'vue';
import MockAdapter from 'axios-mock-adapter';
import Dashboard from '~/monitoring/components/dashboard.vue';
import axios from '~/lib/utils/axios_utils';
import { metricsGroupsAPIResponse, mockApiEndpoint } from './mock_data';
import { metricsGroupsAPIResponse, mockApiEndpoint, environmentData } from './mock_data';
describe('Dashboard', () => {
let DashboardComponent;
......@@ -20,6 +20,8 @@ describe('Dashboard', () => {
emptyLoadingSvgPath: '/path/to/loading.svg',
emptyNoDataSvgPath: '/path/to/no-data.svg',
emptyUnableToConnectSvgPath: '/path/to/unable-to-connect.svg',
environmentsEndpoint: '/root/hello-prometheus/environments/35',
currentEnvironmentName: 'production',
};
beforeEach(() => {
......@@ -50,7 +52,7 @@ describe('Dashboard', () => {
mock.restore();
});
it('shows up a loading state', (done) => {
it('shows up a loading state', done => {
const component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'),
propsData: { ...propsData, hasMetrics: true },
......@@ -62,7 +64,7 @@ describe('Dashboard', () => {
});
});
it('hides the legend when showLegend is false', (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 },
......@@ -76,7 +78,7 @@ describe('Dashboard', () => {
});
});
it('hides the group panels when showPanels is false', (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 },
......@@ -89,5 +91,40 @@ describe('Dashboard', () => {
done();
});
});
it('renders the dropdown with a number of environments', done => {
const component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'),
propsData: { ...propsData, hasMetrics: true, showPanels: false },
});
component.store.storeEnvironmentsData(environmentData);
setTimeout(() => {
const dropdownMenuEnvironments = component.$el.querySelectorAll('.dropdown-menu ul li a');
expect(dropdownMenuEnvironments.length).toEqual(component.store.environmentsData.length);
done();
});
});
it('renders the dropdown with a single is-active element', done => {
const component = new DashboardComponent({
el: document.querySelector('.prometheus-graphs'),
propsData: { ...propsData, hasMetrics: true, showPanels: false },
});
component.store.storeEnvironmentsData(environmentData);
setTimeout(() => {
const dropdownIsActiveElement = component.$el.querySelectorAll(
'.dropdown-menu ul li a.is-active',
);
expect(dropdownIsActiveElement.length).toEqual(1);
expect(dropdownIsActiveElement[0].textContent.trim()).toEqual(
component.currentEnvironmentName,
);
done();
});
});
});
});
......@@ -6542,3 +6542,44 @@ export function convertDatesMultipleSeries(multipleSeries) {
});
return convertedMultiple;
}
export const environmentData = [
{
name: 'production',
size: 1,
latest: {
id: 34,
name: 'production',
state: 'available',
external_url: 'http://root-autodevops-deploy.my-fake-domain.com',
environment_type: null,
stop_action: false,
metrics_path: '/root/hello-prometheus/environments/34/metrics',
environment_path: '/root/hello-prometheus/environments/34',
stop_path: '/root/hello-prometheus/environments/34/stop',
terminal_path: '/root/hello-prometheus/environments/34/terminal',
folder_path: '/root/hello-prometheus/environments/folders/production',
created_at: '2018-06-29T16:53:38.301Z',
updated_at: '2018-06-29T16:57:09.825Z',
},
},
{
name: 'review',
size: 1,
latest: {
id: 35,
name: 'review/noop-branch',
state: 'available',
external_url: 'http://root-autodevops-deploy-review-noop-branc-die93w.my-fake-domain.com',
environment_type: 'review',
stop_action: true,
metrics_path: '/root/hello-prometheus/environments/35/metrics',
environment_path: '/root/hello-prometheus/environments/35',
stop_path: '/root/hello-prometheus/environments/35/stop',
terminal_path: '/root/hello-prometheus/environments/35/terminal',
folder_path: '/root/hello-prometheus/environments/folders/review',
created_at: '2018-07-03T18:39:41.702Z',
updated_at: '2018-07-03T18:44:54.010Z',
},
},
];
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