-
Notifications
You must be signed in to change notification settings - Fork 8.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Report page load asset size (#66224)
* performance_tests: draft version * update cli runner and script * ingest metrics * save asset type for plugins * Update src/dev/performance/ingest_metrics.ts Co-authored-by: Spencer <[email protected]> * follow review comments * fix size calc, add FTR config, move src to kbn/test * fix import, remove unused interface * Update packages/kbn-test/src/page_load_metrics/capture_page_load_metrics.ts Co-authored-by: Spencer <[email protected]> * start chromium with no-sandbox * add logging * check page contains expected element, cut apps to 5 * fix locator & typo * Update packages/kbn-test/src/page_load_metrics/navigation.ts Co-authored-by: Spencer <[email protected]> * Update navigation.ts * Update navigation.ts * bump puppeteer version * fix typo * update navigation script * update config file * update yarn.lock * fix * take screenshot on failure * update screenshot title * fix screenshot saving and error * invalid locator * Revert "invalid locator" This reverts commit 3007539. * run script in a loop 10 times * Revert "run script in a loop 10 times" This reverts commit 6cfa219. * path config value directly * fix screenshots directory setup * update maps locator, common for landing and new map Co-authored-by: Spencer <[email protected]> Co-authored-by: Elastic Machine <[email protected]> Co-authored-by: Mikhail Shustov <[email protected]>
- Loading branch information
1 parent
ade2f03
commit 6f57fa0
Showing
16 changed files
with
2,992 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
81 changes: 81 additions & 0 deletions
81
packages/kbn-test/src/page_load_metrics/capture_page_load_metrics.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
/* | ||
* Licensed to Elasticsearch B.V. under one or more contributor | ||
* license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright | ||
* ownership. Elasticsearch B.V. licenses this file to you under | ||
* the Apache License, Version 2.0 (the "License"); you may | ||
* not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
import { ToolingLog } from '@kbn/dev-utils'; | ||
import { NavigationOptions, createUrl, navigateToApps } from './navigation'; | ||
|
||
export async function capturePageLoadMetrics(log: ToolingLog, options: NavigationOptions) { | ||
const responsesByPageView = await navigateToApps(log, options); | ||
|
||
const assetSizeMeasurements = new Map<string, number[]>(); | ||
|
||
const numberOfPagesVisited = responsesByPageView.size; | ||
|
||
for (const [, frameResponses] of responsesByPageView) { | ||
for (const [, { url, dataLength }] of frameResponses) { | ||
if (url.length === 0) { | ||
throw new Error('navigateToApps(); failed to identify the url of the request'); | ||
} | ||
if (assetSizeMeasurements.has(url)) { | ||
assetSizeMeasurements.set(url, [dataLength].concat(assetSizeMeasurements.get(url) || [])); | ||
} else { | ||
assetSizeMeasurements.set(url, [dataLength]); | ||
} | ||
} | ||
} | ||
|
||
return Array.from(assetSizeMeasurements.entries()) | ||
.map(([url, measurements]) => { | ||
const baseUrl = createUrl('/', options.appConfig.url); | ||
const relativeUrl = url | ||
// remove the baseUrl (expect the trailing slash) to make url relative | ||
.replace(baseUrl.slice(0, -1), '') | ||
// strip the build number from asset urls | ||
.replace(/^\/\d+\//, '/'); | ||
return [relativeUrl, measurements] as const; | ||
}) | ||
.filter(([url, measurements]) => { | ||
if (measurements.length !== numberOfPagesVisited) { | ||
// ignore urls seen only on some pages | ||
return false; | ||
} | ||
|
||
if (url.startsWith('data:')) { | ||
// ignore data urls since they are already counted by other assets | ||
return false; | ||
} | ||
|
||
if (url.startsWith('/api/') || url.startsWith('/internal/')) { | ||
// ignore api requests since they don't have deterministic sizes | ||
return false; | ||
} | ||
|
||
const allMetricsAreEqual = measurements.every((x, i) => | ||
i === 0 ? true : x === measurements[i - 1] | ||
); | ||
if (!allMetricsAreEqual) { | ||
throw new Error(`measurements for url [${url}] are not equal [${measurements.join(',')}]`); | ||
} | ||
|
||
return true; | ||
}) | ||
.map(([url, measurements]) => { | ||
return { group: 'page load asset size', id: url, value: measurements[0] }; | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
/* | ||
* Licensed to Elasticsearch B.V. under one or more contributor | ||
* license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright | ||
* ownership. Elasticsearch B.V. licenses this file to you under | ||
* the Apache License, Version 2.0 (the "License"); you may | ||
* not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
import Url from 'url'; | ||
|
||
import { run, createFlagError } from '@kbn/dev-utils'; | ||
import { resolve, basename } from 'path'; | ||
import { capturePageLoadMetrics } from './capture_page_load_metrics'; | ||
|
||
const defaultScreenshotsDir = resolve(__dirname, 'screenshots'); | ||
|
||
export function runPageLoadMetricsCli() { | ||
run( | ||
async ({ flags, log }) => { | ||
const kibanaUrl = flags['kibana-url']; | ||
if (!kibanaUrl || typeof kibanaUrl !== 'string') { | ||
throw createFlagError('Expect --kibana-url to be a string'); | ||
} | ||
|
||
const parsedUrl = Url.parse(kibanaUrl); | ||
|
||
const [username, password] = parsedUrl.auth | ||
? parsedUrl.auth.split(':') | ||
: [flags.username, flags.password]; | ||
|
||
if (typeof username !== 'string' || typeof password !== 'string') { | ||
throw createFlagError( | ||
'Mising username and/or password, either specify in --kibana-url or pass --username and --password' | ||
); | ||
} | ||
|
||
const headless = !flags.head; | ||
|
||
const screenshotsDir = flags.screenshotsDir || defaultScreenshotsDir; | ||
|
||
if (typeof screenshotsDir !== 'string' || screenshotsDir === basename(screenshotsDir)) { | ||
throw createFlagError('Expect screenshotsDir to be valid path string'); | ||
} | ||
|
||
const metrics = await capturePageLoadMetrics(log, { | ||
headless, | ||
appConfig: { | ||
url: kibanaUrl, | ||
username, | ||
password, | ||
}, | ||
screenshotsDir, | ||
}); | ||
for (const metric of metrics) { | ||
log.info(`${metric.id}: ${metric.value}`); | ||
} | ||
}, | ||
{ | ||
description: `Loads several pages with Puppeteer to capture the size of assets`, | ||
flags: { | ||
string: ['kibana-url', 'username', 'password', 'screenshotsDir'], | ||
boolean: ['head'], | ||
default: { | ||
username: 'elastic', | ||
password: 'changeme', | ||
debug: true, | ||
screenshotsDir: defaultScreenshotsDir, | ||
}, | ||
help: ` | ||
--kibana-url Url for Kibana we should connect to, can include login info | ||
--head Run puppeteer with graphical user interface | ||
--username Set username, defaults to 'elastic' | ||
--password Set password, defaults to 'changeme' | ||
--screenshotsDir Set screenshots directory, defaults to '${defaultScreenshotsDir}' | ||
`, | ||
}, | ||
} | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/* | ||
* Licensed to Elasticsearch B.V. under one or more contributor | ||
* license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright | ||
* ownership. Elasticsearch B.V. licenses this file to you under | ||
* the Apache License, Version 2.0 (the "License"); you may | ||
* not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
export interface ResponseReceivedEvent { | ||
frameId: string; | ||
loaderId: string; | ||
requestId: string; | ||
response: Record<string, any>; | ||
timestamp: number; | ||
type: string; | ||
} | ||
|
||
export interface DataReceivedEvent { | ||
encodedDataLength: number; | ||
dataLength: number; | ||
requestId: string; | ||
timestamp: number; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/* | ||
* Licensed to Elasticsearch B.V. under one or more contributor | ||
* license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright | ||
* ownership. Elasticsearch B.V. licenses this file to you under | ||
* the Apache License, Version 2.0 (the "License"); you may | ||
* not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
export * from './cli'; | ||
export { capturePageLoadMetrics } from './capture_page_load_metrics'; |
Oops, something went wrong.