docs: function logger (options = {}) {
    if (typeof options.fullName !== 'boolean') {
      options.fullName = false
    }
  
    if (options.timestamp === true) {
      options.timestamp = epochTime
    } else if (typeof options.timestamp !== 'function') {
      options.timestamp = false
    }
  
    if (options.request === true) {
      options.request = JSON.stringify
    } else if (typeof options.request !== 'function') {
      options.request = false
    }
  
    if (options.response === true) {
      options.response = JSON.stringify
    } else if (typeof options.response !== 'function') {
      options.response = false
    }
  
    return function logger (ctx, next) {
      const start = new Date()
  
      const timestamp = options.timestamp ? options.timestamp(start) : ''
  
      const request = options.request ? options.request(ctx.req) : ''
  
      console.log(
        '  ' + chalk.gray('-->') +
        chalk.cyan('%s') +
        ' ' + chalk.bold('%s') +
        '%s' +
        ' ' + chalk.gray('%s'),
        timestamp ? ` ${timestamp}` : '',
        options.fullName ? ctx.fullName : ctx.name,
        request ? ` ${request}` : '',
        ctx.type)
  
      return next().then(() => {
        if (!isStream(ctx.res) || (ctx.type !== 'response_stream' && ctx.type !== 'duplex')) {
          return log(options, ctx, start, null, null)
        }
  
        const res = ctx.res
        const onfinish = done.bind(null, 'finish')
        const onclose = done.bind(null, 'close')
        const onend = done.bind(null, 'end')
  
        res.once('finish', onfinish)
        res.once('close', onclose)
        res.once('end', onend)
  
        function done (event) {
          res.removeListener('finish', onfinish)
          res.removeListener('close', onclose)
          res.removeListener('end', onend)
          log(options, ctx, start, null, event)
        }
      }, (err) => {
        log(options, ctx, start, err)
        throw err
      })
    }
  }