fix(xo-web): enhance RRD stats (#6903)
- fix infinite requests - avoid duplicate requests
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
- [Remote] Fix `remote is disabled` error when editing a disabled remote
|
||||
- [Settings/Servers] Fix connectiong using an explicit IPv6 address
|
||||
- [Backups/Health check] Use the right SR for health check during replication job (PR [#6902](https://github.com/vatesfr/xen-orchestra/pull/6902))
|
||||
- [RRD stats] Improve RRD stats performance (PR [#6903](https://github.com/vatesfr/xen-orchestra/pull/6903))
|
||||
|
||||
### Packages to release
|
||||
|
||||
|
||||
@@ -12,6 +12,13 @@ export const DEFAULT_GRANULARITY = {
|
||||
value: 'lastTenMinutes',
|
||||
}
|
||||
|
||||
export const INTERVAL_BY_GRANULARITY = {
|
||||
seconds: 5,
|
||||
minutes: 60,
|
||||
hours: 3600,
|
||||
days: 86400,
|
||||
}
|
||||
|
||||
const OPTIONS = [
|
||||
DEFAULT_GRANULARITY,
|
||||
{
|
||||
|
||||
@@ -18,19 +18,29 @@ export default class MiniStats extends Component {
|
||||
fetchStats: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
state = {
|
||||
statsIsPending: false,
|
||||
}
|
||||
|
||||
_fetch = () => {
|
||||
if (this.state.statsIsPending) {
|
||||
return
|
||||
}
|
||||
this.setState({
|
||||
statsIsPending: true,
|
||||
})
|
||||
this.props.fetch().then(stats => {
|
||||
this.setState({ stats })
|
||||
this._timeout = setTimeout(this._fetch, 5e3)
|
||||
this.setState({ stats, statsIsPending: false })
|
||||
})
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this._fetch()
|
||||
this._interval = setInterval(this._fetch, 5e3)
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
clearTimeout(this._timeout)
|
||||
clearInterval(this._interval)
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -4,7 +4,7 @@ import Icon from 'icon'
|
||||
import React from 'react'
|
||||
import Tooltip from 'tooltip'
|
||||
import { Container, Row, Col } from 'grid'
|
||||
import { DEFAULT_GRANULARITY, fetchStats, SelectGranularity } from 'stats'
|
||||
import { DEFAULT_GRANULARITY, fetchStats, SelectGranularity, INTERVAL_BY_GRANULARITY } from 'stats'
|
||||
import { Toggle } from 'form'
|
||||
import { CpuLineChart, MemoryLineChart, PifLineChart, LoadLineChart } from 'xo-line-chart'
|
||||
|
||||
@@ -12,48 +12,52 @@ export default class HostStats extends Component {
|
||||
state = {
|
||||
granularity: DEFAULT_GRANULARITY,
|
||||
useCombinedValues: false,
|
||||
statsIsPending: false,
|
||||
}
|
||||
|
||||
loop(host = this.props.host) {
|
||||
if (this.cancel) {
|
||||
this.cancel()
|
||||
fetchHostStats = () => {
|
||||
if (this.state.statsIsPending) {
|
||||
return
|
||||
}
|
||||
|
||||
const host = this.props.host
|
||||
|
||||
if (host.power_state !== 'Running') {
|
||||
return
|
||||
}
|
||||
|
||||
let cancelled = false
|
||||
this.cancel = () => {
|
||||
cancelled = true
|
||||
if (this.props.statsOverview?.interval === INTERVAL_BY_GRANULARITY[this.state.granularity.granularity]) {
|
||||
this.setState({
|
||||
stats: this.props.statsOverview,
|
||||
selectStatsLoading: false,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
this.setState({
|
||||
statsIsPending: true,
|
||||
})
|
||||
fetchStats(host, 'host', this.state.granularity).then(stats => {
|
||||
if (cancelled) {
|
||||
return
|
||||
}
|
||||
this.cancel = null
|
||||
|
||||
clearTimeout(this.timeout)
|
||||
this.setState(
|
||||
{
|
||||
stats,
|
||||
selectStatsLoading: false,
|
||||
},
|
||||
() => {
|
||||
this.timeout = setTimeout(this.loop, stats.interval * 1000)
|
||||
}
|
||||
)
|
||||
this.setState({
|
||||
stats,
|
||||
selectStatsLoading: false,
|
||||
statsIsPending: false,
|
||||
})
|
||||
})
|
||||
}
|
||||
loop = ::this.loop
|
||||
|
||||
initFetchHostStats() {
|
||||
this.fetchHostStats()
|
||||
this.interval = setInterval(this.fetchHostStats, INTERVAL_BY_GRANULARITY[this.state.granularity.granularity] * 1000)
|
||||
}
|
||||
initFetchHostStats = ::this.initFetchHostStats
|
||||
|
||||
componentWillMount() {
|
||||
this.loop()
|
||||
this.initFetchHostStats()
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
clearTimeout(this.timeout)
|
||||
clearInterval(this.interval)
|
||||
}
|
||||
|
||||
componentWillReceiveProps(props) {
|
||||
@@ -61,7 +65,7 @@ export default class HostStats extends Component {
|
||||
const hostNext = props.host
|
||||
|
||||
if (hostCur.power_state !== 'Running' && hostNext.power_state === 'Running') {
|
||||
this.loop(hostNext)
|
||||
this.initFetchHostStats(hostNext)
|
||||
} else if (hostCur.power_state === 'Running' && hostNext.power_state !== 'Running') {
|
||||
this.setState({
|
||||
stats: undefined,
|
||||
@@ -70,14 +74,14 @@ export default class HostStats extends Component {
|
||||
}
|
||||
|
||||
handleSelectStats(granularity) {
|
||||
clearTimeout(this.timeout)
|
||||
clearInterval(this.interval)
|
||||
|
||||
this.setState(
|
||||
{
|
||||
granularity,
|
||||
selectStatsLoading: true,
|
||||
},
|
||||
this.loop
|
||||
this.initFetchHostStats
|
||||
)
|
||||
}
|
||||
handleSelectStats = ::this.handleSelectStats
|
||||
|
||||
@@ -4,7 +4,7 @@ import Icon from 'icon'
|
||||
import React from 'react'
|
||||
import Tooltip from 'tooltip'
|
||||
import { Container, Row, Col } from 'grid'
|
||||
import { DEFAULT_GRANULARITY, fetchStats, SelectGranularity } from 'stats'
|
||||
import { DEFAULT_GRANULARITY, fetchStats, INTERVAL_BY_GRANULARITY, SelectGranularity } from 'stats'
|
||||
import { Toggle } from 'form'
|
||||
import { CpuLineChart, MemoryLineChart, VifLineChart, XvdLineChart } from 'xo-line-chart'
|
||||
|
||||
@@ -12,48 +12,52 @@ export default class VmStats extends Component {
|
||||
state = {
|
||||
granularity: DEFAULT_GRANULARITY,
|
||||
useCombinedValues: false,
|
||||
statsIsPending: false,
|
||||
}
|
||||
|
||||
loop(vm = this.props.vm) {
|
||||
if (this.cancel) {
|
||||
this.cancel()
|
||||
fetchVmStats = () => {
|
||||
if (this.state.statsIsPending) {
|
||||
return
|
||||
}
|
||||
|
||||
const vm = this.props.vm
|
||||
|
||||
if (vm.power_state !== 'Running') {
|
||||
return
|
||||
}
|
||||
|
||||
let cancelled = false
|
||||
this.cancel = () => {
|
||||
cancelled = true
|
||||
if (this.props.statsOverview?.interval === INTERVAL_BY_GRANULARITY[this.state.granularity.granularity]) {
|
||||
this.setState({
|
||||
stats: this.props.statsOverview,
|
||||
selectStatsLoading: false,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
this.setState({
|
||||
statsIsPending: true,
|
||||
})
|
||||
fetchStats(vm, 'vm', this.state.granularity).then(stats => {
|
||||
if (cancelled) {
|
||||
return
|
||||
}
|
||||
this.cancel = null
|
||||
|
||||
clearTimeout(this.timeout)
|
||||
this.setState(
|
||||
{
|
||||
stats,
|
||||
selectStatsLoading: false,
|
||||
},
|
||||
() => {
|
||||
this.timeout = setTimeout(this.loop, stats.interval * 1000)
|
||||
}
|
||||
)
|
||||
this.setState({
|
||||
stats,
|
||||
selectStatsLoading: false,
|
||||
statsIsPending: false,
|
||||
})
|
||||
})
|
||||
}
|
||||
loop = ::this.loop
|
||||
|
||||
initFetchVmStats() {
|
||||
this.fetchVmStats()
|
||||
this.interval = setInterval(this.fetchVmStats, INTERVAL_BY_GRANULARITY[this.state.granularity.granularity] * 1000)
|
||||
}
|
||||
initFetchVmStats = ::this.initFetchVmStats
|
||||
|
||||
componentWillMount() {
|
||||
this.loop()
|
||||
this.initFetchVmStats()
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
clearTimeout(this.timeout)
|
||||
clearInterval(this.interval)
|
||||
}
|
||||
|
||||
componentWillReceiveProps(props) {
|
||||
@@ -61,7 +65,7 @@ export default class VmStats extends Component {
|
||||
const vmNext = props.vm
|
||||
|
||||
if (vmCur.power_state !== 'Running' && vmNext.power_state === 'Running') {
|
||||
this.loop(vmNext)
|
||||
this.initFetchVmStats(vmNext)
|
||||
} else if (vmCur.power_state === 'Running' && vmNext.power_state !== 'Running') {
|
||||
this.setState({
|
||||
stats: undefined,
|
||||
@@ -70,14 +74,14 @@ export default class VmStats extends Component {
|
||||
}
|
||||
|
||||
handleSelectStats(granularity) {
|
||||
clearTimeout(this.timeout)
|
||||
clearInterval(this.interval)
|
||||
|
||||
this.setState(
|
||||
{
|
||||
granularity,
|
||||
selectStatsLoading: true,
|
||||
},
|
||||
this.loop
|
||||
this.initFetchVmStats
|
||||
)
|
||||
}
|
||||
handleSelectStats = ::this.handleSelectStats
|
||||
|
||||
Reference in New Issue
Block a user