diff options
30 files changed, 6119 insertions, 1984 deletions
diff --git a/app/assets/javascripts/monitoring/components/monitoring.vue b/app/assets/javascripts/monitoring/components/monitoring.vue new file mode 100644 index 00000000000..a6a2d3119e3 --- /dev/null +++ b/app/assets/javascripts/monitoring/components/monitoring.vue @@ -0,0 +1,157 @@ +<script> + /* global Flash */ + import _ from 'underscore'; + import statusCodes from '../../lib/utils/http_status'; + import MonitoringService from '../services/monitoring_service'; + import monitoringRow from './monitoring_row.vue'; + import monitoringState from './monitoring_state.vue'; + import MonitoringStore from '../stores/monitoring_store'; + import eventHub from '../event_hub'; + + export default { + + data() { + const metricsData = document.querySelector('#prometheus-graphs').dataset; + const store = new MonitoringStore(); + + return { + store, + state: 'gettingStarted', + hasMetrics: gl.utils.convertPermissionToBoolean(metricsData.hasMetrics), + documentationPath: metricsData.documentationPath, + settingsPath: metricsData.settingsPath, + endpoint: metricsData.additionalMetrics, + deploymentEndpoint: metricsData.deploymentEndpoint, + showEmptyState: true, + backOffRequestCounter: 0, + updateAspectRatio: false, + updatedAspectRatios: 0, + resizeThrottled: {}, + }; + }, + + components: { + monitoringRow, + monitoringState, + }, + + methods: { + getGraphsData() { + const maxNumberOfRequests = 3; + this.state = 'loading'; + gl.utils.backOff((next, stop) => { + this.service.get().then((resp) => { + if (resp.status === statusCodes.NO_CONTENT) { + this.backOffRequestCounter = this.backOffRequestCounter += 1; + if (this.backOffRequestCounter < maxNumberOfRequests) { + next(); + } else { + stop(new Error('Failed to connect to the prometheus server')); + } + } else { + stop(resp); + } + }).catch(stop); + }) + .then((resp) => { + if (resp.status === statusCodes.NO_CONTENT) { + this.state = 'unableToConnect'; + return false; + } + return resp.json(); + }) + .then((metricGroupsData) => { + if (!metricGroupsData) return false; + this.store.storeMetrics(metricGroupsData.data); + return this.getDeploymentData(); + }) + .then((deploymentData) => { + if (deploymentData !== false) { + this.store.storeDeploymentData(deploymentData.deployments); + this.showEmptyState = false; + } + return {}; + }) + .catch(() => { + this.state = 'unableToConnect'; + }); + }, + + getDeploymentData() { + return this.service.getDeploymentData(this.deploymentEndpoint) + .then(resp => resp.json()) + .catch(() => new Flash('Error getting deployment information.')); + }, + + resize() { + this.updateAspectRatio = true; + }, + + toggleAspectRatio() { + this.updatedAspectRatios = this.updatedAspectRatios += 1; + if (this.store.getMetricsCount() === this.updatedAspectRatios) { + this.updateAspectRatio = !this.updateAspectRatio; + this.updatedAspectRatios = 0; + } + }, + + }, + + created() { + this.service = new MonitoringService(this.endpoint); + eventHub.$on('toggleAspectRatio', this.toggleAspectRatio); + }, + + beforeDestroy() { + eventHub.$off('toggleAspectRatio', this.toggleAspectRatio); + window.removeEventListener('resize', this.resizeThrottled, false); + }, + + mounted() { + this.resizeThrottled = _.throttle(this.resize, 600); + if (!this.hasMetrics) { + this.state = 'gettingStarted'; + } else { + this.getGraphsData(); + window.addEventListener('resize', this.resizeThrottled, false); + } + }, + }; +</script> +<template> + <div + class="prometheus-graphs" + v-if="!showEmptyState"> + <div + class="row" + v-for="(groupData, index) in store.groups" + :key="index"> + <div + class="col-md-12"> + <div + class="panel panel-default prometheus-panel"> + <div + class="panel-heading"> + <h4>{{groupData.group}}</h4> + </div> + <div + class="panel-body"> + <monitoring-row + v-for="(row, index) in groupData.metrics" + :key="index" + :row-data="row" + :update-aspect-ratio="updateAspectRatio" + :deployment-data="store.deploymentData" + /> + </div> + </div> + </div> + </div> + </div> + <monitoring-state + :selected-state="state" + :documentation-path="documentationPath" + :settings-path="settingsPath" + v-else + /> +</template> diff --git a/app/assets/javascripts/monitoring/components/monitoring_column.vue b/app/assets/javascripts/monitoring/components/monitoring_column.vue new file mode 100644 index 00000000000..4f4792877ee --- /dev/null +++ b/app/assets/javascripts/monitoring/components/monitoring_column.vue @@ -0,0 +1,291 @@ +<script> + /* global Breakpoints */ + import d3 from 'd3'; + import monitoringLegends from './monitoring_legends.vue'; + import monitoringFlag from './monitoring_flag.vue'; + import monitoringDeployment from './monitoring_deployment.vue'; + import MonitoringMixin from '../mixins/monitoring_mixins'; + import eventHub from '../event_hub'; + import measurements from '../utils/measurements'; + import { formatRelevantDigits } from '../../lib/utils/number_utils'; + + const bisectDate = d3.bisector(d => d.time).left; + + export default { + props: { + columnData: { + type: Object, + required: true, + }, + classType: { + type: String, + required: true, + }, + updateAspectRatio: { + type: Boolean, + required: true, + }, + deploymentData: { + type: Array, + required: true, + }, + }, + + mixins: [MonitoringMixin], + + data() { + return { + graphHeight: 500, + graphWidth: 600, + graphHeightOffset: 120, + xScale: {}, + yScale: {}, + margin: {}, + data: [], + breakpointHandler: Breakpoints.get(), + unitOfDisplay: '', + areaColorRgb: '#8fbce8', + lineColorRgb: '#1f78d1', + yAxisLabel: '', + legendTitle: '', + reducedDeploymentData: [], + area: '', + line: '', + measurements: measurements.large, + currentData: { + time: new Date(), + value: 0, + }, + currentYCoordinate: 0, + currentXCoordinate: 0, + currentFlagPosition: 0, + metricUsage: '', + showFlag: false, + showDeployInfo: true, + }; + }, + + components: { + monitoringLegends, + monitoringFlag, + monitoringDeployment, + }, + + computed: { + outterViewBox() { + return `0 0 ${this.graphWidth} ${this.graphHeight}`; + }, + + innerViewBox() { + if ((this.graphWidth - 150) > 0) { + return `0 0 ${this.graphWidth - 150} ${this.graphHeight}`; + } + return '0 0 0 0'; + }, + + axisTransform() { + return `translate(70, ${this.graphHeight - 100})`; + }, + + paddingBottomRootSvg() { + return (Math.ceil(this.graphHeight * 100) / this.graphWidth) || 0; + }, + }, + + methods: { + draw() { + const breakpointSize = this.breakpointHandler.getBreakpointSize(); + const query = this.columnData.queries[0]; + this.margin = measurements.large.margin; + if (breakpointSize === 'xs' || breakpointSize === 'sm') { + this.graphHeight = 300; + this.margin = measurements.small.margin; + this.measurements = measurements.small; + } + this.data = query.result[0].values; + this.unitOfDisplay = query.unit || 'N/A'; + this.yAxisLabel = this.columnData.y_axis || 'Values'; + this.legendTitle = query.legend || 'Average'; + this.graphWidth = this.$refs.baseSvg.clientWidth - + this.margin.left - this.margin.right; + this.graphHeight = this.graphHeight - this.margin.top - this.margin.bottom; + if (this.data !== undefined) { + this.renderAxesPaths(); + this.formatDeployments(); + } + }, + + handleMouseOverGraph(e) { + let point = this.$refs.graphData.createSVGPoint(); + point.x = e.clientX; + point.y = e.clientY; + point = point.matrixTransform(this.$refs.graphData.getScreenCTM().inverse()); + point.x = point.x += 7; + const timeValueOverlay = this.xScale.invert(point.x); + const overlayIndex = bisectDate(this.data, timeValueOverlay, 1); + const d0 = this.data[overlayIndex - 1]; + const d1 = this.data[overlayIndex]; + if (d0 === undefined || d1 === undefined) return; + const evalTime = timeValueOverlay - d0[0] > d1[0] - timeValueOverlay; + this.currentData = evalTime ? d1 : d0; + this.currentXCoordinate = Math.floor(this.xScale(this.currentData.time)); + const currentDeployXPos = this.mouseOverDeployInfo(point.x); + this.currentYCoordinate = this.yScale(this.currentData.value); + + if (this.currentXCoordinate > (this.graphWidth - 200)) { + this.currentFlagPosition = this.currentXCoordinate - 103; + } else { + this.currentFlagPosition = this.currentXCoordinate; + } + + if (currentDeployXPos) { + this.showFlag = false; + } else { + this.showFlag = true; + } + + this.metricUsage = `${formatRelevantDigits(this.currentData.value)} ${this.unitOfDisplay}`; + }, + + renderAxesPaths() { + const axisXScale = d3.time.scale() + .range([0, this.graphWidth]); + this.yScale = d3.scale.linear() + .range([this.graphHeight - this.graphHeightOffset, 0]); + axisXScale.domain(d3.extent(this.data, d => d.time)); + this.yScale.domain([0, d3.max(this.data.map(d => d.value))]); + + const xAxis = d3.svg.axis() + .scale(axisXScale) + .ticks(measurements.ticks) + .orient('bottom'); + + const yAxis = d3.svg.axis() + .scale(this.yScale) + .ticks(measurements.ticks) + .orient('left'); + + d3.select(this.$refs.baseSvg).select('.x-axis').call(xAxis); + + const width = this.graphWidth; + d3.select(this.$refs.baseSvg).select('.y-axis').call(yAxis) + .selectAll('.tick') + .each(function createTickLines() { + d3.select(this).select('line').attr('x2', width); + }); // This will select all of the ticks once they're rendered + + this.xScale = d3.time.scale() + .range([0, this.graphWidth - 70]); + + this.xScale.domain(d3.extent(this.data, d => d.time)); + + const areaFunction = d3.svg.area() + .x(d => this.xScale(d.time)) + .y0(this.graphHeight - this.graphHeightOffset) + .y1(d => this.yScale(d.value)) + .interpolate('linear'); + + const lineFunction = d3.svg.line() + .x(d => this.xScale(d.time)) + .y(d => this.yScale(d.value)); + + this.line = lineFunction(this.data); + + this.area = areaFunction(this.data); + }, + }, + + watch: { + updateAspectRatio() { + if (this.updateAspectRatio) { + this.graphHeight = 500; + this.graphWidth = 600; + this.measurements = measurements.large; + this.draw(); + eventHub.$emit('toggleAspectRatio'); + } + }, + }, + + mounted() { + this.draw(); + }, + }; +</script> +<template> + <div + :class="classType"> + <h5 + class="text-center"> + {{columnData.title}} + </h5> + <div + class="prometheus-svg-container"> + <svg + :viewBox="outterViewBox" + :style="{ 'padding-bottom': paddingBottomRootSvg }" + ref="baseSvg"> + <g + class="x-axis" + :transform="axisTransform"> + </g> + <g + class="y-axis" + transform="translate(70, 20)"> + </g> + <monitoring-legends + :graph-width="graphWidth" + :graph-height="graphHeight" + :margin="margin" + :measurements="measurements" + :area-color-rgb="areaColorRgb" + :legend-title="legendTitle" + :y-axis-label="yAxisLabel" + :metric-usage="metricUsage" + /> + <svg + class="graph-data" + :viewBox="innerViewBox" + ref="graphData"> + <path + class="metric-area" + :d="area" + :fill="areaColorRgb" + transform="translate(-5, 20)"> + </path> + <path + class="metric-line" + :d="line" + :stroke="lineColorRgb" + fill="none" + stroke-width="2" + transform="translate(-5, 20)"> + </path> + <rect + class="prometheus-graph-overlay" + :width="(graphWidth - 70)" + :height="(graphHeight - 100)" + transform="translate(-5, 20)" + ref="graphOverlay" + @mousemove="handleMouseOverGraph($event)"> + </rect> + <monitoring-deployment + :show-deploy-info="showDeployInfo" + :deployment-data="reducedDeploymentData" + :graph-height="graphHeight" + :graph-height-offset="graphHeightOffset" + /> + <monitoring-flag + v-if="showFlag" + :current-x-coordinate="currentXCoordinate" + :current-y-coordinate="currentYCoordinate" + :current-data="currentData" + :current-flag-position="currentFlagPosition" + :graph-height="graphHeight" + :graph-height-offset="graphHeightOffset" + /> + </svg> + </svg> + </div> + </div> +</template> diff --git a/app/assets/javascripts/monitoring/components/monitoring_deployment.vue b/app/assets/javascripts/monitoring/components/monitoring_deployment.vue new file mode 100644 index 00000000000..e6432ba3191 --- /dev/null +++ b/app/assets/javascripts/monitoring/components/monitoring_deployment.vue @@ -0,0 +1,136 @@ +<script> + import { + dateFormat, + timeFormat, + } from '../constants'; + + export default { + props: { + showDeployInfo: { + type: Boolean, + required: true, + }, + deploymentData: { + type: Array, + required: true, + }, + graphHeight: { + type: Number, + required: true, + }, + graphHeightOffset: { + type: Number, + required: true, + }, + }, + + computed: { + calculatedHeight() { + return this.graphHeight - this.graphHeightOffset; + }, + }, + + methods: { + refText(d) { + return d.tag ? d.ref : d.sha.slice(0, 6); + }, + + formatTime(deploymentTime) { + return timeFormat(deploymentTime); + }, + + formatDate(deploymentTime) { + return dateFormat(deploymentTime); + }, + + nameDeploymentClass(deployment) { + return `deploy-info-${deployment.id}`; + }, + + transformDeploymentGroup(deployment) { + return `translate(${Math.floor(deployment.xPos) + 1}, 20)`; + }, + }, + }; +</script> +<template> + <g + class="deploy-info" + v-if="showDeployInfo"> + <g + v-for="(deployment, index) in deploymentData" + :key="index" + :class="nameDeploymentClass(deployment)" + :transform="transformDeploymentGroup(deployment)"> + <rect + x="0" + y="0" + :height="calculatedHeight" + width="3" + fill="url(#shadow-gradient)"> + </rect> + <line + class="deployment-line" + x1="0" + y1="0" + x2="0" + :y2="calculatedHeight" + stroke="#000"> + </line> + <svg + v-if="deployment.showDeploymentFlag" + class="js-deploy-info-box" + x="3" + y="0" + width="92" + height="60"> + <rect + class="rect-text-metric deploy-info-rect rect-metric" + x="1" + y="1" + rx="2" + width="90" + height="58"> + </rect> + <g + transform="translate(5, 2)"> + <text + class="deploy-info-text text-metric-bold"> + {{refText(deployment)}} + </text> + </g> + <text + class="deploy-info-text" + y="18" + transform="translate(5, 2)"> + {{formatDate(deployment.time)}} + </text> + <text + class="deploy-info-text text-metric-bold" + y="38" + transform="translate(5, 2)"> + {{formatTime(deployment.time)}} + </text> + </svg> + </g> + <svg + height="0" + width="0"> + <defs> + <linearGradient + id="shadow-gradient"> + <stop + offset="0%" + stop-color="#000" + stop-opacity="0.4"> + </stop> + <stop + offset="100%" + stop-color="#000" + stop-opacity="0"> + </stop> + </linearGradient> + </defs> + </svg> + </g> +</template> diff --git a/app/assets/javascripts/monitoring/components/monitoring_flag.vue b/app/assets/javascripts/monitoring/components/monitoring_flag.vue new file mode 100644 index 00000000000..180a771415b --- /dev/null +++ b/app/assets/javascripts/monitoring/components/monitoring_flag.vue @@ -0,0 +1,104 @@ +<script> + import { + dateFormat, + timeFormat, + } from '../constants'; + + export default { + props: { + currentXCoordinate: { + type: Number, + required: true, + }, + currentYCoordinate: { + type: Number, + required: true, + }, + currentFlagPosition: { + type: Number, + required: true, + }, + currentData: { + type: Object, + required: true, + }, + graphHeight: { + type: Number, + required: true, + }, + graphHeightOffset: { + type: Number, + required: true, + }, + }, + + data() { + return { + circleColorRgb: '#8fbce8', + }; + }, + + computed: { + formatTime() { + return timeFormat(this.currentData.time); + }, + + formatDate() { + return dateFormat(this.currentData.time); + }, + + calculatedHeight() { + return this.graphHeight - this.graphHeightOffset; + }, + }, + }; +</script> +<template> + <g class="mouse-over-flag"> + <line + class="selected-metric-line" + :x1="currentXCoordinate" + :y1="0" + :x2="currentXCoordinate" + :y2="calculatedHeight" + transform="translate(-5, 20)"> + </line> + <circle + class="circle-metric" + :fill="circleColorRgb" + stroke="#000" + :cx="currentXCoordinate" + :cy="currentYCoordinate" + r="5" + transform="translate(-5, 20)"> + </circle> + <svg + class="rect-text-metric" + :x="currentFlagPosition" + y="0"> + <rect + class="rect-metric" + x="4" + y="1" + rx="2" + width="90" + height="40" + transform="translate(-3, 20)"> + </rect> + <text + class="text-metric text-metric-bold" + x="8" + y="35" + transform="translate(-5, 20)"> + {{formatTime}} + </text> + <text + class="text-metric-date" + x="8" + y="15" + transform="translate(-5, 20)"> + {{formatDate}} + </text> + </svg> + </g> +</template> diff --git a/app/assets/javascripts/monitoring/components/monitoring_legends.vue b/app/assets/javascripts/monitoring/components/monitoring_legends.vue new file mode 100644 index 00000000000..b30ed3cc889 --- /dev/null +++ b/app/assets/javascripts/monitoring/components/monitoring_legends.vue @@ -0,0 +1,144 @@ +<script> + export default { + props: { + graphWidth: { + type: Number, + required: true, + }, + graphHeight: { + type: Number, + required: true, + }, + margin: { + type: Object, + required: true, + }, + measurements: { + type: Object, + required: true, + }, + areaColorRgb: { + type: String, + required: true, + }, + legendTitle: { + type: String, + required: true, + }, + yAxisLabel: { + type: String, + required: true, + }, + metricUsage: { + type: String, + required: true, + }, + }, + data() { + return { + yLabelWidth: 0, + yLabelHeight: 0, + }; + }, + computed: { + textTransform() { + 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) / 2) + + (this.yLabelWidth / 2) + 10 || 0; + + return `translate(0, ${yCoordinate}) rotate(-90)`; + }, + + xPosition() { + return (((this.graphWidth + this.measurements.axisLabelLineOffset) / 2) + - this.margin.right) || 0; + }, + + yPosition() { + return ((this.graphHeight - this.margin.top) + this.measurements.axisLabelLineOffset) || 0; + }, + }, + mounted() { + this.$nextTick(() => { + const bbox = this.$refs.ylabel.getBBox(); + this.yLabelWidth = bbox.width + 10; // Added some padding + this.yLabelHeight = bbox.height + 5; + }); + }, + }; +</script> +<template> + <g + class="axis-label-container"> + <line + class="label-x-axis-line" + stroke="#000000" + stroke-width="1" + x1="10" + :y1="yPosition" + :x2="graphWidth + 20" + :y2="yPosition"> + </line> + <line + class="label-y-axis-line" + stroke="#000000" + stroke-width="1" + x1="10" + y1="0" + :x2="10" + :y2="yPosition"> + </line> + <rect + class="rect-axis-text" + :transform="rectTransform" + :width="yLabelWidth" + :height="yLabelHeight"> + </rect> + <text + class="label-axis-text y-label-text" + text-anchor="middle" + :transform="textTransform" + ref="ylabel"> + {{yAxisLabel}} + </text> + <rect + class="rect-axis-text" + :x="xPosition + 50" + :y="graphHeight - 80" + width="50" + height="50"> + </rect> + <text + class="label-axis-text" + :x="xPosition + 60" + :y="yPosition" + dy=".35em"> + Time + </text> + <rect + :fill="areaColorRgb" + :width="measurements.legends.width" + :height="measurements.legends.height" + x="20" + :y="graphHeight - measurements.legendOffset"> + </rect> + <text + class="text-metric-title" + x="50" + :y="graphHeight - 40"> + {{legendTitle}} + </text> + <text + class="text-metric-usage" + x="50" + :y="graphHeight - 25"> + {{metricUsage}} + </text> + </g> +</template> diff --git a/app/assets/javascripts/monitoring/components/monitoring_row.vue b/app/assets/javascripts/monitoring/components/monitoring_row.vue new file mode 100644 index 00000000000..e5528f17880 --- /dev/null +++ b/app/assets/javascripts/monitoring/components/monitoring_row.vue @@ -0,0 +1,41 @@ +<script> + import monitoringColumn from './monitoring_column.vue'; + + export default { + props: { + rowData: { + type: Array, + required: true, + }, + updateAspectRatio: { + type: Boolean, + required: true, + }, + deploymentData: { + type: Array, + required: true, + }, + }, + components: { + monitoringColumn, + }, + computed: { + bootstrapClass() { + return this.rowData.length >= 2 ? 'col-md-6' : 'col-md-12'; + }, + }, + }; +</script> +<template> + <div + class="prometheus-row row"> + <monitoring-column + v-for="(column, index) in rowData" + :column-data="column" + :class-type="bootstrapClass" + :key="index" + :update-aspect-ratio="updateAspectRatio" + :deployment-data="deploymentData" + /> + </div> +</template> diff --git a/app/assets/javascripts/monitoring/components/monitoring_state.vue b/app/assets/javascripts/monitoring/components/monitoring_state.vue new file mode 100644 index 00000000000..598021aa4df --- /dev/null +++ b/app/assets/javascripts/monitoring/components/monitoring_state.vue @@ -0,0 +1,112 @@ +<script> + import gettingStartedSvg from 'empty_states/monitoring/_getting_started.svg'; + import loadingSvg from 'empty_states/monitoring/_loading.svg'; + import unableToConnectSvg from 'empty_states/monitoring/_unable_to_connect.svg'; + + export default { + props: { + documentationPath: { + type: String, + required: true, + }, + settingsPath: { + type: String, + required: false, + default: '', + }, + selectedState: { + type: String, + required: true, + }, + }, + data() { + return { + states: { + gettingStarted: { + svg: gettingStartedSvg, + title: 'Get started with performance monitoring', + description: 'Stay updated about the performance and health of your environment by configuring Prometheus to monitor your deployments.', + buttonText: 'Configure Prometheus', + }, + loading: { + svg: loadingSvg, + title: 'Waiting for performance data', + description: 'Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available.', + buttonText: 'View documentation', + }, + unableToConnect: { + svg: unableToConnectSvg, + title: 'Unable to connect to Prometheus server', + description: 'Ensure connectivity is available from the GitLab server to the ', + buttonText: 'View documentation', + }, + }, + }; + }, + computed: { + currentState() { + return this.states[this.selectedState]; + }, + + buttonPath() { + if (this.selectedState === 'gettingStarted') { + return this.settingsPath; + } + return this.documentationPath; + }, + + showButtonDescription() { + if (this.selectedState === 'unableToConnect') return true; + return false; + }, + }, + }; +</script> +<template> + <div + class="prometheus-state"> + <div + class="row"> + <div + class="col-md-4 col-md-offset-4 state-svg" + v-html="currentState.svg"> + </div> + </div> + <div + class="row"> + <div + class="col-md-6 col-md-offset-3"> + <h4 + class="text-center state-title"> + {{currentState.title}} + </h4> + </div> + </div> + <div + class="row"> + <div + class="col-md-6 col-md-offset-3"> + <div + class="description-text text-center state-description"> + {{currentState.description}} + <a + :href="settingsPath" + v-if="showButtonDescription"> + Prometheus server + </a> + </div> + </div> + </div> + <div + class="row state-button-section"> + <div + class="col-md-4 col-md-offset-4 text-center state-button"> + <a + class="btn btn-success" + :href="buttonPath"> + {{currentState.buttonText}} + </a> + </div> + </div> + </div> +</template> diff --git a/app/assets/javascripts/monitoring/deployments.js b/app/assets/javascripts/monitoring/deployments.js deleted file mode 100644 index fc92ab61b31..00000000000 --- a/app/assets/javascripts/monitoring/deployments.js +++ /dev/null @@ -1,211 +0,0 @@ -/* global Flash */ -import d3 from 'd3'; -import { - dateFormat, - timeFormat, -} from './constants'; - -export default class Deployments { - constructor(width, height) { - this.width = width; - this.height = height; - - this.endpoint = document.getElementById('js-metrics').dataset.deploymentEndpoint; - - this.createGradientDef(); - } - - init(chartData) { - this.chartData = chartData; - - this.x = d3.time.scale().range([0, this.width]); - this.x.domain(d3.extent(this.chartData, d => d.time)); - - this.charts = d3.selectAll('.prometheus-graph'); - - this.getData(); - } - - getData() { - $.ajax({ - url: this.endpoint, - dataType: 'JSON', - }) - .fail(() => new Flash('Error getting deployment information.')) - .done((data) => { - this.data = data.deployments.reduce((deploymentDataArray, deployment) => { - const time = new Date(deployment.created_at); - const xPos = Math.floor(this.x(time)); - - time.setSeconds(this.chartData[0].time.getSeconds()); - - if (xPos >= 0) { - deploymentDataArray.push({ - id: deployment.id, - time, - sha: deployment.sha, - tag: deployment.tag, - ref: deployment.ref.name, - xPos, - }); - } - - return deploymentDataArray; - }, []); - - this.plotData(); - }); - } - - plotData() { - this.charts.each((d, i) => { - const svg = d3.select(this.charts[0][i]); - const chart = svg.select('.graph-container'); - const key = svg.node().getAttribute('graph-type'); - - this.createLine(chart, key); - this.createDeployInfoBox(chart, key); - }); - } - - createGradientDef() { - const defs = d3.select('body') - .append('svg') - .attr({ - height: 0, - width: 0, - }) - .append('defs'); - - defs.append('linearGradient') - .attr({ - id: 'shadow-gradient', - }) - .append('stop') - .attr({ - offset: '0%', - 'stop-color': '#000', - 'stop-opacity': 0.4, - }) - .select(this.selectParentNode) - .append('stop') - .attr({ - offset: '100%', - 'stop-color': '#000', - 'stop-opacity': 0, - }); - } - - createLine(chart, key) { - chart.append('g') - .attr({ - class: 'deploy-info', - }) - .selectAll('.deploy-info') - .data(this.data) - .enter() - .append('g') - .attr({ - class: d => `deploy-info-${d.id}-${key}`, - transform: d => `translate(${Math.floor(d.xPos) + 1}, 0)`, - }) - .append('rect') - .attr({ - x: 1, - y: 0, - height: this.height + 1, - width: 3, - fill: 'url(#shadow-gradient)', - }) - .select(this.selectParentNode) - .append('line') - .attr({ - class: 'deployment-line', - x1: 0, - x2: 0, - y1: 0, - y2: this.height + 1, - }); - } - - createDeployInfoBox(chart, key) { - chart.selectAll('.deploy-info') - .selectAll('.js-deploy-info-box') - .data(this.data) - .enter() - .select(d => document.querySelector(`.deploy-info-${d.id}-${key}`)) - .append('svg') - .attr({ - class: 'js-deploy-info-box hidden', - x: 3, - y: 0, - width: 92, - height: 60, - }) - .append('rect') - .attr({ - class: 'rect-text-metric deploy-info-rect rect-metric', - x: 1, - y: 1, - rx: 2, - width: 90, - height: 58, - }) - .select(this.selectParentNode) - .append('g') - .attr({ - transform: 'translate(5, 2)', - }) - .append('text') - .attr({ - class: 'deploy-info-text text-metric-bold', - }) - .text(Deployments.refText) - .select(this.selectParentNode) - .append('text') - .attr({ - class: 'deploy-info-text', - y: 18, - }) - .text(d => dateFormat(d.time)) - .select(this.selectParentNode) - .append('text') - .attr({ - class: 'deploy-info-text text-metric-bold', - y: 38, - }) - .text(d => timeFormat(d.time)); - } - - static toggleDeployTextbox(deploy, key, showInfoBox) { - d3.selectAll(`.deploy-info-${deploy.id}-${key} .js-deploy-info-box`) - .classed('hidden', !showInfoBox); - } - - mouseOverDeployInfo(mouseXPos, key) { - if (!this.data) return false; - - let dataFound = false; - - this.data.forEach((d) => { - if (d.xPos >= mouseXPos - 10 && d.xPos <= mouseXPos + 10 && !dataFound) { - dataFound = d.xPos + 1; - - Deployments.toggleDeployTextbox(d, key, true); - } else { - Deployments.toggleDeployTextbox(d, key, false); - } - }); - - return dataFound; - } - - /* `this` is bound to the D3 node */ - selectParentNode() { - return this.parentNode; - } - - static refText(d) { - return d.tag ? d.ref : d.sha.slice(0, 6); - } -} diff --git a/app/assets/javascripts/monitoring/event_hub.js b/app/assets/javascripts/monitoring/event_hub.js new file mode 100644 index 00000000000..0948c2e5352 --- /dev/null +++ b/app/assets/javascripts/monitoring/event_hub.js @@ -0,0 +1,3 @@ +import Vue from 'vue'; + +export default new Vue(); diff --git a/app/assets/javascripts/monitoring/mixins/monitoring_mixins.js b/app/assets/javascripts/monitoring/mixins/monitoring_mixins.js new file mode 100644 index 00000000000..8e62fa63f13 --- /dev/null +++ b/app/assets/javascripts/monitoring/mixins/monitoring_mixins.js @@ -0,0 +1,46 @@ +const mixins = { + methods: { + mouseOverDeployInfo(mouseXPos) { + if (!this.reducedDeploymentData) return false; + + let dataFound = false; + this.reducedDeploymentData = this.reducedDeploymentData.map((d) => { + const deployment = d; + if (d.xPos >= mouseXPos - 10 && d.xPos <= mouseXPos + 10 && !dataFound) { + dataFound = d.xPos + 1; + + deployment.showDeploymentFlag = true; + } else { + deployment.showDeploymentFlag = false; + } + return deployment; + }); + + return dataFound; + }, + formatDeployments() { + this.reducedDeploymentData = this.deploymentData.reduce((deploymentDataArray, deployment) => { + const time = new Date(deployment.created_at); + const xPos = Math.floor(this.xScale(time)); + + time.setSeconds(this.data[0].time.getSeconds()); + + if (xPos >= 0) { + deploymentDataArray.push({ + id: deployment.id, + time, + sha: deployment.sha, + tag: deployment.tag, + ref: deployment.ref.name, + xPos, + showDeploymentFlag: false, + }); + } + + return deploymentDataArray; + }, []); + }, + }, +}; + +export default mixins; diff --git a/app/assets/javascripts/monitoring/monitoring_bundle.js b/app/assets/javascripts/monitoring/monitoring_bundle.js index b3ce9310417..5d5cb56af72 100644 --- a/app/assets/javascripts/monitoring/monitoring_bundle.js +++ b/app/assets/javascripts/monitoring/monitoring_bundle.js @@ -1,6 +1,10 @@ -import PrometheusGraph from './prometheus_graph'; +import Vue from 'vue'; +import Monitoring from './components/monitoring.vue'; -document.addEventListener('DOMContentLoaded', function onLoad() { - document.removeEventListener('DOMContentLoaded', onLoad, false); - return new PrometheusGraph(); -}, false); +document.addEventListener('DOMContentLoaded', () => new Vue({ + el: '#prometheus-graphs', + components: { + 'monitoring-dashboard': Monitoring, + }, + render: createElement => createElement('monitoring-dashboard'), +})); diff --git a/app/assets/javascripts/monitoring/prometheus_graph.js b/app/assets/javascripts/monitoring/prometheus_graph.js deleted file mode 100644 index 6af88769129..00000000000 --- a/app/assets/javascripts/monitoring/prometheus_graph.js +++ /dev/null @@ -1,433 +0,0 @@ -/* eslint-disable no-new */ -/* global Flash */ - -import d3 from 'd3'; -import statusCodes from '~/lib/utils/http_status'; -import Deployments from './deployments'; -import '../lib/utils/common_utils'; -import { formatRelevantDigits } from '../lib/utils/number_utils'; -import '../flash'; -import { - dateFormat, - timeFormat, -} from './constants'; - -const prometheusContainer = '.prometheus-container'; -const prometheusParentGraphContainer = '.prometheus-graphs'; -const prometheusGraphsContainer = '.prometheus-graph'; -const prometheusStatesContainer = '.prometheus-state'; -const metricsEndpoint = 'metrics.json'; -const bisectDate = d3.bisector(d => d.time).left; -const extraAddedWidthParent = 100; - -class PrometheusGraph { - constructor() { - const $prometheusContainer = $(prometheusContainer); - const hasMetrics = $prometheusContainer.data('has-metrics'); - this.docLink = $prometheusContainer.data('doc-link'); - this.integrationLink = $prometheusContainer.data('prometheus-integration'); - this.state = ''; - - $(document).ajaxError(() => {}); - - if (hasMetrics) { - this.margin = { top: 80, right: 180, bottom: 80, left: 100 }; - this.marginLabelContainer = { top: 40, right: 0, bottom: 40, left: 0 }; - const parentContainerWidth = $(prometheusGraphsContainer).parent().width() + - extraAddedWidthParent; - this.originalWidth = parentContainerWidth; - this.originalHeight = 330; - this.width = parentContainerWidth - this.margin.left - this.margin.right; - this.height = this.originalHeight - this.margin.top - this.margin.bottom; - this.backOffRequestCounter = 0; - this.deployments = new Deployments(this.width, this.height); - this.configureGraph(); - this.init(); - } else { - const prevState = this.state; - this.state = '.js-getting-started'; - this.updateState(prevState); - } - } - - createGraph() { - Object.keys(this.graphSpecificProperties).forEach((key) => { - const value = this.graphSpecificProperties[key]; - if (value.data.length > 0) { - this.plotValues(key); - } - }); - } - - init() { - return this.getData().then((metricsResponse) => { - let enoughData = true; - if (typeof metricsResponse === 'undefined') { - enoughData = false; - } else { - Object.keys(metricsResponse.metrics).forEach((key) => { - if (key === 'cpu_values' || key === 'memory_values') { - const currentData = (metricsResponse.metrics[key])[0]; - if (currentData.values.length <= 2) { - enoughData = false; - } - } - }); - } - if (enoughData) { - $(prometheusStatesContainer).hide(); - $(prometheusParentGraphContainer).show(); - this.transformData(metricsResponse); - this.createGraph(); - - const firstMetricData = this.graphSpecificProperties[ - Object.keys(this.graphSpecificProperties)[0] - ].data; - - this.deployments.init(firstMetricData); - } - }); - } - - plotValues(key) { - const graphSpecifics = this.graphSpecificProperties[key]; - - const x = d3.time.scale() - .range([0, this.width]); - - const y = d3.scale.linear() - .range([this.height, 0]); - - graphSpecifics.xScale = x; - graphSpecifics.yScale = y; - - const prometheusGraphContainer = `${prometheusGraphsContainer}[graph-type=${key}]`; - - const chart = d3.select(prometheusGraphContainer) - .attr('width', this.width + this.margin.left + this.margin.right) - .attr('height', this.height + this.margin.bottom + this.margin.top) - .append('g') - .attr('class', 'graph-container') - .attr('transform', `translate(${this.margin.left},${this.margin.top})`); - - const axisLabelContainer = d3.select(prometheusGraphContainer) - .attr('width', this.originalWidth) - .attr('height', this.originalHeight) - .append('g') - .attr('transform', `translate(${this.marginLabelContainer.left},${this.marginLabelContainer.top})`); - - x.domain(d3.extent(graphSpecifics.data, d => d.time)); - y.domain([0, d3.max(graphSpecifics.data.map(metricValue => metricValue.value))]); - - const xAxis = d3.svg.axis() - .scale(x) - .ticks(this.commonGraphProperties.axis_no_ticks) - .orient('bottom'); - - const yAxis = d3.svg.axis() - .scale(y) - .ticks(this.commonGraphProperties.axis_no_ticks) - .tickSize(-this.width) - .outerTickSize(0) - .orient('left'); - - this.createAxisLabelContainers(axisLabelContainer, key); - - chart.append('g') - .attr('class', 'x-axis') - .attr('transform', `translate(0,${this.height})`) - .call(xAxis); - - chart.append('g') - .attr('class', 'y-axis') - .call(yAxis); - - const area = d3.svg.area() - .x(d => x(d.time)) - .y0(this.height) - .y1(d => y(d.value)) - .interpolate('linear'); - - const line = d3.svg.line() - .x(d => x(d.time)) - .y(d => y(d.value)); - - chart.append('path') - .datum(graphSpecifics.data) - .attr('d', area) - .attr('class', 'metric-area') - .attr('fill', graphSpecifics.area_fill_color); - - chart.append('path') - .datum(graphSpecifics.data) - .attr('class', 'metric-line') - .attr('stroke', graphSpecifics.line_color) - .attr('fill', 'none') - .attr('stroke-width', this.commonGraphProperties.area_stroke_width) - .attr('d', line); - - // Overlay area for the mouseover events - chart.append('rect') - .attr('class', 'prometheus-graph-overlay') - .attr('width', this.width) - .attr('height', this.height) - .on('mousemove', this.handleMouseOverGraph.bind(this, prometheusGraphContainer)); - } - - // The legends from the metric - createAxisLabelContainers(axisLabelContainer, key) { - const graphSpecifics = this.graphSpecificProperties[key]; - - axisLabelContainer.append('line') - .attr('class', 'label-x-axis-line') - .attr('stroke', '#000000') - .attr('stroke-width', '1') - .attr({ - x1: 10, - y1: this.originalHeight - this.margin.top, - x2: (this.originalWidth - this.margin.right) + 10, - y2: this.originalHeight - this.margin.top, - }); - - axisLabelContainer.append('line') - .attr('class', 'label-y-axis-line') - .attr('stroke', '#000000') - .attr('stroke-width', '1') - .attr({ - x1: 10, - y1: 0, - x2: 10, - y2: this.originalHeight - this.margin.top, - }); - - axisLabelContainer.append('rect') - .attr('class', 'rect-axis-text') - .attr('x', 0) - .attr('y', 50) - .attr('width', 30) - .attr('height', 150); - - axisLabelContainer.append('text') - .attr('class', 'label-axis-text') - .attr('text-anchor', 'middle') - .attr('transform', `translate(15, ${(this.originalHeight - this.margin.top) / 2}) rotate(-90)`) - .text(graphSpecifics.graph_legend_title); - - axisLabelContainer.append('rect') - .attr('class', 'rect-axis-text') - .attr('x', (this.originalWidth / 2) - this.margin.right) - .attr('y', this.originalHeight - 100) - .attr('width', 30) - .attr('height', 80); - - axisLabelContainer.append('text') - .attr('class', 'label-axis-text') - .attr('x', (this.originalWidth / 2) - this.margin.right) - .attr('y', this.originalHeight - this.margin.top) - .attr('dy', '.35em') - .text('Time'); - - // Legends - - // Metric Usage - axisLabelContainer.append('rect') - .attr('x', this.originalWidth - 170) - .attr('y', (this.originalHeight / 2) - 60) - .style('fill', graphSpecifics.area_fill_color) - .attr('width', 20) - .attr('height', 35); - - axisLabelContainer.append('text') - .attr('class', 'text-metric-title') - .attr('x', this.originalWidth - 140) - .attr('y', (this.originalHeight / 2) - 50) - .text('Average'); - - axisLabelContainer.append('text') - .attr('class', 'text-metric-usage') - .attr('x', this.originalWidth - 140) - .attr('y', (this.originalHeight / 2) - 25); - } - - handleMouseOverGraph(prometheusGraphContainer) { - const rectOverlay = document.querySelector(`${prometheusGraphContainer} .prometheus-graph-overlay`); - const currentXCoordinate = d3.mouse(rectOverlay)[0]; - - Object.keys(this.graphSpecificProperties).forEach((key) => { - const currentGraphProps = this.graphSpecificProperties[key]; - const timeValueOverlay = currentGraphProps.xScale.invert(currentXCoordinate); - const overlayIndex = bisectDate(currentGraphProps.data, timeValueOverlay, 1); - const d0 = currentGraphProps.data[overlayIndex - 1]; - const d1 = currentGraphProps.data[overlayIndex]; - const evalTime = timeValueOverlay - d0.time > d1.time - timeValueOverlay; - const currentData = evalTime ? d1 : d0; - const currentTimeCoordinate = Math.floor(currentGraphProps.xScale(currentData.time)); - const currentDeployXPos = this.deployments.mouseOverDeployInfo(currentXCoordinate, key); - const currentPrometheusGraphContainer = `${prometheusGraphsContainer}[graph-type=${key}]`; - const maxValueFromData = d3.max(currentGraphProps.data.map(metricValue => metricValue.value)); - const maxMetricValue = currentGraphProps.yScale(maxValueFromData); - - // Clear up all the pieces of the flag - d3.selectAll(`${currentPrometheusGraphContainer} .selected-metric-line`).remove(); - d3.selectAll(`${currentPrometheusGraphContainer} .circle-metric`).remove(); - d3.selectAll(`${currentPrometheusGraphContainer} .rect-text-metric:not(.deploy-info-rect)`).remove(); - - const currentChart = d3.select(currentPrometheusGraphContainer).select('g'); - currentChart.append('line') - .attr({ - class: `${currentDeployXPos ? 'hidden' : ''} selected-metric-line`, - x1: currentTimeCoordinate, - y1: currentGraphProps.yScale(0), - x2: currentTimeCoordinate, - y2: maxMetricValue, - }); - - currentChart.append('circle') - .attr('class', 'circle-metric') - .attr('fill', currentGraphProps.line_color) - .attr('cx', currentDeployXPos || currentTimeCoordinate) - .attr('cy', currentGraphProps.yScale(currentData.value)) - .attr('r', this.commonGraphProperties.circle_radius_metric); - - if (currentDeployXPos) return; - - // The little box with text - const rectTextMetric = currentChart.append('svg') - .attr({ - class: 'rect-text-metric', - x: currentTimeCoordinate, - y: 0, - }); - - rectTextMetric.append('rect') - .attr({ - class: 'rect-metric', - x: 4, - y: 1, - rx: 2, - width: this.commonGraphProperties.rect_text_width, - height: this.commonGraphProperties.rect_text_height, - }); - - rectTextMetric.append('text') - .attr({ - class: 'text-metric text-metric-bold', - x: 8, - y: 35, - }) - .text(timeFormat(currentData.time)); - - rectTextMetric.append('text') - .attr({ - class: 'text-metric-date', - x: 8, - y: 15, - }) - .text(dateFormat(currentData.time)); - - let currentMetricValue = formatRelevantDigits(currentData.value); - if (key === 'cpu_values') { - currentMetricValue = `${currentMetricValue}%`; - } else { - currentMetricValue = `${currentMetricValue} MB`; - } - - d3.select(`${currentPrometheusGraphContainer} .text-metric-usage`) - .text(currentMetricValue); - }); - } - - configureGraph() { - this.graphSpecificProperties = { - cpu_values: { - area_fill_color: '#edf3fc', - line_color: '#5b99f7', - graph_legend_title: 'CPU Usage (Cores)', - data: [], - xScale: {}, - yScale: {}, - }, - memory_values: { - area_fill_color: '#fca326', - line_color: '#fc6d26', - graph_legend_title: 'Memory Usage (MB)', - data: [], - xScale: {}, - yScale: {}, - }, - }; - - this.commonGraphProperties = { - area_stroke_width: 2, - median_total_characters: 8, - circle_radius_metric: 5, - rect_text_width: 90, - rect_text_height: 40, - axis_no_ticks: 3, - }; - } - - getData() { - const maxNumberOfRequests = 3; - this.state = '.js-loading'; - this.updateState(); - return gl.utils.backOff((next, stop) => { - $.ajax({ - url: metricsEndpoint, - dataType: 'json', - }) - .done((data, statusText, resp) => { - if (resp.status === statusCodes.NO_CONTENT) { - this.backOffRequestCounter = this.backOffRequestCounter += 1; - if (this.backOffRequestCounter < maxNumberOfRequests) { - next(); - } else if (this.backOffRequestCounter >= maxNumberOfRequests) { - stop(new Error('loading')); - } - } else if (!data.success) { - stop(new Error('loading')); - } else { - stop({ - status: resp.status, - metrics: data, - }); - } - }).fail(stop); - }) - .then((resp) => { - if (resp.status === statusCodes.NO_CONTENT) { - return {}; - } - return resp.metrics; - }) - .catch(() => { - const prevState = this.state; - this.state = '.js-unable-to-connect'; - this.updateState(prevState); - }); - } - - transformData(metricsResponse) { - Object.keys(metricsResponse.metrics).forEach((key) => { - if (key === 'cpu_values' || key === 'memory_values') { - const metricValues = (metricsResponse.metrics[key])[0]; - this.graphSpecificProperties[key].data = metricValues.values.map(metric => ({ - time: new Date(metric[0] * 1000), - value: metric[1], - })); - } - }); - } - - updateState(prevState) { - const $statesContainer = $(prometheusStatesContainer); - $(prometheusParentGraphContainer).hide(); - if (prevState) { - $(`${prevState}`, $statesContainer).addClass('hidden'); - } - $(`${this.state}`, $statesContainer).removeClass('hidden'); - $(prometheusStatesContainer).show(); - } -} - -export default PrometheusGraph; diff --git a/app/assets/javascripts/monitoring/services/monitoring_service.js b/app/assets/javascripts/monitoring/services/monitoring_service.js new file mode 100644 index 00000000000..1e9ae934853 --- /dev/null +++ b/app/assets/javascripts/monitoring/services/monitoring_service.js @@ -0,0 +1,19 @@ +import Vue from 'vue'; +import VueResource from 'vue-resource'; + +Vue.use(VueResource); + +export default class MonitoringService { + constructor(endpoint) { + this.graphs = Vue.resource(endpoint); + } + + get() { + return this.graphs.get(); + } + + // eslint-disable-next-line class-methods-use-this + getDeploymentData(endpoint) { + return Vue.http.get(endpoint); + } +} diff --git a/app/assets/javascripts/monitoring/stores/monitoring_store.js b/app/assets/javascripts/monitoring/stores/monitoring_store.js new file mode 100644 index 00000000000..737c964f12e --- /dev/null +++ b/app/assets/javascripts/monitoring/stores/monitoring_store.js @@ -0,0 +1,61 @@ +import _ from 'underscore'; + +class MonitoringStore { + constructor() { + this.groups = []; + this.deploymentData = []; + } + + // eslint-disable-next-line class-methods-use-this + createArrayRows(metrics = []) { + const currentMetrics = metrics; + const availableMetrics = []; + let metricsRow = []; + let index = 1; + Object.keys(currentMetrics).forEach((key) => { + const metricValues = currentMetrics[key].queries[0].result[0].values; + if (metricValues != null) { + const literalMetrics = metricValues.map(metric => ({ + time: new Date(metric[0] * 1000), + value: metric[1], + })); + currentMetrics[key].queries[0].result[0].values = literalMetrics; + metricsRow.push(currentMetrics[key]); + if (index % 2 === 0) { + availableMetrics.push(metricsRow); + metricsRow = []; + } + index = index += 1; + } + }); + if (metricsRow.length > 0) { + availableMetrics.push(metricsRow); + } + return availableMetrics; + } + + storeMetrics(groups = []) { + this.groups = groups.map((group) => { + const currentGroup = group; + currentGroup.metrics = _.chain(group.metrics).sortBy('weight').sortBy('title').value(); + currentGroup.metrics = this.createArrayRows(currentGroup.metrics); + return currentGroup; + }); + } + + storeDeploymentData(deploymentData = []) { + this.deploymentData = deploymentData; + } + + getMetricsCount() { + let metricsCount = 0; + this.groups.forEach((group) => { + group.metrics.forEach((metric) => { + metricsCount = metricsCount += metric.length; + }); + }); + return metricsCount; + } +} + +export default MonitoringStore; diff --git a/app/assets/javascripts/monitoring/utils/measurements.js b/app/assets/javascripts/monitoring/utils/measurements.js new file mode 100644 index 00000000000..a60d2522f49 --- /dev/null +++ b/app/assets/javascripts/monitoring/utils/measurements.js @@ -0,0 +1,39 @@ +export default { + small: { // Covers both xs and sm screen sizes + margin: { + top: 40, + right: 40, + bottom: 50, + left: 40, + }, + legends: { + width: 15, + height: 30, + }, + backgroundLegend: { + width: 30, + height: 50, + }, + axisLabelLineOffset: -20, + legendOffset: 52, + }, + large: { // This covers both md and lg screen sizes + margin: { + top: 80, + right: 80, + bottom: 100, + left: 80, + }, + legends: { + width: 20, + height: 35, + }, + backgroundLegend: { + width: 30, + height: 150, + }, + axisLabelLineOffset: 20, + legendOffset: 55, + }, + ticks: 3, +}; diff --git a/app/assets/stylesheets/pages/environments.scss b/app/assets/stylesheets/pages/environments.scss index 1046ebfa2e2..a2be957655f 100644 --- a/app/assets/stylesheets/pages/environments.scss +++ b/app/assets/stylesheets/pages/environments.scss @@ -140,23 +140,6 @@ } } -.prometheus-graph { - text { - fill: $gl-text-color; - stroke-width: 0; - } - - .label-axis-text, - .text-metric-usage { - fill: $black; - font-weight: 500; - } - - .legend-axis-text { - fill: $black; - } -} - .x-axis path, .y-axis path, .label-x-axis-line, @@ -205,6 +188,7 @@ .text-metric { font-weight: 600; + font-size: 14px; } .selected-metric-line { @@ -214,20 +198,15 @@ .deployment-line { stroke: $black; - stroke-width: 2; + stroke-width: 1; } .deploy-info-text { dominant-baseline: text-before-edge; } -.text-metric-bold { - font-weight: 600; -} - .prometheus-state { margin-top: 10px; - display: none; .state-button-section { margin-top: 10px; @@ -242,3 +221,59 @@ width: 38px; } } + +.prometheus-panel { + margin-top: 20px; +} + +.prometheus-svg-container { + position: relative; + height: 0; + width: 100%; + padding: 0; + padding-bottom: 100%; + + .text-metric-bold { + font-weight: 600; + } +} + +.prometheus-svg-container > svg { + position: absolute; + height: 100%; + width: 100%; + left: 0; + top: 0; + + text { + fill: $gl-text-color; + stroke-width: 0; + } + + .label-axis-text, + .text-metric-usage { + fill: $black; + font-weight: 500; + font-size: 14px; + } + + .legend-axis-text { + fill: $black; + } + + .tick > text { + font-size: 14px; + } + + @media (max-width: $screen-sm-max) { + .label-axis-text, + .text-metric-usage, + .legend-axis-text { + font-size: 8px; + } + + .tick > text { + font-size: 8px; + } + } +} diff --git a/app/views/projects/environments/metrics.html.haml b/app/views/projects/environments/metrics.html.haml index e8f8fbbcf09..c5722cf5997 100644 --- a/app/views/projects/environments/metrics.html.haml +++ b/app/views/projects/environments/metrics.html.haml @@ -1,11 +1,12 @@ - @no_container = true - page_title "Metrics for environment", @environment.name - content_for :page_specific_javascripts do - = page_specific_javascript_bundle_tag('common_d3') - = page_specific_javascript_bundle_tag('monitoring') + = webpack_bundle_tag 'common_vue' + = webpack_bundle_tag 'common_d3' + = webpack_bundle_tag 'monitoring' = render "projects/pipelines/head" -#js-metrics.prometheus-container{ class: container_class, data: { has_metrics: "#{@environment.has_metrics?}", deployment_endpoint: namespace_project_environment_deployments_path(@project.namespace, @project, @environment, format: :json) } } +.prometheus-container{ class: container_class } .top-area .row .col-sm-6 @@ -13,68 +14,8 @@ Environment: = link_to @environment.name, environment_path(@environment) - .prometheus-state - .js-getting-started.hidden - .row - .col-md-4.col-md-offset-4.state-svg - = render "shared/empty_states/monitoring/getting_started.svg" - .row - .col-md-6.col-md-offset-3 - %h4.text-center.state-title - Get started with performance monitoring - .row - .col-md-6.col-md-offset-3 - .description-text.text-center.state-description - Stay updated about the performance and health of your environment by configuring Prometheus to monitor your deployments. - = link_to help_page_path('administration/monitoring/prometheus/index.md') do - Learn more about performance monitoring - .row.state-button-section - .col-md-4.col-md-offset-4.text-center.state-button - = link_to edit_namespace_project_service_path(@project.namespace, @project, 'prometheus'), class: 'btn btn-success' do - Configure Prometheus - .js-loading.hidden - .row - .col-md-4.col-md-offset-4.state-svg - = render "shared/empty_states/monitoring/loading.svg" - .row - .col-md-6.col-md-offset-3 - %h4.text-center.state-title - Waiting for performance data - .row - .col-md-6.col-md-offset-3 - .description-text.text-center.state-description - Creating graphs uses the data from the Prometheus server. If this takes a long time, ensure that data is available. - .row.state-button-section - .col-md-4.col-md-offset-4.text-center.state-button - = link_to help_page_path('administration/monitoring/prometheus/index.md'), class: 'btn btn-success' do - View documentation - .js-unable-to-connect.hidden - .row - .col-md-4.col-md-offset-4.state-svg - = render "shared/empty_states/monitoring/unable_to_connect.svg" - .row - .col-md-6.col-md-offset-3 - %h4.text-center.state-title - Unable to connect to Prometheus server - .row - .col-md-6.col-md-offset-3 - .description-text.text-center.state-description - Ensure connectivity is available from the GitLab server to the - = link_to edit_namespace_project_service_path(@project.namespace, @project, 'prometheus') do - Prometheus server - .row.state-button-section - .col-md-4.col-md-offset-4.text-center.state-button - = link_to help_page_path('administration/monitoring/prometheus/index.md'), class:'btn btn-success' do - View documentation + #prometheus-graphs{ data: { "settings-path": edit_namespace_project_service_path(@project.namespace, @project, 'prometheus'), + "documentation-path": help_page_path('administration/monitoring/prometheus/index.md'), + "additional-metrics": additional_metrics_namespace_project_environment_path(@project.namespace, @project, @environment, format: :json), + "has-metrics": "#{@environment.has_metrics?}", deployment_endpoint: namespace_project_environment_deployments_path(@project.namespace, @project, @environment, format: :json) } } - .prometheus-graphs - .row - .col-sm-12 - %h4 - CPU utilization - %svg.prometheus-graph{ 'graph-type' => 'cpu_values' } - .row - .col-sm-12 - %h4 - Memory usage - %svg.prometheus-graph{ 'graph-type' => 'memory_values' } diff --git a/config/webpack.config.js b/config/webpack.config.js index 2e8c94655c1..90ef6a5448b 100644 --- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -163,6 +163,7 @@ var config = { 'issue_show', 'job_details', 'merge_conflicts', + 'monitoring', 'notebook_viewer', 'pdf_viewer', 'pipelines', diff --git a/spec/javascripts/monitoring/deployments_spec.js b/spec/javascripts/monitoring/deployments_spec.js deleted file mode 100644 index 19bc11d0f24..00000000000 --- a/spec/javascripts/monitoring/deployments_spec.js +++ /dev/null @@ -1,133 +0,0 @@ -import d3 from 'd3'; -import PrometheusGraph from '~/monitoring/prometheus_graph'; -import Deployments from '~/monitoring/deployments'; -import { prometheusMockData } from './prometheus_mock_data'; - -describe('Metrics deployments', () => { - const fixtureName = 'environments/metrics/metrics.html.raw'; - let deployment; - let prometheusGraph; - - const graphElement = () => document.querySelector('.prometheus-graph'); - - preloadFixtures(fixtureName); - - beforeEach((done) => { - // Setup the view - loadFixtures(fixtureName); - - d3.selectAll('.prometheus-graph') - .append('g') - .attr('class', 'graph-container'); - - prometheusGraph = new PrometheusGraph(); - deployment = new Deployments(1000, 500); - - spyOn(prometheusGraph, 'init'); - spyOn($, 'ajax').and.callFake(() => { - const d = $.Deferred(); - d.resolve({ - deployments: [{ - id: 1, - created_at: deployment.chartData[10].time, - sha: 'testing', - tag: false, - ref: { - name: 'testing', - }, - }, { - id: 2, - created_at: deployment.chartData[15].time, - sha: '', - tag: true, - ref: { - name: 'tag', - }, - }], - }); - - setTimeout(done); - - return d.promise(); - }); - - prometheusGraph.configureGraph(); - prometheusGraph.transformData(prometheusMockData.metrics); - - deployment.init(prometheusGraph.graphSpecificProperties.memory_values.data); - }); - - it('creates line on graph for deploment', () => { - expect( - graphElement().querySelectorAll('.deployment-line').length, - ).toBe(2); - }); - - it('creates hidden deploy boxes', () => { - expect( - graphElement().querySelectorAll('.prometheus-graph .js-deploy-info-box').length, - ).toBe(2); - }); - - it('hides the info boxes by default', () => { - expect( - graphElement().querySelectorAll('.prometheus-graph .js-deploy-info-box.hidden').length, - ).toBe(2); - }); - - it('shows sha short code when tag is false', () => { - expect( - graphElement().querySelector('.deploy-info-1-cpu_values .js-deploy-info-box').textContent.trim(), - ).toContain('testin'); - }); - - it('shows ref name when tag is true', () => { - expect( - graphElement().querySelector('.deploy-info-2-cpu_values .js-deploy-info-box').textContent.trim(), - ).toContain('tag'); - }); - - it('shows info box when moving mouse over line', () => { - deployment.mouseOverDeployInfo(deployment.data[0].xPos, 'cpu_values'); - - expect( - graphElement().querySelectorAll('.prometheus-graph .js-deploy-info-box.hidden').length, - ).toBe(1); - - expect( - graphElement().querySelector('.deploy-info-1-cpu_values .js-deploy-info-box.hidden'), - ).toBeNull(); - }); - - it('hides previously visible info box when moving mouse away', () => { - deployment.mouseOverDeployInfo(500, 'cpu_values'); - - expect( - graphElement().querySelectorAll('.prometheus-graph .js-deploy-info-box.hidden').length, - ).toBe(2); - - expect( - graphElement().querySelector('.deploy-info-1-cpu_values .js-deploy-info-box.hidden'), - ).not.toBeNull(); - }); - - describe('refText', () => { - it('returns shortened SHA', () => { - expect( - Deployments.refText({ - tag: false, - sha: '123456789', - }), - ).toBe('123456'); - }); - - it('returns tag name', () => { - expect( - Deployments.refText({ - tag: true, - ref: 'v1.0', - }), - ).toBe('v1.0'); - }); - }); -}); diff --git a/spec/javascripts/monitoring/mock_data.js b/spec/javascripts/monitoring/mock_data.js new file mode 100644 index 00000000000..6f4cb989847 --- /dev/null +++ b/spec/javascripts/monitoring/mock_data.js @@ -0,0 +1,4229 @@ +/* eslint-disable quote-props, indent, comma-dangle */ + +const metricsGroupsAPIResponse = { + 'success': true, + 'data': [ + { + 'group': 'Kubernetes', + 'priority': 1, + 'metrics': [ + { + 'title': 'Memory usage', + 'weight': 1, + 'queries': [ + { + 'query_range': 'avg(container_memory_usage_bytes{%{environment_filter}}) / 2^20', + 'label': 'Container memory', + 'unit': 'MiB', + 'result': [ + { + 'metric': {}, + 'values': [ + [ + 1495700554.925, + '8.0390625' + ], + [ + 1495700614.925, + '8.0390625' + ], + [ + 1495700674.925, + '8.0390625' + ], + [ + 1495700734.925, + '8.0390625' + ], + [ + 1495700794.925, + '8.0390625' + ], + [ + 1495700854.925, + '8.0390625' + ], + [ + 1495700914.925, + '8.0390625' + ], + [ + 1495700974.925, + '8.0390625' + ], + [ + 1495701034.925, + '8.0390625' + ], + [ + 1495701094.925, + '8.0390625' + ], + [ + 1495701154.925, + '8.0390625' + ], + [ + 1495701214.925, + '8.0390625' + ], + [ + 1495701274.925, + '8.0390625' + ], + [ + 1495701334.925, + '8.0390625' + ], + [ + 1495701394.925, + '8.0390625' + ], + [ + 1495701454.925, + '8.0390625' + ], + [ + 1495701514.925, + '8.0390625' + ], + [ + 1495701574.925, + '8.0390625' + ], + [ + 1495701634.925, + '8.0390625' + ], + [ + 1495701694.925, + '8.0390625' + ], + [ + 1495701754.925, + '8.0390625' + ], + [ + 1495701814.925, + '8.0390625' + ], + [ + 1495701874.925, + '8.0390625' + ], + [ + 1495701934.925, + '8.0390625' + ], + [ + 1495701994.925, + '8.0390625' + ], + [ + 1495702054.925, + '8.0390625' + ], + [ + 1495702114.925, + '8.0390625' + ], + [ + 1495702174.925, + '8.0390625' + ], + [ + 1495702234.925, + '8.0390625' + ], + [ + 1495702294.925, + '8.0390625' + ], + [ + 1495702354.925, + '8.0390625' + ], + [ + 1495702414.925, + '8.0390625' + ], + [ + 1495702474.925, + '8.0390625' + ], + [ + 1495702534.925, + '8.0390625' + ], + [ + 1495702594.925, + '8.0390625' + ], + [ + 1495702654.925, + '8.0390625' + ], + [ + 1495702714.925, + '8.0390625' + ], + [ + 1495702774.925, + '8.0390625' + ], + [ + 1495702834.925, + '8.0390625' + ], + [ + 1495702894.925, + '8.0390625' + ], + [ + 1495702954.925, + '8.0390625' + ], + [ + 1495703014.925, + '8.0390625' + ], + [ + 1495703074.925, + '8.0390625' + ], + [ + 1495703134.925, + '8.0390625' + ], + [ + 1495703194.925, + '8.0390625' + ], + [ + 1495703254.925, + '8.03515625' + ], + [ + 1495703314.925, + '8.03515625' + ], + [ + 1495703374.925, + '8.03515625' + ], + [ + 1495703434.925, + '8.03515625' + ], + [ + 1495703494.925, + '8.03515625' + ], + [ + 1495703554.925, + '8.03515625' + ], + [ + 1495703614.925, + '8.03515625' + ], + [ + 1495703674.925, + '8.03515625' + ], + [ + 1495703734.925, + '8.03515625' + ], + [ + 1495703794.925, + '8.03515625' + ], + [ + 1495703854.925, + '8.03515625' + ], + [ + 1495703914.925, + '8.03515625' + ], + [ + 1495703974.925, + '8.03515625' + ], + [ + 1495704034.925, + '8.03515625' + ], + [ + 1495704094.925, + '8.03515625' + ], + [ + 1495704154.925, + '8.03515625' + ], + [ + 1495704214.925, + '7.9296875' + ], + [ + 1495704274.925, + '7.9296875' + ], + [ + 1495704334.925, + '7.9296875' + ], + [ + 1495704394.925, + '7.9296875' + ], + [ + 1495704454.925, + '7.9296875' + ], + [ + 1495704514.925, + '7.9296875' + ], + [ + 1495704574.925, + '7.9296875' + ], + [ + 1495704634.925, + '7.9296875' + ], + [ + 1495704694.925, + '7.9296875' + ], + [ + 1495704754.925, + '7.9296875' + ], + [ + 1495704814.925, + '7.9296875' + ], + [ + 1495704874.925, + '7.9296875' + ], + [ + 1495704934.925, + '7.9296875' + ], + [ + 1495704994.925, + '7.9296875' + ], + [ + 1495705054.925, + '7.9296875' + ], + [ + 1495705114.925, + '7.9296875' + ], + [ + 1495705174.925, + '7.9296875' + ], + [ + 1495705234.925, + '7.9296875' + ], + [ + 1495705294.925, + '7.9296875' + ], + [ + 1495705354.925, + '7.9296875' + ], + [ + 1495705414.925, + '7.9296875' + ], + [ + 1495705474.925, + '7.9296875' + ], + [ + 1495705534.925, + '7.9296875' + ], + [ + 1495705594.925, + '7.9296875' + ], + [ + 1495705654.925, + '7.9296875' + ], + [ + 1495705714.925, + '7.9296875' + ], + [ + 1495705774.925, + '7.9296875' + ], + [ + 1495705834.925, + '7.9296875' + ], + [ + 1495705894.925, + '7.9296875' + ], + [ + 1495705954.925, + '7.9296875' + ], + [ + 1495706014.925, + '7.9296875' + ], + [ + 1495706074.925, + '7.9296875' + ], + [ + 1495706134.925, + '7.9296875' + ], + [ + 1495706194.925, + '7.9296875' + ], + [ + 1495706254.925, + '7.9296875' + ], + [ + 1495706314.925, + '7.9296875' + ], + [ + 1495706374.925, + '7.9296875' + ], + [ + 1495706434.925, + '7.9296875' + ], + [ + 1495706494.925, + '7.9296875' + ], + [ + 1495706554.925, + '7.9296875' + ], + [ + 1495706614.925, + '7.9296875' + ], + [ + 1495706674.925, + '7.9296875' + ], + [ + 1495706734.925, + '7.9296875' + ], + [ + 1495706794.925, + '7.9296875' + ], + [ + 1495706854.925, + '7.9296875' + ], + [ + 1495706914.925, + '7.9296875' + ], + [ + 1495706974.925, + '7.9296875' + ], + [ + 1495707034.925, + '7.9296875' + ], + [ + 1495707094.925, + '7.9296875' + ], + [ + 1495707154.925, + '7.9296875' + ], + [ + 1495707214.925, + '7.9296875' + ], + [ + 1495707274.925, + '7.9296875' + ], + [ + 1495707334.925, + '7.9296875' + ], + [ + 1495707394.925, + '7.9296875' + ], + [ + 1495707454.925, + '7.9296875' + ], + [ + 1495707514.925, + '7.9296875' + ], + [ + 1495707574.925, + '7.9296875' + ], + [ + 1495707634.925, + '7.9296875' + ], + [ + 1495707694.925, + '7.9296875' + ], + [ + 1495707754.925, + '7.9296875' + ], + [ + 1495707814.925, + '7.9296875' + ], + [ + 1495707874.925, + '7.9296875' + ], + [ + 1495707934.925, + '7.9296875' + ], + [ + 1495707994.925, + '7.9296875' + ], + [ + 1495708054.925, + '7.9296875' + ], + [ + 1495708114.925, + '7.9296875' + ], + [ + 1495708174.925, + '7.9296875' + ], + [ + 1495708234.925, + '7.9296875' + ], + [ + 1495708294.925, + '7.9296875' + ], + [ + 1495708354.925, + '7.9296875' + ], + [ + 1495708414.925, + '7.9296875' + ], + [ + 1495708474.925, + '7.9296875' + ], + [ + 1495708534.925, + '7.9296875' + ], + [ + 1495708594.925, + '7.9296875' + ], + [ + 1495708654.925, + '7.9296875' + ], + [ + 1495708714.925, + '7.9296875' + ], + [ + 1495708774.925, + '7.9296875' + ], + [ + 1495708834.925, + '7.9296875' + ], + [ + 1495708894.925, + '7.9296875' + ], + [ + 1495708954.925, + '7.8984375' + ], + [ + 1495709014.925, + '7.8984375' + ], + [ + 1495709074.925, + '7.8984375' + ], + [ + 1495709134.925, + '7.8984375' + ], + [ + 1495709194.925, + '7.8984375' + ], + [ + 1495709254.925, + '7.89453125' + ], + [ + 1495709314.925, + '7.89453125' + ], + [ + 1495709374.925, + '7.89453125' + ], + [ + 1495709434.925, + '7.89453125' + ], + [ + 1495709494.925, + '7.89453125' + ], + [ + 1495709554.925, + '7.89453125' + ], + [ + 1495709614.925, + '7.89453125' + ], + [ + 1495709674.925, + '7.89453125' + ], + [ + 1495709734.925, + '7.89453125' + ], + [ + 1495709794.925, + '7.89453125' + ], + [ + 1495709854.925, + '7.89453125' + ], + [ + 1495709914.925, + '7.89453125' + ], + [ + 1495709974.925, + '7.89453125' + ], + [ + 1495710034.925, + '7.89453125' + ], + [ + 1495710094.925, + '7.89453125' + ], + [ + 1495710154.925, + '7.89453125' + ], + [ + 1495710214.925, + '7.89453125' + ], + [ + 1495710274.925, + '7.89453125' + ], + [ + 1495710334.925, + '7.89453125' + ], + [ + 1495710394.925, + '7.89453125' + ], + [ + 1495710454.925, + '7.89453125' + ], + [ + 1495710514.925, + '7.89453125' + ], + [ + 1495710574.925, + '7.89453125' + ], + [ + 1495710634.925, + '7.89453125' + ], + [ + 1495710694.925, + '7.89453125' + ], + [ + 1495710754.925, + '7.89453125' + ], + [ + 1495710814.925, + '7.89453125' + ], + [ + 1495710874.925, + '7.89453125' + ], + [ + 1495710934.925, + '7.89453125' + ], + [ + 1495710994.925, + '7.89453125' + ], + [ + 1495711054.925, + '7.89453125' + ], + [ + 1495711114.925, + '7.89453125' + ], + [ + 1495711174.925, + '7.8515625' + ], + [ + 1495711234.925, + '7.8515625' + ], + [ + 1495711294.925, + '7.8515625' + ], + [ + 1495711354.925, + '7.8515625' + ], + [ + 1495711414.925, + '7.8515625' + ], + [ + 1495711474.925, + '7.8515625' + ], + [ + 1495711534.925, + '7.8515625' + ], + [ + 1495711594.925, + '7.8515625' + ], + [ + 1495711654.925, + '7.8515625' + ], + [ + 1495711714.925, + '7.8515625' + ], + [ + 1495711774.925, + '7.8515625' + ], + [ + 1495711834.925, + '7.8515625' + ], + [ + 1495711894.925, + '7.8515625' + ], + [ + 1495711954.925, + '7.8515625' + ], + [ + 1495712014.925, + '7.8515625' + ], + [ + 1495712074.925, + '7.8515625' + ], + [ + 1495712134.925, + '7.8515625' + ], + [ + 1495712194.925, + '7.8515625' + ], + [ + 1495712254.925, + '7.8515625' + ], + [ + 1495712314.925, + '7.8515625' + ], + [ + 1495712374.925, + '7.8515625' + ], + [ + 1495712434.925, + '7.83203125' + ], + [ + 1495712494.925, + '7.83203125' + ], + [ + 1495712554.925, + '7.83203125' + ], + [ + 1495712614.925, + '7.83203125' + ], + [ + 1495712674.925, + '7.83203125' + ], + [ + 1495712734.925, + '7.83203125' + ], + [ + 1495712794.925, + '7.83203125' + ], + [ + 1495712854.925, + '7.83203125' + ], + [ + 1495712914.925, + '7.83203125' + ], + [ + 1495712974.925, + '7.83203125' + ], + [ + 1495713034.925, + '7.83203125' + ], + [ + 1495713094.925, + '7.83203125' + ], + [ + 1495713154.925, + '7.83203125' + ], + [ + 1495713214.925, + '7.83203125' + ], + [ + 1495713274.925, + '7.83203125' + ], + [ + 1495713334.925, + '7.83203125' + ], + [ + 1495713394.925, + '7.8125' + ], + [ + 1495713454.925, + '7.8125' + ], + [ + 1495713514.925, + '7.8125' + ], + [ + 1495713574.925, + '7.8125' + ], + [ + 1495713634.925, + '7.8125' + ], + [ + 1495713694.925, + '7.8125' + ], + [ + 1495713754.925, + '7.8125' + ], + [ + 1495713814.925, + '7.8125' + ], + [ + 1495713874.925, + '7.8125' + ], + [ + 1495713934.925, + '7.8125' + ], + [ + 1495713994.925, + '7.8125' + ], + [ + 1495714054.925, + '7.8125' + ], + [ + 1495714114.925, + '7.8125' + ], + [ + 1495714174.925, + '7.8125' + ], + [ + 1495714234.925, + '7.8125' + ], + [ + 1495714294.925, + '7.8125' + ], + [ + 1495714354.925, + '7.80859375' + ], + [ + 1495714414.925, + '7.80859375' + ], + [ + 1495714474.925, + '7.80859375' + ], + [ + 1495714534.925, + '7.80859375' + ], + [ + 1495714594.925, + '7.80859375' + ], + [ + 1495714654.925, + '7.80859375' + ], + [ + 1495714714.925, + '7.80859375' + ], + [ + 1495714774.925, + '7.80859375' + ], + [ + 1495714834.925, + '7.80859375' + ], + [ + 1495714894.925, + '7.80859375' + ], + [ + 1495714954.925, + '7.80859375' + ], + [ + 1495715014.925, + '7.80859375' + ], + [ + 1495715074.925, + '7.80859375' + ], + [ + 1495715134.925, + '7.80859375' + ], + [ + 1495715194.925, + '7.80859375' + ], + [ + 1495715254.925, + '7.80859375' + ], + [ + 1495715314.925, + '7.80859375' + ], + [ + 1495715374.925, + '7.80859375' + ], + [ + 1495715434.925, + '7.80859375' + ], + [ + 1495715494.925, + '7.80859375' + ], + [ + 1495715554.925, + '7.80859375' + ], + [ + 1495715614.925, + '7.80859375' + ], + [ + 1495715674.925, + '7.80859375' + ], + [ + 1495715734.925, + '7.80859375' + ], + [ + 1495715794.925, + '7.80859375' + ], + [ + 1495715854.925, + '7.80859375' + ], + [ + 1495715914.925, + '7.80078125' + ], + [ + 1495715974.925, + '7.80078125' + ], + [ + 1495716034.925, + '7.80078125' + ], + [ + 1495716094.925, + '7.80078125' + ], + [ + 1495716154.925, + '7.80078125' + ], + [ + 1495716214.925, + '7.796875' + ], + [ + 1495716274.925, + '7.796875' + ], + [ + 1495716334.925, + '7.796875' + ], + [ + 1495716394.925, + '7.796875' + ], + [ + 1495716454.925, + '7.796875' + ], + [ + 1495716514.925, + '7.796875' + ], + [ + 1495716574.925, + '7.796875' + ], + [ + 1495716634.925, + '7.796875' + ], + [ + 1495716694.925, + '7.796875' + ], + [ + 1495716754.925, + '7.796875' + ], + [ + 1495716814.925, + '7.796875' + ], + [ + 1495716874.925, + '7.79296875' + ], + [ + 1495716934.925, + '7.79296875' + ], + [ + 1495716994.925, + '7.79296875' + ], + [ + 1495717054.925, + '7.79296875' + ], + [ + 1495717114.925, + '7.79296875' + ], + [ + 1495717174.925, + '7.7890625' + ], + [ + 1495717234.925, + '7.7890625' + ], + [ + 1495717294.925, + '7.7890625' + ], + [ + 1495717354.925, + '7.7890625' + ], + [ + 1495717414.925, + '7.7890625' + ], + [ + 1495717474.925, + '7.7890625' + ], + [ + 1495717534.925, + '7.7890625' + ], + [ + 1495717594.925, + '7.7890625' + ], + [ + 1495717654.925, + '7.7890625' + ], + [ + 1495717714.925, + '7.7890625' + ], + [ + 1495717774.925, + '7.7890625' + ], + [ + 1495717834.925, + '7.77734375' + ], + [ + 1495717894.925, + '7.77734375' + ], + [ + 1495717954.925, + '7.77734375' + ], + [ + 1495718014.925, + '7.77734375' + ], + [ + 1495718074.925, + '7.77734375' + ], + [ + 1495718134.925, + '7.7421875' + ], + [ + 1495718194.925, + '7.7421875' + ], + [ + 1495718254.925, + '7.7421875' + ], + [ + 1495718314.925, + '7.7421875' + ] + ] + } + ] + } + ] + }, + { + 'title': 'CPU usage', + 'weight': 1, + 'queries': [ + { + 'query_range': 'avg(rate(container_cpu_usage_seconds_total{%{environment_filter}}[2m])) * 100', + 'result': [ + { + 'metric': {}, + 'values': [ + [ + 1495700554.925, + '0.0010794445585559514' + ], + [ + 1495700614.925, + '0.003927214935433527' + ], + [ + 1495700674.925, + '0.0053045219047619975' + ], + [ + 1495700734.925, + '0.0048892095238097155' + ], + [ + 1495700794.925, + '0.005827140952381137' + ], + [ + 1495700854.925, + '0.00569846906219937' + ], + [ + 1495700914.925, + '0.004972616802849382' + ], + [ + 1495700974.925, + '0.005117509523809902' + ], + [ + 1495701034.925, + '0.00512389061919564' + ], + [ + 1495701094.925, + '0.005199100501890691' + ], + [ + 1495701154.925, + '0.005415746394885837' + ], + [ + 1495701214.925, + '0.005607682788146286' + ], + [ + 1495701274.925, + '0.005641300000000118' + ], + [ + 1495701334.925, + '0.0071166279368766495' + ], + [ + 1495701394.925, + '0.0063242138095234044' + ], + [ + 1495701454.925, + '0.005793314698235304' + ], + [ + 1495701514.925, + '0.00703934942237556' + ], + [ + 1495701574.925, + '0.006357007076123191' + ], + [ + 1495701634.925, + '0.003753167300126738' + ], + [ + 1495701694.925, + '0.005018469678430698' + ], + [ + 1495701754.925, + '0.0045217153371887' + ], + [ + 1495701814.925, + '0.006140104285714119' + ], + [ + 1495701874.925, + '0.004818684285714102' + ], + [ + 1495701934.925, + '0.005079509718955242' + ], + [ + 1495701994.925, + '0.005059981142498263' + ], + [ + 1495702054.925, + '0.005269098389538773' + ], + [ + 1495702114.925, + '0.005269954285714175' + ], + [ + 1495702174.925, + '0.014199241435795856' + ], + [ + 1495702234.925, + '0.01511936843111017' + ], + [ + 1495702294.925, + '0.0060933692920682875' + ], + [ + 1495702354.925, + '0.004945682380952493' + ], + [ + 1495702414.925, + '0.005641266666666565' + ], + [ + 1495702474.925, + '0.005223752857142996' + ], + [ + 1495702534.925, + '0.005743098505699831' + ], + [ + 1495702594.925, + '0.00538493380952391' + ], + [ + 1495702654.925, + '0.005507793883751339' + ], + [ + 1495702714.925, + '0.005666705714285466' + ], + [ + 1495702774.925, + '0.006231530000000112' + ], + [ + 1495702834.925, + '0.006570768635394899' + ], + [ + 1495702894.925, + '0.005551146666666895' + ], + [ + 1495702954.925, + '0.005602604737098058' + ], + [ + 1495703014.925, + '0.00613993580402159' + ], + [ + 1495703074.925, + '0.004770258764368832' + ], + [ + 1495703134.925, + '0.005512376671364914' + ], + [ + 1495703194.925, + '0.005254436666666674' + ], + [ + 1495703254.925, + '0.0050109839141320505' + ], + [ + 1495703314.925, + '0.0049478019256960016' + ], + [ + 1495703374.925, + '0.0037666860965123463' + ], + [ + 1495703434.925, + '0.004813526061656314' + ], + [ + 1495703494.925, + '0.005047748095238278' + ], + [ + 1495703554.925, + '0.00386494081008772' + ], + [ + 1495703614.925, + '0.004304037408111405' + ], + [ + 1495703674.925, + '0.004999466661587168' + ], + [ + 1495703734.925, + '0.004689140476190834' + ], + [ + 1495703794.925, + '0.004746126153582475' + ], + [ + 1495703854.925, + '0.004482706382572302' + ], + [ + 1495703914.925, + '0.004032808931864524' + ], + [ + 1495703974.925, + '0.005728319047618988' + ], + [ + 1495704034.925, + '0.004436139179627006' + ], + [ + 1495704094.925, + '0.004553455714285617' + ], + [ + 1495704154.925, + '0.003455244285714341' + ], + [ + 1495704214.925, + '0.004742244761904621' + ], + [ + 1495704274.925, + '0.005366978571428422' + ], + [ + 1495704334.925, + '0.004257954837665058' + ], + [ + 1495704394.925, + '0.005431603259831257' + ], + [ + 1495704454.925, + '0.0052009214498621986' + ], + [ + 1495704514.925, + '0.004317201904761618' + ], + [ + 1495704574.925, + '0.004307384285714157' + ], + [ + 1495704634.925, + '0.004789801146644822' + ], + [ + 1495704694.925, + '0.0051429795906706485' + ], + [ + 1495704754.925, + '0.005322495714285479' + ], + [ + 1495704814.925, + '0.004512809333244233' + ], + [ + 1495704874.925, + '0.004953843582568726' + ], + [ + 1495704934.925, + '0.005812690120858119' + ], + [ + 1495704994.925, + '0.004997024285714838' + ], + [ + 1495705054.925, + '0.005246216154439592' + ], + [ + 1495705114.925, + '0.0063494966618726795' + ], + [ + 1495705174.925, + '0.005306004342898225' + ], + [ + 1495705234.925, + '0.005081412857142978' + ], + [ + 1495705294.925, + '0.00511409523809522' + ], + [ + 1495705354.925, + '0.0047861001481192' + ], + [ + 1495705414.925, + '0.005107688228042962' + ], + [ + 1495705474.925, + '0.005271929582294012' + ], + [ + 1495705534.925, + '0.004453254502681249' + ], + [ + 1495705594.925, + '0.005799134293959226' + ], + [ + 1495705654.925, + '0.005340865929502478' + ], + [ + 1495705714.925, + '0.004911654761904942' + ], + [ + 1495705774.925, + '0.005888234873953261' + ], + [ + 1495705834.925, + '0.005565283333332954' + ], + [ + 1495705894.925, + '0.005522869047618869' + ], + [ + 1495705954.925, + '0.005177549737621646' + ], + [ + 1495706014.925, + '0.0053145810232096465' + ], + [ + 1495706074.925, + '0.004751095238095275' + ], + [ + 1495706134.925, + '0.006242077142856976' + ], + [ + 1495706194.925, + '0.00621034406957871' + ], + [ + 1495706254.925, + '0.006887592738978596' + ], + [ + 1495706314.925, + '0.006328128779726213' + ], + [ + 1495706374.925, + '0.007488363809523927' + ], + [ + 1495706434.925, + '0.006193758571428157' + ], + [ + 1495706494.925, + '0.0068798371839706935' + ], + [ + 1495706554.925, + '0.005757034340423128' + ], + [ + 1495706614.925, + '0.004571388497294698' + ], + [ + 1495706674.925, + '0.00620283044923395' + ], + [ + 1495706734.925, + '0.005607562380952455' + ], + [ + 1495706794.925, + '0.005506969933620308' + ], + [ + 1495706854.925, + '0.005621118095238131' + ], + [ + 1495706914.925, + '0.004876606098698849' + ], + [ + 1495706974.925, + '0.0047871205988517206' + ], + [ + 1495707034.925, + '0.00526405939458784' + ], + [ + 1495707094.925, + '0.005716323800605852' + ], + [ + 1495707154.925, + '0.005301459523809575' + ], + [ + 1495707214.925, + '0.0051613042857144905' + ], + [ + 1495707274.925, + '0.005384792857142714' + ], + [ + 1495707334.925, + '0.005259719047619222' + ], + [ + 1495707394.925, + '0.00584101142857182' + ], + [ + 1495707454.925, + '0.0060066121920326326' + ], + [ + 1495707514.925, + '0.006359978571428453' + ], + [ + 1495707574.925, + '0.006315876322151109' + ], + [ + 1495707634.925, + '0.005590012517198831' + ], + [ + 1495707694.925, + '0.005517419877137072' + ], + [ + 1495707754.925, + '0.006089813430348506' + ], + [ + 1495707814.925, + '0.00466754476190479' + ], + [ + 1495707874.925, + '0.006059954380517721' + ], + [ + 1495707934.925, + '0.005085657142856972' + ], + [ + 1495707994.925, + '0.005897665238095296' + ], + [ + 1495708054.925, + '0.0062282023199555885' + ], + [ + 1495708114.925, + '0.00526214553236979' + ], + [ + 1495708174.925, + '0.0044803300000000644' + ], + [ + 1495708234.925, + '0.005421443333333592' + ], + [ + 1495708294.925, + '0.005694326244512144' + ], + [ + 1495708354.925, + '0.005527721904761457' + ], + [ + 1495708414.925, + '0.005988819523809819' + ], + [ + 1495708474.925, + '0.005484704285714448' + ], + [ + 1495708534.925, + '0.005041123649230085' + ], + [ + 1495708594.925, + '0.005717767639612059' + ], + [ + 1495708654.925, + '0.005412954417342863' + ], + [ + 1495708714.925, + '0.005833343333333254' + ], + [ + 1495708774.925, + '0.005448135238094969' + ], + [ + 1495708834.925, + '0.005117341428571432' + ], + [ + 1495708894.925, + '0.005888345825277833' + ], + [ + 1495708954.925, + '0.005398543809524135' + ], + [ + 1495709014.925, + '0.005325611428571416' + ], + [ + 1495709074.925, + '0.005848668571428527' + ], + [ + 1495709134.925, + '0.005135003105145044' + ], + [ + 1495709194.925, + '0.0054551400000003' + ], + [ + 1495709254.925, + '0.005319472937322171' + ], + [ + 1495709314.925, + '0.00585677857142792' + ], + [ + 1495709374.925, + '0.0062146261904759215' + ], + [ + 1495709434.925, + '0.0067105060904182265' + ], + [ + 1495709494.925, + '0.005829691904762108' + ], + [ + 1495709554.925, + '0.005719280952381261' + ], + [ + 1495709614.925, + '0.005682603793416407' + ], + [ + 1495709674.925, + '0.0055272846277326934' + ], + [ + 1495709734.925, + '0.0057123680952386735' + ], + [ + 1495709794.925, + '0.00520597958075818' + ], + [ + 1495709854.925, + '0.005584358957263837' + ], + [ + 1495709914.925, + '0.005601104275197466' + ], + [ + 1495709974.925, + '0.005991657142857066' + ], + [ + 1495710034.925, + '0.00553722238095218' + ], + [ + 1495710094.925, + '0.005127883122696293' + ], + [ + 1495710154.925, + '0.005498111927534584' + ], + [ + 1495710214.925, + '0.005609934069084202' + ], + [ + 1495710274.925, + '0.00459206285714307' + ], + [ + 1495710334.925, + '0.0047910828571428084' + ], + [ + 1495710394.925, + '0.0056014671288845685' + ], + [ + 1495710454.925, + '0.005686936791078528' + ], + [ + 1495710514.925, + '0.00444480476190448' + ], + [ + 1495710574.925, + '0.005780394696738921' + ], + [ + 1495710634.925, + '0.0053107227550210365' + ], + [ + 1495710694.925, + '0.005096031495761817' + ], + [ + 1495710754.925, + '0.005451377979091524' + ], + [ + 1495710814.925, + '0.005328136666667083' + ], + [ + 1495710874.925, + '0.006020612857143043' + ], + [ + 1495710934.925, + '0.0061063585714285365' + ], + [ + 1495710994.925, + '0.006018346015752312' + ], + [ + 1495711054.925, + '0.005069130952381193' + ], + [ + 1495711114.925, + '0.005458406190476052' + ], + [ + 1495711174.925, + '0.00577219190476179' + ], + [ + 1495711234.925, + '0.005760814645658314' + ], + [ + 1495711294.925, + '0.005371875716579101' + ], + [ + 1495711354.925, + '0.0064232666666665834' + ], + [ + 1495711414.925, + '0.009369806836906667' + ], + [ + 1495711474.925, + '0.008956864761904692' + ], + [ + 1495711534.925, + '0.005266849368559271' + ], + [ + 1495711594.925, + '0.005335111364934262' + ], + [ + 1495711654.925, + '0.006461778319586945' + ], + [ + 1495711714.925, + '0.004687939890762393' + ], + [ + 1495711774.925, + '0.004438831245760684' + ], + [ + 1495711834.925, + '0.005142786666666613' + ], + [ + 1495711894.925, + '0.007257734212054963' + ], + [ + 1495711954.925, + '0.005621991904761494' + ], + [ + 1495712014.925, + '0.007868689999999862' + ], + [ + 1495712074.925, + '0.00910970215275738' + ], + [ + 1495712134.925, + '0.006151004285714278' + ], + [ + 1495712194.925, + '0.005447120924961522' + ], + [ + 1495712254.925, + '0.005150705153929503' + ], + [ + 1495712314.925, + '0.006358108714969314' + ], + [ + 1495712374.925, + '0.0057725354795696475' + ], + [ + 1495712434.925, + '0.005232139047619015' + ], + [ + 1495712494.925, + '0.004932809617949037' + ], + [ + 1495712554.925, + '0.004511607508499662' + ], + [ + 1495712614.925, + '0.00440487701522666' + ], + [ + 1495712674.925, + '0.005479113333333174' + ], + [ + 1495712734.925, + '0.004726317619047547' + ], + [ + 1495712794.925, + '0.005582041102958029' + ], + [ + 1495712854.925, + '0.006381481216082099' + ], + [ + 1495712914.925, + '0.005474260014095208' + ], + [ + 1495712974.925, + '0.00567597142857188' + ], + [ + 1495713034.925, + '0.0064741233333332985' + ], + [ + 1495713094.925, + '0.005467475714285271' + ], + [ + 1495713154.925, + '0.004868648393824457' + ], + [ + 1495713214.925, + '0.005254923286444893' + ], + [ + 1495713274.925, + '0.005599217150312865' + ], + [ + 1495713334.925, + '0.005105413720618919' + ], + [ + 1495713394.925, + '0.007246073333333279' + ], + [ + 1495713454.925, + '0.005990312380952272' + ], + [ + 1495713514.925, + '0.005594601853351101' + ], + [ + 1495713574.925, + '0.004739258673727054' + ], + [ + 1495713634.925, + '0.003932121428571783' + ], + [ + 1495713694.925, + '0.005018188268459395' + ], + [ + 1495713754.925, + '0.004538238095237985' + ], + [ + 1495713814.925, + '0.00561816643265435' + ], + [ + 1495713874.925, + '0.0063132584495033586' + ], + [ + 1495713934.925, + '0.00442385238095213' + ], + [ + 1495713994.925, + '0.004181795887658453' + ], + [ + 1495714054.925, + '0.004437759047619037' + ], + [ + 1495714114.925, + '0.006421748157178241' + ], + [ + 1495714174.925, + '0.006525143809523842' + ], + [ + 1495714234.925, + '0.004715904935144247' + ], + [ + 1495714294.925, + '0.005966040152763461' + ], + [ + 1495714354.925, + '0.005614535466921674' + ], + [ + 1495714414.925, + '0.004934375119415906' + ], + [ + 1495714474.925, + '0.0054122933333327385' + ], + [ + 1495714534.925, + '0.004926540699612279' + ], + [ + 1495714594.925, + '0.006124649517134237' + ], + [ + 1495714654.925, + '0.004629427092013995' + ], + [ + 1495714714.925, + '0.005117951257607005' + ], + [ + 1495714774.925, + '0.004868774512685422' + ], + [ + 1495714834.925, + '0.005310093333333399' + ], + [ + 1495714894.925, + '0.0054907752286127345' + ], + [ + 1495714954.925, + '0.004597678117351089' + ], + [ + 1495715014.925, + '0.0059622552380952' + ], + [ + 1495715074.925, + '0.005352457072655368' + ], + [ + 1495715134.925, + '0.005491630952381143' + ], + [ + 1495715194.925, + '0.006391770078379791' + ], + [ + 1495715254.925, + '0.005933472857142518' + ], + [ + 1495715314.925, + '0.005301314285714163' + ], + [ + 1495715374.925, + '0.0058352959724814165' + ], + [ + 1495715434.925, + '0.006154755147867044' + ], + [ + 1495715494.925, + '0.009391935637482038' + ], + [ + 1495715554.925, + '0.007846462857142592' + ], + [ + 1495715614.925, + '0.00477608215316353' + ], + [ + 1495715674.925, + '0.006132865238094998' + ], + [ + 1495715734.925, + '0.006159762457649516' + ], + [ + 1495715794.925, + '0.005957307073265968' + ], + [ + 1495715854.925, + '0.006652319091792501' + ], + [ + 1495715914.925, + '0.005493557402895287' + ], + [ + 1495715974.925, + '0.0058652434829145166' + ], + [ + 1495716034.925, + '0.005627400430468021' + ], + [ + 1495716094.925, + '0.006240656190475609' + ], + [ + 1495716154.925, + '0.006305997676168624' + ], + [ + 1495716214.925, + '0.005388057732783248' + ], + [ + 1495716274.925, + '0.0052814916048421244' + ], + [ + 1495716334.925, + '0.00699498614272497' + ], + [ + 1495716394.925, + '0.00627768693035141' + ], + [ + 1495716454.925, + '0.0042411487048161145' + ], + [ + 1495716514.925, + '0.005348647473627653' + ], + [ + 1495716574.925, + '0.0047176657142853975' + ], + [ + 1495716634.925, + '0.004437898571428686' + ], + [ + 1495716694.925, + '0.004923527366927261' + ], + [ + 1495716754.925, + '0.005131935066048421' + ], + [ + 1495716814.925, + '0.005046949523809611' + ], + [ + 1495716874.925, + '0.00547184095238092' + ], + [ + 1495716934.925, + '0.005224140016380444' + ], + [ + 1495716994.925, + '0.005297991171665292' + ], + [ + 1495717054.925, + '0.005492965995623498' + ], + [ + 1495717114.925, + '0.005754660000000403' + ], + [ + 1495717174.925, + '0.005949557138639285' + ], + [ + 1495717234.925, + '0.006091816112534666' + ], + [ + 1495717294.925, + '0.005554210080192063' + ], + [ + 1495717354.925, + '0.006411504395279871' + ], + [ + 1495717414.925, + '0.006319643996609606' + ], + [ + 1495717474.925, + '0.005539174405717675' + ], + [ + 1495717534.925, + '0.0053157078842772255' + ], + [ + 1495717594.925, + '0.005247480952381066' + ], + [ + 1495717654.925, + '0.004820141620396252' + ], + [ + 1495717714.925, + '0.005906173868322844' + ], + [ + 1495717774.925, + '0.006173117219570961' + ], + [ + 1495717834.925, + '0.005963340952380661' + ], + [ + 1495717894.925, + '0.005698976627681527' + ], + [ + 1495717954.925, + '0.004751279096346378' + ], + [ + 1495718014.925, + '0.005733142379359711' + ], + [ + 1495718074.925, + '0.004831689010348035' + ], + [ + 1495718134.925, + '0.005188370476191092' + ], + [ + 1495718194.925, + '0.004793227554547938' + ], + [ + 1495718254.925, + '0.003997442857142731' + ], + [ + 1495718314.925, + '0.004386040132951264' + ] + ] + } + ] + } + ] + } + ] + } + ], + 'last_update': '2017-05-25T13:18:34.949Z' +}; + +export default metricsGroupsAPIResponse; + +const responseMockData = { + 'GET': { + '/root/hello-prometheus/environments/30/additional_metrics.json': metricsGroupsAPIResponse, + 'http://test.host/frontend-fixtures/environments-project/environments/1/additional_metrics.json': metricsGroupsAPIResponse, // TODO: MAke sure this works in the monitoring_bundle_spec + }, +}; + +export const deploymentData = [ + { + id: 111, + iid: 3, + sha: 'f5bcd1d9dac6fa4137e2510b9ccd134ef2e84187', + ref: { + name: 'master' + }, + created_at: '2017-05-31T21:23:37.881Z', + tag: false, + 'last?': true + }, + { + id: 110, + iid: 2, + sha: 'f5bcd1d9dac6fa4137e2510b9ccd134ef2e84187', + ref: { + name: 'master' + }, + created_at: '2017-05-30T20:08:04.629Z', + tag: false, + 'last?': false + }, + { + id: 109, + iid: 1, + sha: '6511e58faafaa7ad2228990ec57f19d66f7db7c2', + ref: { + name: 'update2-readme' + }, + created_at: '2017-05-30T17:42:38.409Z', + tag: false, + 'last?': false + } +]; + +export const statePaths = { + settingsPath: '/root/hello-prometheus/services/prometheus/edit', + documentationPath: '/help/administration/monitoring/prometheus/index.md', +}; + +export const singleRowMetrics = [ + { + 'title': 'CPU usage', + 'weight': 1, + 'y_label': 'Values', + 'queries': [ + { + 'query_range': 'avg(rate(container_cpu_usage_seconds_total{%{environment_filter}}[2m])) * 100', + 'result': [ + { + 'metric': { + + }, + 'values': [ + { + 'time': '2017-06-04T21:22:59.508Z', + 'value': '0.06335544298150002' + }, + { + 'time': '2017-06-04T21:23:59.508Z', + 'value': '0.0420347312480917' + }, + { + 'time': '2017-06-04T21:24:59.508Z', + 'value': '0.0023175131665412706' + }, + { + 'time': '2017-06-04T21:25:59.508Z', + 'value': '0.002315870476190476' + }, + { + 'time': '2017-06-04T21:26:59.508Z', + 'value': '0.0025005961904761894' + }, + { + 'time': '2017-06-04T21:27:59.508Z', + 'value': '0.0024612605834341264' + }, + { + 'time': '2017-06-04T21:28:59.508Z', + 'value': '0.002313129398767631' + }, + { + 'time': '2017-06-04T21:29:59.508Z', + 'value': '0.002411067353663882' + }, + { + 'time': '2017-06-04T21:30:59.508Z', + 'value': '0.002577309263721303' + }, + { + 'time': '2017-06-04T21:31:59.508Z', + 'value': '0.00242688307730403' + }, + { + 'time': '2017-06-04T21:32:59.508Z', + 'value': '0.0024168360301330457' + }, + { + 'time': '2017-06-04T21:33:59.508Z', + 'value': '0.0020449528090743714' + }, + { + 'time': '2017-06-04T21:34:59.508Z', + 'value': '0.0019149619047619036' + }, + { + 'time': '2017-06-04T21:35:59.508Z', + 'value': '0.0024491714364625094' + }, + { + 'time': '2017-06-04T21:36:59.508Z', + 'value': '0.002728773131172677' + }, + { + 'time': '2017-06-04T21:37:59.508Z', + 'value': '0.0028439119047618997' + }, + { + 'time': '2017-06-04T21:38:59.508Z', + 'value': '0.0026307480952380917' + }, + { + 'time': '2017-06-04T21:39:59.508Z', + 'value': '0.0025024842620546446' + }, + { + 'time': '2017-06-04T21:40:59.508Z', + 'value': '0.002300662387260825' + }, + { + 'time': '2017-06-04T21:41:59.508Z', + 'value': '0.002052890924848337' + }, + { + 'time': '2017-06-04T21:42:59.508Z', + 'value': '0.0023711195238095275' + }, + { + 'time': '2017-06-04T21:43:59.508Z', + 'value': '0.002513477619047618' + }, + { + 'time': '2017-06-04T21:44:59.508Z', + 'value': '0.0023489776287844897' + }, + { + 'time': '2017-06-04T21:45:59.508Z', + 'value': '0.002542572310212481' + }, + { + 'time': '2017-06-04T21:46:59.508Z', + 'value': '0.0024579470671707952' + }, + { + 'time': '2017-06-04T21:47:59.508Z', + 'value': '0.0028725150236664403' + }, + { + 'time': '2017-06-04T21:48:59.508Z', + 'value': '0.0024356089105610525' + }, + { + 'time': '2017-06-04T21:49:59.508Z', + 'value': '0.002544015828269929' + }, + { + 'time': '2017-06-04T21:50:59.508Z', + 'value': '0.0029595013380824906' + }, + { + 'time': '2017-06-04T21:51:59.508Z', + 'value': '0.0023084015085858' + }, + { + 'time': '2017-06-04T21:52:59.508Z', + 'value': '0.0021070500000000083' + }, + { + 'time': '2017-06-04T21:53:59.508Z', + 'value': '0.0022950066191106617' + }, + { + 'time': '2017-06-04T21:54:59.508Z', + 'value': '0.002492719454470995' + }, + { + 'time': '2017-06-04T21:55:59.508Z', + 'value': '0.00244312761904762' + }, + { + 'time': '2017-06-04T21:56:59.508Z', + 'value': '0.0023495500000000028' + }, + { + 'time': '2017-06-04T21:57:59.508Z', + 'value': '0.0020597072353070005' + }, + { + 'time': '2017-06-04T21:58:59.508Z', + 'value': '0.0021482352044800866' + }, + { + 'time': '2017-06-04T21:59:59.508Z', + 'value': '0.002333490000000004' + }, + { + 'time': '2017-06-04T22:00:59.508Z', + 'value': '0.0025899442857142815' + }, + { + 'time': '2017-06-04T22:01:59.508Z', + 'value': '0.002430299999999999' + }, + { + 'time': '2017-06-04T22:02:59.508Z', + 'value': '0.0023550328092113476' + }, + { + 'time': '2017-06-04T22:03:59.508Z', + 'value': '0.0026521871636872793' + }, + { + 'time': '2017-06-04T22:04:59.508Z', + 'value': '0.0023080671428571398' + }, + { + 'time': '2017-06-04T22:05:59.508Z', + 'value': '0.0024108401032390896' + }, + { + 'time': '2017-06-04T22:06:59.508Z', + 'value': '0.002433249366678738' + }, + { + 'time': '2017-06-04T22:07:59.508Z', + 'value': '0.0023242202306688682' + }, + { + 'time': '2017-06-04T22:08:59.508Z', + 'value': '0.002388222857142859' + }, + { + 'time': '2017-06-04T22:09:59.508Z', + 'value': '0.002115974914046794' + }, + { + 'time': '2017-06-04T22:10:59.508Z', + 'value': '0.0025090043331269917' + }, + { + 'time': '2017-06-04T22:11:59.508Z', + 'value': '0.002445507057277277' + }, + { + 'time': '2017-06-04T22:12:59.508Z', + 'value': '0.0026348773751130976' + }, + { + 'time': '2017-06-04T22:13:59.508Z', + 'value': '0.0025616258583088104' + }, + { + 'time': '2017-06-04T22:14:59.508Z', + 'value': '0.0021544093415751505' + }, + { + 'time': '2017-06-04T22:15:59.508Z', + 'value': '0.002649394767668881' + }, + { + 'time': '2017-06-04T22:16:59.508Z', + 'value': '0.0024023332666685705' + }, + { + 'time': '2017-06-04T22:17:59.508Z', + 'value': '0.0025444105294235306' + }, + { + 'time': '2017-06-04T22:18:59.508Z', + 'value': '0.0027298872305772806' + }, + { + 'time': '2017-06-04T22:19:59.508Z', + 'value': '0.0022880104956379287' + }, + { + 'time': '2017-06-04T22:20:59.508Z', + 'value': '0.002473246666666661' + }, + { + 'time': '2017-06-04T22:21:59.508Z', + 'value': '0.002259948381935587' + }, + { + 'time': '2017-06-04T22:22:59.508Z', + 'value': '0.0025778470886268835' + }, + { + 'time': '2017-06-04T22:23:59.508Z', + 'value': '0.002246127910852894' + }, + { + 'time': '2017-06-04T22:24:59.508Z', + 'value': '0.0020697466666666758' + }, + { + 'time': '2017-06-04T22:25:59.508Z', + 'value': '0.00225859722473547' + }, + { + 'time': '2017-06-04T22:26:59.508Z', + 'value': '0.0026466728254554814' + }, + { + 'time': '2017-06-04T22:27:59.508Z', + 'value': '0.002151247619047619' + }, + { + 'time': '2017-06-04T22:28:59.508Z', + 'value': '0.002324161444543914' + }, + { + 'time': '2017-06-04T22:29:59.508Z', + 'value': '0.002476474313796452' + }, + { + 'time': '2017-06-04T22:30:59.508Z', + 'value': '0.0023922184232080517' + }, + { + 'time': '2017-06-04T22:31:59.508Z', + 'value': '0.0025094934237468933' + }, + { + 'time': '2017-06-04T22:32:59.508Z', + 'value': '0.0025665311098200883' + }, + { + 'time': '2017-06-04T22:33:59.508Z', + 'value': '0.0024154900681661374' + }, + { + 'time': '2017-06-04T22:34:59.508Z', + 'value': '0.0023267450166192037' + }, + { + 'time': '2017-06-04T22:35:59.508Z', + 'value': '0.002156521904761904' + }, + { + 'time': '2017-06-04T22:36:59.508Z', + 'value': '0.0025474356898637007' + }, + { + 'time': '2017-06-04T22:37:59.508Z', + 'value': '0.0025989409624670233' + }, + { + 'time': '2017-06-04T22:38:59.508Z', + 'value': '0.002348336664762987' + }, + { + 'time': '2017-06-04T22:39:59.508Z', + 'value': '0.002665888246554726' + }, + { + 'time': '2017-06-04T22:40:59.508Z', + 'value': '0.002652684787474174' + }, + { + 'time': '2017-06-04T22:41:59.508Z', + 'value': '0.002472620430865355' + }, + { + 'time': '2017-06-04T22:42:59.508Z', + 'value': '0.0020616469210110247' + }, + { + 'time': '2017-06-04T22:43:59.508Z', + 'value': '0.0022434546372311934' + }, + { + 'time': '2017-06-04T22:44:59.508Z', + 'value': '0.0024469386784827982' + }, + { + 'time': '2017-06-04T22:45:59.508Z', + 'value': '0.0026192823809523787' + }, + { + 'time': '2017-06-04T22:46:59.508Z', + 'value': '0.003451999542852798' + }, + { + 'time': '2017-06-04T22:47:59.508Z', + 'value': '0.0031780314285714288' + }, + { + 'time': '2017-06-04T22:48:59.508Z', + 'value': '0.0024403352380952415' + }, + { + 'time': '2017-06-04T22:49:59.508Z', + 'value': '0.001998824761904764' + }, + { + 'time': '2017-06-04T22:50:59.508Z', + 'value': '0.0023792404761904806' + }, + { + 'time': '2017-06-04T22:51:59.508Z', + 'value': '0.002725906190476185' + }, + { + 'time': '2017-06-04T22:52:59.508Z', + 'value': '0.0020989528671155624' + }, + { + 'time': '2017-06-04T22:53:59.508Z', + 'value': '0.00228808226745016' + }, + { + 'time': '2017-06-04T22:54:59.508Z', + 'value': '0.0019860807413192147' + }, + { + 'time': '2017-06-04T22:55:59.508Z', + 'value': '0.0022698085714285897' + }, + { + 'time': '2017-06-04T22:56:59.508Z', + 'value': '0.0022839098467604415' + }, + { + 'time': '2017-06-04T22:57:59.508Z', + 'value': '0.002531114761904749' + }, + { + 'time': '2017-06-04T22:58:59.508Z', + 'value': '0.0028941072550999016' + }, + { + 'time': '2017-06-04T22:59:59.508Z', + 'value': '0.002547169523809506' + }, + { + 'time': '2017-06-04T23:00:59.508Z', + 'value': '0.0024062999999999958' + }, + { + 'time': '2017-06-04T23:01:59.508Z', + 'value': '0.0026939518471604386' + }, + { + 'time': '2017-06-04T23:02:59.508Z', + 'value': '0.002362901428571429' + }, + { + 'time': '2017-06-04T23:03:59.508Z', + 'value': '0.002663927142857154' + }, + { + 'time': '2017-06-04T23:04:59.508Z', + 'value': '0.0026173314285714354' + }, + { + 'time': '2017-06-04T23:05:59.508Z', + 'value': '0.002326527366406044' + }, + { + 'time': '2017-06-04T23:06:59.508Z', + 'value': '0.002035313809523809' + }, + { + 'time': '2017-06-04T23:07:59.508Z', + 'value': '0.002421447414786533' + }, + { + 'time': '2017-06-04T23:08:59.508Z', + 'value': '0.002898313809523804' + }, + { + 'time': '2017-06-04T23:09:59.508Z', + 'value': '0.002544891856112907' + }, + { + 'time': '2017-06-04T23:10:59.508Z', + 'value': '0.002290625356938882' + }, + { + 'time': '2017-06-04T23:11:59.508Z', + 'value': '0.002483028095238096' + }, + { + 'time': '2017-06-04T23:12:59.508Z', + 'value': '0.0023396832350784237' + }, + { + 'time': '2017-06-04T23:13:59.508Z', + 'value': '0.002085529248176153' + }, + { + 'time': '2017-06-04T23:14:59.508Z', + 'value': '0.0022417815068428012' + }, + { + 'time': '2017-06-04T23:15:59.508Z', + 'value': '0.002660293333333341' + }, + { + 'time': '2017-06-04T23:16:59.508Z', + 'value': '0.0029845149093818226' + }, + { + 'time': '2017-06-04T23:17:59.508Z', + 'value': '0.0027716655079475464' + }, + { + 'time': '2017-06-04T23:18:59.508Z', + 'value': '0.0025217708908741128' + }, + { + 'time': '2017-06-04T23:19:59.508Z', + 'value': '0.0025811235131094055' + }, + { + 'time': '2017-06-04T23:20:59.508Z', + 'value': '0.002209904761904762' + }, + { + 'time': '2017-06-04T23:21:59.508Z', + 'value': '0.0025053322926383344' + }, + { + 'time': '2017-06-04T23:22:59.508Z', + 'value': '0.002350917636526411' + }, + { + 'time': '2017-06-04T23:23:59.508Z', + 'value': '0.0018477500000000078' + }, + { + 'time': '2017-06-04T23:24:59.508Z', + 'value': '0.002427629523809527' + }, + { + 'time': '2017-06-04T23:25:59.508Z', + 'value': '0.0019305498147601655' + }, + { + 'time': '2017-06-04T23:26:59.508Z', + 'value': '0.002097250000000006' + }, + { + 'time': '2017-06-04T23:27:59.508Z', + 'value': '0.002675020952780041' + }, + { + 'time': '2017-06-04T23:28:59.508Z', + 'value': '0.0023142214285714374' + }, + { + 'time': '2017-06-04T23:29:59.508Z', + 'value': '0.0023644723809523737' + }, + { + 'time': '2017-06-04T23:30:59.508Z', + 'value': '0.002108696190476198' + }, + { + 'time': '2017-06-04T23:31:59.508Z', + 'value': '0.0019918289697997194' + }, + { + 'time': '2017-06-04T23:32:59.508Z', + 'value': '0.001583584285714283' + }, + { + 'time': '2017-06-04T23:33:59.508Z', + 'value': '0.002073770226383112' + }, + { + 'time': '2017-06-04T23:34:59.508Z', + 'value': '0.0025877664234966818' + }, + { + 'time': '2017-06-04T23:35:59.508Z', + 'value': '0.0021138238095238147' + }, + { + 'time': '2017-06-04T23:36:59.508Z', + 'value': '0.0022140838095238303' + }, + { + 'time': '2017-06-04T23:37:59.508Z', + 'value': '0.0018592674425248847' + }, + { + 'time': '2017-06-04T23:38:59.508Z', + 'value': '0.0020461969533657016' + }, + { + 'time': '2017-06-04T23:39:59.508Z', + 'value': '0.0021593628571428543' + }, + { + 'time': '2017-06-04T23:40:59.508Z', + 'value': '0.0024330682564928188' + }, + { + 'time': '2017-06-04T23:41:59.508Z', + 'value': '0.0021501804779093174' + }, + { + 'time': '2017-06-04T23:42:59.508Z', + 'value': '0.0025787493928397945' + }, + { + 'time': '2017-06-04T23:43:59.508Z', + 'value': '0.002593657082448396' + }, + { + 'time': '2017-06-04T23:44:59.508Z', + 'value': '0.0021316752380952306' + }, + { + 'time': '2017-06-04T23:45:59.508Z', + 'value': '0.0026972905019952086' + }, + { + 'time': '2017-06-04T23:46:59.508Z', + 'value': '0.002580250764292983' + }, + { + 'time': '2017-06-04T23:47:59.508Z', + 'value': '0.00227103000000001' + }, + { + 'time': '2017-06-04T23:48:59.508Z', + 'value': '0.0023678515647321146' + }, + { + 'time': '2017-06-04T23:49:59.508Z', + 'value': '0.002371472857142866' + }, + { + 'time': '2017-06-04T23:50:59.508Z', + 'value': '0.0026181353688500978' + }, + { + 'time': '2017-06-04T23:51:59.508Z', + 'value': '0.0025609667711121217' + }, + { + 'time': '2017-06-04T23:52:59.508Z', + 'value': '0.0027145308139922557' + }, + { + 'time': '2017-06-04T23:53:59.508Z', + 'value': '0.0024249397613310512' + }, + { + 'time': '2017-06-04T23:54:59.508Z', + 'value': '0.002399907142857147' + }, + { + 'time': '2017-06-04T23:55:59.508Z', + 'value': '0.0024753357142857195' + }, + { + 'time': '2017-06-04T23:56:59.508Z', + 'value': '0.0026179149325231575' + }, + { + 'time': '2017-06-04T23:57:59.508Z', + 'value': '0.0024261340368186956' + }, + { + 'time': '2017-06-04T23:58:59.508Z', + 'value': '0.0021061071428571517' + }, + { + 'time': '2017-06-04T23:59:59.508Z', + 'value': '0.0024033971105037015' + }, + { + 'time': '2017-06-05T00:00:59.508Z', + 'value': '0.0028287676190475956' + }, + { + 'time': '2017-06-05T00:01:59.508Z', + 'value': '0.002499719050294778' + }, + { + 'time': '2017-06-05T00:02:59.508Z', + 'value': '0.0026726102153353856' + }, + { + 'time': '2017-06-05T00:03:59.508Z', + 'value': '0.00262582619047618' + }, + { + 'time': '2017-06-05T00:04:59.508Z', + 'value': '0.002280473147363316' + }, + { + 'time': '2017-06-05T00:05:59.508Z', + 'value': '0.002095581470652675' + }, + { + 'time': '2017-06-05T00:06:59.508Z', + 'value': '0.002270768490828408' + }, + { + 'time': '2017-06-05T00:07:59.508Z', + 'value': '0.002728577415023017' + }, + { + 'time': '2017-06-05T00:08:59.508Z', + 'value': '0.002652512857142863' + }, + { + 'time': '2017-06-05T00:09:59.508Z', + 'value': '0.0022781033924455674' + }, + { + 'time': '2017-06-05T00:10:59.508Z', + 'value': '0.0025345038095238234' + }, + { + 'time': '2017-06-05T00:11:59.508Z', + 'value': '0.002376050020000397' + }, + { + 'time': '2017-06-05T00:12:59.508Z', + 'value': '0.002455068143506122' + }, + { + 'time': '2017-06-05T00:13:59.508Z', + 'value': '0.002826705714285719' + }, + { + 'time': '2017-06-05T00:14:59.508Z', + 'value': '0.002343833692070314' + }, + { + 'time': '2017-06-05T00:15:59.508Z', + 'value': '0.00264853297122164' + }, + { + 'time': '2017-06-05T00:16:59.508Z', + 'value': '0.0027656335117426257' + }, + { + 'time': '2017-06-05T00:17:59.508Z', + 'value': '0.0025896543842439564' + }, + { + 'time': '2017-06-05T00:18:59.508Z', + 'value': '0.002180053237081201' + }, + { + 'time': '2017-06-05T00:19:59.508Z', + 'value': '0.002475245002333342' + }, + { + 'time': '2017-06-05T00:20:59.508Z', + 'value': '0.0027559767805101065' + }, + { + 'time': '2017-06-05T00:21:59.508Z', + 'value': '0.0022294836141296607' + }, + { + 'time': '2017-06-05T00:22:59.508Z', + 'value': '0.0021383590476190643' + }, + { + 'time': '2017-06-05T00:23:59.508Z', + 'value': '0.002085417956361494' + }, + { + 'time': '2017-06-05T00:24:59.508Z', + 'value': '0.0024140319047619013' + }, + { + 'time': '2017-06-05T00:25:59.508Z', + 'value': '0.0024513114285714304' + }, + { + 'time': '2017-06-05T00:26:59.508Z', + 'value': '0.0026932152380952446' + }, + { + 'time': '2017-06-05T00:27:59.508Z', + 'value': '0.0022656844350898517' + }, + { + 'time': '2017-06-05T00:28:59.508Z', + 'value': '0.0024483785714285704' + }, + { + 'time': '2017-06-05T00:29:59.508Z', + 'value': '0.002559505804817207' + }, + { + 'time': '2017-06-05T00:30:59.508Z', + 'value': '0.0019485681088751649' + }, + { + 'time': '2017-06-05T00:31:59.508Z', + 'value': '0.00228367984456996' + }, + { + 'time': '2017-06-05T00:32:59.508Z', + 'value': '0.002522149047619049' + }, + { + 'time': '2017-06-05T00:33:59.508Z', + 'value': '0.0026860117715406737' + }, + { + 'time': '2017-06-05T00:34:59.508Z', + 'value': '0.002679669523809523' + }, + { + 'time': '2017-06-05T00:35:59.508Z', + 'value': '0.0022201920970675937' + }, + { + 'time': '2017-06-05T00:36:59.508Z', + 'value': '0.0022917647619047615' + }, + { + 'time': '2017-06-05T00:37:59.508Z', + 'value': '0.0021774059294673576' + }, + { + 'time': '2017-06-05T00:38:59.508Z', + 'value': '0.0024637766666666763' + }, + { + 'time': '2017-06-05T00:39:59.508Z', + 'value': '0.002470468290174195' + }, + { + 'time': '2017-06-05T00:40:59.508Z', + 'value': '0.0022188616082057812' + }, + { + 'time': '2017-06-05T00:41:59.508Z', + 'value': '0.002421840744373875' + }, + { + 'time': '2017-06-05T00:42:59.508Z', + 'value': '0.0023918266666666547' + }, + { + 'time': '2017-06-05T00:43:59.508Z', + 'value': '0.002195743809523809' + }, + { + 'time': '2017-06-05T00:44:59.508Z', + 'value': '0.0025514828571428687' + }, + { + 'time': '2017-06-05T00:45:59.508Z', + 'value': '0.0027981709349612694' + }, + { + 'time': '2017-06-05T00:46:59.508Z', + 'value': '0.002557977142857146' + }, + { + 'time': '2017-06-05T00:47:59.508Z', + 'value': '0.002213244285714286' + }, + { + 'time': '2017-06-05T00:48:59.508Z', + 'value': '0.0025706738095238046' + }, + { + 'time': '2017-06-05T00:49:59.508Z', + 'value': '0.002210976666666671' + }, + { + 'time': '2017-06-05T00:50:59.508Z', + 'value': '0.002055377091646749' + }, + { + 'time': '2017-06-05T00:51:59.508Z', + 'value': '0.002308368095238119' + }, + { + 'time': '2017-06-05T00:52:59.508Z', + 'value': '0.0024687939885141615' + }, + { + 'time': '2017-06-05T00:53:59.508Z', + 'value': '0.002563018571428578' + }, + { + 'time': '2017-06-05T00:54:59.508Z', + 'value': '0.00240563291078959' + } + ] + } + ] + } + ] + }, + { + 'title': 'Memory usage', + 'weight': 1, + 'y_label': 'Values', + 'queries': [ + { + 'query_range': 'avg(container_memory_usage_bytes{%{environment_filter}}) / 2^20', + 'label': 'Container memory', + 'unit': 'MiB', + 'result': [ + { + 'metric': { + + }, + 'values': [ + { + 'time': '2017-06-04T21:22:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:23:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:24:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:25:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:26:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:27:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:28:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:29:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:30:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:31:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:32:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:33:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:34:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:35:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:36:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:37:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:38:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:39:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:40:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:41:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:42:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:43:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:44:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:45:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:46:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:47:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:48:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:49:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:50:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:51:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:52:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:53:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:54:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:55:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:56:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:57:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:58:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T21:59:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:00:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:01:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:02:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:03:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:04:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:05:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:06:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:07:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:08:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:09:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:10:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:11:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:12:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:13:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:14:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:15:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:16:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:17:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:18:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:19:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:20:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:21:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:22:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:23:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:24:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:25:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:26:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:27:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:28:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:29:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:30:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:31:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:32:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:33:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:34:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:35:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:36:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:37:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:38:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:39:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:40:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:41:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:42:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:43:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:44:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:45:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:46:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:47:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:48:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:49:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:50:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:51:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:52:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:53:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:54:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:55:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:56:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:57:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:58:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T22:59:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:00:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:01:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:02:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:03:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:04:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:05:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:06:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:07:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:08:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:09:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:10:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:11:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:12:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:13:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:14:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:15:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:16:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:17:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:18:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:19:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:20:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:21:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:22:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:23:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:24:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:25:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:26:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:27:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:28:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:29:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:30:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:31:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:32:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:33:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:34:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:35:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:36:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:37:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:38:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:39:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:40:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:41:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:42:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:43:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:44:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:45:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:46:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:47:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:48:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:49:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:50:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:51:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:52:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:53:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:54:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:55:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:56:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:57:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:58:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-04T23:59:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:00:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:01:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:02:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:03:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:04:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:05:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:06:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:07:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:08:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:09:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:10:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:11:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:12:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:13:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:14:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:15:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:16:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:17:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:18:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:19:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:20:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:21:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:22:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:23:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:24:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:25:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:26:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:27:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:28:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:29:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:30:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:31:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:32:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:33:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:34:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:35:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:36:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:37:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:38:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:39:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:40:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:41:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:42:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:43:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:44:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:45:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:46:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:47:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:48:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:49:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:50:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:51:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:52:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:53:59.508Z', + 'value': '15.0859375' + }, + { + 'time': '2017-06-05T00:54:59.508Z', + 'value': '15.0859375' + } + ] + } + ] + } + ] + } +]; + +export function MonitorMockInterceptor(request, next) { + const body = responseMockData[request.method.toUpperCase()][request.url]; + + next(request.respondWith(JSON.stringify(body), { + status: 200, + })); +} diff --git a/spec/javascripts/monitoring/monitoring_column_spec.js b/spec/javascripts/monitoring/monitoring_column_spec.js new file mode 100644 index 00000000000..c8787f9708c --- /dev/null +++ b/spec/javascripts/monitoring/monitoring_column_spec.js @@ -0,0 +1,97 @@ +import Vue from 'vue'; +import _ from 'underscore'; +import MonitoringColumn from '~/monitoring/components/monitoring_column.vue'; +import MonitoringMixins from '~/monitoring/mixins/monitoring_mixins'; +import eventHub from '~/monitoring/event_hub'; +import { deploymentData, singleRowMetrics } from './mock_data'; + +const createComponent = (propsData) => { + const Component = Vue.extend(MonitoringColumn); + + return new Component({ + propsData, + }).$mount(); +}; + +describe('MonitoringColumn', () => { + beforeEach(() => { + spyOn(MonitoringMixins.methods, 'formatDeployments').and.callFake(function fakeFormat() { + return {}; + }); + }); + + it('has a title', () => { + const component = createComponent({ + columnData: singleRowMetrics[0], + classType: 'col-md-6', + updateAspectRatio: false, + deploymentData, + }); + + expect(component.$el.querySelector('.text-center').innerText.trim()).toBe(component.columnData.title); + }); + + it('creates a path for the line and area of the graph', (done) => { + const component = createComponent({ + columnData: singleRowMetrics[0], + classType: 'col-md-6', + updateAspectRatio: false, + deploymentData, + }); + + Vue.nextTick(() => { + expect(component.area).toBeDefined(); + expect(component.line).toBeDefined(); + expect(typeof component.area).toEqual('string'); + expect(typeof component.line).toEqual('string'); + expect(_.isFunction(component.xScale)).toBe(true); + expect(_.isFunction(component.yScale)).toBe(true); + done(); + }); + }); + + describe('Computed props', () => { + it('axisTransform translates an element Y position depending of its height', () => { + const component = createComponent({ + columnData: singleRowMetrics[0], + classType: 'col-md-6', + updateAspectRatio: false, + deploymentData, + }); + + const transformedHeight = `${component.graphHeight - 100}`; + expect(component.axisTransform.indexOf(transformedHeight)) + .not.toEqual(-1); + }); + + it('outterViewBox gets a width and height property based on the DOM size of the element', () => { + const component = createComponent({ + columnData: singleRowMetrics[0], + classType: 'col-md-6', + updateAspectRatio: false, + deploymentData, + }); + + const viewBoxArray = component.outterViewBox.split(' '); + expect(typeof component.outterViewBox).toEqual('string'); + expect(viewBoxArray[2]).toEqual(component.graphWidth.toString()); + expect(viewBoxArray[3]).toEqual(component.graphHeight.toString()); + }); + }); + + it('sends an event to the eventhub when it has finished resizing', (done) => { + const component = createComponent({ + columnData: singleRowMetrics[0], + classType: 'col-md-6', + updateAspectRatio: false, + deploymentData, + }); + spyOn(eventHub, '$emit'); + + component.updateAspectRatio = true; + Vue.nextTick(() => { + expect(eventHub.$emit).toHaveBeenCalled(); + done(); + }); + }); +}); diff --git a/spec/javascripts/monitoring/monitoring_deployment_spec.js b/spec/javascripts/monitoring/monitoring_deployment_spec.js new file mode 100644 index 00000000000..5cc5b514824 --- /dev/null +++ b/spec/javascripts/monitoring/monitoring_deployment_spec.js @@ -0,0 +1,137 @@ +import Vue from 'vue'; +import MonitoringState from '~/monitoring/components/monitoring_deployment.vue'; +import { deploymentData } from './mock_data'; + +const createComponent = (propsData) => { + const Component = Vue.extend(MonitoringState); + + return new Component({ + propsData, + }).$mount(); +}; + +describe('MonitoringDeployment', () => { + const reducedDeploymentData = [deploymentData[0]]; + reducedDeploymentData[0].ref = reducedDeploymentData[0].ref.name; + reducedDeploymentData[0].xPos = 10; + reducedDeploymentData[0].time = new Date(reducedDeploymentData[0].created_at); + describe('Methods', () => { + it('refText shows the ref when a tag is available', () => { + reducedDeploymentData[0].tag = '1.0'; + const component = createComponent({ + showDeployInfo: false, + deploymentData: reducedDeploymentData, + graphHeight: 300, + graphHeightOffset: 120, + }); + + expect( + component.refText(reducedDeploymentData[0]), + ).toEqual(reducedDeploymentData[0].ref); + }); + + it('refText shows the sha when no tag is available', () => { + reducedDeploymentData[0].tag = null; + const component = createComponent({ + showDeployInfo: false, + deploymentData: reducedDeploymentData, + graphHeight: 300, + graphHeightOffset: 120, + }); + + expect( + component.refText(reducedDeploymentData[0]), + ).toContain('f5bcd1'); + }); + + it('nameDeploymentClass creates a class with the prefix deploy-info-', () => { + const component = createComponent({ + showDeployInfo: false, + deploymentData: reducedDeploymentData, + graphHeight: 300, + graphHeightOffset: 120, + }); + + expect( + component.nameDeploymentClass(reducedDeploymentData[0]), + ).toContain('deploy-info'); + }); + + it('transformDeploymentGroup translates an available deployment', () => { + const component = createComponent({ + showDeployInfo: false, + deploymentData: reducedDeploymentData, + graphHeight: 300, + graphHeightOffset: 120, + }); + + expect( + component.transformDeploymentGroup(reducedDeploymentData[0]), + ).toContain('translate(11, 20)'); + }); + + it('hides the deployment flag', () => { + reducedDeploymentData[0].showDeploymentFlag = false; + const component = createComponent({ + showDeployInfo: true, + deploymentData: reducedDeploymentData, + graphHeight: 300, + graphHeightOffset: 120, + }); + + expect(component.$el.querySelector('.js-deploy-info-box')).toBeNull(); + }); + + it('shows the deployment flag', () => { + reducedDeploymentData[0].showDeploymentFlag = true; + const component = createComponent({ + showDeployInfo: true, + deploymentData: reducedDeploymentData, + graphHeight: 300, + graphHeightOffset: 120, + }); + + expect( + component.$el.querySelector('.js-deploy-info-box').style.display, + ).not.toEqual('display: none;'); + }); + + it('shows the refText inside a text element with the deploy-info-text class', () => { + reducedDeploymentData[0].showDeploymentFlag = true; + const component = createComponent({ + showDeployInfo: true, + deploymentData: reducedDeploymentData, + graphHeight: 300, + graphHeightOffset: 120, + }); + + expect( + component.$el.querySelector('.deploy-info-text').firstChild.nodeValue.trim(), + ).toEqual(component.refText(reducedDeploymentData[0])); + }); + + it('should contain a hidden gradient', () => { + const component = createComponent({ + showDeployInfo: true, + deploymentData: reducedDeploymentData, + graphHeight: 300, + graphHeightOffset: 120, + }); + + expect(component.$el.querySelector('#shadow-gradient')).not.toBeNull(); + }); + + describe('Computed props', () => { + it('calculatedHeight', () => { + const component = createComponent({ + showDeployInfo: true, + deploymentData: reducedDeploymentData, + graphHeight: 300, + graphHeightOffset: 120, + }); + + expect(component.calculatedHeight).toEqual(180); + }); + }); + }); +}); diff --git a/spec/javascripts/monitoring/monitoring_flag_spec.js b/spec/javascripts/monitoring/monitoring_flag_spec.js new file mode 100644 index 00000000000..3861a95ff07 --- /dev/null +++ b/spec/javascripts/monitoring/monitoring_flag_spec.js @@ -0,0 +1,76 @@ +import Vue from 'vue'; +import MonitoringFlag from '~/monitoring/components/monitoring_flag.vue'; + +const createComponent = (propsData) => { + const Component = Vue.extend(MonitoringFlag); + + return new Component({ + propsData, + }).$mount(); +}; + +function getCoordinate(component, selector, coordinate) { + const coordinateVal = component.$el.querySelector(selector).getAttribute(coordinate); + return parseInt(coordinateVal, 10); +} + +describe('MonitoringFlag', () => { + it('has a line and a circle located at the currentXCoordinate and currentYCoordinate', () => { + const component = createComponent({ + currentXCoordinate: 200, + currentYCoordinate: 100, + currentFlagPosition: 100, + currentData: { + time: new Date('2017-06-04T18:17:33.501Z'), + value: '1.49609375', + }, + graphHeight: 300, + graphHeightOffset: 120, + }); + + expect(getCoordinate(component, '.selected-metric-line', 'x1')) + .toEqual(component.currentXCoordinate); + expect(getCoordinate(component, '.selected-metric-line', 'x2')) + .toEqual(component.currentXCoordinate); + expect(getCoordinate(component, '.circle-metric', 'cx')) + .toEqual(component.currentXCoordinate); + expect(getCoordinate(component, '.circle-metric', 'cy')) + .toEqual(component.currentYCoordinate); + }); + + it('has a SVG with the class rect-text-metric at the currentFlagPosition', () => { + const component = createComponent({ + currentXCoordinate: 200, + currentYCoordinate: 100, + currentFlagPosition: 100, + currentData: { + time: new Date('2017-06-04T18:17:33.501Z'), + value: '1.49609375', + }, + graphHeight: 300, + graphHeightOffset: 120, + }); + + const svg = component.$el.querySelector('.rect-text-metric'); + expect(svg.tagName).toEqual('svg'); + expect(parseInt(svg.getAttribute('x'), 10)).toEqual(component.currentFlagPosition); + }); + + describe('Computed props', () => { + it('calculatedHeight', () => { + const component = createComponent({ + currentXCoordinate: 200, + currentYCoordinate: 100, + currentFlagPosition: 100, + currentData: { + time: new Date('2017-06-04T18:17:33.501Z'), + value: '1.49609375', + }, + graphHeight: 300, + graphHeightOffset: 120, + }); + + expect(component.calculatedHeight).toEqual(180); + }); + }); +}); diff --git a/spec/javascripts/monitoring/monitoring_legends_spec.js b/spec/javascripts/monitoring/monitoring_legends_spec.js new file mode 100644 index 00000000000..4c69b81e650 --- /dev/null +++ b/spec/javascripts/monitoring/monitoring_legends_spec.js @@ -0,0 +1,111 @@ +import Vue from 'vue'; +import MonitoringLegends from '~/monitoring/components/monitoring_legends.vue'; +import measurements from '~/monitoring/utils/measurements'; + +const createComponent = (propsData) => { + const Component = Vue.extend(MonitoringLegends); + + return new Component({ + propsData, + }).$mount(); +}; + +function getTextFromNode(component, selector) { + return component.$el.querySelector(selector).firstChild.nodeValue.trim(); +} + +describe('MonitoringLegends', () => { + describe('Computed props', () => { + it('textTransform', () => { + const component = createComponent({ + graphWidth: 500, + graphHeight: 300, + margin: measurements.large.margin, + measurements: measurements.large, + areaColorRgb: '#f0f0f0', + legendTitle: 'Title', + yAxisLabel: 'Values', + metricUsage: 'Value', + }); + + expect(component.textTransform).toContain('translate(15, 120) rotate(-90)'); + }); + + it('xPosition', () => { + const component = createComponent({ + graphWidth: 500, + graphHeight: 300, + margin: measurements.large.margin, + measurements: measurements.large, + areaColorRgb: '#f0f0f0', + legendTitle: 'Title', + yAxisLabel: 'Values', + metricUsage: 'Value', + }); + + expect(component.xPosition).toEqual(180); + }); + + it('yPosition', () => { + const component = createComponent({ + graphWidth: 500, + graphHeight: 300, + margin: measurements.large.margin, + measurements: measurements.large, + areaColorRgb: '#f0f0f0', + legendTitle: 'Title', + yAxisLabel: 'Values', + metricUsage: 'Value', + }); + + expect(component.yPosition).toEqual(240); + }); + + it('rectTransform', () => { + const component = createComponent({ + graphWidth: 500, + graphHeight: 300, + margin: measurements.large.margin, + measurements: measurements.large, + areaColorRgb: '#f0f0f0', + legendTitle: 'Title', + yAxisLabel: 'Values', + metricUsage: 'Value', + }); + + expect(component.rectTransform).toContain('translate(0, 120) rotate(-90)'); + }); + }); + + it('has 2 rect-axis-text rect svg elements', () => { + const component = createComponent({ + graphWidth: 500, + graphHeight: 300, + margin: measurements.large.margin, + measurements: measurements.large, + areaColorRgb: '#f0f0f0', + legendTitle: 'Title', + yAxisLabel: 'Values', + metricUsage: 'Value', + }); + + expect(component.$el.querySelectorAll('.rect-axis-text').length).toEqual(2); + }); + + it('contains text to signal the usage, title and time', () => { + const component = createComponent({ + graphWidth: 500, + graphHeight: 300, + margin: measurements.large.margin, + measurements: measurements.large, + areaColorRgb: '#f0f0f0', + legendTitle: 'Title', + yAxisLabel: 'Values', + metricUsage: 'Value', + }); + + expect(getTextFromNode(component, '.text-metric-title')).toEqual(component.legendTitle); + expect(getTextFromNode(component, '.text-metric-usage')).toEqual(component.metricUsage); + expect(getTextFromNode(component, '.label-axis-text')).toEqual(component.yAxisLabel); + }); +}); diff --git a/spec/javascripts/monitoring/monitoring_row_spec.js b/spec/javascripts/monitoring/monitoring_row_spec.js new file mode 100644 index 00000000000..a82480e8342 --- /dev/null +++ b/spec/javascripts/monitoring/monitoring_row_spec.js @@ -0,0 +1,57 @@ +import Vue from 'vue'; +import MonitoringRow from '~/monitoring/components/monitoring_row.vue'; +import { deploymentData, singleRowMetrics } from './mock_data'; + +const createComponent = (propsData) => { + const Component = Vue.extend(MonitoringRow); + + return new Component({ + propsData, + }).$mount(); +}; + +describe('MonitoringRow', () => { + describe('Computed props', () => { + it('bootstrapClass is set to col-md-6 when rowData is higher/equal to 2', () => { + const component = createComponent({ + rowData: singleRowMetrics, + updateAspectRatio: false, + deploymentData, + }); + + expect(component.bootstrapClass).toEqual('col-md-6'); + }); + + it('bootstrapClass is set to col-md-12 when rowData is lower than 2', () => { + const component = createComponent({ + rowData: [singleRowMetrics[0]], + updateAspectRatio: false, + deploymentData, + }); + + expect(component.bootstrapClass).toEqual('col-md-12'); + }); + }); + + it('has one column', () => { + const component = createComponent({ + rowData: singleRowMetrics, + updateAspectRatio: false, + deploymentData, + }); + + expect(component.$el.querySelectorAll('.prometheus-svg-container').length) + .toEqual(component.rowData.length); + }); + + it('has two columns', () => { + const component = createComponent({ + rowData: singleRowMetrics, + updateAspectRatio: false, + deploymentData, + }); + + expect(component.$el.querySelectorAll('.col-md-6').length) + .toEqual(component.rowData.length); + }); +}); diff --git a/spec/javascripts/monitoring/monitoring_spec.js b/spec/javascripts/monitoring/monitoring_spec.js new file mode 100644 index 00000000000..6c7b691baa4 --- /dev/null +++ b/spec/javascripts/monitoring/monitoring_spec.js @@ -0,0 +1,49 @@ +import Vue from 'vue'; +import Monitoring from '~/monitoring/components/monitoring.vue'; +import { MonitorMockInterceptor } from './mock_data'; + +describe('Monitoring', () => { + const fixtureName = 'environments/metrics/metrics.html.raw'; + let MonitoringComponent; + let component; + preloadFixtures(fixtureName); + + beforeEach(() => { + loadFixtures(fixtureName); + MonitoringComponent = Vue.extend(Monitoring); + }); + + describe('no metrics are available yet', () => { + it('shows a getting started empty state when no metrics are present', () => { + component = new MonitoringComponent({ + el: document.querySelector('#prometheus-graphs'), + }); + + component.$mount(); + expect(component.$el.querySelector('#prometheus-graphs')).toBe(null); + expect(component.state).toEqual('gettingStarted'); + }); + }); + + describe('requests information to the server', () => { + beforeEach(() => { + document.querySelector('#prometheus-graphs').setAttribute('data-has-metrics', 'true'); + Vue.http.interceptors.push(MonitorMockInterceptor); + }); + + afterEach(() => { + Vue.http.interceptors = _.without(Vue.http.interceptors, MonitorMockInterceptor); + }); + + it('shows up a loading state', (done) => { + component = new MonitoringComponent({ + el: document.querySelector('#prometheus-graphs'), + }); + component.$mount(); + Vue.nextTick(() => { + expect(component.state).toEqual('loading'); + done(); + }); + }); + }); +}); diff --git a/spec/javascripts/monitoring/monitoring_state_spec.js b/spec/javascripts/monitoring/monitoring_state_spec.js new file mode 100644 index 00000000000..4c0c558502f --- /dev/null +++ b/spec/javascripts/monitoring/monitoring_state_spec.js @@ -0,0 +1,110 @@ +import Vue from 'vue'; +import MonitoringState from '~/monitoring/components/monitoring_state.vue'; +import { statePaths } from './mock_data'; + +const createComponent = (propsData) => { + const Component = Vue.extend(MonitoringState); + + return new Component({ + propsData, + }).$mount(); +}; + +function getTextFromNode(component, selector) { + return component.$el.querySelector(selector).firstChild.nodeValue.trim(); +} + +describe('MonitoringState', () => { + describe('Computed props', () => { + it('currentState', () => { + const component = createComponent({ + selectedState: 'gettingStarted', + settingsPath: statePaths.settingsPath, + documentationPath: statePaths.documentationPath, + }); + + expect(component.currentState).toBe(component.states.gettingStarted); + }); + + it('buttonPath returns settings path for the state "gettingStarted"', () => { + const component = createComponent({ + selectedState: 'gettingStarted', + settingsPath: statePaths.settingsPath, + documentationPath: statePaths.documentationPath, + }); + + expect(component.buttonPath).toEqual(statePaths.settingsPath); + expect(component.buttonPath).not.toEqual(statePaths.documentationPath); + }); + + it('buttonPath returns documentation path for any of the other states', () => { + const component = createComponent({ + selectedState: 'loading', + settingsPath: statePaths.settingsPath, + documentationPath: statePaths.documentationPath, + }); + + expect(component.buttonPath).toEqual(statePaths.documentationPath); + expect(component.buttonPath).not.toEqual(statePaths.settingsPath); + }); + + it('showButtonDescription returns a description with a link for the unableToConnect state', () => { + const component = createComponent({ + selectedState: 'unableToConnect', + settingsPath: statePaths.settingsPath, + documentationPath: statePaths.documentationPath, + }); + + expect(component.showButtonDescription).toEqual(true); + }); + + it('showButtonDescription returns the description without a link for any other state', () => { + const component = createComponent({ + selectedState: 'loading', + settingsPath: statePaths.settingsPath, + documentationPath: statePaths.documentationPath, + }); + + expect(component.showButtonDescription).toEqual(false); + }); + }); + + it('should show the gettingStarted state', () => { + const component = createComponent({ + selectedState: 'gettingStarted', + settingsPath: statePaths.settingsPath, + documentationPath: statePaths.documentationPath, + }); + + expect(component.$el.querySelector('svg')).toBeDefined(); + expect(getTextFromNode(component, '.state-title')).toEqual(component.states.gettingStarted.title); + expect(getTextFromNode(component, '.state-description')).toEqual(component.states.gettingStarted.description); + expect(getTextFromNode(component, '.btn-success')).toEqual(component.states.gettingStarted.buttonText); + }); + + it('should show the loading state', () => { + const component = createComponent({ + selectedState: 'loading', + settingsPath: statePaths.settingsPath, + documentationPath: statePaths.documentationPath, + }); + + expect(component.$el.querySelector('svg')).toBeDefined(); + expect(getTextFromNode(component, '.state-title')).toEqual(component.states.loading.title); + expect(getTextFromNode(component, '.state-description')).toEqual(component.states.loading.description); + expect(getTextFromNode(component, '.btn-success')).toEqual(component.states.loading.buttonText); + }); + + it('should show the unableToConnect state', () => { + const component = createComponent({ + selectedState: 'unableToConnect', + settingsPath: statePaths.settingsPath, + documentationPath: statePaths.documentationPath, + }); + + expect(component.$el.querySelector('svg')).toBeDefined(); + expect(getTextFromNode(component, '.state-title')).toEqual(component.states.unableToConnect.title); + expect(component.$el.querySelector('.state-description a')).toBeDefined(); + expect(getTextFromNode(component, '.btn-success')).toEqual(component.states.unableToConnect.buttonText); + }); +}); diff --git a/spec/javascripts/monitoring/monitoring_store_spec.js b/spec/javascripts/monitoring/monitoring_store_spec.js new file mode 100644 index 00000000000..20c1e6a0005 --- /dev/null +++ b/spec/javascripts/monitoring/monitoring_store_spec.js @@ -0,0 +1,24 @@ +import MonitoringStore from '~/monitoring/stores/monitoring_store'; +import MonitoringMock, { deploymentData } from './mock_data'; + +describe('MonitoringStore', () => { + this.store = new MonitoringStore(); + this.store.storeMetrics(MonitoringMock.data); + + it('contains one group that contains two queries sorted by priority in one row', () => { + expect(this.store.groups).toBeDefined(); + expect(this.store.groups.length).toEqual(1); + expect(this.store.groups[0].metrics.length).toEqual(1); + }); + + it('gets the metrics count for every group', () => { + expect(this.store.getMetricsCount()).toEqual(2); + }); + + it('contains deployment data', () => { + this.store.storeDeploymentData(deploymentData); + expect(this.store.deploymentData).toBeDefined(); + expect(this.store.deploymentData.length).toEqual(3); + expect(typeof this.store.deploymentData[0]).toEqual('object'); + }); +}); diff --git a/spec/javascripts/monitoring/prometheus_graph_spec.js b/spec/javascripts/monitoring/prometheus_graph_spec.js deleted file mode 100644 index 25578bf1c6e..00000000000 --- a/spec/javascripts/monitoring/prometheus_graph_spec.js +++ /dev/null @@ -1,98 +0,0 @@ -import 'jquery'; -import PrometheusGraph from '~/monitoring/prometheus_graph'; -import { prometheusMockData } from './prometheus_mock_data'; - -describe('PrometheusGraph', () => { - const fixtureName = 'environments/metrics/metrics.html.raw'; - const prometheusGraphContainer = '.prometheus-graph'; - const prometheusGraphContents = `${prometheusGraphContainer}[graph-type=cpu_values]`; - - preloadFixtures(fixtureName); - - beforeEach(() => { - loadFixtures(fixtureName); - $('.prometheus-container').data('has-metrics', 'true'); - this.prometheusGraph = new PrometheusGraph(); - const self = this; - const fakeInit = (metricsResponse) => { - self.prometheusGraph.transformData(metricsResponse); - self.prometheusGraph.createGraph(); - }; - spyOn(this.prometheusGraph, 'init').and.callFake(fakeInit); - }); - - it('initializes graph properties', () => { - // Test for the measurements - expect(this.prometheusGraph.margin).toBeDefined(); - expect(this.prometheusGraph.marginLabelContainer).toBeDefined(); - expect(this.prometheusGraph.originalWidth).toBeDefined(); - expect(this.prometheusGraph.originalHeight).toBeDefined(); - expect(this.prometheusGraph.height).toBeDefined(); - expect(this.prometheusGraph.width).toBeDefined(); - expect(this.prometheusGraph.backOffRequestCounter).toBeDefined(); - // Test for the graph properties (colors, radius, etc.) - expect(this.prometheusGraph.graphSpecificProperties).toBeDefined(); - expect(this.prometheusGraph.commonGraphProperties).toBeDefined(); - }); - - it('transforms the data', () => { - this.prometheusGraph.init(prometheusMockData.metrics); - Object.keys(this.prometheusGraph.graphSpecificProperties, (key) => { - const graphProps = this.prometheusGraph.graphSpecificProperties[key]; - expect(graphProps.data).toBeDefined(); - expect(graphProps.data.length).toBe(121); - }); - }); - - it('creates two graphs', () => { - this.prometheusGraph.init(prometheusMockData.metrics); - expect($(prometheusGraphContainer).length).toBe(2); - }); - - describe('Graph contents', () => { - beforeEach(() => { - this.prometheusGraph.init(prometheusMockData.metrics); - }); - - it('has axis, an area, a line and a overlay', () => { - const $graphContainer = $(prometheusGraphContents).find('.x-axis').parent(); - expect($graphContainer.find('.x-axis')).toBeDefined(); - expect($graphContainer.find('.y-axis')).toBeDefined(); - expect($graphContainer.find('.prometheus-graph-overlay')).toBeDefined(); - expect($graphContainer.find('.metric-line')).toBeDefined(); - expect($graphContainer.find('.metric-area')).toBeDefined(); - }); - - it('has legends, labels and an extra axis that labels the metrics', () => { - const $prometheusGraphContents = $(prometheusGraphContents); - const $axisLabelContainer = $(prometheusGraphContents).find('.label-x-axis-line').parent(); - expect($prometheusGraphContents.find('.label-x-axis-line')).toBeDefined(); - expect($prometheusGraphContents.find('.label-y-axis-line')).toBeDefined(); - expect($prometheusGraphContents.find('.label-axis-text')).toBeDefined(); - expect($prometheusGraphContents.find('.rect-axis-text')).toBeDefined(); - expect($axisLabelContainer.find('rect').length).toBe(3); - expect($axisLabelContainer.find('text').length).toBe(4); - }); - }); -}); - -describe('PrometheusGraphs UX states', () => { - const fixtureName = 'environments/metrics/metrics.html.raw'; - preloadFixtures(fixtureName); - - beforeEach(() => { - loadFixtures(fixtureName); - this.prometheusGraph = new PrometheusGraph(); - }); - - it('shows a specified state', () => { - this.prometheusGraph.state = '.js-getting-started'; - this.prometheusGraph.updateState(); - const $state = $('.js-getting-started'); - expect($state).toBeDefined(); - expect($('.state-title', $state)).toBeDefined(); - expect($('.state-svg', $state)).toBeDefined(); - expect($('.state-description', $state)).toBeDefined(); - expect($('.state-button', $state)).toBeDefined(); - }); -}); diff --git a/spec/javascripts/monitoring/prometheus_mock_data.js b/spec/javascripts/monitoring/prometheus_mock_data.js deleted file mode 100644 index 1cdc14faaa8..00000000000 --- a/spec/javascripts/monitoring/prometheus_mock_data.js +++ /dev/null @@ -1,1014 +0,0 @@ -/* eslint-disable import/prefer-default-export*/ -export const prometheusMockData = { - status: 200, - metrics: { - success: true, - metrics: { - memory_values: [ - { - metric: { - }, - values: [ - [ - 1488462917.256, - '10.12890625', - ], - [ - 1488462977.256, - '10.140625', - ], - [ - 1488463037.256, - '10.140625', - ], - [ - 1488463097.256, - '10.14453125', - ], - [ - 1488463157.256, - '10.1484375', - ], - [ - 1488463217.256, - '10.15625', - ], - [ - 1488463277.256, - '10.15625', - ], - [ - 1488463337.256, - '10.15625', - ], - [ - 1488463397.256, - '10.1640625', - ], - [ - 1488463457.256, - '10.171875', - ], - [ - 1488463517.256, - '10.171875', - ], - [ - 1488463577.256, - '10.171875', - ], - [ - 1488463637.256, - '10.18359375', - ], - [ - 1488463697.256, - '10.1953125', - ], - [ - 1488463757.256, - '10.203125', - ], - [ - 1488463817.256, - '10.20703125', - ], - [ - 1488463877.256, - '10.20703125', - ], - [ - 1488463937.256, - '10.20703125', - ], - [ - 1488463997.256, - '10.20703125', - ], - [ - 1488464057.256, - '10.2109375', - ], - [ - 1488464117.256, - '10.2109375', - ], - [ - 1488464177.256, - '10.2109375', - ], - [ - 1488464237.256, - '10.2109375', - ], - [ - 1488464297.256, - '10.21484375', - ], - [ - 1488464357.256, - '10.22265625', - ], - [ - 1488464417.256, - '10.22265625', - ], - [ - 1488464477.256, - '10.2265625', - ], - [ - 1488464537.256, - '10.23046875', - ], - [ - 1488464597.256, - '10.23046875', - ], - [ - 1488464657.256, - '10.234375', - ], - [ - 1488464717.256, - '10.234375', - ], - [ - 1488464777.256, - '10.234375', - ], - [ - 1488464837.256, - '10.234375', - ], - [ - 1488464897.256, - '10.234375', - ], - [ - 1488464957.256, - '10.234375', - ], - [ - 1488465017.256, - '10.23828125', - ], - [ - 1488465077.256, - '10.23828125', - ], - [ - 1488465137.256, - '10.2421875', - ], - [ - 1488465197.256, - '10.2421875', - ], - [ - 1488465257.256, - '10.2421875', - ], - [ - 1488465317.256, - '10.2421875', - ], - [ - 1488465377.256, - '10.2421875', - ], - [ - 1488465437.256, - '10.2421875', - ], - [ - 1488465497.256, - '10.2421875', - ], - [ - 1488465557.256, - '10.2421875', - ], - [ - 1488465617.256, - '10.2421875', - ], - [ - 1488465677.256, - '10.2421875', - ], - [ - 1488465737.256, - '10.2421875', - ], - [ - 1488465797.256, - '10.24609375', - ], - [ - 1488465857.256, - '10.25', - ], - [ - 1488465917.256, - '10.25390625', - ], - [ - 1488465977.256, - '9.98828125', - ], - [ - 1488466037.256, - '9.9921875', - ], - [ - 1488466097.256, - '9.9921875', - ], - [ - 1488466157.256, - '9.99609375', - ], - [ - 1488466217.256, - '10', - ], - [ - 1488466277.256, - '10.00390625', - ], - [ - 1488466337.256, - '10.0078125', - ], - [ - 1488466397.256, - '10.01171875', - ], - [ - 1488466457.256, - '10.0234375', - ], - [ - 1488466517.256, - '10.02734375', - ], - [ - 1488466577.256, - '10.02734375', - ], - [ - 1488466637.256, - '10.03125', - ], - [ - 1488466697.256, - '10.03125', - ], - [ - 1488466757.256, - '10.03125', - ], - [ - 1488466817.256, - '10.03125', - ], - [ - 1488466877.256, - '10.03125', - ], - [ - 1488466937.256, - '10.03125', - ], - [ - 1488466997.256, - '10.03125', - ], - [ - 1488467057.256, - '10.0390625', - ], - [ - 1488467117.256, - '10.0390625', - ], - [ - 1488467177.256, - '10.04296875', - ], - [ - 1488467237.256, - '10.05078125', - ], - [ - 1488467297.256, - '10.05859375', - ], - [ - 1488467357.256, - '10.06640625', - ], - [ - 1488467417.256, - '10.06640625', - ], - [ - 1488467477.256, - '10.0703125', - ], - [ - 1488467537.256, - '10.07421875', - ], - [ - 1488467597.256, - '10.0859375', - ], - [ - 1488467657.256, - '10.0859375', - ], - [ - 1488467717.256, - '10.09765625', - ], - [ - 1488467777.256, - '10.1015625', - ], - [ - 1488467837.256, - '10.10546875', - ], - [ - 1488467897.256, - '10.10546875', - ], - [ - 1488467957.256, - '10.125', - ], - [ - 1488468017.256, - '10.13671875', - ], - [ - 1488468077.256, - '10.1484375', - ], - [ - 1488468137.256, - '10.15625', - ], - [ - 1488468197.256, - '10.16796875', - ], - [ - 1488468257.256, - '10.171875', - ], - [ - 1488468317.256, - '10.171875', - ], - [ - 1488468377.256, - '10.171875', - ], - [ - 1488468437.256, - '10.171875', - ], - [ - 1488468497.256, - '10.171875', - ], - [ - 1488468557.256, - '10.171875', - ], - [ - 1488468617.256, - '10.171875', - ], - [ - 1488468677.256, - '10.17578125', - ], - [ - 1488468737.256, - '10.17578125', - ], - [ - 1488468797.256, - '10.265625', - ], - [ - 1488468857.256, - '10.19921875', - ], - [ - 1488468917.256, - '10.19921875', - ], - [ - 1488468977.256, - '10.19921875', - ], - [ - 1488469037.256, - '10.19921875', - ], - [ - 1488469097.256, - '10.19921875', - ], - [ - 1488469157.256, - '10.203125', - ], - [ - 1488469217.256, - '10.43359375', - ], - [ - 1488469277.256, - '10.20703125', - ], - [ - 1488469337.256, - '10.2109375', - ], - [ - 1488469397.256, - '10.22265625', - ], - [ - 1488469457.256, - '10.21484375', - ], - [ - 1488469517.256, - '10.21484375', - ], - [ - 1488469577.256, - '10.21484375', - ], - [ - 1488469637.256, - '10.22265625', - ], - [ - 1488469697.256, - '10.234375', - ], - [ - 1488469757.256, - '10.234375', - ], - [ - 1488469817.256, - '10.234375', - ], - [ - 1488469877.256, - '10.2421875', - ], - [ - 1488469937.256, - '10.25', - ], - [ - 1488469997.256, - '10.25390625', - ], - [ - 1488470057.256, - '10.26171875', - ], - [ - 1488470117.256, - '10.2734375', - ], - ], - }, - ], - memory_current: [ - { - metric: { - }, - value: [ - 1488470117.737, - '10.2734375', - ], - }, - ], - cpu_values: [ - { - metric: { - }, - values: [ - [ - 1488462918.15, - '0.0002996458625058103', - ], - [ - 1488462978.15, - '0.0002652382333333314', - ], - [ - 1488463038.15, - '0.0003485461333333421', - ], - [ - 1488463098.15, - '0.0003420421999999886', - ], - [ - 1488463158.15, - '0.00023107150000001297', - ], - [ - 1488463218.15, - '0.00030463981666664826', - ], - [ - 1488463278.15, - '0.0002477177833333677', - ], - [ - 1488463338.15, - '0.00026936656666665115', - ], - [ - 1488463398.15, - '0.000406264750000022', - ], - [ - 1488463458.15, - '0.00029592802026561453', - ], - [ - 1488463518.15, - '0.00023426999683316343', - ], - [ - 1488463578.15, - '0.0003057080666666915', - ], - [ - 1488463638.15, - '0.0003408470500000149', - ], - [ - 1488463698.15, - '0.00025497336666665166', - ], - [ - 1488463758.15, - '0.0003009282833333534', - ], - [ - 1488463818.15, - '0.0003119383499999924', - ], - [ - 1488463878.15, - '0.00028719019999998705', - ], - [ - 1488463938.15, - '0.000327864749999988', - ], - [ - 1488463998.15, - '0.0002514917333333422', - ], - [ - 1488464058.15, - '0.0003614651166666742', - ], - [ - 1488464118.15, - '0.0003221668000000122', - ], - [ - 1488464178.15, - '0.00023323083333330884', - ], - [ - 1488464238.15, - '0.00028531499475009274', - ], - [ - 1488464298.15, - '0.0002627695294921391', - ], - [ - 1488464358.15, - '0.00027145463333333453', - ], - [ - 1488464418.15, - '0.00025669488333335266', - ], - [ - 1488464478.15, - '0.00022307761666665965', - ], - [ - 1488464538.15, - '0.0003307265833333517', - ], - [ - 1488464598.15, - '0.0002817050666666709', - ], - [ - 1488464658.15, - '0.00022357458333332285', - ], - [ - 1488464718.15, - '0.00032648590000000275', - ], - [ - 1488464778.15, - '0.00028410750000000816', - ], - [ - 1488464838.15, - '0.0003038076999999954', - ], - [ - 1488464898.15, - '0.00037568226666667335', - ], - [ - 1488464958.15, - '0.00020160354999999202', - ], - [ - 1488465018.15, - '0.0003229403333333399', - ], - [ - 1488465078.15, - '0.00033516069999999236', - ], - [ - 1488465138.15, - '0.0003365978333333371', - ], - [ - 1488465198.15, - '0.00020262178333331585', - ], - [ - 1488465258.15, - '0.00040567498333331876', - ], - [ - 1488465318.15, - '0.00029114155000001436', - ], - [ - 1488465378.15, - '0.0002498841000000122', - ], - [ - 1488465438.15, - '0.00027296763333331715', - ], - [ - 1488465498.15, - '0.0002958794000000135', - ], - [ - 1488465558.15, - '0.0002922354666666867', - ], - [ - 1488465618.15, - '0.00034186624999999653', - ], - [ - 1488465678.15, - '0.0003397984166666627', - ], - [ - 1488465738.15, - '0.0002658284166666469', - ], - [ - 1488465798.15, - '0.00026221139999999346', - ], - [ - 1488465858.15, - '0.00029467960000001034', - ], - [ - 1488465918.15, - '0.0002634141333333358', - ], - [ - 1488465978.15, - '0.0003202958333333209', - ], - [ - 1488466038.15, - '0.00037890760000000394', - ], - [ - 1488466098.15, - '0.00023453356666666518', - ], - [ - 1488466158.15, - '0.0002866827333333433', - ], - [ - 1488466218.15, - '0.0003335935499999998', - ], - [ - 1488466278.15, - '0.00022787131666666125', - ], - [ - 1488466338.15, - '0.00033821938333333064', - ], - [ - 1488466398.15, - '0.00029233375000001043', - ], - [ - 1488466458.15, - '0.00026562758333333514', - ], - [ - 1488466518.15, - '0.0003142600999999819', - ], - [ - 1488466578.15, - '0.00027392178333333444', - ], - [ - 1488466638.15, - '0.00028178598333334173', - ], - [ - 1488466698.15, - '0.0002463400666666911', - ], - [ - 1488466758.15, - '0.00040234373333332125', - ], - [ - 1488466818.15, - '0.00023677453333332822', - ], - [ - 1488466878.15, - '0.00030852703333333523', - ], - [ - 1488466938.15, - '0.0003582272833333455', - ], - [ - 1488466998.15, - '0.0002176380833332973', - ], - [ - 1488467058.15, - '0.00026180203333335447', - ], - [ - 1488467118.15, - '0.00027862966666667436', - ], - [ - 1488467178.15, - '0.0002769731166666567', - ], - [ - 1488467238.15, - '0.0002832899166666477', - ], - [ - 1488467298.15, - '0.0003446533500000311', - ], - [ - 1488467358.15, - '0.0002691345999999761', - ], - [ - 1488467418.15, - '0.000284919933333357', - ], - [ - 1488467478.15, - '0.0002396026166666528', - ], - [ - 1488467538.15, - '0.00035625295000002075', - ], - [ - 1488467598.15, - '0.00036759816666664946', - ], - [ - 1488467658.15, - '0.00030326608333333855', - ], - [ - 1488467718.15, - '0.00023584972418043393', - ], - [ - 1488467778.15, - '0.00025744508892115107', - ], - [ - 1488467838.15, - '0.00036737541666663395', - ], - [ - 1488467898.15, - '0.00034325741666666094', - ], - [ - 1488467958.15, - '0.00026390046666667407', - ], - [ - 1488468018.15, - '0.0003302534500000102', - ], - [ - 1488468078.15, - '0.00035243794999999527', - ], - [ - 1488468138.15, - '0.00020149738333333407', - ], - [ - 1488468198.15, - '0.0003183469666666679', - ], - [ - 1488468258.15, - '0.0003835329166666845', - ], - [ - 1488468318.15, - '0.0002485075333333124', - ], - [ - 1488468378.15, - '0.0003011457166666768', - ], - [ - 1488468438.15, - '0.00032242785497684965', - ], - [ - 1488468498.15, - '0.0002659713747457531', - ], - [ - 1488468558.15, - '0.0003476860333333202', - ], - [ - 1488468618.15, - '0.00028336403333334794', - ], - [ - 1488468678.15, - '0.00017132354999998728', - ], - [ - 1488468738.15, - '0.0003001915833333276', - ], - [ - 1488468798.15, - '0.0003025715666666725', - ], - [ - 1488468858.15, - '0.0003012370166666815', - ], - [ - 1488468918.15, - '0.00030203619999997025', - ], - [ - 1488468978.15, - '0.0002804355000000314', - ], - [ - 1488469038.15, - '0.00033194884999998564', - ], - [ - 1488469098.15, - '0.00025201496666665455', - ], - [ - 1488469158.15, - '0.0002777531500000189', - ], - [ - 1488469218.15, - '0.0003314885833333392', - ], - [ - 1488469278.15, - '0.0002234891422095589', - ], - [ - 1488469338.15, - '0.000349117355867791', - ], - [ - 1488469398.15, - '0.0004036731333333303', - ], - [ - 1488469458.15, - '0.00024553911666667835', - ], - [ - 1488469518.15, - '0.0003056456833333184', - ], - [ - 1488469578.15, - '0.0002618737166666681', - ], - [ - 1488469638.15, - '0.00022972643333331414', - ], - [ - 1488469698.15, - '0.0003713522500000307', - ], - [ - 1488469758.15, - '0.00018322576666666515', - ], - [ - 1488469818.15, - '0.00034534762753952466', - ], - [ - 1488469878.15, - '0.00028200510008501677', - ], - [ - 1488469938.15, - '0.0002773708499999768', - ], - [ - 1488469998.15, - '0.00027547160000001013', - ], - [ - 1488470058.15, - '0.00031713610000000023', - ], - [ - 1488470118.15, - '0.00035276853333332525', - ], - ], - }, - ], - cpu_current: [ - { - metric: { - }, - value: [ - 1488470118.566, - '0.00035276853333332525', - ], - }, - ], - last_update: '2017-03-02T15:55:18.981Z', - }, - }, -}; |