function convert(filename) {
let contents = fs.readFileSync(filename, 'utf8');
if (filename.endsWith('json')) {
let json = JSON.parse(contents);
let yaml = YAML.dump(json);
let newFilename = path.basename(filename, '.json') + '.yml';
if (!fs.existsSync(newFilename)) {
fs.writeFileSync(newFilename, yaml, 'utf8');
} else {
console.log(`File ${newFilename} already exists, not overwriting`);
process.exit(1);
}
} else if (filename.endsWith('yml') || filename.endsWith('yaml')) {
let yaml = YAML.load(contents);
let json = JSON.stringify(yaml, null, 2);
let newFilename = path.basename(filename, '.yml') + '.json';
if (!fs.existsSync(newFilename)) {
fs.writeFileSync(newFilename, json, 'utf8');
} else {
console.log(`File ${newFilename} already exists, not overwriting`);
process.exit(1);
}
} else {
console.log('File name should end with json or y[a]ml');
}
}n/a
function dino(options) {
const balloon = !options.quiet ?
' ____________\n' +
'< artillery! >\n' +
' ------------\n'
:
' _______________________\n' +
'< You can\'t silence me! >\n' +
' -----------------------\n';
console.log(balloon +
' \\\n' +
' \\');
let today = new Date();
let year = today.getFullYear();
let month = today.getMonth() + 1;
let day = today.getDate();
let i = year * month * day % dinos.length;
console.log(dinos[i]);
}n/a
function quick(url, options) {
var rate = options.r || options.rate;
var duration = options.d || options.duration;
var arrivalCount = options.c || options.count;
let script = {
config: {
target: '',
phases: [
],
mode: 'uniform'
},
scenarios: [
{
flow: [
]
}
]
};
let p = parse(url);
let target = p.protocol + '//' + p.host;
script.config.target = target;
if (options.count && options.rate) {
console.log('Error: either a fixed number of arrivals or arrivals per ' +
'second should be set, not both');
process.exit(1);
}
if (options.insecure && p.protocol.match(/https/)) {
script.config.tls = {
rejectUnauthorized: false
};
}
if (options.rate) {
script.config.phases.push({
duration: options.duration || 60,
arrivalRate: options.rate || 20
});
} else if (options.count) {
script.config.phases.push({
duration: options.duration || Math.ceil(options.count / 50),
arrivalCount: options.count || 1
});
} else {
console.log('Error: either arrival rate or an arrival count must be ' +
'specified');
process.exit(1);
}
let requestSpec = {};
if (options.payload && p.protocol.match(/http/)) {
requestSpec.post = {
url: url,
headers: {'Content-Type': options.contentType || 'application/json'},
body: options.payload || ''
};
} else if (options.payload && p.protocol.match(/ws/)) {
requestSpec.send = options.payload;
} else if (p.protocol.match(/http/)) {
requestSpec.get = {url: url};
} else if (p.protocol.match(/ws/)) {
requestSpec.send = 'hello from Artillery';
} else {
throw new Error('Unknown protocol');
}
if (options.num) {
requestSpec = {
loop: [requestSpec],
count: options.num
};
}
debug('requestSpec: %s', JSON.stringify(requestSpec, null, 2));
script.scenarios[0].flow.push(requestSpec);
if (p.protocol.match(/ws/)) {
script.scenarios[0].engine = 'ws';
}
let tmpf = tmp.fileSync();
fs.writeFileSync(tmpf.name, JSON.stringify(script, null, 2), {flag: 'w'});
run(tmpf.name, {quiet: options.quiet, output: options.output});
}n/a
function report(jsonReportPath, options) {
let reportFilename = options.output || jsonReportPath + '.html';
let data = JSON.parse(fs.readFileSync(jsonReportPath, 'utf-8'));
let templateFn = path.join(
path.dirname(__filename),
'../report/index.html.ejs');
let template = fs.readFileSync(templateFn, 'utf-8');
let compiledTemplate = l.template(template);
let html = compiledTemplate({report: JSON.stringify(data, null, 2)});
fs.writeFileSync(
reportFilename,
html,
{encoding: 'utf-8', flag: 'w'});
console.log('Report generated: %s', reportFilename);
if (!options.output) {
openfile(reportFilename);
}
}...
phase.index,
(phase.name ? ' (' + phase.name + ')' : ''),
phase.duration || phase.think);
spinnerOn();
});
runner.events.on('stats', function(stats) {
let report = stats.report();
intermediates.push(report);
spinnerOff();
log('Report for the previous %ss @ %s',
script.config.statsInterval,
report.timestamp);
if (!options.quiet) {
printReport(report);
...function run(scriptPath, options) {
let logfile;
// is the destination a directory that exists?
let isDir = false;
if (options.output && options.output !== defaultOptions.output) {
try {
isDir = fs.statSync(options.output).isDirectory();
} catch (err) {
// ENOENT, don't need to do anything
}
}
const defaultFormat = '[artillery_report_]YMMDD_HHmmSS[.json]';
if (!isDir && options.output) {
// -o is set with a filename (existing or not)
logfile = options.output;
} else if (!isDir && !options.output) {
// no -o set
logfile = moment().format(defaultOptions.output ||
defaultFormat);
} else {
// -o is set with a directory
logfile = path.join(options.output, moment().format(defaultOptions.output ||
defaultFormat));
}
function log() {
if (options.quiet) { return; }
console.log.apply(console, arguments);
}
async.waterfall([
async.constant(scriptPath),
readScript,
parseScript,
checkTimersBug,
checkIfXPathIsUsed,
function(script, callback) {
return callback(null, script, scriptPath, options);
},
checkConfig,
readPayload
], function done(err, script) {
if (err) {
console.log(err.message);
process.exit(1);
}
script.config.statsInterval = script.config.statsInterval || 10;
log('Log file: %s', logfile);
var spinnerOn = function() {
if (!options.quiet && process.stdout.isTTY) {
cli.spinner('');
}
};
var spinnerOff = function() {
if (!options.quiet && process.stdout.isTTY) {
cli.spinner('', true);
}
};
let runner = createRunner(script,
script.payload,
{
environment: options.environment,
// This is used in the worker to resolve
// the path to the processor module
scriptPath: scriptPath
});
let intermediates = [];
runner.events.on('phaseStarted', function(phase) {
spinnerOff();
log(
'Phase %s%s started - duration: %ss',
phase.index,
(phase.name ? ' (' + phase.name + ')' : ''),
phase.duration || phase.think);
spinnerOn();
});
runner.events.on('stats', function(stats) {
let report = stats.report();
intermediates.push(report);
spinnerOff();
log('Report for the previous %ss @ %s',
script.config.statsInterval,
report.timestamp);
if (!options.quiet) {
printReport(report);
}
spinnerOn();
});
runner.events.on('done', function(allStats) {
let report = allStats.report();
delete report.concurrency; // doesn't make sense in this context
delete report.pendingRequests;
spinnerOff();
log('all scenarios completed');
log('Complete report @ %s', report.timestamp);
if (!options.quiet) {
printReport(report, { showScenarioCounts: true });
}
report.phases = _.get(script, 'config.phases', []);
delete report.latencies;
fs.writeFileSync(
logfile, JSON.stringify({
aggregate: report,
intermediate: intermediates
}, null, 2),
{flag: 'w'});
if (script.config.ensure) {
const latency = report.latency;
_.each(script.config.ensure, function(max, k) {
let bucket = k === 'p50' ? 'median' : k;
if (latency[bucket]) {
if (latency[bucket] > max) {
const msg = util.format(
'ensure condition failed: ensure.%s < %s', bucket, max);
log(msg);
process.exit(1);
}
}
});
}
});
spinnerOn();
runner.run(); ......
var runner = createRunner(opts.script, opts.payload, opts.options);
runner.on('phaseStarted', onPhaseStarted);
runner.on('phaseCompleted', onPhaseCompleted);
runner.on('stats', onStats);
runner.on('done', onDone);
runner.run();
function onPhaseStarted(phase) {
send({ event: 'phaseStarted', phase: phase });
}
function onPhaseCompleted(phase) {
send({ event: 'phaseCompleted', phase: phase });
...