use median values for phantomjd timings

This commit is contained in:
soulgalore 2014-09-17 20:22:12 +02:00
parent 89d4ceb5f3
commit 73e6a0b28d
3 changed files with 275 additions and 279 deletions

View File

@ -5,283 +5,282 @@
* Released under the Apache 2.0 License
*/
var fs = require('fs-extra'),
defaultConfig = require('./default'),
cli = require('nomnom').options({
url: {
abbr: 'u',
metavar: '<URL>',
help: 'The start url'
},
file: {
abbr: 'f',
metavar: '<FILE>',
help: 'The path to a plain text file with one URL on each row. Each line must end with a new line in the file.',
callback: function(file) {
if (!fs.existsSync(file)) {
return 'Could not find the file:' + file;
defaultConfig = require('./default'),
cli = require('nomnom').options({
url: {
abbr: 'u',
metavar: '<URL>',
help: 'The start url'
},
file: {
abbr: 'f',
metavar: '<FILE>',
help: 'The path to a plain text file with one URL on each row. Each line must end with a new line in the file.',
callback: function(file) {
if (!fs.existsSync(file)) {
return 'Could not find the file:' + file;
}
}
}
},
sites: {
metavar: '<FILE>',
help: 'The path to a plain text file with one URL on each row. Each line must end with a new line in the file.',
callback: function(file) {
if (!fs.existsSync(file)) {
return 'Couldnt find the file:' + file;
},
sites: {
metavar: '<FILE>',
help: 'The path to a plain text file with one URL on each row. Each line must end with a new line in the file.',
callback: function(file) {
if (!fs.existsSync(file)) {
return 'Couldnt find the file:' + file;
}
}
}
},
version: {
flag: true,
abbr: 'v',
help: 'Display the sitespeed.io version',
callback: function() {
return require('../package.json').version;
}
},
deep: {
abbr: 'd',
metavar: '<INTEGER>',
default: defaultConfig.deep,
help: 'How deep to crawl.',
callback: function(deep) {
if (deep != parseInt(deep)) { // jshint ignore:line
return 'You must specify an integer of how deep you want to crawl';
},
version: {
flag: true,
abbr: 'v',
help: 'Display the sitespeed.io version',
callback: function() {
return require('../package.json').version;
}
}
},
containInPath: {
abbr: 'c',
metavar: '<KEYWORD>',
help: 'Only crawl URLs that contains this in the path'
},
skip: {
abbr: 's',
metavar: '<KEYWORD>',
help: 'Do not crawl pages that contains this in the path'
},
threads: {
abbr: 't',
metavar: '<NOOFTHREADS>',
default: defaultConfig.threads,
help: 'The number of threads/processes that will analyze pages.',
callback: function(threads) {
if (threads != parseInt(threads)) { // jshint ignore:line
return 'You must specify an integer of how many processes/threads that will analyze your page';
},
deep: {
abbr: 'd',
metavar: '<INTEGER>',
default: defaultConfig.deep,
help: 'How deep to crawl.',
callback: function(deep) {
if (deep != parseInt(deep)) { // jshint ignore:line
return 'You must specify an integer of how deep you want to crawl';
}
}
else if (parseInt(threads) <= 0) {
return 'You must specify a positive integer';
},
containInPath: {
abbr: 'c',
metavar: '<KEYWORD>',
help: 'Only crawl URLs that contains this in the path'
},
skip: {
abbr: 's',
metavar: '<KEYWORD>',
help: 'Do not crawl pages that contains this in the path'
},
threads: {
abbr: 't',
metavar: '<NOOFTHREADS>',
default: defaultConfig.threads,
help: 'The number of threads/processes that will analyze pages.',
callback: function(threads) {
if (threads != parseInt(threads)) { // jshint ignore:line
return 'You must specify an integer of how many processes/threads that will analyze your page';
} else if (parseInt(threads) <= 0) {
return 'You must specify a positive integer';
}
}
}
},
name: {
metavar: '<NAME>',
help: 'Give your test a name, it will be added to all HTML pages'
},
memory: {
metavar: '<INTEGER>',
default: defaultConfig.memory,
help: 'We still use Java for a couple of things and you can configure how much memory that the process will have (in mb).'
},
resultBaseDir: {
abbr: 'r',
metavar: '<DIR>',
default: defaultConfig.resultBaseDir,
help: 'The result base directory',
callback: function(file) {
if (!fs.existsSync(file)) {
fs.mkdirs(file, function(err){
if (err) {
return 'Couldnt create the result base dir:' + err;
}
},
name: {
metavar: '<NAME>',
help: 'Give your test a name, it will be added to all HTML pages'
},
memory: {
metavar: '<INTEGER>',
default: defaultConfig.memory,
help: 'We still use Java for a couple of things and you can configure how much memory that the process will have (in mb).'
},
resultBaseDir: {
abbr: 'r',
metavar: '<DIR>',
default: defaultConfig.resultBaseDir,
help: 'The result base directory',
callback: function(file) {
if (!fs.existsSync(file)) {
fs.mkdirs(file, function(err) {
if (err) {
return 'Couldnt create the result base dir:' + err;
}
});
}
}
}
},
userAgent: {
metavar: '<USER-AGENT>',
default: defaultConfig.userAgent,
help: 'The full User Agent string, default is Chrome for MacOSX. You can also set the value as iphone or ipad (will automagically change the viewport)'
},
viewPort: {
metavar: '<WidthxHeight>',
default: defaultConfig.viewPort,
help: 'The view port, the page viewport size WidthxHeight, like 400x300.'
},
yslow: {
abbr: 'y',
metavar: '<FILE>',
default: defaultConfig.yslow,
help: 'The compiled YSlow file.',
callback: function(file) {
if (!fs.existsSync(file)) {
return 'Couldnt find the file:' + fs.realpathSync(file);
},
userAgent: {
metavar: '<USER-AGENT>',
default: defaultConfig.userAgent,
help: 'The full User Agent string, default is Chrome for MacOSX. You can also set the value as iphone or ipad (will automagically change the viewport)'
},
viewPort: {
metavar: '<WidthxHeight>',
default: defaultConfig.viewPort,
help: 'The view port, the page viewport size WidthxHeight, like 400x300.'
},
yslow: {
abbr: 'y',
metavar: '<FILE>',
default: defaultConfig.yslow,
help: 'The compiled YSlow file.',
callback: function(file) {
if (!fs.existsSync(file)) {
return 'Couldnt find the file:' + fs.realpathSync(file);
}
}
}
},
ruleSet: {
metavar: '<RULE-SET>',
default: defaultConfig.ruleSet,
help: 'Which ruleset to use.'
},
limitFile: {
metavar: '<PATH>',
default: defaultConfig.limitFile,
help: 'The path to the limit configuration file'
},
basicAuth: {
metavar: '<USERNAME:PASSWORD>',
help: 'Basic auth user & password'
},
browser: {
abbr: 'b',
metavar: '<BROWSER>',
help: 'Choose which browser to use to collect timing data. You can set multiple browsers in a comma separated list (firefox|chrome|ie|phantomjs)',
callback: function(browsers) {
var b = browsers.split(','),
invalidBrowsers = b.filter(function(browser) {
return defaultConfig.supportedBrowsers.indexOf(browser) < 0;
});
},
ruleSet: {
metavar: '<RULE-SET>',
default: defaultConfig.ruleSet,
help: 'Which ruleset to use.'
},
limitFile: {
metavar: '<PATH>',
default: defaultConfig.limitFile,
help: 'The path to the limit configuration file'
},
basicAuth: {
metavar: '<USERNAME:PASSWORD>',
help: 'Basic auth user & password'
},
browser: {
abbr: 'b',
metavar: '<BROWSER>',
help: 'Choose which browser to use to collect timing data. You can set multiple browsers in a comma separated list (firefox|chrome|ie|phantomjs)',
callback: function(browsers) {
var b = browsers.split(','),
invalidBrowsers = b.filter(function(browser) {
return defaultConfig.supportedBrowsers.indexOf(browser.toLowerCase()) < 0;
});
if (invalidBrowsers.length > 0) {
return 'You specified a browser that is not supported:' + invalidBrowsers;
if (invalidBrowsers.length > 0) {
return 'You specified a browser that is not supported:' + invalidBrowsers;
}
}
},
profile: {
metavar: '<desktop|mobile>',
choices: ['desktop', 'mobile'],
default: defaultConfig.profile,
help: 'Choose between testing for desktop or mobile. Testing for desktop will use desktop rules & user agents, and vice verca'
},
no: {
abbr: 'n',
metavar: '<NUMBEROFTIMES>',
default: defaultConfig.no,
help: 'The number of times you should test each URL when fetching timing metrics. Default is ' + defaultConfig.no +
' times',
callback: function(n) {
if (n != parseInt(n)) { // jshint ignore:line
return 'You must specify an integer of how many times you want to test one URL';
} else if (parseInt(n) <= 0) {
return 'You must specify a positive integer of how many times you want to test one URL';
}
}
},
screenshot: {
flag: true,
help: 'Take screenshots for each page (using the configured view port).'
},
junit: {
flag: true,
help: 'Create JUnit output'
},
tap: {
flag: true,
help: 'Create TAP output'
},
skipTest: {
metavar: '<ruleid1,ruleid2,...>',
help: 'A comma separeted list of rules to skip when generating JUnit'
},
threshold: {
default: defaultConfig.threshold,
metavar: '[0-100]',
help: 'Threshold score for tests, will be used of no mathing thresholdFile with values match. Use : --threshold 95'
},
thresholdFile: {
metavar: '<FILE>',
help: 'A file containing JSON like {\'overall\': 90, \'thirdpartyversions\': 85}'
},
timingsThresholdFile: {
metavar: '<FILE>',
help: 'A file containing JSON like ...'
},
csv: {
flag: true,
help: 'Also output CSV where applicable'
},
maxPagesToTest: {
abbr: 'm',
metavar: '<NUMBEROFPAGES>',
help: 'The max number of pages to test. Default is no limit'
},
proxy: {
abbr: 'p',
metavar: '<PROXY>',
help: 'http://proxy.soulgalore.com:80'
},
cdns: {
metavar: '<cdn1,cdn2>',
list: true,
help: 'A comma separated list of additional CDNs'
},
boxes: {
metavar: '<box1,box2>',
list: true,
help: 'The boxes showed on site summary page, see http://www.sitespeed.io/documentation/#config-boxes for more info'
},
columns: {
abbr: 'c',
metavar: '<column1,column2>',
list: true,
help: 'The columns showed on detailed page summary table, see http://www.sitespeed.io/documentation/#config-columns for more info'
},
configFile: {
metavar: '<PATH>',
help: 'The path to a sitespeed.io config.json file, if it exists all other input parameters will be overidden'
},
// TODO How to override existing
aggregators: {
metavar: '<PATH>',
help: 'The path to a directory with extra aggregators, see YYY'
},
// TODO maybe collectors are overkill
collectors: {
metavar: '<PATH>',
help: 'The path to a directory with extra collectors, see YYY'
},
graphiteHost: {
metavar: '<HOST>',
help: 'The Graphite host'
},
graphitePort: {
metavar: '<INTEGER>',
default: defaultConfig.graphitePort,
help: 'Graphite port'
},
graphiteNamespace: {
metavar: '<NAMESPACE>',
default: defaultConfig.graphiteNamespace,
help: 'The namespace of the data sent to Graphite'
},
graphiteData: {
default: defaultConfig.graphiteData,
help: 'Choose which data to send to Graphite by a comma separated list. Default all data is sent. [summary,rules,pagemetrics,timings]'
},
gpsiKey: {
help: 'Your Google API Key, configure it to also fetch data from Google Page Speed Insights'
},
noYslow: {
flag: true,
help: 'Set to true to turn of collecting metrics using YSlow.',
},
wptLocation: {
metavar: '<STRING>',
help: 'WebPageTest location, something like Dulles:Chrome ',
},
wptUrl: {
metavar: '<URL>',
help: 'The URL to your private webpagetest instance'
},
wptKey: {
metavar: '<KEY>',
help: 'The API key if running on webpagetest on the public instances'
},
requestHeaders: {
metavar: '<JSON>',
help: 'Any request headers to use, in the JSON form of {\"name\":\"value\",\"name\":\"value\"}. Not supported for WPT & GPSI'
}
},
profile: {
metavar: '<desktop|mobile>',
choices: ['desktop', 'mobile'],
default: defaultConfig.profile,
help: 'Choose between testing for desktop or mobile. Testing for desktop will use desktop rules & user agents, and vice verca'
},
no: {
abbr: 'n',
metavar: '<NUMBEROFTIMES>',
default: defaultConfig.no,
help: 'The number of times you should test each URL when fetching timing metrics. Default is ' + defaultConfig.no + ' times',
callback: function(n) {
if (n != parseInt(n)) { // jshint ignore:line
return 'You must specify an integer of how many times you want to test one URL';
}
else if (parseInt(n) <= 0) {
return 'You must specify a positive integer of how many times you want to test one URL';
}
}
},
screenshot: {
flag: true,
help: 'Take screenshots for each page (using the configured view port).'
},
junit: {
flag: true,
help: 'Create JUnit output'
},
tap: {
flag: true,
help: 'Create TAP output'
},
skipTest: {
metavar: '<ruleid1,ruleid2,...>',
help: 'A comma separeted list of rules to skip when generating JUnit'
},
threshold: {
default: defaultConfig.threshold,
metavar: '[0-100]',
help: 'Threshold score for tests, will be used of no mathing thresholdFile with values match. Use : --threshold 95'
},
thresholdFile: {
metavar: '<FILE>',
help: 'A file containing JSON like {\'overall\': 90, \'thirdpartyversions\': 85}'
},
timingsThresholdFile: {
metavar: '<FILE>',
help: 'A file containing JSON like ...'
},
csv: {
flag: true,
help: 'Also output CSV where applicable'
},
maxPagesToTest: {
abbr: 'm',
metavar: '<NUMBEROFPAGES>',
help: 'The max number of pages to test. Default is no limit'
},
proxy: {
abbr: 'p',
metavar: '<PROXY>',
help: 'http://proxy.soulgalore.com:80'
},
cdns: {
metavar: '<cdn1,cdn2>',
list: true,
help: 'A comma separated list of additional CDNs'
},
boxes: {
metavar: '<box1,box2>',
list: true,
help: 'The boxes showed on site summary page, see http://www.sitespeed.io/documentation/#config-boxes for more info'
},
columns: {
abbr: 'c',
metavar: '<column1,column2>',
list: true,
help: 'The columns showed on detailed page summary table, see http://www.sitespeed.io/documentation/#config-columns for more info'
},
configFile: {
metavar: '<PATH>',
help: 'The path to a sitespeed.io config.json file, if it exists all other input parameters will be overidden'
},
// TODO How to override existing
aggregators: {
metavar: '<PATH>',
help: 'The path to a directory with extra aggregators, see YYY'
},
// TODO maybe collectors are overkill
collectors: {
metavar: '<PATH>',
help: 'The path to a directory with extra collectors, see YYY'
},
graphiteHost: {
metavar: '<HOST>',
help: 'The Graphite host'
},
graphitePort: {
metavar: '<INTEGER>',
default: defaultConfig.graphitePort,
help: 'Graphite port'
},
graphiteNamespace: {
metavar: '<NAMESPACE>',
default: defaultConfig.graphiteNamespace,
help: 'The namespace of the data sent to Graphite'
},
graphiteData: {
default: defaultConfig.graphiteData,
help: 'Choose which data to send to Graphite by a comma separated list. Default all data is sent. [summary,rules,pagemetrics,timings]'
},
gpsiKey: {
help: 'Your Google API Key, configure it to also fetch data from Google Page Speed Insights'
},
noYslow: {
flag: true,
help: 'Set to true to turn of collecting metrics using YSlow.',
},
wptLocation: {
metavar: '<STRING>',
help: 'WebPageTest location, something like Dulles:Chrome ',
},
wptUrl: {
metavar: '<URL>',
help: 'The URL to your private webpagetest instance'
},
wptKey: {
metavar: '<KEY>',
help: 'The API key if running on webpagetest on the public instances'
},
requestHeaders: {
metavar: '<JSON>',
help: 'Any request headers to use, in the JSON form of {\"name\":\"value\",\"name\":\"value\"}. Not supported for WPT & GPSI'
}
}).parse();
}).parse();
module.exports = cli;
module.exports = cli;

View File

@ -186,20 +186,17 @@ function collectGPSI(pageData, p) {
}
function collectPhantomJS(pageData, p) {
// for now just take the first value, in the future calculate median etc
var timingsWeWillPush = ['min', 'mean', 'median', 'p90', 'p99', 'max'];
p.phantomjs = {};
pageData.phantomjs.runs.forEach(function(run) {
Object.keys(run.timings).forEach(function(timing) {
p.phantomjs[timing] = {
'v': run.timings[timing],
pageData.phantomjs.getStats().forEach(function(timing) {
p.phantomjs[timing.id] = {};
timingsWeWillPush.forEach(function(number) {
p.phantomjs[timing.id][number] = {
'v': timing.stats[number],
'unit': 'milliseconds'
};
});
});
console.log(JSON.stringify(p.phantomjs));
}

View File

@ -402,7 +402,7 @@ function setupConfiguration(config) {
if (config.browser) {
var b = config.browser.split(','),
configuredBrowsers = b.filter(function(browser) {
return supportedBrowsers.indexOf(browser) > -1;
return supportedBrowsers.indexOf(browser.toLowerCase()) > -1;
});
if (configuredBrowsers.indexOf('phantomjs') > -1) {
@ -516,7 +516,7 @@ function setupConfiguration(config) {
else if (config.phantomjs) {
config.summaryBoxes.push('domContentLoadedTimePhantomJS', 'pageLoadTimePhantomJS');
config.sitesColumns.push('domContentLoadedTimePhantomJS');
config.pageColumns.push('phantomjs.domContentLoadedTime');
config.pageColumns.push('phantomjs.domContentLoadedTime.median');
}
if (config.boxes) {