UNPKG

1.88 kBJavaScriptView Raw
1'use strict';
2
3const deferToConnect = require('defer-to-connect');
4
5module.exports = request => {
6 const timings = {
7 start: Date.now(),
8 socket: null,
9 lookup: null,
10 connect: null,
11 upload: null,
12 response: null,
13 end: null,
14 error: null,
15 phases: {
16 wait: null,
17 dns: null,
18 tcp: null,
19 request: null,
20 firstByte: null,
21 download: null,
22 total: null
23 }
24 };
25
26 const handleError = origin => {
27 const emit = origin.emit.bind(origin);
28 origin.emit = (event, ...args) => {
29 // Catches the `error` event
30 if (event === 'error') {
31 timings.error = Date.now();
32 timings.phases.total = timings.error - timings.start;
33 }
34
35 // Saves the original behavior
36 return emit(event, ...args);
37 };
38 };
39
40 handleError(request);
41
42 request.once('socket', socket => {
43 timings.socket = Date.now();
44 timings.phases.wait = timings.socket - timings.start;
45
46 const lookupListener = () => {
47 timings.lookup = Date.now();
48 timings.phases.dns = timings.lookup - timings.socket;
49 };
50
51 socket.once('lookup', lookupListener);
52
53 deferToConnect(socket, () => {
54 timings.connect = Date.now();
55
56 if (timings.lookup === null) {
57 socket.removeListener('lookup', lookupListener);
58 timings.lookup = timings.connect;
59 timings.phases.dns = timings.lookup - timings.socket;
60 }
61
62 timings.phases.tcp = timings.connect - timings.lookup;
63 });
64 });
65
66 request.once('finish', () => {
67 timings.upload = Date.now();
68 timings.phases.request = timings.upload - timings.connect;
69 });
70
71 request.once('response', response => {
72 timings.response = Date.now();
73 timings.phases.firstByte = timings.response - timings.upload;
74
75 handleError(response);
76
77 response.once('end', () => {
78 timings.end = Date.now();
79 timings.phases.download = timings.end - timings.response;
80 timings.phases.total = timings.end - timings.start;
81 });
82 });
83
84 return timings;
85};