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,