function colorize() { if (hasFlag('no-color')) { return false; } if (hasFlag('color')) { return true; } return supportsColor(); }
function addColor(str) { if (hasFlag('no-color')) { return str; } if (hasFlag('color')) { return gray(str); } if (supportsColor(colorDetectionOptions)) { return gray(str); } return str; }
function addColor (str) { if (hasFlag('no-color')) { return str } if (hasFlag('color')) { return gray(str) } if (supportsColor()) { return gray(str) } return str }
function track (instance, opts) { if (!instance) { throw new Error('instance required for tracking') } opts = xtend(defaults, opts) const chalk = new Chalk.constructor({ enabled: testColorSupport({ stream: opts.outputStream }) }) // this default needs to be set after chalk is setup, because chalk is now local to this func opts.progressBarString = opts.progressBarString || `${chalk.green('running')} [:bar] :percent` const iOpts = instance.opts let durationProgressBar let amountProgressBar instance.on('start', () => { if (opts.renderProgressBar) { let msg = `${iOpts.connections} connections` if (iOpts.pipelining > 1) { msg += ` with ${iOpts.pipelining} pipelining factor` } if (!iOpts.amount) { logToStream(`Running ${iOpts.duration}s test @ ${iOpts.url}\n${msg}\n`) durationProgressBar = trackDuration(instance, opts, iOpts) } else { logToStream(`Running ${iOpts.amount} requests test @ ${iOpts.url}\n${msg}\n`) amountProgressBar = trackAmount(instance, opts, iOpts) } } }) // add listeners for progress bar to instance here so they aren't // added on restarting, causing listener leaks // note: Attempted to curry the functions below, but that breaks the functionality // as they use the scope/closure of the progress bar variables to allow them to be reset if (opts.renderProgressBar && opts.outputStream.isTTY) { if (!iOpts.amount) { // duration progress bar instance.on('tick', () => { durationProgressBar.tick() }) instance.on('done', () => { durationProgressBar.tick(iOpts.duration - 1) }) process.once('SIGINT', () => { durationProgressBar.tick(iOpts.duration - 1) }) } else { // amount progress bar instance.on('response', () => { amountProgressBar.tick() }) instance.on('reqError', () => { amountProgressBar.tick() }) instance.on('done', () => { amountProgressBar.tick(iOpts.amount - 1) }) process.once('SIGINT', () => { amountProgressBar.tick(iOpts.amount - 1) }) } } instance.on('done', (result) => { // the code below this `if` just renders the results table... // if the user doesn't want to render the table, we can just return early if (!opts.renderResultsTable) return const out = table([ asColor(chalk.cyan, ['Stat', 'Avg', 'Stdev', 'Max']), asRow(chalk.bold('Latency (ms)'), result.latency), asRow(chalk.bold('Req/Sec'), result.requests), asRow(chalk.bold('Bytes/Sec'), asBytes(result.throughput)) ], { border: getBorderCharacters('void'), columnDefault: { paddingLeft: 0, paddingRight: 1 }, drawHorizontalLine: () => false }) logToStream(out) if (opts.renderLatencyTable) { const latency = table([ asColor(chalk.cyan, ['Percentile', 'Latency (ms)']) ].concat(percentiles.map((perc) => { const key = ('p' + perc).replace('.', '') return [ chalk.bold('' + perc), result.latency[key] ] })), { border: getBorderCharacters('void'), columnDefault: { paddingLeft: 0, paddingRight: 6 }, drawHorizontalLine: () => false }) logToStream(latency) } if (result.non2xx) { logToStream(`${result['2xx']} 2xx responses, ${result.non2xx} non 2xx responses`) } logToStream(`${format(result.requests.total)} requests in ${result.duration}s, ${prettyBytes(result.throughput.total)} read`) if (result.errors) { logToStream(`${format(result.errors)} errors (${format(result.timeouts)} timeouts)`) } }) function logToStream (msg) { opts.outputStream.write(msg + '\n') } }
function track (instance, opts) { if (!instance) { throw new Error('instance required for tracking') } opts = Object.assign({}, defaults, opts) const chalk = new Chalk.constructor({ enabled: testColorSupport({ stream: opts.outputStream }) }) // this default needs to be set after chalk is setup, because chalk is now local to this func opts.progressBarString = opts.progressBarString || `${chalk.green('running')} [:bar] :percent` const iOpts = instance.opts let durationProgressBar let amountProgressBar let addedListeners = false instance.on('start', () => { if (opts.renderProgressBar) { const socketPath = iOpts.socketPath ? ` (${iOpts.socketPath})` : '' let msg = `${iOpts.connections} connections` if (iOpts.pipelining > 1) { msg += ` with ${iOpts.pipelining} pipelining factor` } if (!iOpts.amount) { logToStream(`Running ${iOpts.duration}s test @ ${iOpts.url}${socketPath}\n${msg}\n`) durationProgressBar = trackDuration(instance, opts, iOpts) } else { logToStream(`Running ${iOpts.amount} requests test @ ${iOpts.url}${socketPath}\n${msg}\n`) amountProgressBar = trackAmount(instance, opts, iOpts) } addListener() } }) function addListener () { // add listeners for progress bar to instance here so they aren't // added on restarting, causing listener leaks if (addedListeners) { return } addedListeners = true // note: Attempted to curry the functions below, but that breaks the functionality // as they use the scope/closure of the progress bar variables to allow them to be reset if (opts.outputStream.isTTY) { if (!iOpts.amount) { // duration progress bar instance.on('tick', () => { durationProgressBar.tick() }) instance.on('done', () => { durationProgressBar.tick(iOpts.duration - 1) }) process.once('SIGINT', () => { durationProgressBar.tick(iOpts.duration - 1) }) } else { // amount progress bar instance.on('response', () => { amountProgressBar.tick() }) instance.on('reqError', () => { amountProgressBar.tick() }) instance.on('done', () => { amountProgressBar.tick(iOpts.amount - 1) }) process.once('SIGINT', () => { amountProgressBar.tick(iOpts.amount - 1) }) } } } instance.on('done', (result) => { // the code below this `if` just renders the results table... // if the user doesn't want to render the table, we can just return early if (!opts.renderResultsTable) return const shortLatency = new Table({ head: asColor(chalk.cyan, ['Stat', '2.5%', '50%', '97.5%', '99%', 'Avg', 'Stdev', 'Max']) }) shortLatency.push(asLowRow(chalk.bold('Latency'), asMs(result.latency))) logToStream(shortLatency.toString()) const requests = new Table({ head: asColor(chalk.cyan, ['Stat', '1%', '2.5%', '50%', '97.5%', 'Avg', 'Stdev', 'Min']) }) requests.push(asHighRow(chalk.bold('Req/Sec'), result.requests)) requests.push(asHighRow(chalk.bold('Bytes/Sec'), asBytes(result.throughput))) logToStream(requests.toString()) logToStream('') logToStream('Req/Bytes counts sampled once per second.\n') if (opts.renderLatencyTable) { const latencies = new Table({ head: asColor(chalk.cyan, ['Percentile', 'Latency (ms)']) }) percentiles.map((perc) => { const key = `p${perc}`.replace('.', '_') return [ chalk.bold('' + perc), result.latency[key] ] }).forEach(row => { latencies.push(row) }) logToStream(latencies.toString()) logToStream('') } if (result.non2xx) { logToStream(`${result['2xx']} 2xx responses, ${result.non2xx} non 2xx responses`) } logToStream(`${format(result.requests.total)} requests in ${result.duration}s, ${prettyBytes(result.throughput.total)} read`) if (result.errors) { logToStream(`${format(result.errors)} errors (${format(result.timeouts)} timeouts)`) } }) function logToStream (msg) { opts.outputStream.write(msg + '\n') } }
'use strict'; var fs = require('fs'); var Vinyl = require('vinyl'); var path = require('path'); var through = require('through2'); var PluginError = require('plugin-error'); var supportsColor = require('color-support'); // ______________________________________________ LOGS ______________________________________________ var hasColors = supportsColor(); var red = hasColors ? '\x1b[31m' : ''; var yellow = hasColors ? '\x1b[33m' : ''; var green = hasColors ? '\x1b[32m' : ''; var gray = hasColors ? '\x1b[90m' : ''; var white = hasColors ? '\x1b[97m' : ''; var clear = hasColors ? '\x1b[0m' : ''; var currentColor = undefined; function getTimestamp() { var time = new Date(); var timeInString = ("0" + time.getHours()).slice(-2) + ":" + ("0" + time.getMinutes()).slice(-2) + ":" + ("0" + time.getSeconds()).slice(-2); if (currentColor) { return white + '[' + currentColor + timeInString + clear + white + ']'; }