Metrics per run side by side (#3439)
Adds a new page that show metrics (that exists as friendly names) side by side for all runs. Helpful to use to see the spread of the metrics.
This commit is contained in:
parent
13216a1de6
commit
1acaf332fa
|
|
@ -342,7 +342,6 @@ class HTMLBuilder {
|
|||
const pageRuns = this.pageRuns.filter(
|
||||
run => !!get(pageInfo.data, [run.id, 'run'])
|
||||
);
|
||||
|
||||
let rootPath = this.storageManager.rootPathFromUrl(url, daurlAlias);
|
||||
let data = {
|
||||
daurl: url,
|
||||
|
|
@ -380,6 +379,7 @@ class HTMLBuilder {
|
|||
headers: this.summary,
|
||||
version: packageInfo.version,
|
||||
timestamp: runTimestamp,
|
||||
friendlyNames,
|
||||
context: this.context,
|
||||
pageRuns
|
||||
};
|
||||
|
|
@ -387,10 +387,18 @@ class HTMLBuilder {
|
|||
for (const run of pageRuns) {
|
||||
pugs[run.id] = renderer.renderTemplate(run.id, data);
|
||||
}
|
||||
|
||||
data.pugs = pugs;
|
||||
urlPageRenders.push(
|
||||
this._renderUrlRunPage(url, parseInt(runIndex) + 1, data, daurlAlias)
|
||||
);
|
||||
|
||||
// Do only once per URL
|
||||
if (parseInt(runIndex) === 0) {
|
||||
urlPageRenders.push(
|
||||
this._renderMetricSummaryPage(url, 'metrics', data, daurlAlias)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -486,6 +494,16 @@ class HTMLBuilder {
|
|||
);
|
||||
}
|
||||
|
||||
async _renderMetricSummaryPage(url, name, locals, alias) {
|
||||
log.debug('Render URL metric page %s', name);
|
||||
return this.storageManager.writeHtmlForUrl(
|
||||
renderer.renderTemplate('url/summary/metrics/index', locals),
|
||||
name + '.html',
|
||||
url,
|
||||
alias
|
||||
);
|
||||
}
|
||||
|
||||
async _renderSummaryPage(name, locals) {
|
||||
log.debug('Render summary page %s', name);
|
||||
|
||||
|
|
|
|||
|
|
@ -27,9 +27,12 @@ block content
|
|||
each val, index in runPages
|
||||
- value = Number(index) + 1
|
||||
a(href='./' + value + '.html') #{value}
|
||||
if (value !== Object.keys(runPages).length)
|
||||
if (value === Object.keys(runPages).length)
|
||||
| -
|
||||
|
|
||||
a(href='metrics.html') (side by side)
|
||||
else
|
||||
| -
|
||||
|
|
||||
|
||||
if pageInfo.errors
|
||||
.errors
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
extends ../layout.pug
|
||||
|
||||
block content
|
||||
h1 Metrics per run
|
||||
- const daTitle = daurlAlias ? daurlAlias : daurl
|
||||
h5.url
|
||||
a(href=daurl) #{decodeURIComponent(daTitle)}
|
||||
|
||||
include ../../includes/pageRunInfo
|
||||
|
||||
- const tools = ['browsertime', 'pagexray']
|
||||
- const metrics = {};
|
||||
- for (let tool of Object.keys(friendlyNames)) {
|
||||
- if (tools.indexOf(tool) > -1) {
|
||||
- metrics[tool] = friendlyNames[tool]
|
||||
- }
|
||||
- }
|
||||
|
||||
h3 Side by side
|
||||
.responsive
|
||||
table
|
||||
tr
|
||||
- let run = 1
|
||||
th Metric
|
||||
each page in runPages
|
||||
th
|
||||
b #{run}
|
||||
- run++
|
||||
each tool in Object.keys(metrics)
|
||||
each metricType in Object.keys(metrics[tool])
|
||||
each metric in Object.keys(metrics[tool][metricType])
|
||||
- const friendly = metrics[tool][metricType][metric]
|
||||
- const m = get (runPages[0], 'data.' + tool + '.run.' + (friendly.runPath || friendly.path), 'hepp')
|
||||
if (m !== 'hepp')
|
||||
tr
|
||||
td
|
||||
b #{friendly.name}
|
||||
each page in runPages
|
||||
td #{friendly.format(get (page, 'data.' + tool + '.run.' + (friendly.runPath || friendly.path)))}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
'use strict';
|
||||
const { noop, size, time, co2 } = require('./helpers');
|
||||
const { noop, size, time, co2, httpErrors, decimals } = require('./helpers');
|
||||
|
||||
module.exports = {
|
||||
browsertime: {
|
||||
|
|
@ -7,128 +7,149 @@ module.exports = {
|
|||
firstContentfulPaint: {
|
||||
path: "statistics.timings.paintTiming['first-contentful-paint'].median",
|
||||
summaryPath: "paintTiming['first-contentful-paint']",
|
||||
runPath: "timings.paintTiming['first-contentful-paint']",
|
||||
name: 'First Contentful Paint',
|
||||
format: time.ms
|
||||
},
|
||||
largestContentfulPaint: {
|
||||
path: 'statistics.timings.largestContentfulPaint.renderTime.median',
|
||||
summaryPath: 'timings.largestContentfulPaint',
|
||||
runPath: 'timings.largestContentfulPaint.renderTime',
|
||||
name: 'Largest Contentful Paint',
|
||||
format: time.ms
|
||||
},
|
||||
totalBlockingTime: {
|
||||
path: 'statistics.cpu.longTasks.totalBlockingTime.median',
|
||||
summaryPath: 'cpu.longTasks.totalBlockingTime',
|
||||
runPath: 'cpu.longTasks.totalBlockingTime',
|
||||
name: 'Total Blocking Time',
|
||||
format: time.ms
|
||||
},
|
||||
cumulativeLayoutShift: {
|
||||
path: 'statistics.pageinfo.cumulativeLayoutShift.median',
|
||||
runPath: 'pageinfo.cumulativeLayoutShift',
|
||||
summaryPath: 'pageinfo.cumulativeLayoutShift',
|
||||
name: 'Cumulative Layout Shift',
|
||||
format: noop
|
||||
format: decimals
|
||||
}
|
||||
},
|
||||
timings: {
|
||||
firstPaint: {
|
||||
path: 'statistics.timings.firstPaint.median',
|
||||
summaryPath: 'firstPaint',
|
||||
runPath: 'timings.firstPaint',
|
||||
name: 'First Paint',
|
||||
format: time.ms
|
||||
},
|
||||
firstContentfulPaint: {
|
||||
path: "statistics.timings.paintTiming['first-contentful-paint'].median",
|
||||
summaryPath: "paintTiming['first-contentful-paint']",
|
||||
runPath: "timings.paintTiming['first-contentful-paint']",
|
||||
name: 'First Contentful Paint',
|
||||
format: time.ms
|
||||
},
|
||||
largestContentfulPaint: {
|
||||
path: 'statistics.timings.largestContentfulPaint.renderTime.median',
|
||||
summaryPath: 'timings.largestContentfulPaint',
|
||||
runPath: 'timings.largestContentfulPaint.renderTime',
|
||||
name: 'Largest Contentful Paint',
|
||||
format: time.ms
|
||||
},
|
||||
loadEventEnd: {
|
||||
path: 'statistics.timings.loadEventEnd.median',
|
||||
summaryPath: 'loadEventEnd',
|
||||
runPath: 'timings.loadEventEnd',
|
||||
name: 'Load Event End',
|
||||
format: time.ms
|
||||
},
|
||||
fullyLoaded: {
|
||||
path: 'statistics.timings.fullyLoaded.median',
|
||||
summaryPath: 'timings.fullyLoaded',
|
||||
runPath: 'timings.fullyLoaded',
|
||||
name: 'Fully Loaded',
|
||||
format: time.ms
|
||||
},
|
||||
serverResponseTime: {
|
||||
path: 'statistics.timings.pageTimings.serverResponseTime.median',
|
||||
summaryPath: 'pageTimings.serverResponseTime',
|
||||
runPath: 'timings.pageTimings.serverResponseTime',
|
||||
name: 'Server Response Time',
|
||||
format: time.ms
|
||||
},
|
||||
backEndTime: {
|
||||
path: 'statistics.timings.pageTimings.backEndTime.median',
|
||||
summaryPath: 'pageTimings.backEndTime',
|
||||
runPath: 'timings.pageTimings.backEndTime',
|
||||
name: 'TTFB',
|
||||
format: time.ms
|
||||
},
|
||||
pageLoadTime: {
|
||||
path: 'statistics.timings.pageTimings.pageLoadTime.median',
|
||||
summaryPath: 'pageTimings.pageLoadTime',
|
||||
runPath: 'timings.pageTimings.pageLoadTime',
|
||||
name: 'Page Load Time',
|
||||
format: time.ms
|
||||
},
|
||||
FirstVisualChange: {
|
||||
path: 'statistics.visualMetrics.FirstVisualChange.median',
|
||||
summaryPath: 'visualMetrics.FirstVisualChange',
|
||||
runPath: 'visualMetrics.FirstVisualChange',
|
||||
name: 'First Visual Change',
|
||||
format: time.ms
|
||||
},
|
||||
LastVisualChange: {
|
||||
path: 'statistics.visualMetrics.LastVisualChange.median',
|
||||
name: 'Last Visual Change',
|
||||
summaryPath: 'visualMetrics.LastVisualChange',
|
||||
runPath: 'visualMetrics.LastVisualChange',
|
||||
name: 'Last Visual Change',
|
||||
format: time.ms
|
||||
},
|
||||
SpeedIndex: {
|
||||
path: 'statistics.visualMetrics.SpeedIndex.median',
|
||||
summaryPath: 'visualMetrics.SpeedIndex',
|
||||
runPath: 'visualMetrics.SpeedIndex',
|
||||
name: 'Speed Index',
|
||||
format: time.ms
|
||||
},
|
||||
ContentfulSpeedIndex: {
|
||||
path: 'statistics.visualMetrics.ContentfulSpeedIndex.median',
|
||||
summaryPath: 'visualMetrics.ContentfulSpeedIndex',
|
||||
runPath: 'visualMetrics.ContentfulSpeedIndex',
|
||||
name: 'Contentful Speed Index',
|
||||
format: time.ms
|
||||
},
|
||||
PerceptualSpeedIndex: {
|
||||
path: 'statistics.visualMetrics.PerceptualSpeedIndex.median',
|
||||
summaryPath: 'visualMetrics.PerceptualSpeedIndex',
|
||||
runPath: 'visualMetrics.PerceptualSpeedIndex',
|
||||
name: 'Perceptual Speed Index',
|
||||
format: time.ms
|
||||
},
|
||||
VisualReadiness: {
|
||||
path: 'statistics.visualMetrics.VisualReadiness.median',
|
||||
summaryPath: 'visualMetrics.VisualReadiness',
|
||||
runPath: 'visualMetrics.VisualReadiness',
|
||||
name: 'Visual Readiness',
|
||||
format: time.ms
|
||||
},
|
||||
VisualComplete95: {
|
||||
path: 'statistics.visualMetrics.VisualComplete95.median',
|
||||
summaryPath: 'visualMetrics.VisualComplete95',
|
||||
runPath: 'visualMetrics.VisualComplete95',
|
||||
name: 'Visual Complete 95',
|
||||
format: time.ms
|
||||
},
|
||||
VisualComplete99: {
|
||||
path: 'statistics.visualMetrics.VisualComplete99.median',
|
||||
summaryPath: 'visualMetrics.VisualComplete99',
|
||||
runPath: 'visualMetrics.VisualComplete99',
|
||||
name: 'Visual Complete 99',
|
||||
format: time.ms
|
||||
},
|
||||
VisualComplete: {
|
||||
path: 'statistics.visualMetrics.VisualComplete.median',
|
||||
summaryPath: 'visualMetrics.VisualComplete',
|
||||
runPath: 'visualMetrics.VisualComplete',
|
||||
name: 'Visual Complete',
|
||||
format: time.ms
|
||||
}
|
||||
|
|
@ -137,33 +158,61 @@ module.exports = {
|
|||
totalBlockingTime: {
|
||||
path: 'statistics.cpu.longTasks.totalBlockingTime.median',
|
||||
summaryPath: 'cpu.longTasks.totalBlockingTime',
|
||||
runPath: 'cpu.longTasks.totalBlockingTime',
|
||||
name: 'Total Blocking Time',
|
||||
format: time.ms
|
||||
},
|
||||
maxPotentialFid: {
|
||||
path: 'statistics.cpu.longTasks.maxPotentialFid.median',
|
||||
summaryPath: 'cpu.longTasks.maxPotentialFid',
|
||||
runPath: 'cpu.longTasks.maxPotentialFid',
|
||||
name: 'Max Potential FID',
|
||||
format: time.ms
|
||||
},
|
||||
longTasks: {
|
||||
path: 'statistics.cpu.longTasks.tasks.median',
|
||||
summaryPath: 'cpu.longTasks.tasks',
|
||||
runPath: 'cpu.longTasks.tasks',
|
||||
name: 'Number of Long Tasks',
|
||||
format: noop
|
||||
},
|
||||
longTasksTotalDuration: {
|
||||
path: 'statistics.cpu.longTasks.totalDuration.median',
|
||||
summaryPath: 'cpu.longTasks.totalDuration',
|
||||
runPath: 'cpu.longTasks.totalDuration',
|
||||
name: 'Total Duration of Long Tasks',
|
||||
format: time.ms
|
||||
}
|
||||
},
|
||||
browser: {
|
||||
cpuBenchmark: {
|
||||
path: 'statistics.browser.cpuBenchmark.median',
|
||||
summaryPath: 'browser.cpuBenchmark',
|
||||
runPath: 'browser.cpuBenchmark',
|
||||
name: 'CPU benchmark score',
|
||||
format: time.ms
|
||||
}
|
||||
},
|
||||
pageinfo: {
|
||||
cumulativeLayoutShift: {
|
||||
path: 'statistics.pageinfo.cumulativeLayoutShift.median',
|
||||
summaryPath: 'pageinfo.cumulativeLayoutShift',
|
||||
runPath: 'pageinfo.cumulativeLayoutShift',
|
||||
name: 'Cumulative Layout Shift',
|
||||
format: decimals
|
||||
},
|
||||
domElements: {
|
||||
path: 'statistics.pageinfo.domElements.median',
|
||||
summaryPath: 'pageinfo.domElements',
|
||||
runPath: 'pageinfo.domElements',
|
||||
name: 'DOM elements',
|
||||
format: noop
|
||||
},
|
||||
documentHeight: {
|
||||
path: 'statistics.pageinfo.documentHeight.median',
|
||||
summaryPath: 'pageinfo.documentHeight',
|
||||
runPath: 'pageinfo.documentHeight',
|
||||
name: 'Document height',
|
||||
format: noop
|
||||
}
|
||||
}
|
||||
|
|
@ -196,7 +245,11 @@ module.exports = {
|
|||
name: 'Font Requests',
|
||||
format: noop
|
||||
},
|
||||
httpErrors: { path: 'responseCodes', name: 'HTTP Errors', format: noop }
|
||||
httpErrors: {
|
||||
path: 'responseCodes',
|
||||
name: 'HTTP Errors',
|
||||
format: httpErrors
|
||||
}
|
||||
},
|
||||
transferSize: {
|
||||
total: {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = function(decimals) {
|
||||
let number = Number(decimals).toFixed(3);
|
||||
if (number === '0.000') {
|
||||
return 0;
|
||||
} else return number;
|
||||
};
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = function(httpCodes) {
|
||||
let data = '';
|
||||
for (let code of Object.keys(httpCodes)) {
|
||||
if (Number(code) > 399) {
|
||||
data += `${code}: ${httpCodes[code]} `;
|
||||
}
|
||||
}
|
||||
return data === '' ? '0' : data;
|
||||
};
|
||||
|
|
@ -12,5 +12,7 @@ module.exports = {
|
|||
shortAsset: require('./shortAsset'),
|
||||
co2: require('./co2'),
|
||||
noop: require('./noop'),
|
||||
percent: require('./percent')
|
||||
percent: require('./percent'),
|
||||
httpErrors: require('./httpErrors'),
|
||||
decimals: require('./decimals')
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue