138 lines
5.4 KiB
React
138 lines
5.4 KiB
React
|
import React from 'react';
|
||
|
import Server from './Server.jsx';
|
||
|
import axios from 'axios';
|
||
|
import { Circle } from 'rc-progress';
|
||
|
export default class Status extends React.Component {
|
||
|
constructor(props) {
|
||
|
super(props);
|
||
|
this.state = {
|
||
|
fetching: true,
|
||
|
statuses: {},
|
||
|
error: '',
|
||
|
serverId: '',
|
||
|
foundInfo: { shard: '', cluster: '' },
|
||
|
foundInfoError: '',
|
||
|
percentage: 0,
|
||
|
onlineOffline: '',
|
||
|
};
|
||
|
}
|
||
|
|
||
|
async componentDidMount() {
|
||
|
this.getStatus();
|
||
|
}
|
||
|
|
||
|
getStatus = async () => {
|
||
|
try {
|
||
|
this.setState({ fetching: true });
|
||
|
let statusRequest = await axios.get('/api/status');
|
||
|
const totalShards = 864;
|
||
|
|
||
|
let connectedShards = 0;
|
||
|
for (let server in statusRequest.data) {
|
||
|
statusRequest.data[server].forEach(function(cluster) {
|
||
|
let connectedCount = 0;
|
||
|
if (cluster.result) connectedCount += cluster.result.connectedCount;
|
||
|
connectedShards += connectedCount || 0;
|
||
|
});
|
||
|
}
|
||
|
let percentage = (connectedShards / totalShards) * 100;
|
||
|
percentage = percentage.toFixed(0);
|
||
|
this.setState({
|
||
|
statuses: statusRequest.data,
|
||
|
fetching: false,
|
||
|
percentage,
|
||
|
onlineOffline: `${connectedShards} / ${totalShards}`
|
||
|
});
|
||
|
this.findInfo();
|
||
|
} catch (e) {
|
||
|
this.setState({ error: 'Failed to load status, trying again in 30 seconds.', fetching: false });
|
||
|
}
|
||
|
setTimeout(this.getStatus, 30 * 1000);
|
||
|
}
|
||
|
|
||
|
onServerIDChange = (serverId) => {
|
||
|
this.setState({ serverId: serverId.target.value });
|
||
|
}
|
||
|
|
||
|
findInfo = () => {
|
||
|
this.setState({ foundInfo: { shard: '', cluster: '' }, foundInfoError: ''})
|
||
|
if (this.state.serverId === '') return;
|
||
|
let serverId = this.state.serverId.match(/(\d{15,})/);
|
||
|
const totalShards = 864;
|
||
|
if (serverId === null || serverId[1] === undefined) {
|
||
|
this.setState({ foundInfo: { shard: '', cluster: '' }, foundInfoError: 'Invalid Server ID'});
|
||
|
return;
|
||
|
}
|
||
|
let shard = ~~((serverId[1]*1 / 4194304) % totalShards);
|
||
|
let cluster = 0;
|
||
|
Object.keys(this.state.statuses).forEach(server => {
|
||
|
if (cluster !== 0) { return; }
|
||
|
let search = this.state.statuses[server].find(i => (i.result && i.result.shards.includes(shard)) || (i.guessedShards && i.guessedShards.includes(shard)));
|
||
|
if (search !== undefined) {
|
||
|
cluster = server[0] + search.id;
|
||
|
return;
|
||
|
}
|
||
|
});
|
||
|
if (cluster === 0) {
|
||
|
cluster = 'unknown';
|
||
|
}
|
||
|
this.setState({ foundInfo: { shard, cluster }, foundInfoError: ''})
|
||
|
}
|
||
|
|
||
|
render() {
|
||
|
let servers;
|
||
|
let foundInfo;
|
||
|
let hasLoaded = !!Object.keys(this.state.statuses).length;
|
||
|
let percent = this.state.percentage;
|
||
|
let shards = this.state.onlineOffline;
|
||
|
if (this.state.foundInfoError !== '') {
|
||
|
foundInfo = (<p>{this.state.foundInfoError}</p>);
|
||
|
}
|
||
|
if (this.state.foundInfo.shard !== '') {
|
||
|
foundInfo = (<p>This server is on shard #{this.state.foundInfo.shard} which is on cluster {this.state.foundInfo.cluster}. <strong>The cluster has been highlighted blue, hover over it to see if there's any problems with it.</strong></p>);
|
||
|
}
|
||
|
if (this.state.error === '') {
|
||
|
servers = Object.keys(this.state.statuses).map(server => <Server key={server} server={server} foundInfo={this.state.foundInfo} clusters={this.state.statuses[server]}/>);
|
||
|
}
|
||
|
let fetching = (<p>This page auto-updates every 30 seconds.</p>);
|
||
|
if (this.state.fetching) {
|
||
|
fetching = (<p>Getting status information, please wait...</p>);
|
||
|
}
|
||
|
return (<div>
|
||
|
<div className="status-wrapper">
|
||
|
<div className="container">{fetching}</div>
|
||
|
{hasLoaded ? (<div className="server-finder container">
|
||
|
<label className="label">Enter your Server ID to find your shard and cluster information.</label>
|
||
|
<div className="text-form">
|
||
|
<p className="control has-addons">
|
||
|
<input className="input" type="text" onChange={this.onServerIDChange} />
|
||
|
<a className="button is-info" onClick={this.findInfo}>Find info</a>
|
||
|
</p>
|
||
|
</div>
|
||
|
{foundInfo}
|
||
|
</div>) : ''}
|
||
|
<div className='container'><p>{this.state.error}</p></div>
|
||
|
<div className='legend container'>
|
||
|
<div className='cluster-grid'>
|
||
|
<p>Legend:</p>
|
||
|
<div className='cluster bg-success'>Operational</div>
|
||
|
<div className='cluster bg-warning'>Partial Outage</div>
|
||
|
<div className='cluster bg-error'>Major Outage</div>
|
||
|
<div className='cluster bg-ipc-timeout'>IPC Timeout</div>
|
||
|
</div>
|
||
|
<p><strong>Hover over a cluster for more information.</strong></p>
|
||
|
</div>
|
||
|
<div className='container percentage'>
|
||
|
<Circle className='percent-circle' percent={percent} trailWidth="10" trailColor="#ed6c63" strokeWidth="10" strokeColor="#009b54"/>
|
||
|
<ul className='up-info'>
|
||
|
<li>{percent}% online</li>
|
||
|
<li>{shards} shards connected</li>
|
||
|
</ul>
|
||
|
</div>
|
||
|
<div className="servers">
|
||
|
{servers}
|
||
|
</div>
|
||
|
</div></div>);
|
||
|
}
|
||
|
}
|