mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-22 09:23:21 +01:00
Adding artifacts (#15145)
This commit is contained in:
parent
df646a03eb
commit
45cecf385d
@ -136,6 +136,9 @@ workflows:
|
||||
- benchmark:
|
||||
requires:
|
||||
- prep-build-test
|
||||
- stats-module-load-init:
|
||||
requires:
|
||||
- prep-build-test-mv3
|
||||
- job-publish-prerelease:
|
||||
requires:
|
||||
- prep-deps
|
||||
@ -143,7 +146,9 @@ workflows:
|
||||
- prep-build-beta
|
||||
- prep-build-flask
|
||||
- prep-build-storybook
|
||||
- prep-build-test-mv3
|
||||
- benchmark
|
||||
- stats-module-load-init
|
||||
- all-tests-pass
|
||||
- job-publish-release:
|
||||
filters:
|
||||
@ -596,6 +601,40 @@ jobs:
|
||||
paths:
|
||||
- test-artifacts
|
||||
|
||||
stats-module-load-init:
|
||||
executor: node-browsers-medium-plus
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Re-Install Chrome
|
||||
command: ./.circleci/scripts/chrome-install.sh
|
||||
- attach_workspace:
|
||||
at: .
|
||||
- run:
|
||||
name: Move test build to dist
|
||||
command: mv ./dist-test-mv3 ./dist
|
||||
- run:
|
||||
name: Move test zips to builds
|
||||
command: mv ./builds-test-mv3 ./builds
|
||||
- run:
|
||||
name: Run page load benchmark
|
||||
command: |
|
||||
mkdir -p test-artifacts/chrome/mv3
|
||||
cp -R development/charts/flamegraph test-artifacts/chrome/mv3/initialisation
|
||||
cp -R development/charts/flamegraph/chart test-artifacts/chrome/mv3/initialisation/background
|
||||
cp -R development/charts/flamegraph/chart test-artifacts/chrome/mv3/initialisation/ui
|
||||
cp -R development/charts/table test-artifacts/chrome/mv3/load_time
|
||||
- run:
|
||||
name: Run page load benchmark
|
||||
command: yarn mv3:stats:chrome --out test-artifacts/chrome/mv3
|
||||
- store_artifacts:
|
||||
path: test-artifacts
|
||||
destination: test-artifacts
|
||||
- persist_to_workspace:
|
||||
root: .
|
||||
paths:
|
||||
- test-artifacts
|
||||
|
||||
job-publish-prerelease:
|
||||
executor: node-browsers
|
||||
steps:
|
||||
|
@ -8,6 +8,7 @@ module.exports = {
|
||||
'app/vendor/**',
|
||||
'builds/**/*',
|
||||
'development/chromereload.js',
|
||||
'development/charts/**',
|
||||
'dist/**/*',
|
||||
'node_modules/**/*',
|
||||
],
|
||||
|
170
development/charts/flamegraph/chart/index.html
Normal file
170
development/charts/flamegraph/chart/index.html
Normal file
@ -0,0 +1,170 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
|
||||
/>
|
||||
<link rel="stylesheet" type="text/css" href="../lib/d3-flamegraph.css" />
|
||||
|
||||
<style>
|
||||
/* Space out content a bit */
|
||||
body {
|
||||
padding-top: 20px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
/* Custom page header */
|
||||
.header {
|
||||
padding-bottom: 20px;
|
||||
padding-right: 15px;
|
||||
padding-left: 15px;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
}
|
||||
|
||||
/* Make the masthead heading the same height as the navigation */
|
||||
.header h3 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
/* Customize container */
|
||||
.container {
|
||||
max-width: 990px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<title>Performance Measurements</title>
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="header clearfix">
|
||||
<nav>
|
||||
<div class="pull-right">
|
||||
<form class="form-inline" id="form">
|
||||
<a class="btn" href="javascript: resetZoom();">Reset zoom</a>
|
||||
<a class="btn" href="javascript: clear();">Clear</a>
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" id="term" />
|
||||
</div>
|
||||
<a class="btn btn-primary" href="javascript: search();">Search</a>
|
||||
</form>
|
||||
</div>
|
||||
</nav>
|
||||
<h3 class="text-muted">d3-flame-graph</h3>
|
||||
</div>
|
||||
<div id="chart"></div>
|
||||
<hr />
|
||||
<div id="details"></div>
|
||||
</div>
|
||||
|
||||
<!-- D3.js -->
|
||||
<script src="https://d3js.org/d3.v7.js" charset="utf-8"></script>
|
||||
|
||||
<!-- d3-flamegraph -->
|
||||
<script type="text/javascript" src="../lib/d3-flamegraph.js"></script>
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="../lib/d3-flamegraph-tooltip.js"
|
||||
></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
var chart = flamegraph()
|
||||
.width(960)
|
||||
.cellHeight(18)
|
||||
.transitionDuration(750)
|
||||
.minFrameSize(5)
|
||||
.transitionEase(d3.easeCubic)
|
||||
.sort(true)
|
||||
//Example to sort in reverse order
|
||||
//.sort(function(a,b){ return d3.descending(a.name, b.name);})
|
||||
.title('')
|
||||
.onClick(onClick)
|
||||
.selfValue(false)
|
||||
.setColorMapper((d, originalColor) =>
|
||||
d.highlight ? '#6aff8f' : originalColor,
|
||||
);
|
||||
|
||||
// Example on how to use custom a tooltip.
|
||||
var tip = flamegraph.tooltip
|
||||
.defaultFlamegraphTooltip()
|
||||
.text((d) => 'name: ' + d.data.name + ', value: ' + d.data.value);
|
||||
chart.tooltip(tip);
|
||||
|
||||
var details = document.getElementById('details');
|
||||
chart.setDetailsElement(details);
|
||||
|
||||
// Example on how to use searchById() function in flamegraph.
|
||||
// To invoke this function after loading the graph itself, this function should be registered in d3 datum(data).call()
|
||||
// (See d3.json invocation in this file)
|
||||
function invokeFind() {
|
||||
var searchId = parseInt(location.hash.substring(1), 10);
|
||||
if (searchId) {
|
||||
find(searchId);
|
||||
}
|
||||
}
|
||||
|
||||
// Example on how to use custom labels
|
||||
// var label = function(d) {
|
||||
// return "name: " + d.name + ", value: " + d.value;
|
||||
// }
|
||||
// chart.label(label);
|
||||
|
||||
// Example of how to set fixed chart height
|
||||
// chart.height(540);
|
||||
|
||||
d3.json('stacks.json')
|
||||
.then((data) => {
|
||||
d3.select('#chart').datum(data).call(chart).call(invokeFind);
|
||||
})
|
||||
.catch((error) => {
|
||||
return console.warn(error);
|
||||
});
|
||||
|
||||
document
|
||||
.getElementById('form')
|
||||
.addEventListener('submit', function (event) {
|
||||
event.preventDefault();
|
||||
search();
|
||||
});
|
||||
|
||||
function search() {
|
||||
var term = document.getElementById('term').value;
|
||||
chart.search(term);
|
||||
}
|
||||
|
||||
function find(id) {
|
||||
var elem = chart.findById(id);
|
||||
if (elem) {
|
||||
console.log(elem);
|
||||
chart.zoomTo(elem);
|
||||
}
|
||||
}
|
||||
|
||||
function clear() {
|
||||
document.getElementById('term').value = '';
|
||||
chart.clear();
|
||||
}
|
||||
|
||||
function resetZoom() {
|
||||
chart.resetZoom();
|
||||
}
|
||||
|
||||
function onClick(d) {
|
||||
console.info(`Clicked on ${d.data.name}, id: "${d.id}"`);
|
||||
history.pushState({ id: d.id }, d.data.name, `#${d.id}`);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
3117
development/charts/flamegraph/lib/d3-flamegraph-tooltip.js
vendored
Normal file
3117
development/charts/flamegraph/lib/d3-flamegraph-tooltip.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
46
development/charts/flamegraph/lib/d3-flamegraph.css
Normal file
46
development/charts/flamegraph/lib/d3-flamegraph.css
Normal file
@ -0,0 +1,46 @@
|
||||
.d3-flame-graph rect {
|
||||
stroke: #EEEEEE;
|
||||
fill-opacity: .8;
|
||||
}
|
||||
|
||||
.d3-flame-graph rect:hover {
|
||||
stroke: #474747;
|
||||
stroke-width: 0.5;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.d3-flame-graph-label {
|
||||
pointer-events: none;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
font-size: 12px;
|
||||
font-family: Verdana;
|
||||
margin-left: 4px;
|
||||
margin-right: 4px;
|
||||
line-height: 1.5;
|
||||
padding: 0 0 0;
|
||||
font-weight: 400;
|
||||
color: black;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.d3-flame-graph .fade {
|
||||
opacity: 0.6 !important;
|
||||
}
|
||||
|
||||
.d3-flame-graph .title {
|
||||
font-size: 20px;
|
||||
font-family: Verdana;
|
||||
}
|
||||
|
||||
.d3-flame-graph-tip {
|
||||
background-color: black;
|
||||
border: none;
|
||||
border-radius: 3px;
|
||||
padding: 5px 10px 5px 10px;
|
||||
min-width: 250px;
|
||||
text-align: left;
|
||||
color: white;
|
||||
z-index: 10;
|
||||
}
|
5719
development/charts/flamegraph/lib/d3-flamegraph.js
vendored
Normal file
5719
development/charts/flamegraph/lib/d3-flamegraph.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
67
development/charts/table/index.html
Normal file
67
development/charts/table/index.html
Normal file
@ -0,0 +1,67 @@
|
||||
<html>
|
||||
<head>
|
||||
<script type="text/javascript" src="./jquery.min.js"></script>
|
||||
<style>
|
||||
table {
|
||||
border: 1px solid black;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
tr {
|
||||
border: 1px solid black;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
$(function () {
|
||||
var loadTime = [];
|
||||
|
||||
$.getJSON('stats.json', function (data) {
|
||||
$.each(data.children, function (index, datum) {
|
||||
if (datum.name) {
|
||||
var tblRow =
|
||||
'<tr>' +
|
||||
'<td>' +
|
||||
index +
|
||||
'</td>' +
|
||||
'<td>' +
|
||||
datum.name +
|
||||
'</td>' +
|
||||
'<td>' +
|
||||
datum.value +
|
||||
'</td>' +
|
||||
'</tr>';
|
||||
$(tblRow).appendTo('#loaddata tbody');
|
||||
}
|
||||
});
|
||||
$(
|
||||
'<tr>' +
|
||||
'<td>' +
|
||||
'Total' +
|
||||
'</td>' +
|
||||
'<td>' +
|
||||
'--' +
|
||||
'</td>' +
|
||||
'<td>' +
|
||||
data.value +
|
||||
'</td>' +
|
||||
'</tr>',
|
||||
).appendTo('#loaddata tbody');
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="wrapper">
|
||||
<div class="profile">
|
||||
<table id="loaddata">
|
||||
<thead>
|
||||
<th>S.No</th>
|
||||
<th>Name</th>
|
||||
<th>TotalTime</th>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
18
development/charts/table/jquery.min.js
vendored
Normal file
18
development/charts/table/jquery.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -94,6 +94,12 @@ async function start() {
|
||||
// links to bundle browser builds
|
||||
const depVizUrl = `${BUILD_LINK_BASE}/build-artifacts/build-viz/index.html`;
|
||||
const depVizLink = `<a href="${depVizUrl}">Build System</a>`;
|
||||
const moduleInitStatsBackgroundUrl = `${BUILD_LINK_BASE}/test-artifacts/chrome/mv3/initialisation/background/index.html`;
|
||||
const moduleInitStatsBackgroundLink = `<a href="${moduleInitStatsBackgroundUrl}">MV3 Background Module Init Stats</a>`;
|
||||
const moduleInitStatsUIUrl = `${BUILD_LINK_BASE}/test-artifacts/chrome/mv3/initialisation/ui/index.html`;
|
||||
const moduleInitStatsUILink = `<a href="${moduleInitStatsUIUrl}">MV3 UI Init Stats</a>`;
|
||||
const moduleLoadStatsUrl = `${BUILD_LINK_BASE}/test-artifacts/chrome/mv3/load_time/index.html`;
|
||||
const moduleLoadStatsLink = `<a href="${moduleLoadStatsUrl}">Module Load Stats</a>`;
|
||||
|
||||
// link to artifacts
|
||||
const allArtifactsUrl = `https://circleci.com/gh/MetaMask/metamask-extension/${CIRCLE_BUILD_NUM}#artifacts/containers/0`;
|
||||
@ -103,6 +109,9 @@ async function start() {
|
||||
`builds (beta): ${betaBuildLinks}`,
|
||||
`builds (flask): ${flaskBuildLinks}`,
|
||||
`build viz: ${depVizLink}`,
|
||||
`mv3: ${moduleInitStatsBackgroundLink}`,
|
||||
`mv3: ${moduleInitStatsUILink}`,
|
||||
`mv3: ${moduleLoadStatsLink}`,
|
||||
`code coverage: ${coverageLink}`,
|
||||
`storybook: ${storybookLink}`,
|
||||
`<a href="${allArtifactsUrl}">all artifacts</a>`,
|
||||
|
@ -1,12 +1,16 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const path = require('path');
|
||||
const { promises: fs, constants: fsConstants } = require('fs');
|
||||
const { promises: fs } = require('fs');
|
||||
const yargs = require('yargs/yargs');
|
||||
const { hideBin } = require('yargs/helpers');
|
||||
const ttest = require('ttest');
|
||||
const { retry } = require('../../development/lib/retry');
|
||||
const { exitWithError } = require('../../development/lib/exit-with-error');
|
||||
const {
|
||||
isWritable,
|
||||
getFirstParentDirectoryThatExists,
|
||||
} = require('../helpers/file');
|
||||
const { withFixtures, tinyDelayMs } = require('./helpers');
|
||||
const { PAGES } = require('./webdriver/driver');
|
||||
|
||||
@ -108,35 +112,6 @@ async function profilePageLoad(pages, numSamples, retries) {
|
||||
return results;
|
||||
}
|
||||
|
||||
async function isWritable(directory) {
|
||||
try {
|
||||
await fs.access(directory, fsConstants.W_OK);
|
||||
return true;
|
||||
} catch (error) {
|
||||
if (error.code !== 'EACCES') {
|
||||
throw error;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function getFirstParentDirectoryThatExists(directory) {
|
||||
let nextDirectory = directory;
|
||||
for (;;) {
|
||||
try {
|
||||
await fs.access(nextDirectory, fsConstants.F_OK);
|
||||
return nextDirectory;
|
||||
} catch (error) {
|
||||
if (error.code !== 'ENOENT') {
|
||||
throw error;
|
||||
} else if (nextDirectory === path.dirname(nextDirectory)) {
|
||||
throw new Error('Failed to find parent directory that exists');
|
||||
}
|
||||
nextDirectory = path.dirname(nextDirectory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const { argv } = yargs(hideBin(process.argv)).usage(
|
||||
'$0 [options]',
|
||||
|
111
test/e2e/mv3-stats.js
Normal file
111
test/e2e/mv3-stats.js
Normal file
@ -0,0 +1,111 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/* eslint-disable node/shebang */
|
||||
const path = require('path');
|
||||
const { promises: fs } = require('fs');
|
||||
const yargs = require('yargs/yargs');
|
||||
const { hideBin } = require('yargs/helpers');
|
||||
|
||||
const { exitWithError } = require('../../development/lib/exit-with-error');
|
||||
const {
|
||||
isWritable,
|
||||
getFirstParentDirectoryThatExists,
|
||||
} = require('../helpers/file');
|
||||
const { withFixtures, tinyDelayMs } = require('./helpers');
|
||||
|
||||
/**
|
||||
* The e2e test case is used to capture load and initialisation time statistics for extension in MV3 environment.
|
||||
*/
|
||||
|
||||
async function profilePageLoad() {
|
||||
const parsedLogs = {};
|
||||
try {
|
||||
await withFixtures({ fixtures: 'imported-account' }, async ({ driver }) => {
|
||||
await driver.delay(tinyDelayMs);
|
||||
await driver.navigate();
|
||||
await driver.delay(1000);
|
||||
const logs = await driver.checkBrowserForLavamoatLogs();
|
||||
|
||||
let logString = '';
|
||||
let logType = '';
|
||||
|
||||
logs.forEach((log) => {
|
||||
if (log.indexOf('"version": 1') >= 0) {
|
||||
// log end here
|
||||
logString += log;
|
||||
parsedLogs[logType] = JSON.parse(`{${logString}}`);
|
||||
logString = '';
|
||||
logType = '';
|
||||
} else if (logType) {
|
||||
// log string continues
|
||||
logString += log;
|
||||
} else if (
|
||||
log.search(/"name": ".*app\/scripts\/background.js",/u) >= 0
|
||||
) {
|
||||
// background log starts
|
||||
logString += log;
|
||||
logType = 'background';
|
||||
} else if (log.search(/"name": ".*app\/scripts\/ui.js",/u) >= 0) {
|
||||
// ui log starts
|
||||
logString += log;
|
||||
logType = 'ui';
|
||||
} else if (log.search(/"name": "Total"/u) >= 0) {
|
||||
// load time log starts
|
||||
logString += log;
|
||||
logType = 'loadTime';
|
||||
}
|
||||
});
|
||||
});
|
||||
} catch (error) {
|
||||
console.log('Error in trying to parse logs.');
|
||||
}
|
||||
return parsedLogs;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const { argv } = yargs(hideBin(process.argv)).usage(
|
||||
'$0 [options]',
|
||||
'Run a page load benchmark',
|
||||
(_yargs) =>
|
||||
_yargs.option('out', {
|
||||
description:
|
||||
'Output filename. Output printed to STDOUT of this is omitted.',
|
||||
type: 'string',
|
||||
normalize: true,
|
||||
}),
|
||||
);
|
||||
|
||||
const results = await profilePageLoad();
|
||||
const { out } = argv;
|
||||
|
||||
const logCategories = [
|
||||
{ key: 'background', dirPath: 'initialisation/background/stacks.json' },
|
||||
{ key: 'ui', dirPath: 'initialisation/ui/stacks.json' },
|
||||
{ key: 'loadTime', dirPath: 'load_time/stats.json' },
|
||||
];
|
||||
|
||||
if (out) {
|
||||
logCategories.forEach(async ({ key, dirPath }) => {
|
||||
if (results[key]) {
|
||||
const outPath = `${out}/${dirPath}`;
|
||||
const outputDirectory = path.dirname(outPath);
|
||||
const existingParentDirectory = await getFirstParentDirectoryThatExists(
|
||||
outputDirectory,
|
||||
);
|
||||
if (!(await isWritable(existingParentDirectory))) {
|
||||
throw new Error('Specified output file directory is not writable');
|
||||
}
|
||||
if (outputDirectory !== existingParentDirectory) {
|
||||
await fs.mkdir(outputDirectory, { recursive: true });
|
||||
}
|
||||
await fs.writeFile(outPath, JSON.stringify(results[key], null, 2));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.log(JSON.stringify(results, null, 2));
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
exitWithError(error);
|
||||
});
|
37
test/helpers/file.js
Normal file
37
test/helpers/file.js
Normal file
@ -0,0 +1,37 @@
|
||||
/* eslint-disable node/shebang */
|
||||
const path = require('path');
|
||||
const { promises: fs, constants: fsConstants } = require('fs');
|
||||
|
||||
async function isWritable(directory) {
|
||||
try {
|
||||
await fs.access(directory, fsConstants.W_OK);
|
||||
return true;
|
||||
} catch (error) {
|
||||
if (error.code !== 'EACCES') {
|
||||
throw error;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function getFirstParentDirectoryThatExists(directory) {
|
||||
let nextDirectory = directory;
|
||||
for (;;) {
|
||||
try {
|
||||
await fs.access(nextDirectory, fsConstants.F_OK);
|
||||
return nextDirectory;
|
||||
} catch (error) {
|
||||
if (error.code !== 'ENOENT') {
|
||||
throw error;
|
||||
} else if (nextDirectory === path.dirname(nextDirectory)) {
|
||||
throw new Error('Failed to find parent directory that exists');
|
||||
}
|
||||
nextDirectory = path.dirname(nextDirectory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
isWritable,
|
||||
getFirstParentDirectoryThatExists,
|
||||
};
|
Loading…
Reference in New Issue
Block a user