Statistics for PageXray per URL (#4061)
* Collect the standard PageXray statistics
This commit is contained in:
parent
28916076fc
commit
f3a28fa731
|
|
@ -105,7 +105,6 @@ export default class PageXrayPlugin extends SitespeedioPlugin {
|
|||
}
|
||||
}
|
||||
this.pageXrayAggregator.addToAggregate(pageSummary, group);
|
||||
|
||||
if (this.multi) {
|
||||
// The HAR file can have multiple URLs
|
||||
const sentURL = {};
|
||||
|
|
@ -116,6 +115,9 @@ export default class PageXrayPlugin extends SitespeedioPlugin {
|
|||
sentURL[summary.url] += 1;
|
||||
} else {
|
||||
sentURL[summary.url] = 1;
|
||||
summary.statistics = this.pageXrayAggregator.summarizePerUrl(
|
||||
summary.url
|
||||
);
|
||||
queue.postMessage(
|
||||
make('pagexray.pageSummary', summary, {
|
||||
url: summary.url,
|
||||
|
|
@ -134,6 +136,9 @@ export default class PageXrayPlugin extends SitespeedioPlugin {
|
|||
);
|
||||
}
|
||||
} else {
|
||||
pageSummary[0].statistics = this.pageXrayAggregator.summarizePerUrl(
|
||||
message.url
|
||||
);
|
||||
queue.postMessage(
|
||||
make('pagexray.pageSummary', pageSummary[0], {
|
||||
url: message.url,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,16 @@
|
|||
import forEach from 'lodash.foreach';
|
||||
|
||||
import { pushGroupStats, setStatsSummary } from '../../support/statsHelpers.js';
|
||||
import {
|
||||
pushGroupStats,
|
||||
setStatsSummary,
|
||||
pushStats
|
||||
} from '../../support/statsHelpers.js';
|
||||
|
||||
const METRIC_NAMES = ['transferSize', 'contentSize', 'requests'];
|
||||
|
||||
export class PageXrayAggregator {
|
||||
constructor() {
|
||||
this.urls = {};
|
||||
this.stats = {};
|
||||
this.groups = {};
|
||||
}
|
||||
|
|
@ -19,6 +24,11 @@ export class PageXrayAggregator {
|
|||
let groups = this.groups;
|
||||
|
||||
for (const summary of pageSummary) {
|
||||
let url = summary.url;
|
||||
if (this.urls[url] === undefined) {
|
||||
this.urls[url] = {};
|
||||
}
|
||||
|
||||
// stats for the whole page
|
||||
for (const metric of METRIC_NAMES) {
|
||||
// There's a bug in Firefox/https://github.com/devtools-html/har-export-trigger
|
||||
|
|
@ -26,6 +36,7 @@ export class PageXrayAggregator {
|
|||
// https://github.com/sitespeedio/sitespeed.io/issues/2090
|
||||
if (!Number.isNaN(summary[metric])) {
|
||||
pushGroupStats(stats, groups[group], metric, summary[metric]);
|
||||
pushStats(this.urls[url], metric, summary[metric]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -41,6 +52,12 @@ export class PageXrayAggregator {
|
|||
'contentTypes.' + contentType + '.' + metric,
|
||||
summary.contentTypes[contentType][metric]
|
||||
);
|
||||
|
||||
pushStats(
|
||||
this.urls[url],
|
||||
'contentTypes.' + contentType + '.' + metric,
|
||||
summary.contentTypes[contentType][metric]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -52,6 +69,12 @@ export class PageXrayAggregator {
|
|||
'responseCodes.' + responseCode,
|
||||
summary.responseCodes[responseCode]
|
||||
);
|
||||
|
||||
pushStats(
|
||||
this.urls[url],
|
||||
'responseCodes.' + responseCode,
|
||||
summary.responseCodes[responseCode]
|
||||
);
|
||||
}
|
||||
/*
|
||||
for (const responseCode of Object.keys(summary.responseCodes)) {
|
||||
|
|
@ -73,6 +96,11 @@ export class PageXrayAggregator {
|
|||
'firstParty' + '.' + metric,
|
||||
summary.firstParty[metric]
|
||||
);
|
||||
pushStats(
|
||||
this.urls[url],
|
||||
'firstParty' + '.' + metric,
|
||||
summary.firstParty[metric]
|
||||
);
|
||||
}
|
||||
if (summary.thirdParty[metric] !== undefined) {
|
||||
pushGroupStats(
|
||||
|
|
@ -81,6 +109,12 @@ export class PageXrayAggregator {
|
|||
'thirdParty' + '.' + metric,
|
||||
summary.thirdParty[metric]
|
||||
);
|
||||
|
||||
pushStats(
|
||||
this.urls[url],
|
||||
'thirdParty' + '.' + metric,
|
||||
summary.thirdParty[metric]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -107,6 +141,9 @@ export class PageXrayAggregator {
|
|||
});
|
||||
}
|
||||
}
|
||||
summarizePerUrl(url) {
|
||||
return this.summarizePerObject(this.urls[url]);
|
||||
}
|
||||
summarize() {
|
||||
if (Object.keys(this.stats).length === 0) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -239,177 +239,249 @@ export default {
|
|||
},
|
||||
pagexray: {
|
||||
requests: {
|
||||
total: { path: 'requests', name: 'Total Requests', format: noop },
|
||||
total: {
|
||||
path: 'statistics.requests.median',
|
||||
summaryPath: 'requests',
|
||||
runPath: 'requests',
|
||||
name: 'Total Requests',
|
||||
format: noop
|
||||
},
|
||||
html: {
|
||||
path: 'contentTypes.html.requests',
|
||||
path: 'statistics.contentTypes.html.requests.median',
|
||||
summaryPath: 'contentTypes.html.requests',
|
||||
runPath: 'contentTypes.html.requests',
|
||||
name: 'HTML Requests',
|
||||
format: noop
|
||||
},
|
||||
javascript: {
|
||||
path: 'rontentTypes.javascript.requests',
|
||||
path: 'statistics.contentTypes.javascript.requests.median',
|
||||
summaryPath: 'contentTypes.javascript.requests',
|
||||
runPath: 'contentTypes.javascript.requests',
|
||||
name: 'JavaScript Requests',
|
||||
format: noop
|
||||
},
|
||||
css: {
|
||||
path: 'contentTypes.css.request',
|
||||
path: 'statistics.contentTypes.css.requests.median',
|
||||
summaryPath: 'contentTypes.css.requests',
|
||||
runPath: 'contentTypes.css.requests',
|
||||
name: 'CSS Requests',
|
||||
format: noop
|
||||
},
|
||||
image: {
|
||||
path: 'contentTypes.image.requests',
|
||||
path: 'statistics.contentTypes.images.requests.median',
|
||||
summaryPath: 'contentTypes.images.requests',
|
||||
runPath: 'contentTypes.images.requests',
|
||||
name: 'Image Requests',
|
||||
format: noop
|
||||
},
|
||||
font: {
|
||||
path: 'contentTypes.font.requests',
|
||||
path: 'statistics.contentTypes.font.requests.median',
|
||||
summaryPath: 'contentTypes.font.requests',
|
||||
runPath: 'contentTypes.font.requests',
|
||||
name: 'Font Requests',
|
||||
format: noop
|
||||
},
|
||||
httpErrors: {
|
||||
path: 'responseCodes',
|
||||
path: 'statistics.responseCodes.median',
|
||||
summaryPath: 'responseCodes',
|
||||
runPath: 'responseCodes',
|
||||
name: 'HTTP Errors',
|
||||
format: httpErrors
|
||||
}
|
||||
},
|
||||
transferSize: {
|
||||
total: {
|
||||
path: 'transferSize',
|
||||
path: 'statistics.transferSize.median',
|
||||
summaryPath: 'transferSize',
|
||||
runPath: 'transferSize',
|
||||
name: 'Total Transfer Size',
|
||||
format: size.format
|
||||
},
|
||||
html: {
|
||||
path: 'contentTypes.html.transferSize',
|
||||
path: 'statistics.contentTypes.html.transferSize.median',
|
||||
summaryPath: 'contentTypes.html.transferSize',
|
||||
runPath: 'contentTypes.html.transferSize',
|
||||
name: 'HTML Transfer Size',
|
||||
format: size.format
|
||||
},
|
||||
javascript: {
|
||||
path: 'contentTypes.javascript.transferSize',
|
||||
path: 'statistics.contentTypes.javascript.transferSize.median',
|
||||
summaryPath: 'contentTypes.javascript.transferSize',
|
||||
runPath: 'contentTypes.javascript.transferSize',
|
||||
name: 'JavaScript Transfer Size',
|
||||
format: size.format
|
||||
},
|
||||
css: {
|
||||
path: 'contentTypes.css.transferSize',
|
||||
path: 'statistics.contentTypes.css.transferSize.median',
|
||||
summaryPath: 'contentTypes.css.transferSize',
|
||||
runPath: 'contentTypes.css.transferSize',
|
||||
name: 'CSS Transfer Size',
|
||||
format: size.format
|
||||
},
|
||||
image: {
|
||||
path: 'contentTypes.image.transferSize',
|
||||
path: 'statistics.contentTypes.image.transferSize.median',
|
||||
summaryPath: 'contentTypes.image.transferSize',
|
||||
runPath: 'contentTypes.iamge.transferSize',
|
||||
name: 'Image Transfer Size',
|
||||
format: size.format
|
||||
},
|
||||
font: {
|
||||
path: 'contentTypes.font.transferSize',
|
||||
path: 'statistics.contentTypes.font.transferSize.median',
|
||||
summaryPath: 'contentTypes.font.transferSize',
|
||||
runPath: 'contentTypes.font.transferSize',
|
||||
name: 'Font Transfer Size',
|
||||
format: size.format
|
||||
},
|
||||
favicon: {
|
||||
path: 'contentTypes.favicon.transferSize',
|
||||
path: 'statistics.contentTypes.favicon.transferSize.median',
|
||||
summaryPath: 'contentTypes.favicon.transferSize',
|
||||
runPath: 'contentTypes.favicon.transferSize',
|
||||
name: 'Favicon Transfer Size',
|
||||
format: size.format
|
||||
},
|
||||
json: {
|
||||
path: 'contentTypes.json.transferSize',
|
||||
path: 'statistics.contentTypes.json.transferSize.median',
|
||||
summaryPath: 'contentTypes.json.transferSize',
|
||||
runPath: 'contentTypes.json.transferSize',
|
||||
name: 'JSON Transfer Size',
|
||||
format: size.format
|
||||
},
|
||||
other: {
|
||||
path: 'contentTypes.other.transferSize',
|
||||
path: 'statistics.contentTypes.other.transferSize.median',
|
||||
summaryPath: 'contentTypes.other.transferSize',
|
||||
runPath: 'contentTypes.other.transferSize',
|
||||
name: 'Other Transfer Size',
|
||||
format: size.format
|
||||
},
|
||||
plain: {
|
||||
path: 'contentTypes.plain.transferSize',
|
||||
path: 'statistics.contentTypes.plain.transferSize.median',
|
||||
summaryPath: 'contentTypes.plain.transferSize',
|
||||
runPath: 'contentTypes.plain.transferSize',
|
||||
name: 'Plain Transfer Size',
|
||||
format: size.format
|
||||
},
|
||||
svg: {
|
||||
path: 'contentTypes.svg.transferSize',
|
||||
path: 'statistics.contentTypes.svg.transferSize.median',
|
||||
summaryPath: 'contentTypes.svg.transferSize',
|
||||
runPath: 'contentTypes.svg.transferSize',
|
||||
name: 'SVG Transfer Size',
|
||||
format: size.format
|
||||
}
|
||||
},
|
||||
contentSize: {
|
||||
total: {
|
||||
path: 'contentSize',
|
||||
path: 'statistics.contentSize.median',
|
||||
summaryPath: 'contentSize',
|
||||
runPath: 'contentSize',
|
||||
name: 'Total Content Size',
|
||||
format: size.format
|
||||
},
|
||||
html: {
|
||||
path: 'contentTypes.html.contentSize',
|
||||
path: 'statistics.contentTypes.html.contentSize.median',
|
||||
summaryPath: 'contentTypes.html.contentSize',
|
||||
runPath: 'contentTypes.html.contentSize',
|
||||
name: 'HTML Content Size',
|
||||
format: size.format
|
||||
},
|
||||
javascript: {
|
||||
path: 'contentTypes.javascript.contentSize',
|
||||
path: 'statistics.contentTypes.javascript.contentSize.median',
|
||||
summaryPath: 'contentTypes.javascript.contentSize',
|
||||
runPath: 'contentTypes.javascript.contentSize',
|
||||
name: 'JavaScript Content Size',
|
||||
format: size.format
|
||||
},
|
||||
css: {
|
||||
path: 'contentTypes.css.contentSize',
|
||||
path: 'statistics.contentTypes.css.contentSize.median',
|
||||
summaryPath: 'contentTypes.css.contentSize',
|
||||
runPath: 'contentTypes.css.contentSize',
|
||||
name: 'CSS Content Size',
|
||||
format: size.format
|
||||
},
|
||||
image: {
|
||||
path: 'contentTypes.image.contentSize',
|
||||
path: 'statistics.contentTypes.image.contentSize.median',
|
||||
summaryPath: 'contentTypes.image.contentSize',
|
||||
runPath: 'contentTypes.image.contentSize',
|
||||
name: 'Image Content Size',
|
||||
format: size.format
|
||||
},
|
||||
font: {
|
||||
path: 'contentTypes.font.contentSize',
|
||||
path: 'statistics.contentTypes.font.contentSize.median',
|
||||
summaryPath: 'contentTypes.font.contentSize',
|
||||
runPath: 'contentTypes.font.contentSize',
|
||||
name: 'Font Content Size',
|
||||
format: size.format
|
||||
},
|
||||
favicon: {
|
||||
path: 'contentTypes.favicon.contentSize',
|
||||
path: 'statistics.contentTypes.favicon.contentSize.median',
|
||||
summaryPath: 'contentTypes.favicon.contentSize',
|
||||
runPath: 'contentTypes.favicon.contentSize',
|
||||
name: 'Favicon Content Size',
|
||||
format: size.format
|
||||
},
|
||||
json: {
|
||||
path: 'contentTypes.json.contentSize',
|
||||
path: 'statistics.contentTypes.json.contentSize.median',
|
||||
summaryPath: 'contentTypes.json.contentSize',
|
||||
runPath: 'contentTypes.json.contentSize',
|
||||
name: 'JSON Content Size',
|
||||
format: size.format
|
||||
},
|
||||
other: {
|
||||
path: 'contentTypes.other.contentSize',
|
||||
path: 'statistics.contentTypes.other.contentSize.median',
|
||||
summaryPath: 'contentTypes.other.contentSize',
|
||||
runPath: 'contentTypes.other.contentSize',
|
||||
name: 'Other Content Size',
|
||||
format: size.format
|
||||
},
|
||||
plain: {
|
||||
path: 'contentTypes.plain.contentSize',
|
||||
path: 'statistics.contentTypes.plain.contentSize.median',
|
||||
summaryPath: 'contentTypes.plain.contentSize',
|
||||
runPath: 'contentTypes.plain.contentSize',
|
||||
name: 'Plain Content Size',
|
||||
format: size.format
|
||||
},
|
||||
svg: {
|
||||
path: 'contentTypes.svg.contentSize',
|
||||
path: 'statistics.contentTypes.svg.contentSize.median',
|
||||
summaryPath: 'contentTypes.svg.contentSize',
|
||||
runPath: 'contentTypes.svg.contentSize',
|
||||
name: 'SVG Content Size',
|
||||
format: size.format
|
||||
}
|
||||
},
|
||||
thirdParty: {
|
||||
transferSize: {
|
||||
path: 'thirdParty.transferSize',
|
||||
path: 'statistics.thirdParty.transferSize.median',
|
||||
summaryPath: 'thirdParty.transferSize',
|
||||
runPath: 'thirdParty.transferSize',
|
||||
name: 'Third Party Transfer Size',
|
||||
format: size.format
|
||||
},
|
||||
requests: {
|
||||
path: 'thirdParty.requests',
|
||||
path: 'statistics.thirdParty.requests.median',
|
||||
summaryPath: 'thirdParty.requests',
|
||||
runPath: 'thirdParty.requests',
|
||||
name: 'Third Party Requests',
|
||||
format: noop
|
||||
}
|
||||
},
|
||||
firstParty: {
|
||||
requests: {
|
||||
path: 'firstParty.requests',
|
||||
path: 'statistics.firstParty.requests.median',
|
||||
summaryPath: 'firstParty.requests',
|
||||
runPath: 'firstParty.requests',
|
||||
name: 'First Party Requests',
|
||||
format: noop
|
||||
},
|
||||
transferSize: {
|
||||
path: 'firstParty.transferSize',
|
||||
path: 'statistics.firstParty.transferSize.median',
|
||||
summaryPath: 'firstParty.transferSize',
|
||||
runPath: 'firstParty.transferSize',
|
||||
name: 'First Party Total Transfer Size',
|
||||
format: size.format
|
||||
},
|
||||
contentSize: {
|
||||
path: 'firstParty.contentSize',
|
||||
path: 'statistics.firstParty.contentSize.median',
|
||||
summaryPath: 'firstParty.contentSize',
|
||||
runPath: 'firstParty.contentSize',
|
||||
name: 'First Party Total Content Size',
|
||||
format: size.format
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,12 @@ export function summarizeStats(stats, options) {
|
|||
|
||||
let data = {
|
||||
median: Number.parseFloat(stats.median().toFixed(decimals)),
|
||||
mean: Number.parseFloat(stats.amean().toFixed(decimals))
|
||||
mean: Number.parseFloat(stats.amean().toFixed(decimals)),
|
||||
rsd:
|
||||
stats.stddev() > 0
|
||||
? Number.parseFloat((100 * stats.stddev()) / stats.amean())
|
||||
: 0, // Relative standard deviation
|
||||
stddev: Number.parseFloat(stats.stddev().toFixed(decimals))
|
||||
};
|
||||
for (const p of percentiles) {
|
||||
let name = percentileName(p);
|
||||
|
|
|
|||
Loading…
Reference in New Issue