pr-ws-monitor
Version:
Websockets monitoring
106 lines (91 loc) • 3.1 kB
JavaScript
;
const EventEmitter = require("events");
var defaults = {
"ts": 1000, // 1-sec
"error": 60000, // 1-min
"audit": 15000 // 15-sec (4-times within error-interval)
};
function getOptions(options) {
var opts = options || {};
opts = Object.assign.apply(null, Object.keys(defaults).map(prop => ({
[prop]: opts[prop]
})));
Object.keys(defaults).forEach(function each(o) {
opts[o] = opts[o] || defaults[o];
});
return opts;
}
function getObjectData(self) {
self._wsmon = self._wsmon || {};
return self._wsmon;
}
class WsMonitor extends EventEmitter {
constructor(wss, options) {
var data;
super();
data = getObjectData(this);
data.wss = wss;
data.opts = getOptions(options);
}
start() {
var data = getObjectData(this);
// check client-tracking
if (data.wss.options.clientTracking === false) {
this.emit("error", "need to enable clientTracking in ws-server");
}
// setup now time-stamp
data.now = Date.now();
data.nowId = setInterval(function nowTs() {
data.now = Date.now();
}, data.opts.ts);
// setup time-stamp for existing connections
data.wss.clients.forEach(function eachSock(sock) {
sock._updateSockTs = function _updateSockTs() {
sock._ats = data.now;
};
sock._ats = data.now;
sock.on("pong", sock._updateSockTs);
sock.on("message", sock._updateSockTs);
});
// setup time-stamp for new connections
data.wss.on("connection", function sockConnection(sock) {
sock._updateSockTs = function _updateSockTs() {
sock._ats = data.now;
};
sock._ats = data.now;
sock.on("pong", sock._updateSockTs);
sock.on("message", sock._updateSockTs);
});
// setup auditing
data.auditId = setInterval(function auditConnections() {
data.wss.clients.forEach(function eachSock(sock) {
var lag = Date.now() - sock._ats;
if (lag > data.opts.error) {
sock.removeListener("pong", sock._updateSockTs);
sock.removeListener("message", sock._updateSockTs);
sock.close();
} else if (lag > data.opts.audit) {
sock.ping("WsMonitor PING", {}, false);
}
});
}, data.opts.audit);
}
stop() {
var data = getObjectData(this);
// clear now & audit
if (data.nowId) {
clearInterval(data.nowId);
data.nowId = null;
}
if (data.auditId) {
clearInterval(data.auditId);
data.auditId = null;
}
data.wss.clients.forEach(function eachSock(sock) {
sock.removeListener("pong", sock._updateSockTs);
sock.removeListener("message", sock._updateSockTs);
});
}
}
// export
module.exports = WsMonitor;