UNPKG

pinus-robot

Version:

pinus-robot is a simple tool to benchmark the socket.io server's performance.

208 lines 17.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.HTTP_SERVER = exports.HttpServer = void 0; // ------------------------------------ // HTTP Server // ------------------------------------ // // This file defines HttpServer and the singleton HTTP_SERVER. // // This file defines a generic HTTP server that serves static files and that can be configured // with new routes. It also starts the nodeload HTTP server unless require('nodeload/config') // .disableServer() was called. // const http = require("http"); const fs = require("fs"); let qputs = console.log; const events_1 = require("events"); const __ = require("underscore"); const monitor_1 = require("../monitor/monitor"); /** By default, HttpServer knows how to return static files from the current directory. Add new route regexs using HttpServer.on(). */ class HttpServer extends events_1.EventEmitter { constructor() { super(...arguments); this.routes = []; this.running = false; } /** Start the server listening on the given port */ start(robotMasterUrl, port, hostname) { if (this.running) { return; } this.running = true; this.robotMasterUrl = robotMasterUrl; let self = this; port = port || 8000; self.hostname = hostname || 'localhost'; self.port = port; self.connections = []; self.server = http.createServer(function (req, res) { self.route_(req, res); }); self.server.on('connection', function (c) { // We need to track incoming connections, beause Server.close() won't terminate active // connections by default. c.on('close', function () { let idx = self.connections.indexOf(c); if (idx !== -1) { self.connections.splice(idx, 1); } }); self.connections.push(c); }); self.server.listen(this.port, this.hostname); self.emit('start', self.hostname, self.port); return self; } /** Terminate the server */ stop() { if (!this.running) { return; } this.running = false; this.connections.forEach(function (c) { c.destroy(); }); this.server.close(); this.server = null; this.emit('end'); } /** When an incoming request matches a given regex, route it to the provided handler: function(url, ServerRequest, ServerResponse) */ addRoute(regex, handler) { this.routes.unshift({ regex: regex, handler: handler }); return this; } removeRoute(regex, handler) { this.routes = this.routes.filter(function (r) { return !((regex === r.regex) && (!handler || handler === r.handler)); }); return this; } route_(req, res) { for (let i = 0; i < this.routes.length; i++) { if (req.url.match(this.routes[i].regex)) { this.routes[i].handler(req.url, req, res); return; } } if (req.method === 'GET') { this.serveFile_('.' + req.url, res); } else { res.writeHead(405, { 'Content-Length': '0' }); res.end(); } } doReport(response) { let pdata = (0, monitor_1.getData)(); // console.log('pdata %j',pdata); let mdata = []; let _show = false; __.each(pdata, function (val, key) { let single = {}; _show = true; single['name'] = key; single['uid'] = key; let keycolumns = []; let maxId = 0; __.each(val, function (kval, akey) { let _length = __.size(kval); if (_length > maxId) maxId = _length; if (_length > 0) keycolumns.push(akey); }); let gcolumns = []; gcolumns.push('users'); let glastkeyData = {}; __.each(keycolumns, function (dkey) { gcolumns.push(dkey); }); let grows = []; for (let i = 0; i < maxId; i++) { let rows = []; rows.push(i + 1); __.each(keycolumns, function (dkey) { // console.log('dkey' + dkey + ' ' +i + JSON.stringify(val[dkey])) rows.push(val[dkey][i] || 0); // _vaild = true; }); grows.push(rows); } let gsummary = {}; __.each(keycolumns, function (dkey) { let summary = {}; let kdata = val[dkey]; let min = Number.MAX_VALUE, max = 0; let sindex = 0, sum = 0; __.each(kdata, function (time) { if (time > max) max = time; if (time < min) min = time; sum += time; ++sindex; }); let avg = Math.round(sum / sindex); summary = { 'max': max, 'min': min, 'avg': avg, 'qs': Math.round(sindex * 1000 / avg) }; gsummary[dkey] = (summary); }); single['summary'] = gsummary; single['charts'] = { 'latency': { 'name': 'robot', 'uid': single['uid'], 'columns': gcolumns, 'rows': grows } }; if (grows.length > 0) mdata.push(single); }); if (_show) { let data = JSON.stringify(mdata); // response.writeHead(200, { 'Content-Length': pdata.length }); response.write(data, 'binary'); } response.end(); } serveFile_(basefile, response) { if (basefile.lastIndexOf('report') !== -1) { this.doReport(response); return; } if (basefile === './') basefile = 'index.html'; let file = __dirname + '/' + basefile; fs.stat(file, (err, stat) => { if (err) { response.writeHead(404, { 'Content-Type': 'text/plain' }); response.write('Cannot find file: ' + file); response.end(); return; } fs.readFile(file, 'binary', (err, data) => { if (err) { response.writeHead(500, { 'Content-Type': 'text/plain' }); response.write('Error opening file ' + file + ': ' + err); } else { if (file.lastIndexOf('.html') === -1) { if (basefile === './js/webclient.js') { data = data.replace('${robotMasterUrl}', this.robotMasterUrl); } response.writeHead(200, { 'Content-Length': data.length }); response.write(data, 'binary'); } else { response.writeHead(200, { 'Content-Length': data.length, 'Content-Type': 'text/html; charset=utf-8' }); response.write(data, 'binary'); } } response.end(); }); }); } } exports.HttpServer = HttpServer; // ================= // Singletons // ================= /** The global HTTP server used by nodeload */ exports.HTTP_SERVER = new HttpServer(); exports.HTTP_SERVER.on('start', function (hostname, port) { console.log(`Started Robot Master Http server on : http://${hostname}:${port}`); }); exports.HTTP_SERVER.on('end', function () { qputs('Shutdown Robot Master Http server.'); }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaHR0cC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9jb25zb2xlL2h0dHAudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsdUNBQXVDO0FBQ3ZDLGNBQWM7QUFDZCx1Q0FBdUM7QUFDdkMsRUFBRTtBQUNGLDhEQUE4RDtBQUM5RCxFQUFFO0FBQ0YsOEZBQThGO0FBQzlGLDZGQUE2RjtBQUM3RiwrQkFBK0I7QUFDL0IsRUFBRTtBQUNGLDZCQUE2QjtBQUM3Qix5QkFBeUI7QUFHekIsSUFBSSxLQUFLLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQztBQUN4QixtQ0FBc0M7QUFFdEMsaUNBQWlDO0FBQ2pDLGdEQUE2QztBQUM3QztnQ0FDZ0M7QUFFaEMsTUFBYSxVQUFXLFNBQVEscUJBQVk7SUFBNUM7O1FBS0ksV0FBTSxHQUF3QyxFQUFFLENBQUM7UUFDakQsWUFBTyxHQUFHLEtBQUssQ0FBQztJQW9LcEIsQ0FBQztJQWxLRyxtREFBbUQ7SUFDbkQsS0FBSyxDQUFDLGNBQXNCLEVBQUcsSUFBYSxFQUFFLFFBQWlCO1FBQzNELElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRTtZQUFFLE9BQU87U0FBRTtRQUM3QixJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQztRQUNwQixJQUFJLENBQUMsY0FBYyxHQUFHLGNBQWMsQ0FBQztRQUVyQyxJQUFJLElBQUksR0FBRyxJQUFJLENBQUM7UUFDaEIsSUFBSSxHQUFHLElBQUksSUFBSSxJQUFJLENBQUM7UUFDcEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLElBQUksV0FBVyxDQUFDO1FBQ3hDLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO1FBQ2pCLElBQUksQ0FBQyxXQUFXLEdBQUcsRUFBRSxDQUFDO1FBRXRCLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxVQUFVLEdBQUcsRUFBRSxHQUFHLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxH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