123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- '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;
- };
|