mirror of https://github.com/bra1n/townsquare.git
added more metrics
This commit is contained in:
parent
3a5a8bfc9a
commit
e2d7fa64f2
|
@ -1,5 +1,11 @@
|
|||
# Release Notes
|
||||
|
||||
## Version 2.0.3
|
||||
|
||||
- added a few more metrics
|
||||
|
||||
---
|
||||
|
||||
## Version 2.0.2
|
||||
- fix nomination history type not detecting travelers
|
||||
- fix live session domain whitelist
|
||||
|
|
|
@ -1266,6 +1266,11 @@
|
|||
"file-uri-to-path": "1.0.0"
|
||||
}
|
||||
},
|
||||
"bintrees": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.1.tgz",
|
||||
"integrity": "sha1-DmVcm5wkNeqraL9AJyJtK1WjRSQ="
|
||||
},
|
||||
"bluebird": {
|
||||
"version": "3.7.2",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
|
||||
|
@ -6894,6 +6899,14 @@
|
|||
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
|
||||
"dev": true
|
||||
},
|
||||
"prom-client": {
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/prom-client/-/prom-client-13.0.0.tgz",
|
||||
"integrity": "sha512-M7ZNjIO6x+2R/vjSD13yjJPjpoZA8eEwH2Bp2Re0/PvzozD7azikv+SaBtZes4Q1ca/xHjZ4RSCuTag3YZLg1A==",
|
||||
"requires": {
|
||||
"tdigest": "^0.1.1"
|
||||
}
|
||||
},
|
||||
"promise-inflight": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
|
||||
|
@ -8213,6 +8226,14 @@
|
|||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
|
||||
"integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA=="
|
||||
},
|
||||
"tdigest": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.1.tgz",
|
||||
"integrity": "sha1-Ljyyw56kSeVdHmzZEReszKRYgCE=",
|
||||
"requires": {
|
||||
"bintrees": "1.0.1"
|
||||
}
|
||||
},
|
||||
"terser": {
|
||||
"version": "4.8.0",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz",
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
"@fortawesome/free-solid-svg-icons": "^5.15.1",
|
||||
"@fortawesome/vue-fontawesome": "^0.1.10",
|
||||
"@vue/cli-service": "^4.5.9",
|
||||
"prom-client": "^13.0.0",
|
||||
"sass": "^1.30.0",
|
||||
"sass-loader": "^8.0.2",
|
||||
"vue": "^2.6.12",
|
||||
|
|
|
@ -1,6 +1,14 @@
|
|||
const fs = require("fs");
|
||||
const https = require("https");
|
||||
const WebSocket = require("ws");
|
||||
const client = require("prom-client");
|
||||
|
||||
// Create a Registry which registers the metrics
|
||||
const register = new client.Registry();
|
||||
// Add a default label which is added to all metrics
|
||||
register.setDefaultLabels({
|
||||
app: "clocktower-online"
|
||||
});
|
||||
|
||||
const PING_INTERVAL = 30000; // 30 seconds
|
||||
|
||||
|
@ -29,6 +37,49 @@ function heartbeat() {
|
|||
// map of channels currently in use
|
||||
const channels = {};
|
||||
|
||||
// metrics
|
||||
const metrics = {
|
||||
players_concurrent: new client.Gauge({
|
||||
name: "players_concurrent",
|
||||
help: "Concurrent Players",
|
||||
collect() {
|
||||
this.set(wss.clients.size);
|
||||
}
|
||||
}),
|
||||
channels_concurrent: new client.Gauge({
|
||||
name: "channels_concurrent",
|
||||
help: "Concurrent Channels",
|
||||
collect() {
|
||||
this.set(Object.keys(channels).length);
|
||||
}
|
||||
}),
|
||||
messages_incoming: new client.Counter({
|
||||
name: "messages_incoming",
|
||||
help: "Incoming messages"
|
||||
}),
|
||||
messages_outgoing: new client.Counter({
|
||||
name: "messages_outgoing",
|
||||
help: "Outgoing messages"
|
||||
}),
|
||||
connection_terminated_host: new client.Counter({
|
||||
name: "connection_terminated_host",
|
||||
help: "Terminated connection due to host already present"
|
||||
}),
|
||||
connection_terminated_spam: new client.Counter({
|
||||
name: "connection_terminated_spam",
|
||||
help: "Terminated connection due to message spam"
|
||||
}),
|
||||
connection_terminated_timeout: new client.Counter({
|
||||
name: "connection_terminated_timeout",
|
||||
help: "Terminated connection due to timeout"
|
||||
})
|
||||
};
|
||||
|
||||
// register metrics
|
||||
for (let metric in metrics) {
|
||||
register.registerMetric(metrics[metric]);
|
||||
}
|
||||
|
||||
// a new client connects
|
||||
wss.on("connection", function connection(ws, req) {
|
||||
// url pattern: clocktower.online/<channel>/<playerId|host>
|
||||
|
@ -48,6 +99,7 @@ wss.on("connection", function connection(ws, req) {
|
|||
) {
|
||||
console.log(ws.channel, "duplicate host");
|
||||
ws.close(1000, `The channel "${ws.channel}" already has a host`);
|
||||
metrics.connection_terminated_host.inc();
|
||||
return;
|
||||
}
|
||||
ws.isAlive = true;
|
||||
|
@ -71,6 +123,7 @@ wss.on("connection", function connection(ws, req) {
|
|||
});
|
||||
// handle message
|
||||
ws.on("message", function incoming(data) {
|
||||
metrics.messages_incoming.inc();
|
||||
// check rate limit (max 5msg/second)
|
||||
ws.counter++;
|
||||
if (ws.counter > (5 * PING_INTERVAL) / 1000) {
|
||||
|
@ -79,6 +132,7 @@ wss.on("connection", function connection(ws, req) {
|
|||
1000,
|
||||
"Your app seems to be malfunctioning, please clear your browser cache."
|
||||
);
|
||||
metrics.connection_terminated_spam.inc();
|
||||
return;
|
||||
}
|
||||
const messageType = data
|
||||
|
@ -101,6 +155,7 @@ wss.on("connection", function connection(ws, req) {
|
|||
dataToPlayer[client.playerId]
|
||||
) {
|
||||
client.send(JSON.stringify(dataToPlayer[client.playerId]));
|
||||
metrics.messages_outgoing.inc();
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
|
@ -116,6 +171,7 @@ wss.on("connection", function connection(ws, req) {
|
|||
} else {
|
||||
client.send(data);
|
||||
}
|
||||
metrics.messages_outgoing.inc();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -125,7 +181,10 @@ wss.on("connection", function connection(ws, req) {
|
|||
// start ping interval timer
|
||||
const interval = setInterval(function ping() {
|
||||
wss.clients.forEach(function each(ws) {
|
||||
if (ws.isAlive === false) return ws.terminate();
|
||||
if (ws.isAlive === false) {
|
||||
metrics.connection_terminated_timeout.inc();
|
||||
return ws.terminate();
|
||||
}
|
||||
ws.isAlive = false;
|
||||
ws.pingStart = new Date().getTime();
|
||||
ws.ping(noop);
|
||||
|
@ -142,16 +201,7 @@ if (process.env.NODE_ENV !== "development") {
|
|||
console.log("server starting");
|
||||
server.listen(8080);
|
||||
server.on("request", (req, res) => {
|
||||
res.writeHead(200);
|
||||
res.end(
|
||||
`# HELP players_concurrent Concurrent players
|
||||
# TYPE players_concurrent gauge
|
||||
players_concurrent{app="clocktower-online"} ${wss.clients.size}
|
||||
|
||||
# HELP channels_concurrent Concurrent channels
|
||||
# TYPE channels_concurrent gauge
|
||||
channels_concurrent{app="clocktower-online"} ${Object.keys(channels).length}
|
||||
`
|
||||
);
|
||||
res.setHeader("Content-Type", register.contentType);
|
||||
register.metrics().then(out => res.end(out));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
class LiveSession {
|
||||
constructor(store) {
|
||||
this._wss = "wss://live.clocktower.online:8080/";
|
||||
//this._wss = "wss://baumgart.biz:8080/"; //todo: delete this
|
||||
//this._wss = "ws://localhost:8081/";
|
||||
//this._wss = "wss://localhost:8081/";
|
||||
this._socket = null;
|
||||
this._isSpectator = true;
|
||||
this._gamestate = [];
|
||||
|
|
Loading…
Reference in New Issue