const express = require('express'); const bodyParser = require('body-parser'); const onFinished = require('on-finished'); // it may be necessary to modify the request object in various ways, this can // be done in this function. For example, a `_metrics_gatherer` object is // added to req and req.connection for the purposes of metrics observing functions const modifyReq = (req) => { req._metrics_gatherer = {}; if (!req.connection._metrics_gatherer) { req.connection._metrics_gatherer = {}; } } // A specific sequence of steps is used to keep track of the changing values of // req.connection.bytesRead and req.connection.bytesWritten // // These two quantities are observed when the request arrives and when it // has finished to subtract the difference, rather than simply observing them // when the request has finished, because the net.Socket objects (as // `.connection` on Request objects) are re-used by express, and so // connection.bytesRead will, at the very start of the request, give us the // bytesRead/bytesWritten by the last request to use the same net.Socket object. const observeBytesRW = (req, res) => { const bytesReadPreviously = req.connection._metrics_gatherer.bytesRead || 0; const bytesWrittenPreviously = req.connection._metrics_gatherer.bytesWritten || 0; return () => { const bytesReadDelta = req.connection.bytesRead - bytesReadPreviously; const bytesWrittenDelta = req.connection.bytesWritten - bytesWrittenPreviously; req.connection._metrics_gatherer.bytesRead = req.connection.bytesRead; req.connection._metrics_gatherer.bytesWritten = req.connection.bytesWritten; console.log(`bytesReadDelta: ${bytesReadDelta}`); console.log(`bytesWrittenDelta: ${bytesWrittenDelta}`); }; }; // observe the request latency using process.hrtime const observeLatency = (req, res) => { const t0 = process.hrtime(); return () => { const t1 = process.hrtime(); const dt = (t1[0] - t0[0]) + (t1[1] - t0[1]) / 1e6; console.log(`dt: ${dt}`); }; }; // attach a middleware to all requests to observe various metrics const metricsMiddleware = (req, res, next) => { modifyReq(req); const onFinishFuncs = [ observeBytesRW(req, res), observeLatency(req, res) ]; onFinished(res, () => { onFinishFuncs.forEach(f => f()); }); next(); }; const server = () => { const app = express(); app.use(bodyParser.json()); app.use(metricsMiddleware) app.all('*', (req, res) => { res.send(req.body); }); const server = app.listen(process.env.PORT || 3001); console.log(`listening on ${process.env.PORT || 3001}`); }; server();