diff --git a/frontend/.eslintrc b/frontend/.eslintrc index a0918716..389bd5c1 100644 --- a/frontend/.eslintrc +++ b/frontend/.eslintrc @@ -49,7 +49,6 @@ "react/prefer-stateless-function": 2, "react/self-closing-comp": 2, "react/sort-comp": 2, - "react/sort-prop-types": 2, "react/style-prop-object": 2, "react/jsx-boolean-value": [2, "never"], "react/jsx-closing-bracket-location": 2, diff --git a/frontend/package.json b/frontend/package.json index 22420783..78e6e0c6 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -31,7 +31,6 @@ "lodash.get": "^4.4.2", "lodash.isempty": "^4.4.0", "lodash.template": "^4.4.0", - "lodash.uniq": "^4.5.0", "moment": "^2.17.1", "param-case": "^2.1.0", "querystring": "^0.2.0", diff --git a/frontend/src/components/instance-item/index.js b/frontend/src/components/instance-item/index.js index 2ed32ae8..477a324b 100644 --- a/frontend/src/components/instance-item/index.js +++ b/frontend/src/components/instance-item/index.js @@ -1,6 +1,6 @@ import React from 'react'; -import MetricsOutlet from '@components/metrics-outlet'; +import ItemMetricGroup from '@components/item-metric-group'; import PropTypes from '@root/prop-types'; import { @@ -20,7 +20,9 @@ const InstanceItem = ({ {instance.name} - + … diff --git a/frontend/src/components/metrics-outlet/index.js b/frontend/src/components/item-metric-group/index.js similarity index 59% rename from frontend/src/components/metrics-outlet/index.js rename to frontend/src/components/item-metric-group/index.js index c997d0b0..d7e8c6cb 100644 --- a/frontend/src/components/metrics-outlet/index.js +++ b/frontend/src/components/item-metric-group/index.js @@ -5,14 +5,7 @@ import Column from '@ui/components/column'; import { ListItemOutlet } from '@ui/components/list'; import PropTypes from '@root/prop-types'; import Row from '@ui/components/row'; - -import { - MetricGraph, - MiniMetricMeta, - MiniMetricTitle, - MiniMetricSubtitle, - MetricView -} from '@ui/components/metric'; +import MetricItem from './item'; const StyledOutlet = styled(ListItemOutlet)` padding-left: 0; @@ -28,19 +21,15 @@ const StyledRow = styled(Row)` } `; -const MetricsOutlet = ({ +const ItemMetricGroup = ({ datasets = [], ...props }) => { const _datasets = datasets.map((metric, i) => ( - - - - Memory: 54% - (1280/3000 MB) - - - + + )); @@ -53,8 +42,8 @@ const MetricsOutlet = ({ ); }; -MetricsOutlet.propTypes = { +ItemMetricGroup.propTypes = { datasets: React.PropTypes.arrayOf(PropTypes.dataset) }; -export default MetricsOutlet; +export default ItemMetricGroup; diff --git a/frontend/src/components/item-metric-group/item.js b/frontend/src/components/item-metric-group/item.js new file mode 100644 index 00000000..6254eb9c --- /dev/null +++ b/frontend/src/components/item-metric-group/item.js @@ -0,0 +1,20 @@ +import React from 'react'; + +import { MetricGraph, MetricView } from '@ui/components/metric'; +import PropTypes from '@root/prop-types'; + +const MetricItem = ({ + uuid, + data +}) => ( + + + +); + +MetricItem.propTypes = { + uuid: React.PropTypes.string, + data: PropTypes.data +}; + +export default MetricItem; diff --git a/frontend/src/components/service/item.js b/frontend/src/components/service/item.js index 3a8beae2..e9029dea 100644 --- a/frontend/src/components/service/item.js +++ b/frontend/src/components/service/item.js @@ -1,6 +1,6 @@ import styled from 'styled-components'; import { Link } from '@ui/components/anchor'; -import MetricsOutlet from '@components/metrics-outlet'; +import ItemMetricGroup from '@components/item-metric-group'; import { Checkbox, FormGroup } from '@ui/components/form'; import PropTypes from '@root/prop-types'; import forceArray from 'force-array'; @@ -101,7 +101,9 @@ const ServiceItem = ({ {isChild && subtitle} {description} - + ); diff --git a/frontend/src/containers/services/index.js b/frontend/src/containers/services/index.js index f2027a40..a145de22 100644 --- a/frontend/src/containers/services/index.js +++ b/frontend/src/containers/services/index.js @@ -21,7 +21,6 @@ const Services = (props) => { push } = props; - // TODO: Move into "components" and fix absolute // positioning on responsive screens const instances = (instances = 0) => { @@ -33,6 +32,7 @@ const Services = (props) => { `; if ( instances.length <= 0 || instances <= 0 ) return; + return ( You have 5 instances @@ -40,13 +40,15 @@ const Services = (props) => { ); }; - const toggleValue = path === '/:org/projects/:projectId/services' ? - 'topology' : 'list'; + const toggleValue = path === '/:org/projects/:projectId/services' + ? 'topology' + : 'list'; const onToggle = (value) => { const path = `/${org.id}/projects/${project.id}/services${ value === 'list' ? '/list' : '' }`; + push(path); }; @@ -56,7 +58,7 @@ const Services = (props) => { toggleValue={toggleValue} services={services} > - { instances() } + {instances()} {children} ); diff --git a/frontend/src/containers/services/list.js b/frontend/src/containers/services/list.js index 98d8925c..510bc1be 100644 --- a/frontend/src/containers/services/list.js +++ b/frontend/src/containers/services/list.js @@ -6,6 +6,7 @@ import ServiceItem from '@components/service/item'; import UnmanagedInstances from '@components/services/unmanaged-instances'; import { toggleTooltip } from '@state/actions'; import ServicesTooltip from '@components/services/tooltip'; +import { subscribeMetric } from '@state/thunks'; import { orgByIdSelector, @@ -18,8 +19,17 @@ const StyledContainer = styled.div` position: relative; `; +// TMP - single source of truth +const duration = '1 hour'; +const interval = '2 minutes'; + class Services extends React.Component { + // we DON'T want to unsubscribe once we started going + componentWillMount() { + this.props.subscribeMetric(interval); + } + ref(name) { this._refs = this._refs || {}; @@ -33,7 +43,7 @@ class Services extends React.Component { org = {}, project = {}, services = [], - toggleTooltip = (() => {}), + toggleTooltip = () => ({}), uiTooltip = {} } = this.props; @@ -87,7 +97,8 @@ Services.propTypes = { project: PropTypes.project, services: React.PropTypes.arrayOf(PropTypes.service), toggleTooltip: React.PropTypes.func, - uiTooltip: React.PropTypes.object + uiTooltip: React.PropTypes.object, + subscribeMetric: React.PropTypes.func }; const mapStateToProps = (state, { @@ -98,12 +109,16 @@ const mapStateToProps = (state, { }) => ({ org: orgByIdSelector(match.params.org)(state), project: projectByIdSelector(match.params.projectId)(state), - services: servicesByProjectIdSelector(match.params.projectId)(state), + services: servicesByProjectIdSelector(match.params.projectId, { + duration, + interval + })(state), uiTooltip: serviceUiTooltipSelector(state) }); const mapDispatchToProps = (dispatch) => ({ - toggleTooltip: (data) => dispatch(toggleTooltip(data)) + toggleTooltip: (data) => dispatch(toggleTooltip(data)), + subscribeMetric: (payload) => dispatch(subscribeMetric(payload)) }); export default connect( diff --git a/frontend/src/datasets.json b/frontend/src/datasets.json new file mode 100644 index 00000000..56e38f77 --- /dev/null +++ b/frontend/src/datasets.json @@ -0,0 +1,1144 @@ +{ + "3e6ee79a-7453-4fc6-b9da-7ae1e41138ec": [ + [1489425668, "1.12"], + [1489425668, "1.03"], + [1489425683, "1.04"], + [1489425683, "1.25"], + [1489425683, "1.1300000000000001"], + [1489425683, "1.35"], + [1489425698, "1.68"], + [1489425698, "1.8800000000000001"], + [1489425698, "1.1700000000000002"], + [1489425698, "1.47"], + [1489425713, "1.66"], + [1489425713, "2.12"], + [1489425713, "1.1900000000000002"], + [1489425713, "2.4699999999999998"], + [1489425728, "2.21"], + [1489425728, "1.2500000000000002"], + [1489425728, "2.7600000000000002"], + [1489425728, "2.7299999999999995"], + [1489425743, "1.2800000000000002"], + [1489425743, "2.9800000000000004"], + [1489425743, "3.26"], + [1489425743, "2.48"], + [1489425758, "3.6399999999999997"], + [1489425758, "1.3000000000000003"], + [1489425758, "2.9200000000000004"], + [1489425758, "3.3300000000000005"], + [1489425773, "4.13"], + [1489425773, "1.3100000000000003"], + [1489425773, "3.0600000000000005"], + [1489425773, "3.5000000000000004"], + [1489425788, "3.7400000000000007"], + [1489425788, "3.3200000000000003"], + [1489425788, "1.3600000000000003"], + [1489425788, "4.4"], + [1489425803, "1.3800000000000003"], + [1489425803, "5.050000000000001"], + [1489425803, "3.8900000000000006"], + [1489425803, "3.43"], + [1489425818, "1.4400000000000004"], + [1489425818, "4.250000000000001"], + [1489425818, "3.71"], + [1489425818, "5.290000000000001"], + [1489425833, "1.4700000000000004"], + [1489425833, "4.390000000000001"], + [1489425833, "3.82"], + [1489425833, "5.860000000000001"], + [1489425848, "6.130000000000001"], + [1489425848, "1.5000000000000004"], + [1489425848, "4.01"], + [1489425848, "4.680000000000001"], + [1489425863, "4.2"], + [1489425863, "4.790000000000001"], + [1489425863, "6.630000000000001"], + [1489425863, "1.5100000000000005"], + [1489425878, "5.040000000000001"], + [1489425878, "1.5200000000000005"], + [1489425878, "6.930000000000001"], + [1489425878, "4.37"], + [1489425893, "4.48"], + [1489425893, "5.250000000000001"], + [1489425893, "1.5400000000000005"], + [1489425893, "7.400000000000001"], + [1489425908, "4.680000000000001"], + [1489425908, "5.520000000000001"], + [1489425908, "1.5500000000000005"], + [1489425908, "7.670000000000002"], + [1489425923, "8.310000000000002"], + [1489425923, "4.8500000000000005"], + [1489425923, "1.5800000000000005"], + [1489425923, "5.700000000000001"], + [1489425938, "5.9300000000000015"], + [1489425938, "5.24"], + [1489425938, "8.540000000000003"], + [1489425938, "1.5900000000000005"], + [1489425953, "6.020000000000001"], + [1489425953, "9.010000000000003"], + [1489425953, "1.6000000000000005"], + [1489425953, "5.34"], + [1489425968, "5.52"], + [1489425968, "6.210000000000001"], + [1489425968, "9.200000000000003"], + [1489425968, "1.6200000000000006"], + [1489425983, "1.6200000000000006"], + [1489425983, "9.200000000000003"], + [1489425983, "5.6"], + [1489425983, "6.320000000000001"], + [1489425998, "1.6400000000000006"], + [1489425998, "5.779999999999999"], + [1489425998, "9.200000000000003"], + [1489425998, "6.490000000000001"], + [1489426013, "5.859999999999999"], + [1489426013, "9.200000000000003"], + [1489426013, "1.6500000000000006"], + [1489426013, "6.600000000000001"], + [1489426028, "6.029999999999999"], + [1489426028, "9.200000000000003"], + [1489426028, "1.6600000000000006"], + [1489426028, "6.870000000000001"], + [1489426043, "1.6700000000000006"], + [1489426043, "6.990000000000001"], + [1489426043, "6.129999999999999"], + [1489426043, "1.4500000000000002"], + [1489426058, "6.339999999999999"], + [1489426058, "7.190000000000001"], + [1489426058, "1.6900000000000006"], + [1489426058, "1.8200000000000003"], + [1489426073, "7.370000000000001"], + [1489426073, "1.7000000000000006"], + [1489426073, "6.429999999999999"], + [1489426073, "2.5300000000000002"], + [1489426088, "2.8400000000000003"], + [1489426088, "1.7200000000000006"], + [1489426088, "6.589999999999999"], + [1489426088, "7.670000000000001"], + [1489426103, "7.790000000000001"], + [1489426103, "6.699999999999999"], + [1489426103, "3.41"], + [1489426103, "1.7300000000000006"], + [1489426118, "6.8999999999999995"], + [1489426118, "1.7500000000000007"], + [1489426118, "3.66"], + [1489426118, "7.99"], + [1489426133, "1.7500000000000007"], + [1489426133, "4.23"], + [1489426133, "7.029999999999999"], + [1489426133, "8.1"], + [1489426148, "8.309999999999999"], + [1489426148, "7.209999999999999"], + [1489426148, "4.460000000000001"], + [1489426148, "1.7600000000000007"], + [1489426163, "1.7700000000000007"], + [1489426163, "8.419999999999998"], + [1489426163, "4.9300000000000015"], + [1489426163, "7.309999999999999"], + [1489426178, "1.7900000000000007"], + [1489426178, "8.629999999999997"], + [1489426178, "7.499999999999999"], + [1489426178, "5.230000000000001"], + [1489426193, "1.8000000000000007"], + [1489426193, "7.579999999999999"], + [1489426193, "5.760000000000002"], + [1489426193, "8.739999999999997"], + [1489426208, "8.939999999999996"], + [1489426208, "1.8100000000000007"], + [1489426208, "6.050000000000002"], + [1489426208, "7.749999999999999"], + [1489426223, "9.099999999999996"], + [1489426223, "1.8200000000000007"], + [1489426223, "7.839999999999999"], + [1489426223, "6.570000000000002"], + [1489426238, "8.04"], + [1489426238, "1.8300000000000007"], + [1489426238, "6.900000000000002"], + [1489426238, "9.269999999999996"], + [1489426253, "9.359999999999996"], + [1489426253, "7.520000000000002"], + [1489426253, "1.8400000000000007"], + [1489426253, "8.129999999999999"], + [1489426268, "8.319999999999999"], + [1489426268, "1.8500000000000008"], + [1489426268, "7.770000000000002"], + [1489426268, "9.559999999999995"], + [1489426283, "8.399999999999999"], + [1489426283, "9.559999999999995"], + [1489426283, "1.8600000000000008"], + [1489426283, "8.440000000000001"], + [1489426298, "9.559999999999995"], + [1489426298, "1.8700000000000008"], + [1489426298, "8.589999999999998"], + [1489426298, "8.650000000000002"], + [1489426313, "9.280000000000001"], + [1489426313, "8.709999999999997"], + [1489426313, "1.8800000000000008"], + [1489426313, "9.559999999999995"], + [1489426328, "9.280000000000001"], + [1489426328, "8.969999999999997"], + [1489426328, "1.9000000000000008"], + [1489426328, "1.06"], + [1489426343, "8.969999999999997"], + [1489426343, "9.280000000000001"], + [1489426343, "1.9100000000000008"], + [1489426343, "1.58"], + [1489426358, "8.969999999999997"], + [1489426358, "9.280000000000001"], + [1489426358, "1.76"], + [1489426358, "1.9200000000000008"], + [1489426373, "2.2"], + [1489426373, "1.1"], + [1489426373, "9.280000000000001"], + [1489426373, "1.9200000000000008"], + [1489426388, "1.33"], + [1489426388, "2.3600000000000003"], + [1489426388, "1.9300000000000008"], + [1489426388, "9.280000000000001"], + [1489426403, "9.280000000000001"], + [1489426403, "1.7200000000000002"], + [1489426403, "2.7200000000000006"], + [1489426403, "1.9300000000000008"], + [1489426418, "2.8600000000000008"], + [1489426418, "1.9700000000000002"], + [1489426418, "1.35"], + [1489426418, "1.9500000000000008"], + [1489426433, "2.22"], + [1489426433, "2.0900000000000003"], + [1489426433, "1.9500000000000008"], + [1489426433, "3.170000000000001"], + [1489426448, "3.460000000000001"], + [1489426448, "2.4000000000000004"], + [1489426448, "1.9700000000000009"], + [1489426448, "2.3400000000000003"], + [1489426463, "3.2"], + [1489426463, "2.5700000000000003"], + [1489426463, "1.9700000000000009"], + [1489426463, "3.750000000000001"], + [1489426478, "2.68"], + [1489426478, "3.920000000000001"], + [1489426478, "1.9800000000000009"], + [1489426478, "3.6300000000000003"], + [1489426493, "4.300000000000001"], + [1489426493, "4.19"], + [1489426493, "2.92"], + [1489426493, "1.9900000000000009"], + [1489426508, "4.460000000000001"], + [1489426508, "3.08"], + [1489426508, "4.470000000000001"], + [1489426508, "2.000000000000001"], + [1489426523, "4.750000000000001"], + [1489426523, "5.180000000000001"], + [1489426523, "3.27"], + [1489426523, "2.0100000000000007"], + [1489426538, "2.0200000000000005"], + [1489426538, "5.000000000000001"], + [1489426538, "5.48"], + [1489426538, "3.41"], + [1489426553, "6.530000000000001"], + [1489426553, "2.0300000000000002"], + [1489426553, "3.7600000000000002"], + [1489426553, "5.410000000000001"], + [1489426568, "5.570000000000001"], + [1489426568, "3.91"], + [1489426568, "2.05"], + [1489426568, "6.840000000000001"], + [1489426583, "4.23"], + [1489426583, "2.0599999999999996"], + [1489426583, "5.920000000000002"], + [1489426583, "7.61"], + [1489426598, "4.390000000000001"], + [1489426598, "2.0799999999999996"], + [1489426598, "6.100000000000001"], + [1489426598, "7.98"], + [1489426613, "4.750000000000001"], + [1489426613, "6.580000000000001"], + [1489426613, "2.0999999999999996"], + [1489426613, "9.18"], + [1489426628, "9.78"], + [1489426628, "6.950000000000001"], + [1489426628, "2.1199999999999997"], + [1489426628, "4.940000000000001"], + [1489426643, "7.380000000000001"], + [1489426643, "2.1399999999999997"], + [1489426643, "5.240000000000002"], + [1489426643, "10.540000000000001"], + [1489426658, "2.1899999999999995"], + [1489426658, "7.660000000000001"], + [1489426658, "11.090000000000002"], + [1489426658, "5.410000000000002"], + [1489426673, "6.020000000000001"], + [1489426673, "12.730000000000002"], + [1489426673, "8.120000000000001"], + [1489426673, "2.1999999999999993"], + [1489426688, "8.450000000000001"], + [1489426688, "6.2200000000000015"], + [1489426688, "13.250000000000002"], + [1489426688, "2.2199999999999993"], + [1489426703, "6.600000000000001"], + [1489426703, "14.490000000000002"], + [1489426703, "2.229999999999999"], + [1489426703, "8.940000000000001"], + [1489426718, "2.2499999999999987"], + [1489426718, "14.490000000000002"], + [1489426718, "6.840000000000002"], + [1489426718, "9.14"], + [1489426733, "7.260000000000002"], + [1489426733, "9.65"], + [1489426733, "14.490000000000002"], + [1489426733, "2.2599999999999985"], + [1489426748, "14.490000000000002"], + [1489426748, "2.2699999999999982"], + [1489426748, "9.870000000000001"], + [1489426748, "7.420000000000002"], + [1489426763, "2.54"], + [1489426763, "2.299999999999998"], + [1489426763, "10.46"], + [1489426763, "8.050000000000002"], + [1489426778, "2.319999999999998"], + [1489426778, "3.27"], + [1489426778, "8.430000000000003"], + [1489426778, "10.680000000000001"], + [1489426793, "11.090000000000002"], + [1489426793, "2.329999999999998"], + [1489426793, "8.880000000000004"], + [1489426793, "4.59"], + [1489426808, "11.330000000000002"], + [1489426808, "2.3699999999999974"], + [1489426808, "9.050000000000004"], + [1489426808, "5.09"], + [1489426823, "6.050000000000001"], + [1489426823, "11.750000000000002"], + [1489426823, "2.3699999999999974"], + [1489426823, "9.340000000000005"], + [1489426838, "6.720000000000001"], + [1489426838, "9.500000000000005"], + [1489426838, "11.990000000000002"], + [1489426838, "2.3899999999999975"], + [1489426853, "2.3999999999999972"], + [1489426853, "12.38"], + [1489426853, "7.760000000000001"], + [1489426853, "9.840000000000005"], + [1489426868, "12.690000000000001"], + [1489426868, "8.3"], + [1489426868, "10.030000000000005"], + [1489426868, "2.4199999999999973"], + [1489426883, "13.690000000000001"], + [1489426883, "10.34"], + [1489426883, "2.6399999999999975"], + [1489426883, "11.020000000000005"], + [1489426898, "2.6499999999999972"], + [1489426898, "11.300000000000004"], + [1489426898, "10.82"], + [1489426898, "13.870000000000001"], + [1489426913, "14.400000000000002"], + [1489426913, "11.61"], + [1489426913, "2.659999999999997"], + [1489426913, "11.570000000000006"], + [1489426928, "12.08"], + [1489426928, "2.679999999999997"], + [1489426928, "14.400000000000002"], + [1489426928, "11.750000000000005"], + [1489426943, "2.689999999999997"], + [1489426943, "14.400000000000002"], + [1489426943, "12.84"], + [1489426943, "12.190000000000005"], + [1489426958, "13.26"], + [1489426958, "2.7199999999999966"], + [1489426958, "12.510000000000005"], + [1489426958, "14.400000000000002"], + [1489426973, "12.970000000000006"], + [1489426973, "14.92"], + [1489426973, "2.7399999999999967"], + [1489426973, "14.400000000000002"], + [1489426988, "2.7799999999999967"], + [1489426988, "14.400000000000002"], + [1489426988, "13.440000000000007"], + [1489426988, "15.74"], + [1489427003, "14.400000000000002"], + [1489427003, "13.960000000000008"], + [1489427003, "17.16"], + [1489427003, "2.7999999999999967"], + [1489427018, "14.140000000000008"], + [1489427018, "2.8099999999999965"], + [1489427018, "14.400000000000002"], + [1489427018, "17.56"], + [1489427033, "14.400000000000002"], + [1489427033, "18.369999999999997"], + [1489427033, "14.140000000000008"], + [1489427033, "2.8199999999999963"], + [1489427048, "14.140000000000008"], + [1489427048, "19.089999999999996"], + [1489427048, "14.400000000000002"], + [1489427048, "2.849999999999996"], + [1489427063, "14.140000000000008"], + [1489427063, "2.859999999999996"], + [1489427063, "19.089999999999996"], + [1489427063, "14.400000000000002"], + [1489427078, "14.400000000000002"], + [1489427078, "14.140000000000008"], + [1489427078, "19.089999999999996"], + [1489427078, "2.8699999999999957"], + [1489427093, "19.089999999999996"], + [1489427093, "14.140000000000008"], + [1489427093, "2.8899999999999957"], + [1489427093, "14.400000000000002"], + [1489427108, "2.9199999999999955"], + [1489427108, "19.089999999999996"], + [1489427108, "14.140000000000008"], + [1489427108, "2.81"], + [1489427123, "3.19"], + [1489427123, "3.73"], + [1489427123, "2.9299999999999953"], + [1489427123, "14.140000000000008"], + [1489427138, "4.61"], + [1489427138, "2.959999999999995"], + [1489427138, "14.140000000000008"], + [1489427138, "3.94"], + [1489427153, "2.999999999999995"], + [1489427153, "5.36"], + [1489427153, "5.11"], + [1489427153, "2.67"], + [1489427168, "5.69"], + [1489427168, "2.9699999999999998"], + [1489427168, "3.009999999999995"], + [1489427168, "5.720000000000001"], + [1489427183, "3.0199999999999947"], + [1489427183, "3.6399999999999997"], + [1489427183, "5.960000000000001"], + [1489427183, "6.37"], + [1489427198, "3.9699999999999998"], + [1489427198, "3.0399999999999947"], + [1489427198, "6.76"], + [1489427198, "6.49"], + [1489427213, "3.0499999999999945"], + [1489427213, "6.91"], + [1489427213, "7.93"], + [1489427213, "4.8"], + [1489427228, "5.1499999999999995"], + [1489427228, "7.58"], + [1489427228, "8.35"], + [1489427228, "3.069999999999994"], + [1489427243, "3.079999999999994"], + [1489427243, "5.609999999999999"], + [1489427243, "8.09"], + [1489427243, "9.629999999999999"], + [1489427258, "5.869999999999999"], + [1489427258, "10.18"], + [1489427258, "8.629999999999999"], + [1489427258, "3.0899999999999936"], + [1489427273, "11.139999999999999"], + [1489427273, "3.1199999999999934"], + [1489427273, "8.85"], + [1489427273, "6.39"], + [1489427288, "3.1499999999999932"], + [1489427288, "6.75"], + [1489427288, "9.719999999999999"], + [1489427288, "11.759999999999998"], + [1489427303, "3.1499999999999932"], + [1489427303, "12.769999999999998"], + [1489427303, "10.079999999999998"], + [1489427303, "7.199999999999999"], + [1489427318, "3.159999999999993"], + [1489427318, "7.43"], + [1489427318, "10.579999999999998"], + [1489427318, "13.249999999999998"], + [1489427333, "3.169999999999993"], + [1489427333, "7.8"], + [1489427333, "10.839999999999998"], + [1489427333, "14.159999999999998"], + [1489427348, "3.1899999999999924"], + [1489427348, "7.96"], + [1489427348, "14.519999999999998"], + [1489427348, "11.239999999999998"], + [1489427363, "8.33"], + [1489427363, "15.329999999999998"], + [1489427363, "11.429999999999998"], + [1489427363, "3.1899999999999924"], + [1489427378, "15.689999999999998"], + [1489427378, "8.51"], + [1489427378, "11.789999999999997"], + [1489427378, "3.209999999999992"], + [1489427393, "11.989999999999997"], + [1489427393, "16.48"], + [1489427393, "8.99"], + [1489427393, "3.2199999999999918"], + [1489427408, "3.2299999999999915"], + [1489427408, "16.87"], + [1489427408, "12.509999999999996"], + [1489427408, "9.25"], + [1489427423, "12.709999999999996"], + [1489427423, "9.639999999999999"], + [1489427423, "3.2399999999999913"], + [1489427423, "16.87"], + [1489427438, "3.249999999999991"], + [1489427438, "16.87"], + [1489427438, "9.77"], + [1489427438, "13.169999999999996"], + [1489427453, "13.339999999999996"], + [1489427453, "3.259999999999991"], + [1489427453, "16.87"], + [1489427453, "10.06"], + [1489427468, "13.889999999999995"], + [1489427468, "10.190000000000001"], + [1489427468, "3.2699999999999907"], + [1489427468, "16.87"], + [1489427483, "10.57"], + [1489427483, "3.2799999999999905"], + [1489427483, "16.87"], + [1489427483, "14.089999999999995"], + [1489427498, "16.87"], + [1489427498, "10.75"], + [1489427498, "14.719999999999994"], + [1489427498, "3.2899999999999903"], + [1489427513, "11.44"], + [1489427513, "15.119999999999994"], + [1489427513, "3.3099999999999903"], + [1489427513, "3.64"], + [1489427528, "15.739999999999995"], + [1489427528, "3.31999999999999"], + [1489427528, "4.38"], + [1489427528, "11.629999999999999"], + [1489427543, "3.32999999999999"], + [1489427543, "12.069999999999999"], + [1489427543, "5.27"], + [1489427543, "15.999999999999995"], + [1489427558, "6.359999999999999"], + [1489427558, "12.28"], + [1489427558, "3.34999999999999"], + [1489427558, "16.489999999999995"], + [1489427573, "3.40999999999999"], + [1489427573, "12.75"], + [1489427573, "7.209999999999999"], + [1489427573, "17.379999999999995"], + [1489427588, "3.42999999999999"], + [1489427588, "13.03"], + [1489427588, "17.879999999999995"], + [1489427588, "7.579999999999999"], + [1489427603, "13.389999999999999"], + [1489427603, "18.079999999999995"], + [1489427603, "8.409999999999998"], + [1489427603, "3.4399999999999897"], + [1489427618, "3.4599999999999898"], + [1489427618, "13.559999999999999"], + [1489427618, "18.639999999999997"], + [1489427618, "8.879999999999999"], + [1489427633, "18.9"], + [1489427633, "14.049999999999999"], + [1489427633, "3.4699999999999895"], + [1489427633, "9.6"], + [1489427648, "10.02"], + [1489427648, "14.29"], + [1489427648, "19.439999999999998"], + [1489427648, "3.5999999999999894"], + [1489427663, "14.7"], + [1489427663, "3.609999999999989"], + [1489427663, "19.759999999999998"], + [1489427663, "11.089999999999998"], + [1489427678, "3.629999999999989"], + [1489427678, "11.539999999999997"], + [1489427678, "14.899999999999999"], + [1489427678, "20.279999999999998"], + [1489427693, "12.509999999999998"], + [1489427693, "3.6399999999999886"], + [1489427693, "15.29"], + [1489427693, "20.54"], + [1489427708, "20.54"], + [1489427708, "12.929999999999998"], + [1489427708, "15.459999999999999"], + [1489427708, "3.6499999999999884"], + [1489427723, "3.659999999999988"], + [1489427723, "20.54"], + [1489427723, "13.799999999999999"], + [1489427723, "15.9"], + [1489427738, "20.54"], + [1489427738, "3.669999999999988"], + [1489427738, "14.229999999999999"], + [1489427738, "16.11"], + [1489427753, "15.11"], + [1489427753, "3.689999999999988"], + [1489427753, "20.54"], + [1489427753, "16.599999999999998"], + [1489427768, "16.749999999999996"], + [1489427768, "15.549999999999999"], + [1489427768, "3.709999999999988"], + [1489427768, "20.54"], + [1489427783, "20.54"], + [1489427783, "16.52"], + [1489427783, "3.729999999999988"], + [1489427783, "17.089999999999996"], + [1489427798, "20.54"], + [1489427798, "16.52"], + [1489427798, "17.089999999999996"], + [1489427798, "3.739999999999988" ] + ], + "4e6ee79a-7453-4fc6-b9da-7ae1e41138ed": [ + [1489425683, "41349120"], + [1489425683, "40300544"], + [1489425683, "40300544"], + [1489425683, "40824832"], + [1489425698, "40300544"], + [1489425698, "27717632"], + [1489425698, "43446272"], + [1489425698, "27717632"], + [1489425713, "62320640"], + [1489425713, "26669056"], + [1489425713, "28766208"], + [1489425713, "28766208"], + [1489425728, "27193344"], + [1489425728, "27193344"], + [1489425728, "27193344"], + [1489425728, "63893504"], + [1489425743, "27717632"], + [1489425743, "27193344"], + [1489425743, "65466368"], + [1489425743, "28241920"], + [1489425758, "68087808"], + [1489425758, "28766208"], + [1489425758, "27193344"], + [1489425758, "28241920"], + [1489425773, "29290496"], + [1489425773, "69660672"], + [1489425773, "28241920"], + [1489425773, "27193344"], + [1489425788, "28766208"], + [1489425788, "29814784"], + [1489425788, "30863360"], + [1489425788, "26669056"], + [1489425803, "26669056"], + [1489425803, "40300544"], + [1489425803, "29290496"], + [1489425803, "30863360"], + [1489425818, "24571904"], + [1489425818, "29814784"], + [1489425818, "31387648"], + [1489425818, "42397696"], + [1489425833, "31911936"], + [1489425833, "25096192"], + [1489425833, "30339072"], + [1489425833, "29814784"], + [1489425848, "32960512"], + [1489425848, "25096192"], + [1489425848, "30863360"], + [1489425848, "39776256"], + [1489425863, "31911936"], + [1489425863, "50786304"], + [1489425863, "25096192"], + [1489425863, "33484800"], + [1489425878, "25096192"], + [1489425878, "32436224"], + [1489425878, "38727680"], + [1489425878, "34009088"], + [1489425893, "45543424"], + [1489425893, "32960512"], + [1489425893, "23523328"], + [1489425893, "25096192"], + [1489425908, "25096192"], + [1489425908, "24047616"], + [1489425908, "34009088"], + [1489425908, "40824832"], + [1489425923, "22999040"], + [1489425923, "49737728"], + [1489425923, "25096192"], + [1489425923, "24571904"], + [1489425938, "25096192"], + [1489425938, "60223488"], + [1489425938, "25096192"], + [1489425938, "22999040"], + [1489425953, "24047616"], + [1489425953, "25620480"], + [1489425953, "58650624"], + [1489425953, "25096192"], + [1489425968, "24571904"], + [1489425968, "75427840"], + [1489425968, "26144768"], + [1489425968, "25096192"], + [1489425983, "75427840"], + [1489425983, "25096192"], + [1489425983, "25096192"], + [1489425983, "26669056"], + [1489425998, "27717632"], + [1489425998, "75427840"], + [1489425998, "25096192"], + [1489425998, "25620480"], + [1489426013, "25096192"], + [1489426013, "26144768"], + [1489426013, "75427840"], + [1489426013, "28241920"], + [1489426028, "28766208"], + [1489426028, "27193344"], + [1489426028, "41873408"], + [1489426028, "25096192"], + [1489426043, "60223488"], + [1489426043, "25096192"], + [1489426043, "27717632"], + [1489426043, "30339072"], + [1489426058, "25620480"], + [1489426058, "30863360"], + [1489426058, "61272064"], + [1489426058, "28241920"], + [1489426073, "25620480"], + [1489426073, "30863360"], + [1489426073, "29290496"], + [1489426073, "28241920"], + [1489426088, "36106240"], + [1489426088, "29814784"], + [1489426088, "23523328"], + [1489426088, "25620480"], + [1489426103, "37679104"], + [1489426103, "23523328"], + [1489426103, "30339072"], + [1489426103, "25620480"], + [1489426118, "30339072"], + [1489426118, "24047616"], + [1489426118, "47116288"], + [1489426118, "25620480"], + [1489426133, "30339072"], + [1489426133, "24571904"], + [1489426133, "22999040"], + [1489426133, "25620480"], + [1489426148, "25620480"], + [1489426148, "25096192"], + [1489426148, "36630528"], + [1489426148, "23523328"], + [1489426163, "28766208"], + [1489426163, "24571904"], + [1489426163, "25620480"], + [1489426163, "25620480"], + [1489426178, "25096192"], + [1489426178, "25620480"], + [1489426178, "26669056"], + [1489426178, "38203392"], + [1489426193, "49213440"], + [1489426193, "27193344"], + [1489426193, "25620480"], + [1489426193, "25620480"], + [1489426208, "27717632"], + [1489426208, "25620480"], + [1489426208, "37154816"], + [1489426208, "26144768"], + [1489426223, "28766208"], + [1489426223, "25620480"], + [1489426223, "27193344"], + [1489426223, "43970560"], + [1489426238, "29290496"], + [1489426238, "53932032"], + [1489426238, "27717632"], + [1489426238, "26144768"], + [1489426253, "28766208"], + [1489426253, "26144768"], + [1489426253, "47116288"], + [1489426253, "29814784"], + [1489426268, "58650624"], + [1489426268, "26144768"], + [1489426268, "30339072"], + [1489426268, "29290496"], + [1489426283, "26144768"], + [1489426283, "30339072"], + [1489426283, "48164864"], + [1489426283, "30339072"], + [1489426298, "26144768"], + [1489426298, "30863360"], + [1489426298, "55504896"], + [1489426298, "30339072"], + [1489426313, "30863360"], + [1489426313, "30339072"], + [1489426313, "26144768"], + [1489426313, "50786304"], + [1489426328, "41873408"], + [1489426328, "26144768"], + [1489426328, "23523328"], + [1489426328, "50786304"], + [1489426343, "50786304"], + [1489426343, "26144768"], + [1489426343, "23523328"], + [1489426343, "26669056"], + [1489426358, "26144768"], + [1489426358, "23523328"], + [1489426358, "50786304"], + [1489426358, "28241920"], + [1489426373, "41349120"], + [1489426373, "29290496"], + [1489426373, "26144768"], + [1489426373, "50786304"], + [1489426388, "24571904"], + [1489426388, "50786304"], + [1489426388, "26144768"], + [1489426388, "29814784"], + [1489426403, "30339072"], + [1489426403, "50786304"], + [1489426403, "25620480"], + [1489426403, "26144768"], + [1489426418, "30863360"], + [1489426418, "26669056"], + [1489426418, "59699200"], + [1489426418, "26144768"], + [1489426433, "61796352"], + [1489426433, "26144768"], + [1489426433, "31387648"], + [1489426433, "27193344"], + [1489426448, "27717632"], + [1489426448, "62844928"], + [1489426448, "26144768"], + [1489426448, "32960512"], + [1489426463, "26144768"], + [1489426463, "31911936"], + [1489426463, "34009088"], + [1489426463, "28241920"], + [1489426478, "26144768"], + [1489426478, "37679104"], + [1489426478, "34533376"], + [1489426478, "28766208"], + [1489426493, "26144768"], + [1489426493, "47640576"], + [1489426493, "30863360"], + [1489426493, "23523328"], + [1489426508, "31387648"], + [1489426508, "26144768"], + [1489426508, "23523328"], + [1489426508, "29814784"], + [1489426523, "31911936"], + [1489426523, "36106240"], + [1489426523, "26669056"], + [1489426523, "24047616"], + [1489426538, "22999040"], + [1489426538, "26669056"], + [1489426538, "24571904"], + [1489426538, "47116288"], + [1489426553, "22999040"], + [1489426553, "26669056"], + [1489426553, "31911936"], + [1489426553, "25096192"], + [1489426568, "40824832"], + [1489426568, "24047616"], + [1489426568, "26144768"], + [1489426568, "26669056"], + [1489426583, "26669056"], + [1489426583, "24571904"], + [1489426583, "26669056"], + [1489426583, "51834880"], + [1489426598, "36630528"], + [1489426598, "25096192"], + [1489426598, "26669056"], + [1489426598, "27193344"], + [1489426613, "25620480"], + [1489426613, "45543424"], + [1489426613, "26669056"], + [1489426613, "27717632"], + [1489426628, "28766208"], + [1489426628, "56029184"], + [1489426628, "26144768"], + [1489426628, "26669056"], + [1489426643, "27193344"], + [1489426643, "59174912"], + [1489426643, "29814784"], + [1489426643, "26669056"], + [1489426658, "30339072"], + [1489426658, "47640576"], + [1489426658, "27717632"], + [1489426658, "26669056"], + [1489426673, "26669056"], + [1489426673, "30863360"], + [1489426673, "28766208"], + [1489426673, "48689152"], + [1489426688, "26669056"], + [1489426688, "29290496"], + [1489426688, "24571904"], + [1489426688, "57602048"], + [1489426703, "69660672"], + [1489426703, "26669056"], + [1489426703, "30339072"], + [1489426703, "24571904"], + [1489426718, "25096192"], + [1489426718, "69660672"], + [1489426718, "26669056"], + [1489426718, "30863360"], + [1489426733, "25620480"], + [1489426733, "69660672"], + [1489426733, "26669056"], + [1489426733, "30863360"], + [1489426748, "69660672"], + [1489426748, "26669056"], + [1489426748, "23523328"], + [1489426748, "26144768"], + [1489426763, "27193344"], + [1489426763, "23523328"], + [1489426763, "26669056"], + [1489426763, "41349120"], + [1489426778, "24047616"], + [1489426778, "27193344"], + [1489426778, "27717632"], + [1489426778, "60223488"], + [1489426793, "28241920"], + [1489426793, "24571904"], + [1489426793, "27193344"], + [1489426793, "61796352"], + [1489426808, "63369216"], + [1489426808, "25096192"], + [1489426808, "28766208"], + [1489426808, "27193344"], + [1489426823, "27193344"], + [1489426823, "25620480"], + [1489426823, "29814784"], + [1489426823, "65990656"], + [1489426838, "30339072"], + [1489426838, "33484800"], + [1489426838, "27193344"], + [1489426838, "26144768"], + [1489426853, "35057664"], + [1489426853, "27193344"], + [1489426853, "27193344"], + [1489426853, "30863360"], + [1489426868, "40824832"], + [1489426868, "27193344"], + [1489426868, "27717632"], + [1489426868, "31387648"], + [1489426883, "28241920"], + [1489426883, "31387648"], + [1489426883, "27193344"], + [1489426883, "51310592"], + [1489426898, "29814784"], + [1489426898, "49737728"], + [1489426898, "31387648"], + [1489426898, "27193344"], + [1489426913, "30339072"], + [1489426913, "27193344"], + [1489426913, "51834880"], + [1489426913, "25096192"], + [1489426928, "70709248"], + [1489426928, "25096192"], + [1489426928, "30863360"], + [1489426928, "27193344"], + [1489426943, "27193344"], + [1489426943, "24047616"], + [1489426943, "70709248"], + [1489426943, "25096192"], + [1489426958, "25096192"], + [1489426958, "27193344"], + [1489426958, "73330688"], + [1489426958, "24047616"], + [1489426973, "38727680"], + [1489426973, "24571904"], + [1489426973, "25096192"], + [1489426973, "27193344"], + [1489426988, "47640576"], + [1489426988, "25096192"], + [1489426988, "25096192"], + [1489426988, "27193344"], + [1489427003, "25620480"], + [1489427003, "27717632"], + [1489427003, "58650624"], + [1489427003, "25096192"], + [1489427018, "26144768"], + [1489427018, "27717632"], + [1489427018, "25096192"], + [1489427018, "61272064"], + [1489427033, "27717632"], + [1489427033, "81195008"], + [1489427033, "26144768"], + [1489427033, "25096192"], + [1489427048, "26144768"], + [1489427048, "25096192"], + [1489427048, "27717632"], + [1489427048, "51834880"], + [1489427063, "26144768"], + [1489427063, "51834880"], + [1489427063, "25096192"], + [1489427063, "27717632"], + [1489427078, "27717632"], + [1489427078, "51834880"], + [1489427078, "26144768"], + [1489427078, "25096192"], + [1489427093, "25096192"], + [1489427093, "27717632"], + [1489427093, "51834880"], + [1489427093, "26144768"], + [1489427108, "40300544"], + [1489427108, "51834880"], + [1489427108, "26144768"], + [1489427108, "27717632"], + [1489427123, "26144768"], + [1489427123, "40824832"], + [1489427123, "27717632"], + [1489427123, "27717632"], + [1489427138, "27717632"], + [1489427138, "60747776"], + [1489427138, "40300544"], + [1489427138, "28766208"], + [1489427153, "30339072"], + [1489427153, "62844928"], + [1489427153, "27717632"], + [1489427153, "27717632"], + [1489427168, "30863360"], + [1489427168, "63893504"], + [1489427168, "28241920"], + [1489427168, "27717632"], + [1489427183, "65466368"], + [1489427183, "30863360"], + [1489427183, "27717632"], + [1489427183, "27193344"], + [1489427198, "30863360"], + [1489427198, "68087808"], + [1489427198, "27717632"], + [1489427198, "27717632"], + [1489427213, "39251968"], + [1489427213, "28766208"], + [1489427213, "27717632"], + [1489427213, "27717632"], + [1489427228, "27717632"], + [1489427228, "29290496"], + [1489427228, "46592000"], + [1489427228, "28241920"], + [1489427243, "30339072"], + [1489427243, "28766208"], + [1489427243, "36630528"], + [1489427243, "27717632"], + [1489427258, "27717632"], + [1489427258, "30863360"], + [1489427258, "42397696"], + [1489427258, "29290496"], + [1489427273, "27717632"], + [1489427273, "31387648"], + [1489427273, "30339072"], + [1489427273, "44494848"], + [1489427288, "30863360"], + [1489427288, "53932032"], + [1489427288, "30339072"], + [1489427288, "27717632"], + [1489427303, "30339072"], + [1489427303, "27717632"], + [1489427303, "31911936"], + [1489427303, "41349120"], + [1489427318, "28241920"], + [1489427318, "30339072"], + [1489427318, "32436224"], + [1489427318, "40300544"], + [1489427333, "28241920"], + [1489427333, "32960512"], + [1489427333, "55504896"], + [1489427333, "30339072"], + [1489427348, "40300544"], + [1489427348, "33484800"], + [1489427348, "30339072"], + [1489427348, "28241920"], + [1489427363, "28241920"], + [1489427363, "34009088"], + [1489427363, "30339072"], + [1489427363, "50262016"], + [1489427378, "23523328"], + [1489427378, "28241920"], + [1489427378, "60223488"], + [1489427378, "30339072"], + [1489427393, "24047616"], + [1489427393, "54456320"], + [1489427393, "30863360"], + [1489427393, "28241920"], + [1489427408, "28241920"], + [1489427408, "65466368"], + [1489427408, "31911936"], + [1489427408, "24047616"], + [1489427423, "65466368"], + [1489427423, "24047616"], + [1489427423, "28241920"], + [1489427423, "32436224"], + [1489427438, "65466368"], + [1489427438, "28241920"], + [1489427438, "24571904"], + [1489427438, "32960512"], + [1489427453, "28241920"], + [1489427453, "34009088"], + [1489427453, "65466368"], + [1489427453, "25620480"], + [1489427468, "34533376"], + [1489427468, "25620480"], + [1489427468, "28241920"], + [1489427468, "65466368"], + [1489427483, "34533376"], + [1489427483, "65466368"], + [1489427483, "26669056"], + [1489427483, "28241920"], + [1489427498, "34533376"], + [1489427498, "40824832"], + [1489427498, "27193344"], + [1489427498, "28241920"], + [1489427513, "28241920"], + [1489427513, "28241920"], + [1489427513, "34533376"], + [1489427513, "60747776"], + [1489427528, "29290496"], + [1489427528, "34533376"], + [1489427528, "28241920"], + [1489427528, "62320640"], + [1489427543, "29814784"], + [1489427543, "63893504"], + [1489427543, "34533376"], + [1489427543, "28241920"], + [1489427558, "30339072"], + [1489427558, "34533376"], + [1489427558, "28241920"], + [1489427558, "65466368"], + [1489427573, "27193344"], + [1489427573, "30863360"], + [1489427573, "68087808"], + [1489427573, "28241920"], + [1489427588, "28241920"], + [1489427588, "71233536"], + [1489427588, "31387648"], + [1489427588, "27193344"], + [1489427603, "31387648"], + [1489427603, "31387648"], + [1489427603, "28766208"], + [1489427603, "27193344"], + [1489427618, "24047616"], + [1489427618, "27717632"], + [1489427618, "40300544"], + [1489427618, "28766208"], + [1489427633, "51310592"], + [1489427633, "23523328"], + [1489427633, "25096192"], + [1489427633, "28766208"], + [1489427648, "28766208"], + [1489427648, "30863360"], + [1489427648, "24047616"], + [1489427648, "24047616"], + [1489427663, "24571904"], + [1489427663, "24047616"], + [1489427663, "28766208"], + [1489427663, "39251968"], + [1489427678, "25096192"], + [1489427678, "28766208"], + [1489427678, "50262016"], + [1489427678, "24571904"], + [1489427693, "35581952"], + [1489427693, "25620480"], + [1489427693, "25096192"], + [1489427693, "29290496"], + [1489427708, "29290496"], + [1489427708, "45543424"], + [1489427708, "26669056"], + [1489427708, "25096192"], + [1489427723, "56029184"], + [1489427723, "25096192"], + [1489427723, "29290496"], + [1489427723, "27193344"], + [1489427738, "27717632"], + [1489427738, "45543424"], + [1489427738, "25096192"], + [1489427738, "29290496"], + [1489427753, "25096192"], + [1489427753, "61272064"], + [1489427753, "29290496"], + [1489427753, "28766208"], + [1489427768, "25096192"], + [1489427768, "50786304"], + [1489427768, "29290496"], + [1489427768, "29290496"], + [1489427783, "29814784"], + [1489427783, "29290496"], + [1489427783, "58126336"], + [1489427783, "25096192"], + [1489427798, "25096192"], + [1489427798, "29814784"], + [1489427798, "58126336"], + [1489427798, "29290496"] + ] +} diff --git a/frontend/src/index.js b/frontend/src/index.js index 9aaff0b0..c8f86920 100644 --- a/frontend/src/index.js +++ b/frontend/src/index.js @@ -7,6 +7,7 @@ import React from 'react'; import App from '@containers/app'; import MockState from './mock-state.json'; +import Datasets from './datasets.json'; import Store from '@state/store'; if (process.env.NODE_ENV !== 'production') { @@ -15,6 +16,24 @@ if (process.env.NODE_ENV !== 'production') { }); } +// TMP - ensure datasets are at least 2 hrs long - START +import getTwoHourDatasets from './utils/two-hour-metric-datasets'; +const twoHourLongDatasets = getTwoHourDatasets(Datasets); +// TMP - ensure datasets are at least 2 hrs long - END + +// TMP - plug fake metric data - START +const datasets = MockState.metrics.data.datasets.map((dataset, index) => { + const keyIndex = index%2 ? 0 : 1; + const key = Object.keys(twoHourLongDatasets)[keyIndex]; + return { + ...dataset, + data: twoHourLongDatasets[key] + }; +}); + +MockState.metrics.data.datasets = datasets; +// TMP - plug fake metric data - END + ReactDOM.render( diff --git a/frontend/src/mock-state.json b/frontend/src/mock-state.json index 7d3c686a..6535bdb7 100644 --- a/frontend/src/mock-state.json +++ b/frontend/src/mock-state.json @@ -53,6 +53,7 @@ }, "metrics": { "ui": { + "pos": 0, "durations": [ "360", "720", @@ -163,317 +164,11 @@ "datasets": [{ "type": "2aaa237d-42b3-442f-9094-a17aa470014b", "uuid": "3e6ee79a-7453-4fc6-b9da-7ae1e41138ec", - "data": [{ - "firstQuartile": 15, - "thirdQuartile": 15, - "median": 15, - "max": 15, - "min": 15 - }, { - "firstQuartile": 26, - "thirdQuartile": 26, - "median": 26, - "max": 26, - "min": 26 - }, { - "firstQuartile": 17, - "thirdQuartile": 17, - "median": 17, - "max": 17, - "min": 17 - }, { - "firstQuartile": 15, - "thirdQuartile": 25, - "median": 19, - "max": 19, - "min": 20 - }, { - "firstQuartile": 19, - "thirdQuartile": 25, - "median": 21, - "max": 20, - "min": 25 - }, { - "firstQuartile": 24, - "thirdQuartile": 30, - "median": 25, - "max": 26, - "min": 27 - }, { - "firstQuartile": 28, - "thirdQuartile": 34, - "median": 30, - "max": 30, - "min": 30 - }, { - "firstQuartile": 30, - "thirdQuartile": 45, - "median": 35, - "max": 40, - "min": 40 - }, { - "firstQuartile": 20, - "thirdQuartile": 55, - "median": 45, - "max": 44, - "min": 44 - }, { - "firstQuartile": 55, - "thirdQuartile": 55, - "median": 55, - "max": 55, - "min": 55 - }, { - "firstQuartile": 57, - "thirdQuartile": 56, - "median": 57, - "max": 58, - "min": 57 - }, { - "firstQuartile": 57, - "thirdQuartile": 56, - "median": 56, - "max": 56, - "min": 56 - }, { - "firstQuartile": 60, - "thirdQuartile": 56, - "median": 60, - "max": 60, - "min": 60 - }, { - "firstQuartile": 57, - "thirdQuartile": 57, - "median": 57, - "max": 57, - "min": 57 - }, { - "firstQuartile": 57, - "thirdQuartile": 55, - "median": 55, - "max": 55, - "min": 55 - }, { - "firstQuartile": 20, - "thirdQuartile": 45, - "median": 45, - "max": 45, - "min": 45 - }, { - "firstQuartile": 15, - "thirdQuartile": 40, - "median": 30, - "max": 49, - "min": 30 - }, { - "firstQuartile": 15, - "thirdQuartile": 15, - "median": 15, - "max": 15, - "min": 15 - }, { - "firstQuartile": 26, - "thirdQuartile": 26, - "median": 26, - "max": 26, - "min": 26 - }, { - "firstQuartile": 17, - "thirdQuartile": 17, - "median": 17, - "max": 17, - "min": 17 - }, { - "firstQuartile": 15, - "thirdQuartile": 25, - "median": 19, - "max": 19, - "min": 20 - }, { - "firstQuartile": 19, - "thirdQuartile": 25, - "median": 21, - "max": 20, - "min": 25 - }, { - "firstQuartile": 24, - "thirdQuartile": 30, - "median": 25, - "max": 26, - "min": 10 - }, { - "firstQuartile": 28, - "thirdQuartile": 34, - "median": 30, - "max": 30, - "min": 30 - }, { - "firstQuartile": 30, - "thirdQuartile": 45, - "median": 35, - "max": 40, - "min": 40 - }, { - "firstQuartile": 20, - "thirdQuartile": 55, - "median": 45, - "max": 44, - "min": 44 - }, { - "firstQuartile": 55, - "thirdQuartile": 55, - "median": 55, - "max": 55, - "min": 55 - }, { - "firstQuartile": 57, - "thirdQuartile": 56, - "median": 57, - "max": 58, - "min": 57 - }, { - "firstQuartile": 57, - "thirdQuartile": 56, - "median": 56, - "max": 56, - "min": 56 - }, { - "firstQuartile": 60, - "thirdQuartile": 56, - "median": 60, - "max": 60, - "min": 60 - }, { - "firstQuartile": 57, - "thirdQuartile": 57, - "median": 57, - "max": 57, - "min": 57 - }, { - "firstQuartile": 57, - "thirdQuartile": 55, - "median": 55, - "max": 55, - "min": 55 - }, { - "firstQuartile": 20, - "thirdQuartile": 45, - "median": 45, - "max": 45, - "min": 45 - }, { - "firstQuartile": 15, - "thirdQuartile": 40, - "median": 30, - "max": 49, - "min": 30 - }, { - "firstQuartile": 15, - "thirdQuartile": 15, - "median": 15, - "max": 15, - "min": 15 - }, { - "firstQuartile": 26, - "thirdQuartile": 26, - "median": 26, - "max": 26, - "min": 26 - }, { - "firstQuartile": 17, - "thirdQuartile": 17, - "median": 17, - "max": 17, - "min": 17 - }, { - "firstQuartile": 15, - "thirdQuartile": 25, - "median": 19, - "max": 19, - "min": 20 - }, { - "firstQuartile": 19, - "thirdQuartile": 25, - "median": 21, - "max": 20, - "min": 25 - }, { - "firstQuartile": 24, - "thirdQuartile": 30, - "median": 25, - "max": 26, - "min": 27 - }, { - "firstQuartile": 28, - "thirdQuartile": 34, - "median": 30, - "max": 30, - "min": 30 - }, { - "firstQuartile": 30, - "thirdQuartile": 45, - "median": 35, - "max": 40, - "min": 40 - }, { - "firstQuartile": 20, - "thirdQuartile": 55, - "median": 45, - "max": 44, - "min": 44 - }, { - "firstQuartile": 55, - "thirdQuartile": 55, - "median": 55, - "max": 55, - "min": 55 - }, { - "firstQuartile": 57, - "thirdQuartile": 56, - "median": 57, - "max": 58, - "min": 57 - }, { - "firstQuartile": 57, - "thirdQuartile": 56, - "median": 56, - "max": 56, - "min": 56 - }, { - "firstQuartile": 60, - "thirdQuartile": 56, - "median": 60, - "max": 60, - "min": 60 - }, { - "firstQuartile": 57, - "thirdQuartile": 57, - "median": 57, - "max": 57, - "min": 57 - }, { - "firstQuartile": 57, - "thirdQuartile": 55, - "median": 55, - "max": 55, - "min": 55 - }, { - "firstQuartile": 20, - "thirdQuartile": 45, - "median": 45, - "max": 45, - "min": 45 - }, { - "firstQuartile": 15, - "thirdQuartile": 40, - "median": 30, - "max": 49, - "min": 30 - }] + "data": [] },{ - "type": "dca08514-72e5-46ce-ad91-e68b3b0914d9", + "type": "dca08514-72e5-46ce-ad92-e68b3b0914d4", "uuid": "4e6ee79a-7453-4fc6-b9da-7ae1e41138ed", - "data": [{"firstQuartile":1.62,"thirdQuartile":1.62,"median":1.62,"max":1.62,"min":1.62},{"firstQuartile":1.67,"thirdQuartile":1.67,"median":1.67,"max":1.67,"min":1.67},{"firstQuartile":1.63,"thirdQuartile":1.63,"median":1.63,"max":1.63,"min":1.63},{"firstQuartile":1.62,"thirdQuartile":1.66,"median":1.64,"max":1.64,"min":1.64},{"firstQuartile":1.64,"thirdQuartile":1.66,"median":1.64,"max":1.64,"min":1.66},{"firstQuartile":1.66,"thirdQuartile":1.69,"median":1.66,"max":1.67,"min":1.67},{"firstQuartile":1.68,"thirdQuartile":1.70,"median":1.69,"max":1.69,"min":1.69},{"firstQuartile":1.69,"thirdQuartile":1.75,"median":1.71,"max":1.73,"min":1.73},{"firstQuartile":1.64,"thirdQuartile":1.80,"median":1.75,"max":1.75,"min":1.75},{"firstQuartile":1.80,"thirdQuartile":1.80,"median":1.80,"max":1.80,"min":1.80},{"firstQuartile":1.81,"thirdQuartile":1.80,"median":1.81,"max":1.81,"min":1.81},{"firstQuartile":1.81,"thirdQuartile":1.80,"median":1.80,"max":1.80,"min":1.80},{"firstQuartile":1.82,"thirdQuartile":1.80,"median":1.82,"max":1.82,"min":1.82},{"firstQuartile":1.81,"thirdQuartile":1.81,"median":1.81,"max":1.81,"min":1.81},{"firstQuartile":1.81,"thirdQuartile":1.80,"median":1.80,"max":1.80,"min":1.80},{"firstQuartile":1.64,"thirdQuartile":1.75,"median":1.75,"max":1.75,"min":1.75},{"firstQuartile":1.62,"thirdQuartile":1.73,"median":1.69,"max":1.77,"min":1.69},{"firstQuartile":1.62,"thirdQuartile":1.62,"median":1.62,"max":1.62,"min":1.62},{"firstQuartile":1.67,"thirdQuartile":1.67,"median":1.67,"max":1.67,"min":1.67},{"firstQuartile":1.63,"thirdQuartile":1.63,"median":1.63,"max":1.63,"min":1.63},{"firstQuartile":1.62,"thirdQuartile":1.66,"median":1.64,"max":1.64,"min":1.64},{"firstQuartile":1.64,"thirdQuartile":1.66,"median":1.64,"max":1.64,"min":1.66},{"firstQuartile":1.66,"thirdQuartile":1.69,"median":1.66,"max":1.67,"min":1.59},{"firstQuartile":1.68,"thirdQuartile":1.70,"median":1.69,"max":1.69,"min":1.69},{"firstQuartile":1.69,"thirdQuartile":1.75,"median":1.71,"max":1.73,"min":1.73},{"firstQuartile":1.64,"thirdQuartile":1.80,"median":1.75,"max":1.75,"min":1.75},{"firstQuartile":1.80,"thirdQuartile":1.80,"median":1.80,"max":1.80,"min":1.80},{"firstQuartile":1.81,"thirdQuartile":1.80,"median":1.81,"max":1.81,"min":1.81},{"firstQuartile":1.81,"thirdQuartile":1.80,"median":1.80,"max":1.80,"min":1.80},{"firstQuartile":1.82,"thirdQuartile":1.80,"median":1.82,"max":1.82,"min":1.82},{"firstQuartile":1.81,"thirdQuartile":1.81,"median":1.81,"max":1.81,"min":1.81},{"firstQuartile":1.81,"thirdQuartile":1.80,"median":1.80,"max":1.80,"min":1.80},{"firstQuartile":1.64,"thirdQuartile":1.75,"median":1.75,"max":1.75,"min":1.75},{"firstQuartile":1.62,"thirdQuartile":1.73,"median":1.69,"max":1.77,"min":1.69},{"firstQuartile":1.62,"thirdQuartile":1.62,"median":1.62,"max":1.62,"min":1.62},{"firstQuartile":1.67,"thirdQuartile":1.67,"median":1.67,"max":1.67,"min":1.67},{"firstQuartile":1.63,"thirdQuartile":1.63,"median":1.63,"max":1.63,"min":1.63},{"firstQuartile":1.62,"thirdQuartile":1.66,"median":1.64,"max":1.64,"min":1.64},{"firstQuartile":1.64,"thirdQuartile":1.66,"median":1.64,"max":1.64,"min":1.66},{"firstQuartile":1.66,"thirdQuartile":1.69,"median":1.66,"max":1.67,"min":1.67},{"firstQuartile":1.68,"thirdQuartile":1.70,"median":1.69,"max":1.69,"min":1.69},{"firstQuartile":1.69,"thirdQuartile":1.75,"median":1.71,"max":1.73,"min":1.73},{"firstQuartile":1.64,"thirdQuartile":1.80,"median":1.75,"max":1.75,"min":1.75},{"firstQuartile":1.80,"thirdQuartile":1.80,"median":1.80,"max":1.80,"min":1.80},{"firstQuartile":1.81,"thirdQuartile":1.80,"median":1.81,"max":1.81,"min":1.81},{"firstQuartile":1.81,"thirdQuartile":1.80,"median":1.80,"max":1.80,"min":1.80},{"firstQuartile":1.82,"thirdQuartile":1.80,"median":1.82,"max":1.82,"min":1.82},{"firstQuartile":1.81,"thirdQuartile":1.81,"median":1.81,"max":1.81,"min":1.81},{"firstQuartile":1.81,"thirdQuartile":1.80,"median":1.80,"max":1.80,"min":1.80},{"firstQuartile":1.64,"thirdQuartile":1.75,"median":1.75,"max":1.75,"min":1.75},{"firstQuartile":1.62,"thirdQuartile":1.73,"median":1.69,"max":1.77,"min":1.69}] + "data": [] }] } }, diff --git a/frontend/src/prop-types.js b/frontend/src/prop-types.js index f1ac6ed7..11006bd9 100644 --- a/frontend/src/prop-types.js +++ b/frontend/src/prop-types.js @@ -46,18 +46,18 @@ const MetricType = React.PropTypes.shape({ ...BaseObject }); +const Data = React.PropTypes.shape({ + firstQuartile: React.PropTypes.number, + thirdQuartile: React.PropTypes.number, + median: React.PropTypes.number, + max: React.PropTypes.number, + min: React.PropTypes.number +}); + const Dataset = React.PropTypes.shape({ uuid: React.PropTypes.string, type: MetricType, - data: React.PropTypes.arrayOf( - React.PropTypes.shape({ - firstQuartile: React.PropTypes.number, - thirdQuartile: React.PropTypes.number, - median: React.PropTypes.number, - max: React.PropTypes.number, - min: React.PropTypes.number - }) - ) + data: React.PropTypes.arrayOf(Data) }); const Sections = React.PropTypes.arrayOf( @@ -74,5 +74,6 @@ export default { instance: Instance, metric: Metric, metricType: MetricType, - dataset: Dataset + dataset: Dataset, + data: Data }; diff --git a/frontend/src/state/actions.js b/frontend/src/state/actions.js index 7091eab6..c04a4492 100644 --- a/frontend/src/state/actions.js +++ b/frontend/src/state/actions.js @@ -1,6 +1,5 @@ import constantCase from 'constant-case'; import { createAction } from 'redux-actions'; -// import thunks from '@state/thunks'; const APP = constantCase(process.env['APP_NAME']); @@ -54,3 +53,5 @@ export const handleNewProject = createAction(`${APP}/CREATE_NEW_PROJECT`); export const toggleTooltip = createAction(`${APP}/TOGGLE_QUICK_ACTIONS_TOOLTIP`); +export const refreshMetrics = + createAction(`${APP}/REFRESH_METRICS`); diff --git a/frontend/src/state/reducers/metrics.js b/frontend/src/state/reducers/metrics.js index 4d706103..16054cfb 100644 --- a/frontend/src/state/reducers/metrics.js +++ b/frontend/src/state/reducers/metrics.js @@ -1,16 +1,24 @@ import { handleActions } from 'redux-actions'; -import { metricDurationChange } from '@state/actions'; +import { metricDurationChange, refreshMetrics } from '@state/actions'; export default handleActions({ - [metricDurationChange.toString()]: (state, action) => { + [metricDurationChange.toString()]: (state, action) => ({ + ...state, + ui: { + ...state.ui, + [action.payload.dataset]: { + ...state.ui[action.payload.dataset], + duration: action.payload.duration + } + } + }), + [refreshMetrics.toString()]: (state) => { + return ({ ...state, ui: { ...state.ui, - [action.payload.dataset]: { - ...state.ui[action.payload.dataset], - duration: action.payload.duration - } + pos: state.ui.pos + 1 } }); } diff --git a/frontend/src/state/selectors.js b/frontend/src/state/selectors.js index b393c8ec..850f083d 100644 --- a/frontend/src/state/selectors.js +++ b/frontend/src/state/selectors.js @@ -66,14 +66,207 @@ const orgSections = (orgId) => createSelector( const isCollapsed = (collapsed, uuid) => collapsed.indexOf(uuid) >= 0; -const datasets = (metricsData, serviceOrInstanceMetrics, metricsUI) => - serviceOrInstanceMetrics.map((soim) => ({ - ...find(metricsData.datasets, ['uuid', soim.dataset]), - type: find(metricsData.types, ['uuid', soim.type]), - ...metricsUI[soim.dataset] - })); +const metricByInterval = (data = [], { + min = 0, + max = 100 +}, { + duration = '1 hour', + interval = '5 minutes' +}) => { + const getDurationArgs = (value) => { + const [durationNumber, durationType] = value.split(/\s/); + return [Number(durationNumber), durationType]; + }; -const servicesByProjectId = (projectId) => createSelector( + const _duration = moment.duration(...getDurationArgs(duration)); + const _interval = moment.duration(...getDurationArgs(interval)); + + const roundUpDate = (date) => { + const mod = date.valueOf() % _interval.valueOf(); + const diff = moment.duration(_interval.valueOf() - mod); + return moment(date).add(diff); + }; + + const roundDownDate = (date) => { + const mod = date.valueOf() % _interval.valueOf(); + return moment(date).subtract(mod); + }; + + const lastDate = roundUpDate(moment(data[data.length - 1][0], 'X')); + const firstDate = moment(data[0][0], 'X'); + + const getStart = () => { + const hardStart = moment(lastDate).subtract(_duration); + + return hardStart.isBefore(firstDate) + ? roundDownDate(firstDate) + : roundUpDate(hardStart); + }; + + const _start = getStart(); + + const genSample = (start) => ({ + start: start, + end: moment(start).add(_interval), + values: [] + }); + + const genStats = (sample) => { + const data = sample.values.map((r) => r.v); + + return { + start: sample.start.valueOf(), + end: sample.end.valueOf(), + firstQuartile: statistics.quantile(data, 0.25), + median: statistics.median(data), + thirdQuartile: statistics.quantile(data, 0.75), + max: statistics.max(data), + min: statistics.min(data), + stddev: statistics.sampleStandardDeviation(data) + }; + }; + + const intervals = data.reduce((samples, value, i) => { + const sample = samples[samples.length - 1]; + const previousSample = samples[samples.length - 2]; + + const record = { + v: Number(value[1]), + t: moment(value[0], 'X') + }; + + if (record.t.isBefore(_start)) { + return samples; + } + + const split = () => { + const stats = genStats(sample); + + const nextSample = { + ...genSample(sample.end), + values: [record] + }; + + samples[samples.length - 1] = { + ...sample, + stats + }; + + return [ + ...samples, + nextSample + ]; + }; + + const append = (sample) => { + samples[samples.length - 1] = { + ...sample, + values: [...sample.values, record] + }; + + return samples; + }; + + const isWithin = ( + record.t.isSameOrAfter(sample.start) && + record.t.isSameOrBefore(sample.end) + ); + + const isBefore = record.t.isBefore(sample.start); + const isAfter = record.t.isAfter(sample.end); + let newSamples = samples; + + if (isWithin) { + newSamples = append(sample); + } + + if (isBefore) { + newSamples = append(previousSample); + } + + if (isAfter) { + newSamples = split(); + } + + if ((i + 1) >= data.length) { + const thisSample = newSamples[newSamples.length - 1]; + const lastStats = genStats(thisSample); + + newSamples[newSamples.length - 1] = { + ...thisSample, + stats: lastStats + }; + } + + return newSamples; + }, [ + genSample(_start) + ]); + + return { + start: _start.valueOf(), + end: lastDate.valueOf(), + duration: _duration.valueOf(), + interval: _interval.valueOf(), + min: min, + max: max, + values: intervals.map((sample) => sample.stats), + __intervals: IS_TEST ? intervals : [] + }; +}; + +// TMP - get min and max for total data - START +const getMinMax = (data) => { + const values = data.map((d) => Number(d[1])); + const min = statistics.min(values); + const max = statistics.max(values); + + return { + min, + max + }; +}; +// TMP - get min and max for total dataset - END + +// TMP - dataset playback - START +import { getDurationMilliseconds } from '../utils/duration-interval'; + +const getDataSubset = (data, merticsUI, metricOptions) => { + const duration = getDurationMilliseconds(metricOptions.duration)/1000; + const interval = getDurationMilliseconds(metricOptions.interval)/1000; + const start = data[0][0] + interval*merticsUI.pos; + const end = start + duration; + return data.reduce((acc, d) => { + if(d[0] >= start && d[0] <= end) { + acc.push(d); + } + return acc; + }, []); +}; +// TMP - dataset playback - END + +const datasets = ( + metricsData, + serviceOrInstanceMetrics, + metricsUI, + metricOptions = { + duration: '1 hour', + interval: '2 minutes' + } +) => + serviceOrInstanceMetrics.map((soim) => { + const dataset = find(metricsData.datasets, ['uuid', soim.dataset]); + const dataSubset = getDataSubset(dataset.data, metricsUI, metricOptions); + const minMax = getMinMax(dataset.data); + return ({ + ...dataset, + data: metricByInterval(dataSubset, minMax, metricOptions), + type: find(metricsData.types, ['uuid', soim.type]), + ...metricsUI[soim.dataset] + }); + }); + +const servicesByProjectId = (projectId, metricOptions) => createSelector( [services, projectById(projectId), collapsedServices, metricsData, metricsUI], (services, project, collapsed, metrics, metricsUI) => services.filter((s) => s.project === project.uuid) @@ -84,7 +277,7 @@ const servicesByProjectId = (projectId) => createSelector( .filter((s) => !s.parent) .map((service) => ({ ...service, - metrics: datasets(metrics, service.metrics, metricsUI), + metrics: datasets(metrics, service.metrics, metricsUI, metricOptions), collapsed: isCollapsed(collapsed, service.uuid), services: service.services.map((service) => ({ ...service, @@ -229,161 +422,6 @@ const peopleByProjectId = (projectId) => createSelector( } ); -const metricByInterval = (data = [], { - duration = '1 hour', - interval = '5 minutes' -}) => { - const getDurationArgs = (value) => { - const [durationNumber, durationType] = value.split(/\s/); - return [Number(durationNumber), durationType]; - }; - - const _duration = moment.duration(...getDurationArgs(duration)); - const _interval = moment.duration(...getDurationArgs(interval)); - - const roundUpDate = (date) => { - const mod = date.valueOf() % _interval.valueOf(); - const diff = moment.duration(_interval.valueOf() - mod); - return moment(date).add(diff); - }; - - const roundDownDate = (date) => { - const mod = date.valueOf() % _interval.valueOf(); - return moment(date).subtract(mod); - }; - - const lastDate = roundUpDate(moment(data[data.length - 1][0], 'X')); - const firstDate = moment(data[0][0], 'X'); - - const getStart = () => { - const hardStart = moment(lastDate).subtract(_duration); - - return hardStart.isBefore(firstDate) - ? roundDownDate(firstDate) - : roundUpDate(hardStart); - }; - - const _start = getStart(); - - const genSample = (start) => ({ - start: start, - end: moment(start).add(_interval), - values: [] - }); - - const genStats = (sample) => { - const data = sample.values.map((r) => r.v); - - return { - start: sample.start.valueOf(), - end: sample.end.valueOf(), - firstQuartile: statistics.quantile(data, 0.25), - median: statistics.median(data), - thirdQuartile: statistics.quantile(data, 0.75), - max: statistics.max(data), - min: statistics.min(data), - stddev: statistics.sampleStandardDeviation(data) - }; - }; - - const intervals = data.reduce((samples, value, i) => { - const sample = samples[samples.length - 1]; - const previousSample = samples[samples.length - 2]; - - const record = { - v: Number(value[1]), - t: moment(value[0], 'X') - }; - - if (record.t.isBefore(_start)) { - return samples; - } - - const split = () => { - const stats = genStats(sample); - - const nextSample = { - ...genSample(sample.end), - values: [record] - }; - - samples[samples.length - 1] = { - ...sample, - stats - }; - - return [ - ...samples, - nextSample - ]; - }; - - const append = (sample) => { - samples[samples.length - 1] = { - ...sample, - values: [...sample.values, record] - }; - - return samples; - }; - - const isWithin = ( - record.t.isSameOrAfter(sample.start) && - record.t.isSameOrBefore(sample.end) - ); - - const isBefore = record.t.isBefore(sample.start); - const isAfter = record.t.isAfter(sample.end); - let newSamples = samples; - - if (isWithin) { - newSamples = append(sample); - } - - if (isBefore) { - newSamples = append(previousSample); - } - - if (isAfter) { - newSamples = split(); - } - - if ((i + 1) >= data.length) { - const thisSample = newSamples[newSamples.length - 1]; - const lastStats = genStats(thisSample); - - newSamples[newSamples.length - 1] = { - ...thisSample, - stats: lastStats - }; - } - - return newSamples; - }, [ - genSample(_start) - ]); - - // TMP for min / max - const allValues = intervals.reduce((stats, sample) => { - const sampleValues = sample.values.map((value) => value.v); - return stats.concat(sampleValues); - },[]); - - const min = statistics.min(allValues); - const max = statistics.max(allValues); - - return { - start: _start.valueOf(), - end: lastDate.valueOf(), - duration: _duration.valueOf(), - interval: _interval.valueOf(), - min: min, - max: max, - values: intervals.map((sample) => sample.stats), - __intervals: IS_TEST ? intervals : [] - }; -}; - export { account as accountSelector, accountUi as accountUISelector, diff --git a/frontend/src/state/thunks/index.js b/frontend/src/state/thunks/index.js index c763bf66..08fefec7 100644 --- a/frontend/src/state/thunks/index.js +++ b/frontend/src/state/thunks/index.js @@ -1,3 +1,4 @@ -// import app from '@state/thunks/app'; - -export {}; +export { + subscribe as subscribeMetric, + unsubscribe as unsubscribeMetric +} from './metrics'; diff --git a/frontend/src/state/thunks/metrics.js b/frontend/src/state/thunks/metrics.js new file mode 100644 index 00000000..e9c5b52f --- /dev/null +++ b/frontend/src/state/thunks/metrics.js @@ -0,0 +1,24 @@ +import { getDurationMilliseconds } from '../../utils/duration-interval'; +import { refreshMetrics } from '../actions'; + +let timeoutId = null; + +const tick = (dispatch) => { + dispatch(refreshMetrics()); +}; + +export const subscribe = (interval) => (dispatch) => { + if(timeoutId) { + clearTimeout(timeoutId); + } + const timeout = interval ? + getDurationMilliseconds(interval) : + 120 * 1000; + timeoutId = setTimeout(tick, timeout, dispatch); +}; + +export const unsubscribe = () => () => { + if(timeoutId) { + clearTimeout(timeoutId); + } +}; diff --git a/frontend/src/utils/duration-interval.js b/frontend/src/utils/duration-interval.js new file mode 100644 index 00000000..22498285 --- /dev/null +++ b/frontend/src/utils/duration-interval.js @@ -0,0 +1,15 @@ +import moment from 'moment'; + +const getDurationArgs = (value) => { + const [durationNumber, durationType] = value.split(/\s/); + return [Number(durationNumber), durationType]; +}; + +const getDurationMilliseconds = (value) => { + return moment.duration(...getDurationArgs(value)).valueOf(); +}; + +export { + getDurationArgs, + getDurationMilliseconds +}; diff --git a/frontend/src/utils/two-hour-metric-datasets.js b/frontend/src/utils/two-hour-metric-datasets.js new file mode 100644 index 00000000..5a3acfba --- /dev/null +++ b/frontend/src/utils/two-hour-metric-datasets.js @@ -0,0 +1,49 @@ +/* eslint-disable */ +// This needs to be at least two hours long +// We need to establish the start time and calculate what the end time is - two hours later +// Then, add the dataset to the array, and calculate its duration +// Then keep adding the dataset to the array, updating each values timstamp with the duration diff * adding, +// until we have data that's at least two hours long +/* eslint-enable */ + +import moment from 'moment'; + +const getTwoHourDatasets = (Datasets) => { + + return Object.keys(Datasets).reduce((datasets, key) => { + const dataset = Datasets[key]; + + const datasetStart = moment(dataset[0][0], 'X'); + const datasetEnd = moment(dataset[dataset.length - 1][0], 'X'); + const datasetDuration = moment(datasetEnd.valueOf()) + .subtract(datasetStart.valueOf()).valueOf(); + + // number of times we need to add the dataset + // so that it's at least 2 hrs long + const count = Math.ceil(moment.duration(2, 'hours') + .valueOf()/datasetDuration); + + // update each data's timestamp depending on round of being added + const getDataset = (dataset, duration, iterationIndex) => { + return dataset.map((dataset) => { + const timestamp = dataset[0] + duration*iterationIndex; + return [ + timestamp, + dataset[1] + ]; + }); + }; + + const datasetDurationSec = datasetDuration/1000; + let twoHourDataset = []; + let i = 0; + while(i++ < count) { + const ds = getDataset(Datasets[key], datasetDurationSec, i); + twoHourDataset = twoHourDataset.concat(ds); + } + datasets[key] = twoHourDataset; + return datasets; + }, {}); +}; + +export default getTwoHourDatasets; diff --git a/frontend/test/selectors/metric-by-Interval-selector.js b/frontend/test/selectors/metric-by-interval-selector.js similarity index 92% rename from frontend/test/selectors/metric-by-Interval-selector.js rename to frontend/test/selectors/metric-by-interval-selector.js index 7b04ffc5..8980fdfe 100644 --- a/frontend/test/selectors/metric-by-Interval-selector.js +++ b/frontend/test/selectors/metric-by-interval-selector.js @@ -2,13 +2,15 @@ const flatten = require('lodash.flatten'); const { metricByIntervalSelector } = require('@state/selectors'); +const data = require('./metric-by-interval-selector.json'); const moment = require('moment'); const test = require('ava'); -const data = require('./metric-by-Interval-selector.json'); - test('should ouput the right properties', (t) => { const stats = metricByIntervalSelector(data, { + min: 0, + max: 100 + }, { duration: '10 minutes', interval: '30 seconds' }); @@ -33,6 +35,9 @@ test('should ouput the right properties', (t) => { test('should respect order of records', (t) => { const stats = metricByIntervalSelector(data, { + min: 0, + max: 100 + }, { duration: '10 minutes', interval: '30 seconds' }); @@ -47,6 +52,9 @@ test('should respect order of records', (t) => { test('should respect the intervals', (t) => { const stats = metricByIntervalSelector(data, { + min: 0, + max: 100 + }, { duration: '10 minutes', interval: '30 seconds' }); @@ -71,6 +79,9 @@ test('should respect the intervals', (t) => { test('should respect the intervals', (t) => { const stats = metricByIntervalSelector(data, { + min: 0, + max: 100 + }, { duration: '10 minutes', interval: '30 seconds' }); @@ -95,6 +106,9 @@ test('should respect the intervals', (t) => { test('records should be within intervals', (t) => { const stats = metricByIntervalSelector(data, { + min: 0, + max: 100 + }, { duration: '10 minutes', interval: '30 seconds' }); @@ -111,11 +125,17 @@ test('different data chunks should produce almost the same stats', (t) => { const halfData = data.slice(Math.floor(data.length / 2), data.length); const stats1 = metricByIntervalSelector(data, { + min: 0, + max: 100 + }, { duration: '10 minutes', interval: '30 seconds' }); const stats2 = metricByIntervalSelector(halfData, { + min: 0, + max: 100 + }, { duration: '10 minutes', interval: '30 seconds' }); diff --git a/frontend/test/selectors/metric-by-Interval-selector.json b/frontend/test/selectors/metric-by-interval-selector.json similarity index 100% rename from frontend/test/selectors/metric-by-Interval-selector.json rename to frontend/test/selectors/metric-by-interval-selector.json diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 1f1fd060..c507b2a4 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -4685,7 +4685,7 @@ lodash.templatesettings@^4.0.0: dependencies: lodash._reinterpolate "~3.0.0" -lodash.uniq@^4.3.0, lodash.uniq@^4.5.0: +lodash.uniq@^4.3.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" diff --git a/spikes/leak/prometheus.yml b/spikes/leak/prometheus.yml new file mode 100644 index 00000000..f85f04a3 --- /dev/null +++ b/spikes/leak/prometheus.yml @@ -0,0 +1,17 @@ +scrape_configs: + - job_name: 'leak-fast' + scrape_interval: 15s + static_configs: + - targets: ['fast-node:8000', 'another-fast-node:8000'] + - job_name: 'leak-slow' + scrape_interval: 15s + static_configs: + - targets: ['slow-node:8000'] + - job_name: 'no-leak' + scrape_interval: 15s + static_configs: + - targets: ['plain-node:8000'] + # - job_name: 'leak' + # scrape_interval: 1s + # static_configs: + # - targets: ['fast-node:8000', 'another-fast-node:8000', 'slow-node:8000', 'plain-node:8000'] diff --git a/spikes/leak/src/server/metric.js b/spikes/leak/src/server/metric.js new file mode 100644 index 00000000..73bd116b --- /dev/null +++ b/spikes/leak/src/server/metric.js @@ -0,0 +1,103 @@ +const relativeDate = require('relative-date'); +const statistics = require('simple-statistics'); +const prometheus = require('../../scripts/prometheus'); +const async = require('async'); + +const cdm = {}; + +const calc = (sample) => { + return { + firstQuartile: statistics.quantile(sample, 0.25), + median: statistics.median(sample), + thirdQuartile: statistics.quantile(sample, 0.75), + max: statistics.max(sample), + min: statistics.min(sample), + stddev: statistics.sampleStandardDeviation(sample) + }; +}; + +const getMem = ({ + job +}, fn) => { + prometheus.query({ + query: [`node_memory_heap_used_bytes{job="${job}"}`] + }).then((res) => { + if (!res || !res[job]) { + return null + } + + const aggregate = calc(Object.keys(res[job]).map((inst) => { + return Number(res[job][inst].node_memory_heap_used_bytes[1]); + })); + + const instances = Object.keys(res[job]).reduce((sum, inst) => { + return Object.assign(sum, { + [inst]: calc([Number(res[job][inst].node_memory_heap_used_bytes[1])]) + }) + }, {}); + + return { + raw: res[job], + aggregate, + instances + }; + }).then((res) => { + return fn(null, res); + }).catch((err) => { + return fn(err); + }); +}; + +const getStats = (ctx, fn) => { + async.parallel({ + mem: async.apply(getMem, ctx) + }, fn); +}; + +module.exports = (server) => ({ + on: (job) => { + console.log('on', job); + + if (cdm[job] && (cdm[job].sockets > 0)) { + cdm[job].sockets += 1; + return; + } + + let messageId = 0; + + const update = () => { + console.log(`publishing /stats/${job}/${messageId += 1}`); + + getStats({ + job: job + }, (err, stats) => { + if (err) { + return console.error(err); + } + + server.publish(`/stats/${job}`, { + when: new Date().getTime(), + stats + }); + }); + }; + + cdm[job] = { + interval: setInterval(update, 1000), + sockets: 1 + }; + }, + off: (job) => { + console.log('off', job); + + if (!(cdm[job].sockets -= 1)) { + clearInterval(cdm[job].interval); + } + } +}); + +module.exports.tree = (ctx) => { + return prometheus.tree({ + query: ['node_memory_heap_used_bytes'] + }); +}; diff --git a/ui/.eslintrc b/ui/.eslintrc index 152567bf..f853c9c6 100644 --- a/ui/.eslintrc +++ b/ui/.eslintrc @@ -77,7 +77,6 @@ "react/prefer-stateless-function": 2, "react/self-closing-comp": 2, "react/sort-comp": 2, - "react/sort-prop-types": 2, "react/style-prop-object": 2, "react/jsx-boolean-value": [2, "never"], "react/jsx-closing-bracket-location": 2,