UNPKG

@nodefony/monitoring-bundle

Version:
341 lines (313 loc) 9.63 kB
const QS = require("qs"); const shortId = require("shortid"); const request = require("request"); const os = require("os"); const cpuAverage = function () { let totalIdle = 0; let totalTick = 0; const cpus = os.cpus(); // Loop through CPU cores for (let i = 0; i < cpus.length; i++) { const cpu = cpus[i]; // Total up the time in the cores tick for (const type in cpu.times) { totalTick += cpu.times[type]; } // Total up the idle time of the core totalIdle += cpu.times.idle; } // Return the average return { idle: totalIdle / cpus.length, total: totalTick / cpus.length }; }; const cpuInit = function () { const start = cpuAverage.call(this); return () => { const end = cpuAverage.call(this); const dif = {}; dif.idle = end.idle - start.idle; dif.total = end.total - start.total; dif.percent = 100 - ~~(100 * dif.idle / dif.total); this.cpu.push(dif); return dif; }; }; const averaging = class averaging { constructor () { this.timesConcurence = []; this.statusCode = {}; this.requestBySec = []; this.cpu = []; this.total = 0; } addTimeAverage (tab) { const status = {}; let time = 0; for (let i = 0; i < tab.length; i++) { time += tab[i].time; if (tab[i].statusCode in this.statusCode) { this.statusCode[tab[i].statusCode] += 1; } else { this.statusCode[tab[i].statusCode] = 1; } if (tab[i].statusCode in status) { status[tab[i].statusCode] += 1; } else { status[tab[i].statusCode] = 1; } } const res = time / tab.length; this.timesConcurence.push(res); const requestBySec = tab.length / (time / 1000); this.requestBySec.push(requestBySec); return { average: (res / 1000).toFixed(2), total: (time / 1000).toFixed(2), requestBySec: requestBySec.toFixed(2), statusCode: status }; } average () { let time = 0; for (let i = 0; i < this.timesConcurence.length; i++) { time += this.timesConcurence[i]; } return (time / this.timesConcurence.length / 1000).toFixed(2); } cpuAverage () { let idle = 0; let total = 0; let percent = 0; for (let i = 0; i < this.cpu.length; i++) { idle += this.cpu[i].idle; total += this.cpu[i].total; percent += this.cpu[i].percent; } return { idle: ((idle / this.cpu.length)).toFixed(2), total: ((total / this.cpu.length)).toFixed(2), percent: ((percent / this.cpu.length)).toFixed(2) }; } }; const testLoad = class testLoad { constructor (context, manager, options) { this.manager = manager; this.nbRequest = parseInt(options.nbRequest, 10); this.nbRequestSent = 0; this.nbError = 0; this.nbSuccess = 0; this.concurrence = parseInt(options.concurence, 10); this.interval = this.nbRequest / this.concurrence; this.context = context; this.options = options; this.averaging = new averaging(); this.sid = options.sid; this.httpsSettings = this.manager.get("httpsServer").settings; this.rootDir = this.manager.kernel.rootDir; this.stopChain = false; this.running = false; /* this.agentOptions = { key: fs.readFileSync(this.rootDir+this.httpsSettings.certificats.key), cert: fs.readFileSync(this.rootDir+this.httpsSettings.certificats.cert), rejectUnauthorized: false, }; if ( this.httpsSettings.certificats.ca ){ this.agentOptions["ca"] = fs.readFileSync(this.rootDir+this.httpsSettings.certificats.ca) ; }*/ this.agentOptions = { "rejectUnauthorized": false }; } requests (start) { const tab = []; const cpu = cpuInit.call(this.averaging); for (let i = 0; i < this.concurrence; i++) { tab.push(this.HttpRequest()); } let myResult = null; this.running = true; // tab.map(function(ele){return ele()}) Promise.all(tab) .catch((e) => { this.manager.logger(e, "ERROR"); this.running = false; // throw e ; this.context.send(JSON.stringify({ running: this.running, message: e.message })); }) .then((result) => { // console.log(result) // this.manager.logger( "PROMISE HTTP THEN" , "DEBUG"); myResult = result; const stop = new Date().getTime(); if (result) { const addTimeAverage = this.averaging.addTimeAverage(result); const time = stop - start; this.averaging.total += time; const sec = time / 1000; const nbRequestSec = this.concurrence / addTimeAverage.average; // this.averaging.addRequestBySec( nbRequestSec ); this.context.send(JSON.stringify({ average: addTimeAverage.average, statusCode: addTimeAverage.statusCode, requestBySecond: nbRequestSec.toFixed(2), totalTime: sec, // this.averaging.averageResquestBySec(), percentEnd: (this.nbRequestSent * 100 / this.nbRequest).toFixed(2), nbResquest: this.nbRequestSent, running: this.running, cpu: cpu() })); if (this.nbRequestSent < this.nbRequest && this.stopChain === false) { this.requests(new Date().getTime()); } else { this.running = false; const avg = this.averaging.average(); this.context.send(JSON.stringify({ message: "END LOAD TEST", average: avg, averageNet: (avg / this.concurrence * 1000).toFixed(2), // ms totalTime: this.averaging.total / 1000, stop, statusCode: this.averaging.statusCode, requestBySecond: (this.nbRequestSent / (this.averaging.total / 1000)).toFixed(2), percentEnd: 100, nbResquest: this.nbRequestSent, running: this.running, cpu: this.averaging.cpuAverage() // prototcol:prototcol })); this.context.close(); } } }) .done((/* ele*/) => { this.manager.logger("PROMISE concurrence HTTP DONE", "DEBUG"); }); } HttpRequest () { const options = { url: this.options.url, method: this.options.method || "GET", forever: true, // keepAlive followRedirect: true, agentOptions: this.agentOptions, headers: { // 'User-Agent': 'NODEFONY' "User-Agent": this.manager.userAgent }, jar: null }; if (this.context.session) { const j = request.jar(); const cookie = request.cookie(`${this.context.session.name}=${this.context.session.id}`); const {url} = options; j.setCookie(cookie, url); options.jar = j; } const promise = new Promise((resolve /* , reject*/) => { const start = new Date().getTime(); request(options, (error, response /* , body*/) => { const stop = new Date().getTime(); this.nbRequestSent += 1; // console.log(this.nbRequestSent); if (error) { const {code} = error; // console.log(error) this.nbError += 1; resolve({ error, message: error.message, statusCode: code, time: stop - start }); return; } const code = response.statusCode; resolve({ statusCode: code, time: stop - start }); }); }); return promise; } stop (sid) { this.stopChain = true; delete this.manager.connections[sid]; } handleMessage (message) { if (!message) { return; } switch (message.action) { case "stop": this.stop(this.sid); break; default: } } }; // service module.exports = class serverLoad extends nodefony.Service { constructor (container, kernel) { super("serverLoad", container, container.get("notificationsCenter")); this.kernel = kernel; this.connections = {}; this.userAgent = `nodefony/${this.kernel.settings.version} (${process.platform};${process.arch}) V8/${process.versions.v8} node/${process.versions.node}`; } logger (pci, severity, msgid) { if (!msgid) { msgid = "\x1b[34m SERVICE SERVER LOAD \x1b[0m"; } if (this.realTime) { return this.realTime.logger(pci, severity, msgid); } return this.kernel.logger(pci, severity, msgid); } handleConnection (message, context) { switch (message.type) { case "action": if (message.sid) { this.connections[message.sid].handleMessage(message); } break; default: if (message.query) { const obj = QS.parse(message.query); this.loadHTTP(context, obj); } else { this.loadHTTP(context, message); } } } loadHTTP (context, options) { let sid = null; if (!options.sid) { sid = shortId.generate(); const start = new Date().getTime(); context.send(JSON.stringify({ message: "START LOAD TEST", nbRequest: options.nbRequest, running: true, concurence: options.concurence, percentEnd: 0, start, sid })); this.connections[sid] = new testLoad(context, this, options); this.connections[sid].requests(start); } else { sid = options.sid; this.connections[sid].context = null; this.connections[sid].context = context; } context.listen(this, "onClose", function () { this.connections[sid].stop(sid); }); } };