1'use strict'; 2const common = require('../common.js'); 3const dc = require('diagnostics_channel'); 4const { AsyncLocalStorage } = require('async_hooks'); 5const http = require('http'); 6 7const bench = common.createBenchmark(main, { 8 apm: ['none', 'diagnostics_channel', 'patch'], 9 type: 'buffer', 10 len: 1024, 11 chunks: 4, 12 connections: [50, 500], 13 chunkedEnc: 1, 14 duration: 5 15}); 16 17function main({ apm, connections, duration, type, len, chunks, chunkedEnc }) { 18 const done = { none, patch, diagnostics_channel }[apm](); 19 20 const server = require('../fixtures/simple-http-server.js') 21 .listen(common.PORT) 22 .on('listening', () => { 23 const path = `/${type}/${len}/${chunks}/normal/${chunkedEnc}`; 24 bench.http({ 25 path, 26 connections, 27 duration 28 }, () => { 29 server.close(); 30 if (done) done(); 31 }); 32 }); 33} 34 35function none() {} 36 37function patch() { 38 const als = new AsyncLocalStorage(); 39 const times = []; 40 41 const { emit } = http.Server.prototype; 42 function wrappedEmit(...args) { 43 const [name, req, res] = args; 44 if (name === 'request') { 45 als.enterWith({ 46 url: req.url, 47 start: process.hrtime.bigint() 48 }); 49 50 res.on('finish', () => { 51 times.push({ 52 ...als.getStore(), 53 statusCode: res.statusCode, 54 end: process.hrtime.bigint() 55 }); 56 }); 57 } 58 return emit.apply(this, args); 59 } 60 http.Server.prototype.emit = wrappedEmit; 61 62 return () => { 63 http.Server.prototype.emit = emit; 64 }; 65} 66 67function diagnostics_channel() { 68 const als = new AsyncLocalStorage(); 69 const times = []; 70 71 const start = dc.channel('http.server.request.start'); 72 const finish = dc.channel('http.server.response.finish'); 73 74 function onStart(req) { 75 als.enterWith({ 76 url: req.url, 77 start: process.hrtime.bigint() 78 }); 79 } 80 81 function onFinish(res) { 82 times.push({ 83 ...als.getStore(), 84 statusCode: res.statusCode, 85 end: process.hrtime.bigint() 86 }); 87 } 88 89 start.subscribe(onStart); 90 finish.subscribe(onFinish); 91 92 return () => { 93 start.unsubscribe(onStart); 94 finish.unsubscribe(onFinish); 95 }; 96} 97