Skip to content

Commit c1ef38d

Browse files
committed
feat(jsbattle-admin): display info about all nodes
1 parent 03dce07 commit c1ef38d

File tree

7 files changed

+205
-110
lines changed

7 files changed

+205
-110
lines changed

packages/jsbattle-admin/src/containers/SystemView.js

+113-50
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,16 @@ import Col from 'react-bootstrap/Col';
55
import Breadcrumb from 'react-bootstrap/Breadcrumb';
66
import SideMenu from '../components/SideMenu.js';
77
import Loading from '../components/Loading.js';
8-
import SmartTable from '../components/SmartTable.js';
98
import {connect} from 'react-redux';
109
import {getSystemInfo} from '../actions';
10+
import {
11+
faServer,
12+
faCheckCircle
13+
} from '@fortawesome/free-solid-svg-icons';
14+
import {
15+
faCircle
16+
} from '@fortawesome/free-regular-svg-icons';
17+
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
1118

1219
class SystemView extends Component {
1320

@@ -52,10 +59,107 @@ class SystemView extends Component {
5259
return output.join(' ');
5360
}
5461

62+
renderNode(node) {
63+
64+
let cardClass = 'card';
65+
let headerClass = "card-header";
66+
if(node.nodeID.startsWith('gateway')) {
67+
cardClass += " bg-dark";
68+
headerClass += " text-white";
69+
}
70+
return <Col md={6} key={node.nodeID}>
71+
<div className={cardClass}>
72+
<div className={headerClass}>
73+
<FontAwesomeIcon size="lg" icon={faServer} /> &nbsp; <strong>{node.nodeID}</strong>
74+
</div>
75+
<ul className="list-group list-group-flush">
76+
<li className="list-group-item d-flex justify-content-between align-items-center">
77+
Cluster
78+
<span className="badge badge-primary badge-pill">{node.clusterName}</span>
79+
</li>
80+
<li className="list-group-item d-flex justify-content-between align-items-center">
81+
Host
82+
<span className="badge badge-primary badge-pill">{node.hostname}</span>
83+
</li>
84+
<li className="list-group-item d-flex justify-content-between align-items-center">
85+
OS up time
86+
<span className="badge badge-primary badge-pill">{this.formaUptime(node.os.uptime)}</span>
87+
</li>
88+
<li className="list-group-item d-flex justify-content-between align-items-center">
89+
Application up time
90+
<span className="badge badge-primary badge-pill">{this.formaUptime(node.processUptime)}</span>
91+
</li>
92+
<li className="list-group-item d-flex justify-content-between align-items-center">
93+
Client
94+
<span className="badge badge-primary badge-pill">{node.client}</span>
95+
</li>
96+
<li className="list-group-item d-flex justify-content-between align-items-center">
97+
Running services
98+
<span className="badge badge-primary badge-pill">{node.services.length}</span>
99+
</li>
100+
<li className="list-group-item d-flex justify-content-between align-items-center">
101+
CPU (15min average)
102+
<span className="badge badge-primary badge-pill">{node.cpu.load15.toFixed(1)}%</span>
103+
</li>
104+
<li className="list-group-item d-flex justify-content-between align-items-center">
105+
Memory
106+
<span className="badge badge-primary badge-pill">{node.memory.percent.toFixed(1)}%</span>
107+
</li>
108+
<li className="list-group-item d-flex justify-content-between align-items-center">
109+
Server time
110+
<span className="badge badge-primary badge-pill">{node.time.utc}</span>
111+
</li>
112+
</ul>
113+
</div>
114+
</Col>;
115+
}
116+
117+
renderServices(nodes, allServices) {
118+
if(!allServices || !nodes) return;
119+
let data = [];
120+
let header = nodes.map((node) => node.nodeID);
121+
for(let serviceName of allServices) {
122+
data.push({
123+
name: serviceName,
124+
status: nodes.map((node) => node.services.indexOf(serviceName) != -1)
125+
});
126+
}
127+
128+
function checkbox(value) {
129+
if(value) {
130+
return <FontAwesomeIcon size="lg" icon={faCheckCircle} />;
131+
} else {
132+
return <FontAwesomeIcon size="lg" icon={faCircle} />;
133+
}
134+
}
135+
136+
let grid = data.map((row) => (
137+
<tr key={row.name}>
138+
<th scope="row">{row.name}</th>
139+
{row.status.map((s, i) => <td key={i} className="text-center">{checkbox(s)}</td>)}
140+
</tr>
141+
));
142+
143+
return <Col md={12}>
144+
<table className="table table-sm">
145+
<thead className="thead-dark">
146+
<tr>
147+
<th scope="col">Service</th>
148+
{header.map((h, i) => <th key={i} scope="col" className="text-center">{h}</th>)}
149+
</tr>
150+
</thead>
151+
<tbody>
152+
{grid}
153+
</tbody>
154+
</table>
155+
</Col>;
156+
}
157+
55158
render() {
56159
if(this.props.isLoading) {
57160
return<Loading />;
58161
}
162+
let nodes = this.props.nodes ? this.props.nodes.map((n) => this.renderNode(n)) : null;
59163
return (
60164
<div>
61165
<Container fluid>
@@ -68,48 +172,13 @@ class SystemView extends Component {
68172
<Breadcrumb.Item>Dashboard</Breadcrumb.Item>
69173
<Breadcrumb.Item active>System</Breadcrumb.Item>
70174
</Breadcrumb>
175+
<h1 className="display-5">Nodes</h1>
176+
<Row>
177+
{nodes}
178+
</Row>
179+
<h1 className="display-5">Services</h1>
71180
<Row>
72-
<Col md={7}>
73-
<ul className="list-group">
74-
<li className="list-group-item d-flex justify-content-between align-items-center">
75-
OS up time
76-
<span className="badge badge-primary badge-pill">{this.formaUptime(this.props.osUptime)}</span>
77-
</li>
78-
<li className="list-group-item d-flex justify-content-between align-items-center">
79-
Application up time
80-
<span className="badge badge-primary badge-pill">{this.formaUptime(this.props.appUptime)}</span>
81-
</li>
82-
<li className="list-group-item d-flex justify-content-between align-items-center">
83-
Client
84-
<span className="badge badge-primary badge-pill">{this.props.client}</span>
85-
</li>
86-
<li className="list-group-item d-flex justify-content-between align-items-center">
87-
Running services
88-
<span className="badge badge-primary badge-pill">{this.props.node.upServiceCount}/{this.props.node.totalServiceCount}</span>
89-
</li>
90-
<li className="list-group-item d-flex justify-content-between align-items-center">
91-
CPU (15min average)
92-
<span className="badge badge-primary badge-pill">{this.props.cpu.toFixed(1)}%</span>
93-
</li>
94-
<li className="list-group-item d-flex justify-content-between align-items-center">
95-
Memory
96-
<span className="badge badge-primary badge-pill">{this.props.mem.toFixed(1)}%</span>
97-
</li>
98-
<li className="list-group-item d-flex justify-content-between align-items-center">
99-
Server time
100-
<span className="badge badge-primary badge-pill">{this.props.time}</span>
101-
</li>
102-
</ul>
103-
</Col>
104-
<Col md={5}>
105-
<SmartTable
106-
columns={[
107-
{name: 'Service Name', field: 'name'},
108-
{name: 'Running', field: 'up', format: 'check'},
109-
]}
110-
data={{rows: this.props.node.services}}
111-
/>
112-
</Col>
181+
{this.renderServices(this.props.nodes, this.props.allServices)}
113182
</Row>
114183
</Col>
115184
</Row>
@@ -122,14 +191,8 @@ class SystemView extends Component {
122191
// eslint-disable-next-line no-unused-vars
123192
const mapStateToProps = (state) => ({
124193
isLoading: state.loading.SYSTEM_INFO,
125-
node: state.system.info.node,
126-
cpu: state.system.info.health.cpu.load15,
127-
mem: state.system.info.health.mem.percent,
128-
client: state.system.info.health.client.type + " " + state.system.info.health.client.langVersion,
129-
os: state.system.info.health.os,
130-
time: state.system.info.health.time.utc,
131-
osUptime: state.system.info.health.os.uptime,
132-
appUptime: state.system.info.health.process.uptime,
194+
nodes: state.system.info.nodes,
195+
allServices: state.system.info.allServices,
133196
});
134197

135198
const mapDispatchToProps = (dispatch) => ({

packages/jsbattle-admin/src/reducers/systemReducer.js

+1-15
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,6 @@
11
const initState = {
22
info: {
3-
health: {
4-
client: {},
5-
mem: {
6-
percent: 0
7-
},
8-
cpu: {
9-
load15: 0
10-
},
11-
process: {},
12-
os: {},
13-
time: {}
14-
},
15-
node: {
16-
serrvices: []
17-
}
3+
nodes: []
184
}
195
};
206

packages/jsbattle-mockserver/app/init_db.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"admin,info": {"memoryUsage":{"rss":112005120,"heapTotal":73895936,"heapUsed":48082320,"external":20602467,"arrayBuffers":19050402},"health":{"cpu":{"load1":2.88671875,"load5":2.86572265625,"load15":2.9169921875,"cores":8,"utilization":36},"mem":{"free":290983936,"total":17179869184,"percent":1.6937494277954102},"os":{"uptime":420572,"type":"Darwin","release":"19.5.0","hostname":"kjamroz-mbp13.home","arch":"x64","platform":"darwin","user":{"uid":991631923,"gid":1971932948,"username":"kjamroz","homedir":"/Users/kjamroz","shell":"/bin/zsh"}},"process":{"pid":23816,"memory":{"rss":112029696,"heapTotal":73895936,"heapUsed":48108080,"external":20602531,"arrayBuffers":19050426},"uptime":84642.942465808,"argv":["/Users/kjamroz/.nvm/versions/node/v14.2.0/bin/node","/Users/kjamroz/Documents/dev/jsbattle/packages/jsbattle-server/app/runner.js"]},"client":{"type":"nodejs","version":"0.14.7","langVersion":"v14.2.0"},"net":{"ip":["192.168.1.30"]},"time":{"now":1591723813396,"iso":"2020-06-09T17:30:13.396Z","utc":"Tue, 09 Jun 2020 17:30:13 GMT"}},"node":{"hostname":"kjamroz-mbp13.home","totalServiceCount":12,"upServiceCount":11,"downServiceCount":1,"services":[{"name":"$node","up":true},{"name":"auth","up":true},{"name":"ubdValidator","up":true},{"name":"apiGateway","up":true},{"name":"leagueScheduler","up":true},{"name":"challenges","up":true},{"name":"league","up":true},{"name":"scriptStore","up":true},{"name":"userStore","up":true},{"name":"battleStore","up":true},{"name":"ubdPlayer","up":true},{"name":"challenge","up":false}]}},
2+
"admin,info": {"nodeCount":2,"allServices":["apiGateway","auth","battleStore","challenges","league","leagueScheduler","node","queue","scriptStore","ubdPlayer","ubdValidator","userStore"],"nodes":[{"nodeID":"gateway-jsbattle-dev-47845","clusterName":"jsbattle-dev","hostname":"kjamroz-mbp13.home","processUptime":83.16542054,"client":"nodejs v14.2.0","cpu":{"load1":3.3076171875,"load5":3.20068359375,"load15":3.18359375,"cores":8,"utilization":41},"memory":{"free":307081216,"total":17179869184,"percent":1.7874479293823242},"os":{"uptime":659143,"platform":"darwin","user":"kjamroz"},"time":{"now":1591962384717,"iso":"2020-06-12T11:46:24.717Z","utc":"Fri, 12 Jun 2020 11:46:24 GMT"},"services":["queue","auth","ubdValidator","apiGateway","leagueScheduler","node","league","userStore","challenges","scriptStore","battleStore"]},{"nodeID":"worker-jsbattle-dev-47997","clusterName":"jsbattle-dev","hostname":"kjamroz-mbp13.home","processUptime":6.688126715,"client":"nodejs v14.2.0","cpu":{"load1":3.595703125,"load5":3.2548828125,"load15":3.20263671875,"cores":8,"utilization":44},"memory":{"free":305311744,"total":17179869184,"percent":1.7771482467651367},"os":{"uptime":659141,"platform":"darwin","user":"kjamroz"},"time":{"now":1591962382283,"iso":"2020-06-12T11:46:22.283Z","utc":"Fri, 12 Jun 2020 11:46:22 GMT"},"services":["node","ubdPlayer"]}]},
33
"admin,users": [
44
{
55
"username": "fredric.murphy",

packages/jsbattle-server/app/Node.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,14 @@ class Node {
4848
'LeagueScheduler',
4949
'ScriptStore',
5050
'UbdValidator',
51+
'Node',
5152
];
5253
break;
5354
case WORKER:
54-
serviceList = ['UbdPlayer'];
55+
serviceList = [
56+
'UbdPlayer',
57+
'Node',
58+
];
5559
break;
5660
default:
5761
throw Error('unknown node type: ' + this.type);

packages/jsbattle-server/app/runner.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ let config = {
1515
"gaCode": "AB-123456789-Z"
1616
},
1717
"league": {
18-
"scheduleInterval": 1000,
18+
"scheduleInterval": 100000,
1919
"timeLimit": 10000
2020
},
2121
"ubdPlayer": {
22-
"enabled": true,
22+
"enabled": false,
2323
"queueLimit": 3,
2424
"queueQueryTime": 1000,
2525
"speed": 5,

packages/jsbattle-server/app/services/ApiGateway.service.js

+2-41
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,11 @@ const stringReplace = require('../lib/stringReplaceMiddleware.js');
88
const authorize = require('./apiGateway/authorize.js');
99
const configPassport = require('./apiGateway/configPassport.js');
1010
const IO = require("socket.io");
11-
const fs = require('fs');
1211

1312
class ApiGatewayService extends Service {
1413

1514
constructor(broker) {
1615
super(broker);
17-
this._broker = broker;
1816
let corsOrigin = broker.serviceConfig.web.corsOrigin;
1917
if(!Array.isArray(corsOrigin)) {
2018
corsOrigin = [corsOrigin]
@@ -23,7 +21,7 @@ class ApiGatewayService extends Service {
2321
this.parseServiceSchema({
2422
name: "apiGateway",
2523
actions: {
26-
"getInfo": this.getInfo
24+
2725
},
2826
started() {
2927
const svc = broker.createService({
@@ -55,7 +53,7 @@ class ApiGatewayService extends Service {
5553
"PATCH battles/:id": "battleStore.update",
5654
"REST battles": "battleStore",
5755
"GET ubdPlayer/info": "ubdPlayer.getInfo",
58-
"GET info": "apiGateway.getInfo"
56+
"GET info": "node.getInfo"
5957
},
6058
bodyParsers: {
6159
json: true,
@@ -209,43 +207,6 @@ class ApiGatewayService extends Service {
209207
});
210208
}
211209

212-
async getInfo() {
213-
let nodeInfo = this._broker.getLocalNodeInfo();
214-
215-
let upServices = nodeInfo.services.map((s) => s.name);
216-
217-
let downServices = fs
218-
.readdirSync(__dirname)
219-
.filter((name) => name.endsWith('.service.js'))
220-
.map((name) => name.replace(/\.service\.js$/, ''))
221-
.map((name) => name.charAt(0).toLowerCase() + name.slice(1))
222-
.filter((name) => upServices.indexOf(name) == -1);
223-
224-
upServices = upServices.map((name) => ({
225-
name,
226-
up: true
227-
}));
228-
downServices = downServices.map((name) => ({
229-
name,
230-
up: false
231-
}));
232-
233-
let allServices = upServices.concat(downServices);
234-
235-
return {
236-
clusterName: this._broker.serviceConfig.clusterName,
237-
memoryUsage: await process.memoryUsage(),
238-
health: await this._broker.getHealthStatus(),
239-
node: {
240-
hostname: nodeInfo.hostname,
241-
totalServiceCount: allServices.length,
242-
upServiceCount: upServices.length,
243-
downServiceCount: downServices.length,
244-
services: allServices
245-
}
246-
}
247-
}
248-
249210
}
250211

251212
module.exports = ApiGatewayService;

0 commit comments

Comments
 (0)