• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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