feat(Page): Support Page.getMetrics and metrics event. (#939)
Provides access to the current page performance metrics. Allows to push page metrics from the page JavaScript with console.timeStamp() Fixes #309
This commit is contained in:
parent
77d3c2972f
commit
b82d3197ed
32
docs/api.md
32
docs/api.md
@ -25,6 +25,7 @@
|
||||
+ [event: 'framedetached'](#event-framedetached)
|
||||
+ [event: 'framenavigated'](#event-framenavigated)
|
||||
+ [event: 'load'](#event-load)
|
||||
+ [event: 'metrics'](#event-metrics)
|
||||
+ [event: 'pageerror'](#event-pageerror)
|
||||
+ [event: 'request'](#event-request)
|
||||
+ [event: 'requestfailed'](#event-requestfailed)
|
||||
@ -49,6 +50,7 @@
|
||||
+ [page.exposeFunction(name, puppeteerFunction)](#pageexposefunctionname-puppeteerfunction)
|
||||
+ [page.focus(selector)](#pagefocusselector)
|
||||
+ [page.frames()](#pageframes)
|
||||
+ [page.getMetrics()](#pagegetmetrics)
|
||||
+ [page.goBack(options)](#pagegobackoptions)
|
||||
+ [page.goForward(options)](#pagegoforwardoptions)
|
||||
+ [page.goto(url, options)](#pagegotourl-options)
|
||||
@ -326,6 +328,15 @@ Emitted when a frame is navigated to a new url.
|
||||
|
||||
Emitted when the JavaScript [`load`](https://developer.mozilla.org/en-US/docs/Web/Events/load) event is dispatched.
|
||||
|
||||
#### event: 'metrics'
|
||||
- <[Object]>
|
||||
- `title` <[string]> The title passed to `console.timeStamp`.
|
||||
- `metrics` <[Object]> Object containing metrics as key/value pairs. The values
|
||||
of metrics are of <[number]> type.
|
||||
|
||||
Emitted when the JavaScript code makes a call to `console.timeStamp`. For the list
|
||||
of metrics see `page.getMetrics`.
|
||||
|
||||
#### event: 'pageerror'
|
||||
- <[string]> The exception message
|
||||
|
||||
@ -637,6 +648,27 @@ If there's no element matching `selector`, the method throws an error.
|
||||
#### page.frames()
|
||||
- returns: <[Array]<[Frame]>> An array of all frames attached to the page.
|
||||
|
||||
#### page.getMetrics()
|
||||
- returns: <[Object]> Object containing metrics as key/value pairs.
|
||||
- `Timestamp` <[number]> The timestamp when the metrics sample was taken.
|
||||
- `DocumentCount` <[number]> Number of documents in the page.
|
||||
- `FrameCount` <[number]> Number of frames in the page.
|
||||
- `JSEventListenerCount` <[number]> Number of events in the page.
|
||||
- `NodeCount` <[number]> Number of DOM nodes in the page.
|
||||
- `LayoutCount` <[number]> Total number of full or partial page layout.
|
||||
- `RecalcStyleCount` <[number]> Total number of page style recalculations.
|
||||
- `LayoutDuration` <[number]> Combined durations of all page layouts.
|
||||
- `RecalcStyleDuration` <[number]> Combined duration of all page style recalculations.
|
||||
- `ScriptDuration` <[number]> Combined duration of JavaScript execution.
|
||||
- `TaskDuration` <[number]> Combined duration of all tasks performed by the browser.
|
||||
- `JSHeapUsedSize` <[number]> Used JavaScript heap size.
|
||||
- `JSHeapTotalSize` <[number]> Total JavaScript heap size.
|
||||
- `FirstMeaningfulPaint` <[number]> Timestamp of the first meaningful paint event.
|
||||
- `DomContentLoaded` <[number]> Timestamp of the DOM content loaded event.
|
||||
- `NavigationStart` <[number]> Timestamp of the navigation start event.
|
||||
|
||||
> **NOTE** All timestamps are in monotonic time: monotonically increasing time in seconds since an arbitrary point in the past.
|
||||
|
||||
#### page.goBack(options)
|
||||
- `options` <[Object]> Navigation parameters which might have the following properties:
|
||||
- `timeout` <[number]> Maximum navigation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout.
|
||||
|
54
lib/Page.js
54
lib/Page.js
@ -40,6 +40,7 @@ class Page extends EventEmitter {
|
||||
client.send('Page.enable', {}),
|
||||
client.send('Runtime.enable', {}),
|
||||
client.send('Security.enable', {}),
|
||||
client.send('Performance.enable', {})
|
||||
]);
|
||||
if (ignoreHTTPSErrors)
|
||||
await client.send('Security.setOverrideCertificateErrors', {override: true});
|
||||
@ -87,6 +88,7 @@ class Page extends EventEmitter {
|
||||
client.on('Runtime.exceptionThrown', exception => this._handleException(exception.exceptionDetails));
|
||||
client.on('Security.certificateError', event => this._onCertificateError(event));
|
||||
client.on('Inspector.targetCrashed', event => this._onTargetCrashed());
|
||||
client.on('Performance.metrics', event => this._emitMetrics(event));
|
||||
}
|
||||
|
||||
_onTargetCrashed() {
|
||||
@ -304,6 +306,37 @@ class Page extends EventEmitter {
|
||||
return this._networkManager.setUserAgent(userAgent);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {!Promise<!Object>}
|
||||
*/
|
||||
async getMetrics() {
|
||||
const response = await this._client.send('Performance.getMetrics');
|
||||
return this._buildMetricsObject(response.metrics);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {*} event
|
||||
*/
|
||||
_emitMetrics(event) {
|
||||
this.emit(Page.Events.Metrics, {
|
||||
title: event.title,
|
||||
metrics: this._buildMetricsObject(event.metrics)
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {?Array<!{name: string, value: number}>} metrics
|
||||
* @return {!Object}
|
||||
*/
|
||||
_buildMetricsObject(metrics) {
|
||||
const result = {};
|
||||
for (const metric of metrics || []) {
|
||||
if (supportedMetrics.has(metric.name))
|
||||
result[metric.name] = metric.value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {!Object} exceptionDetails
|
||||
*/
|
||||
@ -776,6 +809,26 @@ class Page extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
/** @type {!Set<string>} */
|
||||
const supportedMetrics = new Set([
|
||||
'Timestamp',
|
||||
'DocumentCount',
|
||||
'FrameCount',
|
||||
'JSEventListenerCount',
|
||||
'NodeCount',
|
||||
'LayoutCount',
|
||||
'RecalcStyleCount',
|
||||
'LayoutDuration',
|
||||
'RecalcStyleDuration',
|
||||
'ScriptDuration',
|
||||
'TaskDuration',
|
||||
'JSHeapUsedSize',
|
||||
'JSHeapTotalSize',
|
||||
'FirstMeaningfulPaint',
|
||||
'DomContentLoaded',
|
||||
'NavigationStart',
|
||||
]);
|
||||
|
||||
/** @enum {string} */
|
||||
Page.PaperFormats = {
|
||||
letter: {width: 8.5, height: 11},
|
||||
@ -844,6 +897,7 @@ Page.Events = {
|
||||
FrameDetached: 'framedetached',
|
||||
FrameNavigated: 'framenavigated',
|
||||
Load: 'load',
|
||||
Metrics: 'metrics',
|
||||
};
|
||||
|
||||
/**
|
||||
|
41
test/test.js
41
test/test.js
@ -749,6 +749,47 @@ describe('Page', function() {
|
||||
}));
|
||||
});
|
||||
|
||||
describe('Page.getMetrics', function() {
|
||||
it('should get metrics from a page', SX(async function() {
|
||||
await page.goto('about:blank');
|
||||
const metrics = await page.getMetrics();
|
||||
checkMetrics(metrics);
|
||||
}));
|
||||
it('metrics event fired on console.timeStamp', SX(async function() {
|
||||
const metricsPromise = new Promise(fulfill => page.once('metrics', fulfill));
|
||||
await page.evaluate(() => console.timeStamp('test42'));
|
||||
const metrics = await metricsPromise;
|
||||
expect(metrics.title).toBe('test42');
|
||||
checkMetrics(metrics.metrics);
|
||||
}));
|
||||
function checkMetrics(metrics) {
|
||||
const metricsToCheck = new Set([
|
||||
'Timestamp',
|
||||
'DocumentCount',
|
||||
'FrameCount',
|
||||
'JSEventListenerCount',
|
||||
'NodeCount',
|
||||
'LayoutCount',
|
||||
'RecalcStyleCount',
|
||||
'LayoutDuration',
|
||||
'RecalcStyleDuration',
|
||||
'ScriptDuration',
|
||||
'TaskDuration',
|
||||
'JSHeapUsedSize',
|
||||
'JSHeapTotalSize',
|
||||
'FirstMeaningfulPaint',
|
||||
'DomContentLoaded',
|
||||
'NavigationStart',
|
||||
]);
|
||||
for (const name in metrics) {
|
||||
expect(metricsToCheck.has(name)).toBeTruthy();
|
||||
expect(metrics[name]).toBeGreaterThanOrEqual(0);
|
||||
metricsToCheck.delete(name);
|
||||
}
|
||||
expect(metricsToCheck.size).toBe(0);
|
||||
}
|
||||
});
|
||||
|
||||
describe('Page.goto', function() {
|
||||
it('should navigate to about:blank', SX(async function() {
|
||||
const response = await page.goto('about:blank');
|
||||
|
Loading…
Reference in New Issue
Block a user