docs: function wrapper(my) {
  
    var finished = require('on-finished');
  
    var __denominator = my.denominator;
    var __byte = my.byte;
    var __time = my.time;
    var __out = my.out;
  
    /**
     * response
     * 
     * @function wrapper
     * @param {Object} socket - client socket
     * @param {Array} start - start time
     * @return {String}
     */
    function response(socket, start) {
  
      var diff = process.hrtime(start);
      var nanoseconds = diff[0] * 1e9 + diff[1];
      var bytes = socket.bytesWritten - ~~socket.transferRateBytesWritten;
      var data = (bytes * __byte) / __denominator;
  
      socket.transferRateBytesWritten = socket.bytesWritten; // keep-alive socket
      return (data / (nanoseconds / __time)).toFixed(2) + __out;
    }
  
    /**
     * request
     * 
     * @function wrapper
     * @param {Object} socket - client socket
     * @param {Array} start - start time
     * @return {String}
     */
    function request(socket, start) {
  
      var diff = process.hrtime(start);
      var nanoseconds = diff[0] * 1e9 + diff[1];
      var bytes = socket.bytesRead - ~~socket.transferRateBytesRead;
      var data = (bytes * __byte) / __denominator;
  
      socket.transferRateBytesRead = socket.bytesRead; // keep-alive socket
      return (data / (nanoseconds / __time)).toFixed(2) + __out;
    }
  
    if (my.response) {
  
      /**
       * rate
       * 
       * @function rate
       * @param {Object} req - client request
       * @param {Object} res - client response
       * @param {Array} start - start time
       * @return {String}
       */
      return function rate(req, res, start) {
  
        if (typeof req !== 'object') {
          throw new TypeError('req required');
        } else if (typeof res !== 'object') {
          throw new TypeError('res required');
        } else if (Array.isArray(start) === false) {
          throw new TypeError('start required');
        }
  
        /*
         * single request
         */
        if (finished.isFinished(res)) {
          var socket = res.socket || req.socket;
          var data = response(socket, start);
          req.transferRate = res.transferRate = data;
          return data;
        }
  
        /*
         * chunk
         */
        finished(res, function(err, res) {
  
          if (!err) {
            var socket = res.req.socket;
            var data = response(socket, start);
            req.transferRate = res.transferRate = data;
          }
        });
      };
  
    } else {
  
      /**
       * rate
       * 
       * @function rate
       * @param {Object} req - client request
       * @param {Object} res - client response
       * @param {Array} start - start time
       * @return {String}
       */
      return function rate(req, res, start) {
  
        if (typeof req !== 'object') {
          throw new TypeError('req required');
        } else if (typeof res !== 'object') {
          throw new TypeError('res required');
        } else if (Array.isArray(start) === false) {
          throw new TypeError('start required');
        }
  
        /*
         * single request
         */
        if (finished.isFinished(req)) {
          var socket = req.socket;
          var data = request(socket, start);
          req.transferRate = res.transferRate = data;
          return data;
        }
  
        /*
         * chunk
         */
        finished(req, function(err, req) {
  
          if (!err) {
            var socket = req.socket;
            var data = request(socket, start);
            req.transferRate = res.transferRate = data;
          }
        });
      };
  
    }
  }