d2l-beaker v0.0.6
d2l-beaker
A driver for Google Puppeteer to collect client-side performance metrics.
Installation
Install d2l-beaker.
npm i d2l-beaker -gUsage
Basic Setup
While d2l-beaker supports a few CLI arguments, is relies on a config file to specify details about the target site and measurements to be taken. Specify this configuration in a JS module, such as perf.config.js or this sample config.
module.exports = {
"applicationKey": "your-app",
"caching": true,
"headless": false,
"samplesPerTarget": 10,
"measurements": ["first-paint", "first-contentful-paint"],
"properties": [],
"target": {
"site": "https://yourapp.com",
"login": {
"url": "/login",
"user": {"selector": "#userName", "value": "test-user"},
"password": {"selector": "#password", "value": "test-password"},
"submit": {"selector": "#loginButton"}
},
"targets": [
{"name": "target1", "url": "/some-relative-url-1"},
{"name": "target2", "url": "/some-relative-url-2"},
{"name": "target3", "url": "/some-relative-url-3"}
]
}
};Once this configuration has been defined, d2l-beaker can go to task by running the CLI.
measure --configjs perf.config.jsIt will produce some JSON that summarizes the samples taken for each target - the std. mean (95%). All measurements are reported in milliseconds as per PerformanceEntry.
{
"application-key":"your-app",
"target-site":"https://yourapp.com",
"target-url":"/some-relative-url-1",
"target-name":"target1",
"browser":"Chrome/67.0.3372.0",
"caching":true,
"timestamp":"2018-03-23 15:47:56.182",
"properties":[],
"measurements":[
{"name":"first-paint","entryType":"paint","startTime":0,"duration":940},
{"name":"first-contentful-paint","entryType":"paint","startTime":0,"duration":940}
]
}CLI Options
The CLI supports a number of options to enable re-using configuration, or to avoid saving sensitive user/password info.
measure --user some-user --pwd some-password --configjs perf.config.js--configjsConfiguration JS module (required)--applicationKeyKey for application--cachingWhether to enable caching--headlessWhether to run headless--samplesPerTargetNumber of times to measure each page--targetSiteTarget site to measure targets--userUsername to login--pwdPassword to login
Login Info
The login page info (url, user & password selectors and values, and submit button selector) can be configured.
module.exports = {
"target": {
"login": {
"url": "/login",
"user": {"selector": "#userName", "value": "test-user"},
"password": {"selector": "#password", "value": "test-password"},
"submit": {"selector": "#loginButton"}
}
}
};Alternatively, the user and password can be specified as environment variables.
module.exports = {
"target": {
"login": {
"url": "/login",
"user": {"selector": "#userName", "value": "{{TEST-USER-VAR}}"},
"password": {"selector": "#password", "value": "{{TEST-PASSWORD-VAR}}"},
"submit": {"selector": "#loginButton"}
}
}
};More Measurements
Need to extract different measurements? No problem, as long it's a mark, paint, or measure entry available via the browser performance API, it can be extracted and recorded. It is also possible to specify measurements to be gathered per-target.
Note: if your measurement name ends with a *, the extractor will look for any measures that match, but it won't wait for them beyond page load. If there is a specific measure that may be delayed, list is explicitly and list it only for targets where it's expected.
module.exports = {
"measurements": ["some-measure", "yourapp.*"],
"target": {
"targets": [
{"name": "target1", "url": "/some-relative-url-1", "measurements": ["some-other-measure"]},
{"name": "target2", "url": "/some-relative-url-2"},
{"name": "target3", "url": "/some-relative-url-3"}
]
}
};Properties
d2l-beaker supports extracting properties along with its measurements. The following example shows how an app-version and a polymer-version property could be extracted. Note: the property provider may be async if needed.
module.exports = {
"properties": [
{
"key": "app-version",
"provider": () => { return return document.documentElement.getAttribute('data-app-version'); }
},
{
"key": "polymer-version",
"provider": () => { return Polymer.version; }
}
]
};The extracted properties will be included in the JSON output.
{
"application-key":"your-app",
"target-site":"https://yourapp.com",
"target-url":"/some-relative-url-1",
"target-name":"target1",
"browser":"Chrome/67.0.3372.0",
"caching":true,
"timestamp":"2018-03-23 15:47:56.182",
"properties":[
{"name":"app-version","value":"10.8.1"},
{"name":"polymer-version","value":"2.5.0"}
],
"measurements":[
{"name":"first-paint","entryType":"paint","startTime":0,"duration":940},
{"name":"first-contentful-paint","entryType":"paint","startTime":0,"duration":940}
]
}Upload
Optionally automatically upload results to your favorite S3 bucket via configuration.
module.exports = {
"upload": {
"key": "S3",
"target": "some.bucket/some-folder",
"region": "us-east-1",
"creds": {
"accessKeyId": "some-id",
"secretAccessKey": "some-secret-key"
}
}
};Or using environment variables...
module.exports = {
"upload": {
"key": "S3",
"target": "some.bucket/some-folder",
"region": "us-east-1",
"creds": {
"accessKeyId": "{{SOME-ID-VAR}}",
"secretAccessKey": "{{SOME-SECRET-KEY-VAR}}"
}
}
};Note: keep your secret keys secret!
Contributing
Contributions are welcome, please submit a pull request!
Code Style
This repository is configured with EditorConfig rules and contributions should make use of them.