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