Merge branch 'prettify-monitoring-code' into 'master'
Clean up monitoring components See merge request gitlab-org/gitlab-ce!18030
This commit is contained in:
commit
092445a402
8 changed files with 719 additions and 752 deletions
|
@ -1,20 +1,19 @@
|
|||
<script>
|
||||
import _ from 'underscore';
|
||||
import Flash from '../../flash';
|
||||
import MonitoringService from '../services/monitoring_service';
|
||||
import GraphGroup from './graph_group.vue';
|
||||
import Graph from './graph.vue';
|
||||
import EmptyState from './empty_state.vue';
|
||||
import MonitoringStore from '../stores/monitoring_store';
|
||||
import eventHub from '../event_hub';
|
||||
import _ from 'underscore';
|
||||
import Flash from '../../flash';
|
||||
import MonitoringService from '../services/monitoring_service';
|
||||
import GraphGroup from './graph_group.vue';
|
||||
import Graph from './graph.vue';
|
||||
import EmptyState from './empty_state.vue';
|
||||
import MonitoringStore from '../stores/monitoring_store';
|
||||
import eventHub from '../event_hub';
|
||||
|
||||
export default {
|
||||
export default {
|
||||
components: {
|
||||
Graph,
|
||||
GraphGroup,
|
||||
EmptyState,
|
||||
},
|
||||
|
||||
props: {
|
||||
hasMetrics: {
|
||||
type: Boolean,
|
||||
|
@ -82,7 +81,6 @@
|
|||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
store: new MonitoringStore(),
|
||||
|
@ -94,7 +92,6 @@
|
|||
resizeThrottled: {},
|
||||
};
|
||||
},
|
||||
|
||||
created() {
|
||||
this.service = new MonitoringService({
|
||||
metricsEndpoint: this.metricsEndpoint,
|
||||
|
@ -103,13 +100,11 @@
|
|||
eventHub.$on('toggleAspectRatio', this.toggleAspectRatio);
|
||||
eventHub.$on('hoverChanged', this.hoverChanged);
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
eventHub.$off('toggleAspectRatio', this.toggleAspectRatio);
|
||||
eventHub.$off('hoverChanged', this.hoverChanged);
|
||||
window.removeEventListener('resize', this.resizeThrottled, false);
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.resizeThrottled = _.throttle(this.resize, 600);
|
||||
if (!this.hasMetrics) {
|
||||
|
@ -119,14 +114,13 @@
|
|||
window.addEventListener('resize', this.resizeThrottled, false);
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
getGraphsData() {
|
||||
this.state = 'loading';
|
||||
Promise.all([
|
||||
this.service.getGraphsData()
|
||||
.then(data => this.store.storeMetrics(data)),
|
||||
this.service.getDeploymentData()
|
||||
this.service.getGraphsData().then(data => this.store.storeMetrics(data)),
|
||||
this.service
|
||||
.getDeploymentData()
|
||||
.then(data => this.store.storeDeploymentData(data))
|
||||
.catch(() => new Flash('Error getting deployment information.')),
|
||||
])
|
||||
|
@ -137,13 +131,13 @@
|
|||
}
|
||||
this.showEmptyState = false;
|
||||
})
|
||||
.catch(() => { this.state = 'unableToConnect'; });
|
||||
.catch(() => {
|
||||
this.state = 'unableToConnect';
|
||||
});
|
||||
},
|
||||
|
||||
resize() {
|
||||
this.updateAspectRatio = true;
|
||||
},
|
||||
|
||||
toggleAspectRatio() {
|
||||
this.updatedAspectRatios = this.updatedAspectRatios += 1;
|
||||
if (this.store.getMetricsCount() === this.updatedAspectRatios) {
|
||||
|
@ -151,12 +145,11 @@
|
|||
this.updatedAspectRatios = 0;
|
||||
}
|
||||
},
|
||||
|
||||
hoverChanged(data) {
|
||||
this.hoverData = data;
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
export default {
|
||||
export default {
|
||||
props: {
|
||||
documentationPath: {
|
||||
type: String,
|
||||
|
@ -79,13 +79,12 @@
|
|||
currentState() {
|
||||
return this.states[this.selectedState];
|
||||
},
|
||||
|
||||
showButtonDescription() {
|
||||
if (this.selectedState === 'unableToConnect') return true;
|
||||
return false;
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -1,31 +1,29 @@
|
|||
<script>
|
||||
import { scaleLinear, scaleTime } from 'd3-scale';
|
||||
import { axisLeft, axisBottom } from 'd3-axis';
|
||||
import { max, extent } from 'd3-array';
|
||||
import { select } from 'd3-selection';
|
||||
import GraphLegend from './graph/legend.vue';
|
||||
import GraphFlag from './graph/flag.vue';
|
||||
import GraphDeployment from './graph/deployment.vue';
|
||||
import GraphPath from './graph/path.vue';
|
||||
import MonitoringMixin from '../mixins/monitoring_mixins';
|
||||
import eventHub from '../event_hub';
|
||||
import measurements from '../utils/measurements';
|
||||
import { bisectDate, timeScaleFormat } from '../utils/date_time_formatters';
|
||||
import createTimeSeries from '../utils/multiple_time_series';
|
||||
import bp from '../../breakpoints';
|
||||
import { scaleLinear, scaleTime } from 'd3-scale';
|
||||
import { axisLeft, axisBottom } from 'd3-axis';
|
||||
import { max, extent } from 'd3-array';
|
||||
import { select } from 'd3-selection';
|
||||
import GraphLegend from './graph/legend.vue';
|
||||
import GraphFlag from './graph/flag.vue';
|
||||
import GraphDeployment from './graph/deployment.vue';
|
||||
import GraphPath from './graph/path.vue';
|
||||
import MonitoringMixin from '../mixins/monitoring_mixins';
|
||||
import eventHub from '../event_hub';
|
||||
import measurements from '../utils/measurements';
|
||||
import { bisectDate, timeScaleFormat } from '../utils/date_time_formatters';
|
||||
import createTimeSeries from '../utils/multiple_time_series';
|
||||
import bp from '../../breakpoints';
|
||||
|
||||
const d3 = { scaleLinear, scaleTime, axisLeft, axisBottom, max, extent, select };
|
||||
const d3 = { scaleLinear, scaleTime, axisLeft, axisBottom, max, extent, select };
|
||||
|
||||
export default {
|
||||
export default {
|
||||
components: {
|
||||
GraphLegend,
|
||||
GraphFlag,
|
||||
GraphDeployment,
|
||||
GraphPath,
|
||||
},
|
||||
|
||||
mixins: [MonitoringMixin],
|
||||
|
||||
props: {
|
||||
graphData: {
|
||||
type: Object,
|
||||
|
@ -63,7 +61,6 @@
|
|||
default: false,
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
baseGraphHeight: 450,
|
||||
|
@ -90,31 +87,25 @@
|
|||
realPixelRatio: 1,
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
outerViewBox() {
|
||||
return `0 0 ${this.baseGraphWidth} ${this.baseGraphHeight}`;
|
||||
},
|
||||
|
||||
innerViewBox() {
|
||||
return `0 0 ${this.baseGraphWidth - 150} ${this.baseGraphHeight}`;
|
||||
},
|
||||
|
||||
axisTransform() {
|
||||
return `translate(70, ${this.graphHeight - 100})`;
|
||||
},
|
||||
|
||||
paddingBottomRootSvg() {
|
||||
return {
|
||||
paddingBottom: `${(Math.ceil(this.baseGraphHeight * 100) / this.baseGraphWidth) || 0}%`,
|
||||
paddingBottom: `${Math.ceil(this.baseGraphHeight * 100) / this.baseGraphWidth || 0}%`,
|
||||
};
|
||||
},
|
||||
|
||||
deploymentFlagData() {
|
||||
return this.reducedDeploymentData.find(deployment => deployment.showDeploymentFlag);
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
updateAspectRatio() {
|
||||
if (this.updateAspectRatio) {
|
||||
|
@ -125,16 +116,13 @@
|
|||
eventHub.$emit('toggleAspectRatio');
|
||||
}
|
||||
},
|
||||
|
||||
hoverData() {
|
||||
this.positionFlag();
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.draw();
|
||||
},
|
||||
|
||||
methods: {
|
||||
draw() {
|
||||
const breakpointSize = bp.getBreakpointSize();
|
||||
|
@ -148,19 +136,17 @@
|
|||
this.unitOfDisplay = query.unit || '';
|
||||
this.yAxisLabel = this.graphData.y_label || 'Values';
|
||||
this.legendTitle = query.label || 'Average';
|
||||
this.graphWidth = this.$refs.baseSvg.clientWidth -
|
||||
this.margin.left - this.margin.right;
|
||||
this.graphWidth = this.$refs.baseSvg.clientWidth - this.margin.left - this.margin.right;
|
||||
this.graphHeight = this.graphHeight - this.margin.top - this.margin.bottom;
|
||||
this.baseGraphHeight = this.graphHeight;
|
||||
this.baseGraphWidth = this.graphWidth;
|
||||
|
||||
// pixel offsets inside the svg and outside are not 1:1
|
||||
this.realPixelRatio = (this.$refs.baseSvg.clientWidth / this.baseGraphWidth);
|
||||
this.realPixelRatio = this.$refs.baseSvg.clientWidth / this.baseGraphWidth;
|
||||
|
||||
this.renderAxesPaths();
|
||||
this.formatDeployments();
|
||||
},
|
||||
|
||||
handleMouseOverGraph(e) {
|
||||
let point = this.$refs.graphData.createSVGPoint();
|
||||
point.x = e.clientX;
|
||||
|
@ -174,7 +160,7 @@
|
|||
const d1 = firstTimeSeries.values[overlayIndex];
|
||||
if (d0 === undefined || d1 === undefined) return;
|
||||
const evalTime = timeValueOverlay - d0[0] > d1[0] - timeValueOverlay;
|
||||
const hoveredDataIndex = evalTime ? overlayIndex : (overlayIndex - 1);
|
||||
const hoveredDataIndex = evalTime ? overlayIndex : overlayIndex - 1;
|
||||
const hoveredDate = firstTimeSeries.values[hoveredDataIndex].time;
|
||||
const currentDeployXPos = this.mouseOverDeployInfo(point.x);
|
||||
|
||||
|
@ -183,7 +169,6 @@
|
|||
currentDeployXPos,
|
||||
});
|
||||
},
|
||||
|
||||
renderAxesPaths() {
|
||||
this.timeSeries = createTimeSeries(
|
||||
this.graphData.queries,
|
||||
|
@ -198,39 +183,47 @@
|
|||
this.baseGraphHeight = this.baseGraphHeight += (this.timeSeries.length - 3) * 20;
|
||||
}
|
||||
|
||||
const axisXScale = d3.scaleTime()
|
||||
.range([0, this.graphWidth - 70]);
|
||||
const axisYScale = d3.scaleLinear()
|
||||
.range([this.graphHeight - this.graphHeightOffset, 0]);
|
||||
const axisXScale = d3.scaleTime().range([0, this.graphWidth - 70]);
|
||||
const axisYScale = d3.scaleLinear().range([this.graphHeight - this.graphHeightOffset, 0]);
|
||||
|
||||
const allValues = this.timeSeries.reduce((all, { values }) => all.concat(values), []);
|
||||
axisXScale.domain(d3.extent(allValues, d => d.time));
|
||||
axisYScale.domain([0, d3.max(allValues.map(d => d.value))]);
|
||||
|
||||
const xAxis = d3.axisBottom()
|
||||
const xAxis = d3
|
||||
.axisBottom()
|
||||
.scale(axisXScale)
|
||||
.ticks(this.graphWidth / 120)
|
||||
.tickFormat(timeScaleFormat);
|
||||
|
||||
const yAxis = d3.axisLeft()
|
||||
const yAxis = d3
|
||||
.axisLeft()
|
||||
.scale(axisYScale)
|
||||
.ticks(measurements.yTicks);
|
||||
|
||||
d3.select(this.$refs.baseSvg).select('.x-axis').call(xAxis);
|
||||
d3
|
||||
.select(this.$refs.baseSvg)
|
||||
.select('.x-axis')
|
||||
.call(xAxis);
|
||||
|
||||
const width = this.graphWidth;
|
||||
d3.select(this.$refs.baseSvg).select('.y-axis').call(yAxis)
|
||||
d3
|
||||
.select(this.$refs.baseSvg)
|
||||
.select('.y-axis')
|
||||
.call(yAxis)
|
||||
.selectAll('.tick')
|
||||
.each(function createTickLines(d, i) {
|
||||
if (i > 0) {
|
||||
d3.select(this).select('line')
|
||||
d3
|
||||
.select(this)
|
||||
.select('line')
|
||||
.attr('x2', width)
|
||||
.attr('class', 'axis-tick');
|
||||
} // Avoid adding the class to the first tick, to prevent coloring
|
||||
}); // This will select all of the ticks once they're rendered
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
export default {
|
||||
export default {
|
||||
props: {
|
||||
deploymentData: {
|
||||
type: Array,
|
||||
|
@ -14,19 +14,17 @@
|
|||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
computed: {
|
||||
calculatedHeight() {
|
||||
return this.graphHeight - this.graphHeightOffset;
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
transformDeploymentGroup(deployment) {
|
||||
return `translate(${Math.floor(deployment.xPos) - 5}, 20)`;
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<g class="deploy-info">
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<script>
|
||||
import { dateFormat, timeFormat } from '../../utils/date_time_formatters';
|
||||
import { formatRelevantDigits } from '../../../lib/utils/number_utils';
|
||||
import icon from '../../../vue_shared/components/icon.vue';
|
||||
import { dateFormat, timeFormat } from '../../utils/date_time_formatters';
|
||||
import { formatRelevantDigits } from '../../../lib/utils/number_utils';
|
||||
import icon from '../../../vue_shared/components/icon.vue';
|
||||
|
||||
export default {
|
||||
export default {
|
||||
components: {
|
||||
icon,
|
||||
},
|
||||
|
@ -54,24 +54,21 @@
|
|||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
computed: {
|
||||
formatTime() {
|
||||
return this.deploymentFlagData ?
|
||||
timeFormat(this.deploymentFlagData.time) :
|
||||
timeFormat(this.currentData.time);
|
||||
return this.deploymentFlagData
|
||||
? timeFormat(this.deploymentFlagData.time)
|
||||
: timeFormat(this.currentData.time);
|
||||
},
|
||||
|
||||
formatDate() {
|
||||
return this.deploymentFlagData ?
|
||||
dateFormat(this.deploymentFlagData.time) :
|
||||
dateFormat(this.currentData.time);
|
||||
return this.deploymentFlagData
|
||||
? dateFormat(this.deploymentFlagData.time)
|
||||
: dateFormat(this.currentData.time);
|
||||
},
|
||||
|
||||
cursorStyle() {
|
||||
const xCoordinate = this.deploymentFlagData ?
|
||||
this.deploymentFlagData.xPos :
|
||||
this.currentXCoordinate;
|
||||
const xCoordinate = this.deploymentFlagData
|
||||
? this.deploymentFlagData.xPos
|
||||
: this.currentXCoordinate;
|
||||
|
||||
const offsetTop = 20 * this.realPixelRatio;
|
||||
const offsetLeft = (70 + xCoordinate) * this.realPixelRatio;
|
||||
|
@ -83,7 +80,6 @@
|
|||
height: `${height}px`,
|
||||
};
|
||||
},
|
||||
|
||||
flagOrientation() {
|
||||
if (this.currentXCoordinate * this.realPixelRatio > 120) {
|
||||
return 'left';
|
||||
|
@ -91,20 +87,17 @@
|
|||
return 'right';
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
seriesMetricValue(series) {
|
||||
const index = this.deploymentFlagData ?
|
||||
this.deploymentFlagData.seriesIndex :
|
||||
this.currentDataIndex;
|
||||
const value = series.values[index] &&
|
||||
series.values[index].value;
|
||||
const index = this.deploymentFlagData
|
||||
? this.deploymentFlagData.seriesIndex
|
||||
: this.currentDataIndex;
|
||||
const value = series.values[index] && series.values[index].value;
|
||||
if (isNaN(value)) {
|
||||
return '-';
|
||||
}
|
||||
return `${formatRelevantDigits(value)}${this.unitOfDisplay}`;
|
||||
},
|
||||
|
||||
seriesMetricLabel(index, series) {
|
||||
if (this.timeSeries.length < 2) {
|
||||
return this.legendTitle;
|
||||
|
@ -114,14 +107,13 @@
|
|||
}
|
||||
return `series ${index + 1}`;
|
||||
},
|
||||
|
||||
strokeDashArray(type) {
|
||||
if (type === 'dashed') return '6, 3';
|
||||
if (type === 'dotted') return '3, 3';
|
||||
return null;
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script>
|
||||
import { formatRelevantDigits } from '../../../lib/utils/number_utils';
|
||||
import { formatRelevantDigits } from '../../../lib/utils/number_utils';
|
||||
|
||||
export default {
|
||||
export default {
|
||||
props: {
|
||||
graphWidth: {
|
||||
type: Number,
|
||||
|
@ -55,29 +55,24 @@
|
|||
},
|
||||
computed: {
|
||||
textTransform() {
|
||||
const yCoordinate = (((this.graphHeight - this.margin.top)
|
||||
+ this.measurements.axisLabelLineOffset) / 2) || 0;
|
||||
const yCoordinate =
|
||||
(this.graphHeight - this.margin.top + this.measurements.axisLabelLineOffset) / 2 || 0;
|
||||
|
||||
return `translate(15, ${yCoordinate}) rotate(-90)`;
|
||||
},
|
||||
|
||||
rectTransform() {
|
||||
const yCoordinate = (((this.graphHeight - this.margin.top)
|
||||
+ this.measurements.axisLabelLineOffset) / 2)
|
||||
+ (this.yLabelWidth / 2) || 0;
|
||||
const yCoordinate =
|
||||
(this.graphHeight - this.margin.top + this.measurements.axisLabelLineOffset) / 2 +
|
||||
this.yLabelWidth / 2 || 0;
|
||||
|
||||
return `translate(0, ${yCoordinate}) rotate(-90)`;
|
||||
},
|
||||
|
||||
xPosition() {
|
||||
return (((this.graphWidth + this.measurements.axisLabelLineOffset) / 2)
|
||||
- this.margin.right) || 0;
|
||||
return (this.graphWidth + this.measurements.axisLabelLineOffset) / 2 - this.margin.right || 0;
|
||||
},
|
||||
|
||||
yPosition() {
|
||||
return ((this.graphHeight - this.margin.top) + this.measurements.axisLabelLineOffset) || 0;
|
||||
return this.graphHeight - this.margin.top + this.measurements.axisLabelLineOffset || 0;
|
||||
},
|
||||
|
||||
},
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
|
@ -96,32 +91,29 @@
|
|||
},
|
||||
methods: {
|
||||
translateLegendGroup(index) {
|
||||
return `translate(0, ${12 * (index)})`;
|
||||
return `translate(0, ${12 * index})`;
|
||||
},
|
||||
|
||||
formatMetricUsage(series) {
|
||||
const value = series.values[this.currentDataIndex] &&
|
||||
series.values[this.currentDataIndex].value;
|
||||
const value =
|
||||
series.values[this.currentDataIndex] && series.values[this.currentDataIndex].value;
|
||||
if (isNaN(value)) {
|
||||
return '-';
|
||||
}
|
||||
return `${formatRelevantDigits(value)} ${this.unitOfDisplay}`;
|
||||
},
|
||||
|
||||
createSeriesString(index, series) {
|
||||
if (series.metricTag) {
|
||||
return `${series.metricTag} ${this.formatMetricUsage(series)}`;
|
||||
}
|
||||
return `${this.legendTitle} series ${index + 1} ${this.formatMetricUsage(series)}`;
|
||||
},
|
||||
|
||||
strokeDashArray(type) {
|
||||
if (type === 'dashed') return '6, 3';
|
||||
if (type === 'dotted') return '3, 3';
|
||||
return null;
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<g class="axis-label-container">
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
export default {
|
||||
export default {
|
||||
props: {
|
||||
generatedLinePath: {
|
||||
type: String,
|
||||
|
@ -30,7 +30,7 @@
|
|||
return null;
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<g>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
export default {
|
||||
export default {
|
||||
props: {
|
||||
name: {
|
||||
type: String,
|
||||
|
@ -11,7 +11,7 @@
|
|||
default: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
Loading…
Reference in a new issue