diff options
Diffstat (limited to 'app/assets/javascripts/monitoring')
4 files changed, 77 insertions, 17 deletions
diff --git a/app/assets/javascripts/monitoring/components/graph.vue b/app/assets/javascripts/monitoring/components/graph.vue index e5680a0499f..a13f30e6079 100644 --- a/app/assets/javascripts/monitoring/components/graph.vue +++ b/app/assets/javascripts/monitoring/components/graph.vue @@ -82,11 +82,12 @@ export default { value: 0, }, currentXCoordinate: 0, - currentCoordinates: [], + currentCoordinates: {}, showFlag: false, showFlagContent: false, timeSeries: [], realPixelRatio: 1, + seriesUnderMouse: [], }; }, computed: { @@ -126,6 +127,9 @@ export default { this.draw(); }, methods: { + showDot(path) { + return this.showFlagContent && this.seriesUnderMouse.includes(path); + }, draw() { const breakpointSize = bp.getBreakpointSize(); const query = this.graphData.queries[0]; @@ -155,7 +159,24 @@ export default { point.y = e.clientY; point = point.matrixTransform(this.$refs.graphData.getScreenCTM().inverse()); point.x += 7; - const firstTimeSeries = this.timeSeries[0]; + + this.seriesUnderMouse = this.timeSeries.filter((series) => { + const mouseX = series.timeSeriesScaleX.invert(point.x); + let minDistance = Infinity; + + const closestTickMark = Object.keys(this.allXAxisValues).reduce((closest, x) => { + const distance = Math.abs(Number(new Date(x)) - Number(mouseX)); + if (distance < minDistance) { + minDistance = distance; + return x; + } + return closest; + }); + + return series.values.find(v => v.time.toString() === closestTickMark); + }); + + const firstTimeSeries = this.seriesUnderMouse[0]; const timeValueOverlay = firstTimeSeries.timeSeriesScaleX.invert(point.x); const overlayIndex = bisectDate(firstTimeSeries.values, timeValueOverlay, 1); const d0 = firstTimeSeries.values[overlayIndex - 1]; @@ -190,6 +211,17 @@ export default { axisXScale.domain(d3.extent(allValues, d => d.time)); axisYScale.domain([0, d3.max(allValues.map(d => d.value))]); + this.allXAxisValues = this.timeSeries.reduce((obj, series) => { + const seriesKeys = {}; + series.values.forEach(v => { + seriesKeys[v.time] = true; + }); + return { + ...obj, + ...seriesKeys, + }; + }, {}); + const xAxis = d3 .axisBottom() .scale(axisXScale) @@ -277,9 +309,8 @@ export default { :line-style="path.lineStyle" :line-color="path.lineColor" :area-color="path.areaColor" - :current-coordinates="currentCoordinates[index]" - :current-time-series-index="index" - :show-dot="showFlagContent" + :current-coordinates="currentCoordinates[path.metricTag]" + :show-dot="showDot(path)" /> <graph-deployment :deployment-data="reducedDeploymentData" @@ -303,7 +334,7 @@ export default { :graph-height="graphHeight" :graph-height-offset="graphHeightOffset" :show-flag-content="showFlagContent" - :time-series="timeSeries" + :time-series="seriesUnderMouse" :unit-of-display="unitOfDisplay" :legend-title="legendTitle" :deployment-flag-data="deploymentFlagData" diff --git a/app/assets/javascripts/monitoring/components/graph/flag.vue b/app/assets/javascripts/monitoring/components/graph/flag.vue index 1e6803abf3a..5f00d20ca3f 100644 --- a/app/assets/javascripts/monitoring/components/graph/flag.vue +++ b/app/assets/javascripts/monitoring/components/graph/flag.vue @@ -52,7 +52,7 @@ export default { required: true, }, currentCoordinates: { - type: Array, + type: Object, required: true, }, }, @@ -91,8 +91,8 @@ export default { }, methods: { seriesMetricValue(seriesIndex, series) { - const indexFromCoordinates = this.currentCoordinates[seriesIndex] - ? this.currentCoordinates[seriesIndex].currentDataIndex : 0; + const indexFromCoordinates = this.currentCoordinates[series.metricTag] + ? this.currentCoordinates[series.metricTag].currentDataIndex : 0; const index = this.deploymentFlagData ? this.deploymentFlagData.seriesIndex : indexFromCoordinates; diff --git a/app/assets/javascripts/monitoring/mixins/monitoring_mixins.js b/app/assets/javascripts/monitoring/mixins/monitoring_mixins.js index 4f23814ff3e..007451d5c7a 100644 --- a/app/assets/javascripts/monitoring/mixins/monitoring_mixins.js +++ b/app/assets/javascripts/monitoring/mixins/monitoring_mixins.js @@ -50,19 +50,24 @@ const mixins = { }, positionFlag() { - const timeSeries = this.timeSeries[0]; - const hoveredDataIndex = bisectDate(timeSeries.values, this.hoverData.hoveredDate, 1); + const timeSeries = this.seriesUnderMouse[0]; + if (!timeSeries) { + return; + } + const hoveredDataIndex = bisectDate(timeSeries.values, this.hoverData.hoveredDate); this.currentData = timeSeries.values[hoveredDataIndex]; this.currentXCoordinate = Math.floor(timeSeries.timeSeriesScaleX(this.currentData.time)); - this.currentCoordinates = this.timeSeries.map((series) => { - const currentDataIndex = bisectDate(series.values, this.hoverData.hoveredDate, 1); + this.currentCoordinates = {}; + + this.seriesUnderMouse.forEach((series) => { + const currentDataIndex = bisectDate(series.values, this.hoverData.hoveredDate); const currentData = series.values[currentDataIndex]; const currentX = Math.floor(series.timeSeriesScaleX(currentData.time)); const currentY = Math.floor(series.timeSeriesScaleY(currentData.value)); - return { + this.currentCoordinates[series.metricTag] = { currentX, currentY, currentDataIndex, diff --git a/app/assets/javascripts/monitoring/utils/multiple_time_series.js b/app/assets/javascripts/monitoring/utils/multiple_time_series.js index cee39fd0559..eff0d7325cd 100644 --- a/app/assets/javascripts/monitoring/utils/multiple_time_series.js +++ b/app/assets/javascripts/monitoring/utils/multiple_time_series.js @@ -2,7 +2,7 @@ import _ from 'underscore'; import { scaleLinear, scaleTime } from 'd3-scale'; import { line, area, curveLinear } from 'd3-shape'; import { extent, max, sum } from 'd3-array'; -import { timeMinute } from 'd3-time'; +import { timeMinute, timeSecond } from 'd3-time'; import { capitalizeFirstCharacter } from '~/lib/utils/text_utility'; const d3 = { @@ -14,6 +14,7 @@ const d3 = { extent, max, timeMinute, + timeSecond, sum, }; @@ -51,6 +52,24 @@ function queryTimeSeries(query, graphWidth, graphHeight, graphHeightOffset, xDom return defaultColorPalette[pick]; } + function findByDate(series, time) { + const val = series.find(v => Math.abs(d3.timeSecond.count(time, v.time)) < 60); + if (val) { + return val.value; + } + return NaN; + } + + // The timeseries data may have gaps in it + // but we need a regularly-spaced set of time/value pairs + // this gives us a complete range of one minute intervals + // offset the same amount as the original data + const [minX, maxX] = xDom; + const offset = d3.timeMinute(minX) - Number(minX); + const datesWithoutGaps = d3.timeSecond.every(60) + .range(d3.timeMinute.offset(minX, -1), maxX) + .map(d => d - offset); + query.result.forEach((timeSeries, timeSeriesNumber) => { let metricTag = ''; let lineColor = ''; @@ -119,9 +138,14 @@ function queryTimeSeries(query, graphWidth, graphHeight, graphHeightOffset, xDom }); } + const values = datesWithoutGaps.map(time => ({ + time, + value: findByDate(timeSeries.values, time), + })); + timeSeriesParsed.push({ - linePath: lineFunction(timeSeries.values), - areaPath: areaFunction(timeSeries.values), + linePath: lineFunction(values), + areaPath: areaFunction(values), timeSeriesScaleX, timeSeriesScaleY, values: timeSeries.values, |