Add metric display
This commit is contained in:
parent
9156526ce0
commit
1b42954bf2
@ -25,6 +25,9 @@
|
|||||||
"added-label": "Added",
|
"added-label": "Added",
|
||||||
"link-label": "Learn more"
|
"link-label": "Learn more"
|
||||||
},
|
},
|
||||||
|
"metric": {
|
||||||
|
"settings-label": "Settings"
|
||||||
|
},
|
||||||
"cpu_agg_usage": {
|
"cpu_agg_usage": {
|
||||||
"title": "Aggregated CPU usage",
|
"title": "Aggregated CPU usage",
|
||||||
"description": "CPU usages accross all of the CPU cores."
|
"description": "CPU usages accross all of the CPU cores."
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
"redux-thunk": "^2.1.0",
|
"redux-thunk": "^2.1.0",
|
||||||
"reselect": "^2.5.4",
|
"reselect": "^2.5.4",
|
||||||
"styled-components": "^1.3.0",
|
"styled-components": "^1.3.0",
|
||||||
|
"svg-react-loader": "^0.3.7",
|
||||||
"understood": "^1.0.1",
|
"understood": "^1.0.1",
|
||||||
"url-loader": "^0.5.7"
|
"url-loader": "^0.5.7"
|
||||||
},
|
},
|
||||||
|
@ -5,6 +5,7 @@ const actions = require('@state/actions');
|
|||||||
const AddMetrics = require('./add-metrics');
|
const AddMetrics = require('./add-metrics');
|
||||||
const Button = require('@ui/components/button');
|
const Button = require('@ui/components/button');
|
||||||
const Column = require('@ui/components/column');
|
const Column = require('@ui/components/column');
|
||||||
|
const MetricCharts = require('./metric-charts');
|
||||||
const Monitors = require('./monitors');
|
const Monitors = require('./monitors');
|
||||||
const PropTypes = require('@root/prop-types');
|
const PropTypes = require('@root/prop-types');
|
||||||
const Row = require('@ui/components/row');
|
const Row = require('@ui/components/row');
|
||||||
@ -35,9 +36,13 @@ const Metrics = ({
|
|||||||
</Column>
|
</Column>
|
||||||
</Row>
|
</Row>
|
||||||
<Monitors />
|
<Monitors />
|
||||||
|
<MetricCharts
|
||||||
|
datasets={metrics.datasets}
|
||||||
|
onSettingsClick={toggleMonitorView}
|
||||||
|
/>
|
||||||
<AddMetrics
|
<AddMetrics
|
||||||
metricTypes={metricTypes}
|
metricTypes={metricTypes}
|
||||||
metrics={metrics}
|
metrics={metrics.types}
|
||||||
onAddMetric={addMetric}
|
onAddMetric={addMetric}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
89
frontend/src/containers/metrics/metric-charts.js
Normal file
89
frontend/src/containers/metrics/metric-charts.js
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
const React = require('react');
|
||||||
|
const moment = require('moment');
|
||||||
|
const PropTypes = require('@root/prop-types');
|
||||||
|
const Metric = require('@ui/components/metric');
|
||||||
|
const ReactIntl = require('react-intl');
|
||||||
|
|
||||||
|
const {
|
||||||
|
FormattedMessage
|
||||||
|
} = ReactIntl;
|
||||||
|
|
||||||
|
const {
|
||||||
|
MetricGraph,
|
||||||
|
MetricCloseButton,
|
||||||
|
MetricHeader,
|
||||||
|
MetricSelect,
|
||||||
|
MetricSettingsButton,
|
||||||
|
MetricTitle,
|
||||||
|
MetricView
|
||||||
|
} = Metric;
|
||||||
|
|
||||||
|
const MetricCharts = ({
|
||||||
|
// metricTypes,
|
||||||
|
// metrics,
|
||||||
|
// onAddMetric,
|
||||||
|
datasets,
|
||||||
|
duration = 360,
|
||||||
|
durations = [
|
||||||
|
360,
|
||||||
|
720,
|
||||||
|
1440,
|
||||||
|
2880
|
||||||
|
],
|
||||||
|
onDurationChange = () => {},
|
||||||
|
onSettingsClick = () => {},
|
||||||
|
onRemoveMetric = () => {}
|
||||||
|
// and another one here to come...
|
||||||
|
}) => {
|
||||||
|
|
||||||
|
const optionList = durations.map(duration => (
|
||||||
|
<option key={duration} value={duration}>
|
||||||
|
{moment.duration(duration, 'minutes').humanize()}
|
||||||
|
</option>
|
||||||
|
));
|
||||||
|
|
||||||
|
const metricList = datasets.map((dataset) => {
|
||||||
|
// TODO
|
||||||
|
// - yMeasurement '%' or not
|
||||||
|
// - yMin & yMax should all come from the metric type description
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MetricView key={dataset.uuid + Math.random()}>
|
||||||
|
<MetricHeader>
|
||||||
|
<MetricTitle>{dataset.uuid}</MetricTitle>
|
||||||
|
<MetricSelect onChange={onDurationChange} value={durations[0]}>
|
||||||
|
{optionList}
|
||||||
|
</MetricSelect>
|
||||||
|
<MetricSettingsButton onClick={onSettingsClick}>
|
||||||
|
<FormattedMessage id={'metrics.metric.settings-label'} />
|
||||||
|
</MetricSettingsButton>
|
||||||
|
<MetricCloseButton onClick={onRemoveMetric} />
|
||||||
|
</MetricHeader>
|
||||||
|
<MetricGraph
|
||||||
|
data={dataset.data}
|
||||||
|
duration={duration}
|
||||||
|
yMax={100}
|
||||||
|
yMeasurement='%'
|
||||||
|
yMin={0}
|
||||||
|
/>
|
||||||
|
</MetricView>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{metricList}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
MetricCharts.propTypes = {
|
||||||
|
datasets: React.PropTypes.arrayOf(PropTypes.Dataset),
|
||||||
|
duration: React.PropTypes.number,
|
||||||
|
durations: React.PropTypes.arrayOf(React.PropTypes.number),
|
||||||
|
onDurationChange: React.PropTypes.func.isRequired,
|
||||||
|
onRemoveMetric: React.PropTypes.func.isRequired,
|
||||||
|
onSettingsClick: React.PropTypes.func.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = MetricCharts;
|
@ -28,7 +28,7 @@ const mapStateToProps = (state, {
|
|||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
addMetric: (service) => (metric) => dispatch(addMetric({
|
addMetric: (service) => (metric) => dispatch(addMetric({
|
||||||
id: metric,
|
id: metric,
|
||||||
service: service
|
service: service.uuid
|
||||||
}))
|
}))
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -48,7 +48,6 @@
|
|||||||
},
|
},
|
||||||
"monitors": {
|
"monitors": {
|
||||||
"ui": {
|
"ui": {
|
||||||
"active": "dca08514-72e5-46ce-ad91-e68b3b0914d4",
|
|
||||||
"page": "create"
|
"page": "create"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -69,6 +68,12 @@
|
|||||||
"net_agg_bytes_in",
|
"net_agg_bytes_in",
|
||||||
"net_agg_bytes_out",
|
"net_agg_bytes_out",
|
||||||
"time_of_day"
|
"time_of_day"
|
||||||
|
],
|
||||||
|
"durations": [
|
||||||
|
360,
|
||||||
|
720,
|
||||||
|
1440,
|
||||||
|
2880
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"data": {
|
"data": {
|
||||||
|
@ -89,9 +89,11 @@ const instancesByServiceId = (serviceId) => createSelector(
|
|||||||
);
|
);
|
||||||
|
|
||||||
const metricsByServiceId = (serviceId) => createSelector(
|
const metricsByServiceId = (serviceId) => createSelector(
|
||||||
[metricTypes, serviceById(serviceId)],
|
[metricTypes, serviceById(serviceId), metricDatasets],
|
||||||
(metricTypes, service) =>
|
(metricTypes, service, metrics) => ({
|
||||||
metricTypes.filter((i) => i.service === service.uuid)
|
types: metricTypes.filter((i) => i.service === service.uuid),
|
||||||
|
datasets: datasets(metrics, service.metrics)
|
||||||
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const metricTypeByUuid = (metricTypeUuid) => createSelector(
|
const metricTypeByUuid = (metricTypeUuid) => createSelector(
|
||||||
|
@ -2,7 +2,10 @@ const React = require('react');
|
|||||||
const Styled = require('styled-components');
|
const Styled = require('styled-components');
|
||||||
const fns = require('../../shared/functions');
|
const fns = require('../../shared/functions');
|
||||||
const constants = require('../../shared/constants');
|
const constants = require('../../shared/constants');
|
||||||
const CloseIcon = require('!babel!svg-react!./close.svg?name=CloseIcon');
|
const CloseIcon =
|
||||||
|
require(
|
||||||
|
'!babel-loader!svg-react-loader!./close.svg?name=CloseIcon'
|
||||||
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
default: styled
|
default: styled
|
||||||
|
@ -46,6 +46,7 @@ class Graph extends React.Component {
|
|||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
|
animation: false,
|
||||||
layout: {
|
layout: {
|
||||||
padding: 10
|
padding: 10
|
||||||
},
|
},
|
||||||
|
@ -4,7 +4,9 @@ const fns = require('../../shared/functions');
|
|||||||
const constants = require('../../shared/constants');
|
const constants = require('../../shared/constants');
|
||||||
const Button = require('../button');
|
const Button = require('../button');
|
||||||
const SettingsIcon =
|
const SettingsIcon =
|
||||||
require('!babel!svg-react!./icon-settings.svg?name=SettingsIcon');
|
require(
|
||||||
|
'!babel-loader!svg-react-loader!./icon-settings.svg?name=SettingsIcon'
|
||||||
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
default: styled
|
default: styled
|
||||||
@ -48,9 +50,10 @@ const StyledIcon = styled(SettingsIcon)`
|
|||||||
|
|
||||||
const AddMetricButton = ({
|
const AddMetricButton = ({
|
||||||
children,
|
children,
|
||||||
|
metric,
|
||||||
onClick
|
onClick
|
||||||
}) => {
|
}) => {
|
||||||
const onButtonClick = (e) => onClick();
|
const onButtonClick = (e) => onClick(metric);
|
||||||
return (
|
return (
|
||||||
<StyledButton
|
<StyledButton
|
||||||
name='add-metric-button'
|
name='add-metric-button'
|
||||||
@ -64,6 +67,7 @@ const AddMetricButton = ({
|
|||||||
|
|
||||||
AddMetricButton.propTypes = {
|
AddMetricButton.propTypes = {
|
||||||
children: React.PropTypes.node,
|
children: React.PropTypes.node,
|
||||||
|
metric: React.PropTypes.string,
|
||||||
onClick: React.PropTypes.func,
|
onClick: React.PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ const {
|
|||||||
const Container = styled.div`
|
const Container = styled.div`
|
||||||
position: relative;
|
position: relative;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
margin: ${remcalc(24)} 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: ${remcalc(940)};
|
max-width: ${remcalc(940)};
|
||||||
box-shadow: ${boxes.bottomShaddow};
|
box-shadow: ${boxes.bottomShaddow};
|
||||||
|
13
ui/yarn.lock
13
ui/yarn.lock
@ -1555,12 +1555,9 @@ chart.js@^2.4.0:
|
|||||||
chartjs-color "^2.0.0"
|
chartjs-color "^2.0.0"
|
||||||
moment "^2.10.6"
|
moment "^2.10.6"
|
||||||
|
|
||||||
chartjs-chart-box-plot@^1.0.0-9:
|
chartjs-chart-box-plot@prerelease:
|
||||||
version "1.0.0-9"
|
version "1.0.0-18"
|
||||||
resolved "https://registry.yarnpkg.com/chartjs-chart-box-plot/-/chartjs-chart-box-plot-1.0.0-9.tgz#bd392c689301e71b13f602818629f5a0965eaddb"
|
resolved "https://registry.yarnpkg.com/chartjs-chart-box-plot/-/chartjs-chart-box-plot-1.0.0-18.tgz#66a671af5ea37155b40d85e89dc6cbae38b90330"
|
||||||
dependencies:
|
|
||||||
react "^15.4.1"
|
|
||||||
react-dom "^15.4.1"
|
|
||||||
|
|
||||||
chartjs-color-string@^0.4.0:
|
chartjs-color-string@^0.4.0:
|
||||||
version "0.4.0"
|
version "0.4.0"
|
||||||
@ -5412,7 +5409,7 @@ react-docgen@^2.12.1:
|
|||||||
node-dir "^0.1.10"
|
node-dir "^0.1.10"
|
||||||
recast "^0.11.5"
|
recast "^0.11.5"
|
||||||
|
|
||||||
react-dom@^15.4.1, react-dom@^15.4.2:
|
react-dom@^15.4.2:
|
||||||
version "15.4.2"
|
version "15.4.2"
|
||||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-15.4.2.tgz#015363f05b0a1fd52ae9efdd3a0060d90695208f"
|
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-15.4.2.tgz#015363f05b0a1fd52ae9efdd3a0060d90695208f"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -5487,7 +5484,7 @@ react-stubber@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
babel-runtime "^6.5.0"
|
babel-runtime "^6.5.0"
|
||||||
|
|
||||||
react@^15.4.1, react@^15.4.2:
|
react@^15.4.2:
|
||||||
version "15.4.2"
|
version "15.4.2"
|
||||||
resolved "https://registry.yarnpkg.com/react/-/react-15.4.2.tgz#41f7991b26185392ba9bae96c8889e7e018397ef"
|
resolved "https://registry.yarnpkg.com/react/-/react-15.4.2.tgz#41f7991b26185392ba9bae96c8889e7e018397ef"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
Loading…
Reference in New Issue
Block a user