-
Notifications
You must be signed in to change notification settings - Fork 188
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1592 from HubSpot/resource-usage-ui
Resource Usage UI
- Loading branch information
Showing
37 changed files
with
598 additions
and
229 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { buildApiAction } from './base'; | ||
|
||
export const FetchUtilization = buildApiAction( | ||
'FETCH_UTILIZATION', | ||
{url: '/usage/cluster/utilization'} | ||
); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import React, { PropTypes } from 'react'; | ||
|
||
const Loader = ({fixed}) => ( | ||
<div className={`page-loader ${fixed ? 'fixed' : ''}`} /> | ||
); | ||
|
||
Loader.propTypes = { | ||
fixed: PropTypes.bool | ||
}; | ||
|
||
Loader.defaultProps = { | ||
fixed: true | ||
}; | ||
|
||
export default Loader; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import React, { PropTypes } from 'react'; | ||
import classNames from 'classnames'; | ||
import CircularProgressbar from 'react-circular-progressbar'; | ||
import {Link} from 'react-router'; | ||
|
||
const Aggregate = ({width, vcenter, graph, className, value, label, link}) => { | ||
const valueComponent = ( | ||
graph ? | ||
<CircularProgressbar percentage={value} initialAnimation={true} textForPercentage={(pct) => `${pct}%`} /> : | ||
<div className={classNames('value', {[className]: className})}> | ||
{value} | ||
</div> | ||
); | ||
const labelComponent = ( | ||
<div className={classNames('label', {[className]: className})}> | ||
{label} | ||
</div> | ||
); | ||
|
||
return ( | ||
<div className={classNames( | ||
'aggregate', | ||
`col-xs-${width}`, | ||
{vcenter}, | ||
{graph} | ||
)}> | ||
{link ? | ||
<Link to={link}> | ||
{valueComponent} | ||
{labelComponent} | ||
</Link> : | ||
<div> | ||
{valueComponent} | ||
{labelComponent} | ||
</div> | ||
} | ||
</div> | ||
); | ||
}; | ||
|
||
Aggregate.propTypes = { | ||
width: PropTypes.number.isRequired, | ||
vcenter: PropTypes.bool, | ||
graph: PropTypes.bool, | ||
className: PropTypes.string, | ||
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, | ||
label: PropTypes.string.isRequired, | ||
link: PropTypes.string | ||
}; | ||
|
||
Aggregate.defaultProps = { | ||
vcenter: false, | ||
graph: false | ||
}; | ||
|
||
export default Aggregate; |
112 changes: 112 additions & 0 deletions
112
SingularityUI/app/components/machines/usage/ClusterAggregates.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
import React, { PropTypes } from 'react'; | ||
import { Link } from 'react-router'; | ||
import Utils from '../../../utils'; | ||
import Breakdown from '../../common/Breakdown'; | ||
import { HUNDREDTHS_PLACE } from '../Constants'; | ||
import Loader from "../../common/Loader"; | ||
import LabeledColumn from "./LabeledColumn"; | ||
import Aggregate from './Aggregate'; | ||
|
||
const SlaveAggregates = ({utilization, totalRequests}) => { | ||
return ( | ||
<div> | ||
<h3>CPU</h3> | ||
<div className="row"> | ||
<div className="col-md-2"> | ||
<h4>Requests</h4> | ||
{utilization.numRequestsWithOverUtilizedCpu !== undefined ? | ||
<Breakdown | ||
total={totalRequests} | ||
data={[ | ||
{ | ||
attribute: 'overCpu', | ||
count: utilization.numRequestsWithOverUtilizedCpu, | ||
type: 'danger', | ||
label: 'Over-utilized', | ||
link: '/requests/overUtilizedCpu/all/', | ||
percent: (utilization.numRequestsWithOverUtilizedCpu / totalRequests) * 100 | ||
}, | ||
{ | ||
attribute: 'normal', | ||
count: totalRequests - utilization.numRequestsWithUnderUtilizedCpu - utilization.numRequestsWithOverUtilizedCpu, | ||
type: 'success', | ||
label: 'Normal', | ||
percent: ((totalRequests - utilization.numRequestsWithUnderUtilizedCpu - utilization.numRequestsWithOverUtilizedCpu) / totalRequests) * 100 | ||
}, | ||
{ | ||
attribute: 'underCpu', | ||
count: utilization.numRequestsWithUnderUtilizedCpu, | ||
type: 'warning', | ||
label: 'Under-utilized', | ||
link: '/requests/underUtilizedCpu/all/', | ||
percent: (utilization.numRequestsWithUnderUtilizedCpu / totalRequests) * 100 | ||
} | ||
]} | ||
/> : <Loader fixed={false} />} | ||
</div> | ||
|
||
<LabeledColumn width={10}> | ||
<div className="row"> | ||
<Aggregate width={3} value={Utils.roundTo(utilization.totalOverUtilizedCpu, HUNDREDTHS_PLACE)} label="Total Over-utilized CPUs" className="text-danger" /> | ||
<Aggregate width={3} value={Utils.roundTo(utilization.avgOverUtilizedCpu, HUNDREDTHS_PLACE)} label="Avg Over-utilized CPUs" className="text-danger" /> | ||
<Aggregate width={3} value={Utils.roundTo(utilization.minOverUtilizedCpu, HUNDREDTHS_PLACE)} label="Min Over-utilized CPUs" className="text-danger" /> | ||
<Aggregate width={3} value={Utils.roundTo(utilization.maxOverUtilizedCpu, HUNDREDTHS_PLACE)} label="Max Over-utilized CPUs" className="text-danger" link={utilization.maxOverUtilizedCpuRequestId && `/request/${utilization.maxOverUtilizedCpuRequestId}`} /> | ||
</div> | ||
</LabeledColumn> | ||
|
||
<LabeledColumn width={10}> | ||
<div className="row"> | ||
<Aggregate width={3} value={Utils.roundTo(utilization.totalUnderUtilizedCpu, HUNDREDTHS_PLACE)} label="Total Under-utilized CPUs" className="text-warning" /> | ||
<Aggregate width={3} value={Utils.roundTo(utilization.avgUnderUtilizedCpu, HUNDREDTHS_PLACE)} label="Avg Under-utilized CPUs" className="text-warning" /> | ||
<Aggregate width={3} value={Utils.roundTo(utilization.minUnderUtilizedCpu, HUNDREDTHS_PLACE)} label="Min Under-utilized CPUs" className="text-warning" /> | ||
<Aggregate width={3} value={Utils.roundTo(utilization.maxUnderUtilizedCpu, HUNDREDTHS_PLACE)} label="Max Under-utilized CPUs" className="text-warning" link={utilization.maxUnderUtilizedCpuRequestId && `/request/${utilization.maxUnderUtilizedCpuRequestId}`} /> | ||
</div> | ||
</LabeledColumn> | ||
</div> | ||
|
||
<h3>Memory</h3> | ||
<div className="row"> | ||
<div className="col-md-2"> | ||
<h4>Requests</h4> | ||
{utilization.numRequestsWithUnderUtilizedMemBytes !== undefined ? | ||
<Breakdown | ||
total={totalRequests} | ||
data={[ | ||
{ | ||
attribute: 'normal', | ||
count: totalRequests - utilization.numRequestsWithUnderUtilizedMemBytes, | ||
type: 'success', | ||
label: 'Normal', | ||
percent: ((totalRequests - utilization.numRequestsWithUnderUtilizedMemBytes) / totalRequests) * 100 | ||
}, | ||
{ | ||
attribute: 'underMem', | ||
count: utilization.numRequestsWithUnderUtilizedMemBytes, | ||
type: 'warning', | ||
label: 'Under-utilized', | ||
link: '/requests/underUtilizedMem/all/', | ||
percent: (utilization.numRequestsWithUnderUtilizedMemBytes / totalRequests) * 100 | ||
} | ||
]} | ||
/> : <Loader fixed={false} />} | ||
</div> | ||
|
||
<LabeledColumn width={10}> | ||
<div className="row"> | ||
<Aggregate width={3} value={Utils.humanizeFileSize(utilization.totalUnderUtilizedMemBytes)} label="Total Under-utilized Memory" className="text-warning" /> | ||
<Aggregate width={3} value={Utils.humanizeFileSize(utilization.avgUnderUtilizedMemBytes)} label="Avg Under-utilized Memory" className="text-warning" /> | ||
<Aggregate width={3} value={Utils.humanizeFileSize(utilization.minUnderUtilizedMemBytes)} label="Min Under-utilized Memory" className="text-warning" /> | ||
<Aggregate width={3} value={Utils.humanizeFileSize(utilization.maxUnderUtilizedMemBytes)} label="Max Under-utilized Memory" className="text-warning" link={utilization.maxUnderUtilizedMemBytesRequestId && `/request/${utilization.maxUnderUtilizedMemBytesRequestId}`} /> | ||
</div> | ||
</LabeledColumn> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
SlaveAggregates.propTypes = { | ||
utilization: PropTypes.object.isRequired, | ||
totalRequests: PropTypes.number.isRequired | ||
}; | ||
|
||
export default SlaveAggregates; |
24 changes: 24 additions & 0 deletions
24
SingularityUI/app/components/machines/usage/LabeledColumn.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import React, { PropTypes } from 'react'; | ||
|
||
const LabeledSection = ({title, width, children, className}) => ( | ||
<div className={`col-xs-${width} ${className || ''}`}> | ||
<h4>{title}</h4> | ||
<div className="row"> | ||
<div className="col-xs-12"> | ||
{children} | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
|
||
LabeledSection.propTypes = { | ||
title: PropTypes.string, | ||
width: PropTypes.number.isRequired, | ||
children: React.PropTypes.oneOfType([ | ||
React.PropTypes.arrayOf(React.PropTypes.node), | ||
React.PropTypes.node | ||
]).isRequired, | ||
className: PropTypes.string | ||
}; | ||
|
||
export default LabeledSection; |
Oops, something went wrong.