mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
* 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@spalger.com> * 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@spalger.com> * 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@spalger.com> * 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 commit3007539a69
. * run script in a loop 10 times * Revert "run script in a loop 10 times" This reverts commit6cfa219140
. * path config value directly * fix screenshots directory setup * update maps locator, common for landing and new map Co-authored-by: Spencer <email@spalger.com> Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> Co-authored-by: Mikhail Shustov <restrry@gmail.com> # Conflicts: # Jenkinsfile * [page_load_metrics] fix path for discover * fix url formatting * fix screenshot title
This commit is contained in:
parent
d452d21ad3
commit
b6d6889cf2
16 changed files with 2994 additions and 2 deletions
1
Jenkinsfile
vendored
1
Jenkinsfile
vendored
|
@ -41,6 +41,7 @@ kibanaPipeline(timeoutMinutes: 135, checkPrChanges: true) {
|
|||
'xpack-ciGroup9': kibanaPipeline.xpackCiGroupProcess(9),
|
||||
'xpack-ciGroup10': kibanaPipeline.xpackCiGroupProcess(10),
|
||||
'xpack-accessibility': kibanaPipeline.functionalTestProcess('xpack-accessibility', './test/scripts/jenkins_xpack_accessibility.sh'),
|
||||
'xpack-pageLoadMetrics': kibanaPipeline.functionalTestProcess('xpack-pageLoadMetrics', './test/scripts/jenkins_xpack_page_load_metrics.sh'),
|
||||
'xpack-siemCypress': { processNumber ->
|
||||
whenChanged(['x-pack/plugins/siem/', 'x-pack/test/siem_cypress/']) {
|
||||
kibanaPipeline.functionalTestProcess('xpack-siemCypress', './test/scripts/jenkins_siem_cypress.sh')(processNumber)
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
"@kbn/babel-preset": "1.0.0",
|
||||
"@kbn/dev-utils": "1.0.0",
|
||||
"@types/parse-link-header": "^1.0.0",
|
||||
"@types/puppeteer": "^3.0.0",
|
||||
"@types/strip-ansi": "^5.2.1",
|
||||
"@types/xml2js": "^0.4.5",
|
||||
"diff": "^4.0.1"
|
||||
|
@ -25,6 +26,7 @@
|
|||
"getopts": "^2.2.4",
|
||||
"glob": "^7.1.2",
|
||||
"parse-link-header": "^1.0.1",
|
||||
"puppeteer": "^3.3.0",
|
||||
"strip-ansi": "^5.2.0",
|
||||
"rxjs": "^6.5.3",
|
||||
"tar-fs": "^1.16.3",
|
||||
|
|
|
@ -51,3 +51,5 @@ export { runFailedTestsReporterCli } from './failed_tests_reporter';
|
|||
export { makeJunitReportPath } from './junit_report_path';
|
||||
|
||||
export { CI_PARALLEL_PROCESS_PREFIX } from './ci_parallel_process_prefix';
|
||||
|
||||
export * from './page_load_metrics';
|
||||
|
|
|
@ -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] };
|
||||
});
|
||||
}
|
90
packages/kbn-test/src/page_load_metrics/cli.ts
Normal file
90
packages/kbn-test/src/page_load_metrics/cli.ts
Normal file
|
@ -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}'
|
||||
`,
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
34
packages/kbn-test/src/page_load_metrics/event.ts
Normal file
34
packages/kbn-test/src/page_load_metrics/event.ts
Normal file
|
@ -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;
|
||||
}
|
21
packages/kbn-test/src/page_load_metrics/index.ts
Normal file
21
packages/kbn-test/src/page_load_metrics/index.ts
Normal file
|
@ -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';
|
167
packages/kbn-test/src/page_load_metrics/navigation.ts
Normal file
167
packages/kbn-test/src/page_load_metrics/navigation.ts
Normal file
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
* 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 Fs from 'fs';
|
||||
import Url from 'url';
|
||||
import _ from 'lodash';
|
||||
import puppeteer from 'puppeteer';
|
||||
import { resolve } from 'path';
|
||||
import { ToolingLog } from '@kbn/dev-utils';
|
||||
import { ResponseReceivedEvent, DataReceivedEvent } from './event';
|
||||
|
||||
export interface NavigationOptions {
|
||||
headless: boolean;
|
||||
appConfig: { url: string; username: string; password: string };
|
||||
screenshotsDir: string;
|
||||
}
|
||||
|
||||
export type NavigationResults = Map<string, Map<string, FrameResponse>>;
|
||||
|
||||
interface FrameResponse {
|
||||
url: string;
|
||||
dataLength: number;
|
||||
}
|
||||
|
||||
function joinPath(pathA: string, pathB: string) {
|
||||
return `${pathA.endsWith('/') ? pathA.slice(0, -1) : pathA}/${
|
||||
pathB.startsWith('/') ? pathB.slice(1) : pathB
|
||||
}`;
|
||||
}
|
||||
|
||||
export function createUrl(path: string, url: string) {
|
||||
const baseUrl = Url.parse(url);
|
||||
|
||||
return Url.format({
|
||||
protocol: baseUrl.protocol,
|
||||
hostname: baseUrl.hostname,
|
||||
port: baseUrl.port,
|
||||
pathname: joinPath(baseUrl.pathname || '', path.includes('#') ? path.split('#')[0] : path),
|
||||
hash: path.includes('#') ? path.split('#')[1] : undefined,
|
||||
});
|
||||
}
|
||||
|
||||
async function loginToKibana(
|
||||
log: ToolingLog,
|
||||
browser: puppeteer.Browser,
|
||||
options: NavigationOptions
|
||||
) {
|
||||
log.debug(`log in to the app..`);
|
||||
const page = await browser.newPage();
|
||||
const loginUrl = createUrl('/login', options.appConfig.url);
|
||||
await page.goto(loginUrl, {
|
||||
waitUntil: 'networkidle0',
|
||||
});
|
||||
await page.type('[data-test-subj="loginUsername"]', options.appConfig.username);
|
||||
await page.type('[data-test-subj="loginPassword"]', options.appConfig.password);
|
||||
await page.click('[data-test-subj="loginSubmit"]');
|
||||
await page.waitForNavigation({ waitUntil: 'networkidle0' });
|
||||
await page.close();
|
||||
}
|
||||
|
||||
export async function navigateToApps(log: ToolingLog, options: NavigationOptions) {
|
||||
const browser = await puppeteer.launch({ headless: options.headless, args: ['--no-sandbox'] });
|
||||
const devToolsResponses: NavigationResults = new Map();
|
||||
const apps = [
|
||||
{ path: '/app/kibana#/discover', locator: '[data-test-subj="discover-sidebar"]' },
|
||||
{ path: '/app/kibana#/home', locator: '[data-test-subj="homeApp"]' },
|
||||
{ path: '/app/canvas', locator: '[data-test-subj="create-workpad-button"]' },
|
||||
{ path: '/app/maps', locator: '[title="Maps"]' },
|
||||
{ path: '/app/apm', locator: '[data-test-subj="apmMainContainer"]' },
|
||||
];
|
||||
|
||||
await loginToKibana(log, browser, options);
|
||||
|
||||
await Promise.all(
|
||||
apps.map(async (app) => {
|
||||
const page = await browser.newPage();
|
||||
page.setCacheEnabled(false);
|
||||
page.setDefaultNavigationTimeout(0);
|
||||
const frameResponses = new Map<string, FrameResponse>();
|
||||
devToolsResponses.set(app.path, frameResponses);
|
||||
|
||||
const client = await page.target().createCDPSession();
|
||||
await client.send('Network.enable');
|
||||
|
||||
function getRequestData(requestId: string) {
|
||||
if (!frameResponses.has(requestId)) {
|
||||
frameResponses.set(requestId, { url: '', dataLength: 0 });
|
||||
}
|
||||
|
||||
return frameResponses.get(requestId)!;
|
||||
}
|
||||
|
||||
client.on('Network.responseReceived', (event: ResponseReceivedEvent) => {
|
||||
getRequestData(event.requestId).url = event.response.url;
|
||||
});
|
||||
|
||||
client.on('Network.dataReceived', (event: DataReceivedEvent) => {
|
||||
getRequestData(event.requestId).dataLength += event.dataLength;
|
||||
});
|
||||
|
||||
const url = createUrl(app.path, options.appConfig.url);
|
||||
log.debug(`goto ${url}`);
|
||||
await page.goto(url, {
|
||||
waitUntil: 'networkidle0',
|
||||
});
|
||||
|
||||
let readyAttempt = 0;
|
||||
let selectorFound = false;
|
||||
while (!selectorFound) {
|
||||
readyAttempt += 1;
|
||||
try {
|
||||
await page.waitForSelector(app.locator, { timeout: 5000 });
|
||||
selectorFound = true;
|
||||
} catch (error) {
|
||||
log.error(
|
||||
`Page '${app.path}' was not loaded properly, unable to find '${
|
||||
app.locator
|
||||
}', url: ${page.url()}`
|
||||
);
|
||||
|
||||
if (readyAttempt < 6) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const failureDir = resolve(options.screenshotsDir, 'failure');
|
||||
const screenshotPath = resolve(
|
||||
failureDir,
|
||||
`${app.path.slice(1).split(/#|\//).join('_')}_navigation.png`
|
||||
);
|
||||
Fs.mkdirSync(failureDir, { recursive: true });
|
||||
|
||||
await page.bringToFront();
|
||||
await page.screenshot({
|
||||
path: screenshotPath,
|
||||
type: 'png',
|
||||
fullPage: true,
|
||||
});
|
||||
log.debug(`Saving screenshot to ${screenshotPath}`);
|
||||
|
||||
throw new Error(`Page load timeout: ${app.path} not loaded after 30 seconds`);
|
||||
}
|
||||
}
|
||||
|
||||
await page.close();
|
||||
})
|
||||
);
|
||||
|
||||
await browser.close();
|
||||
|
||||
return devToolsResponses;
|
||||
}
|
21
scripts/page_load_metrics.js
Normal file
21
scripts/page_load_metrics.js
Normal file
|
@ -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.
|
||||
*/
|
||||
|
||||
require('../src/setup_node_env');
|
||||
require('@kbn/test').runPageLoadMetricsCli();
|
9
test/scripts/jenkins_xpack_page_load_metrics.sh
Normal file
9
test/scripts/jenkins_xpack_page_load_metrics.sh
Normal file
|
@ -0,0 +1,9 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
source test/scripts/jenkins_test_setup_xpack.sh
|
||||
|
||||
checks-reporter-with-killswitch "Capture Kibana page load metrics" \
|
||||
node scripts/functional_tests \
|
||||
--debug --bail \
|
||||
--kibana-install-dir "$installDir" \
|
||||
--config test/page_load_metrics/config.ts;
|
1
x-pack/.gitignore
vendored
1
x-pack/.gitignore
vendored
|
@ -3,6 +3,7 @@
|
|||
/target
|
||||
/test/functional/failure_debug
|
||||
/test/functional/screenshots
|
||||
/test/page_load_metrics/screenshots
|
||||
/test/functional/apps/reporting/reports/session
|
||||
/test/reporting/configs/failure_debug/
|
||||
/legacy/plugins/reporting/.chromium/
|
||||
|
|
42
x-pack/test/page_load_metrics/config.ts
Normal file
42
x-pack/test/page_load_metrics/config.ts
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { resolve } from 'path';
|
||||
|
||||
import { FtrConfigProviderContext } from '@kbn/test/types/ftr';
|
||||
import { PuppeteerTestRunner } from './runner';
|
||||
|
||||
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
||||
const kibanaCommonTestsConfig = await readConfigFile(
|
||||
require.resolve('../../../test/common/config.js')
|
||||
);
|
||||
const xpackFunctionalTestsConfig = await readConfigFile(
|
||||
require.resolve('../functional/config.js')
|
||||
);
|
||||
|
||||
return {
|
||||
...kibanaCommonTestsConfig.getAll(),
|
||||
|
||||
testRunner: PuppeteerTestRunner,
|
||||
|
||||
esArchiver: {
|
||||
directory: resolve(__dirname, 'es_archives'),
|
||||
},
|
||||
|
||||
screenshots: {
|
||||
directory: resolve(__dirname, 'screenshots'),
|
||||
},
|
||||
|
||||
esTestCluster: {
|
||||
...xpackFunctionalTestsConfig.get('esTestCluster'),
|
||||
serverArgs: [...xpackFunctionalTestsConfig.get('esTestCluster.serverArgs')],
|
||||
},
|
||||
|
||||
kbnTestServer: {
|
||||
...xpackFunctionalTestsConfig.get('kbnTestServer'),
|
||||
},
|
||||
};
|
||||
}
|
BIN
x-pack/test/page_load_metrics/es_archives/default/data.json.gz
Normal file
BIN
x-pack/test/page_load_metrics/es_archives/default/data.json.gz
Normal file
Binary file not shown.
2402
x-pack/test/page_load_metrics/es_archives/default/mappings.json
Normal file
2402
x-pack/test/page_load_metrics/es_archives/default/mappings.json
Normal file
File diff suppressed because it is too large
Load diff
33
x-pack/test/page_load_metrics/runner.ts
Normal file
33
x-pack/test/page_load_metrics/runner.ts
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { CiStatsReporter } from '@kbn/dev-utils';
|
||||
import { capturePageLoadMetrics } from '@kbn/test';
|
||||
// @ts-ignore not TS yet
|
||||
import getUrl from '../../../src/test_utils/get_url';
|
||||
|
||||
import { FtrProviderContext } from './../functional/ftr_provider_context';
|
||||
|
||||
export async function PuppeteerTestRunner({ getService }: FtrProviderContext) {
|
||||
const log = getService('log');
|
||||
const config = getService('config');
|
||||
const esArchiver = getService('esArchiver');
|
||||
|
||||
await esArchiver.load('default');
|
||||
const metrics = await capturePageLoadMetrics(log, {
|
||||
headless: true,
|
||||
appConfig: {
|
||||
url: getUrl.baseUrl(config.get('servers.kibana')),
|
||||
username: config.get('servers.kibana.username'),
|
||||
password: config.get('servers.kibana.password'),
|
||||
},
|
||||
screenshotsDir: config.get('screenshots.directory'),
|
||||
});
|
||||
const reporter = CiStatsReporter.fromEnv(log);
|
||||
|
||||
log.debug('Report page load asset size');
|
||||
await reporter.metrics(metrics);
|
||||
}
|
90
yarn.lock
90
yarn.lock
|
@ -4574,6 +4574,13 @@
|
|||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/puppeteer@^3.0.0":
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/puppeteer/-/puppeteer-3.0.0.tgz#24cdcc131e319477608d893f0017e08befd70423"
|
||||
integrity sha512-59+fkfHHXHzX5rgoXIMnZyzum7ZLx/Wc3fhsOduFThpTpKbzzdBHMZsrkKGLunimB4Ds/tI5lXTRLALK8Mmnhg==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/q@^1.5.1":
|
||||
version "1.5.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8"
|
||||
|
@ -7637,6 +7644,15 @@ bl@^3.0.0:
|
|||
dependencies:
|
||||
readable-stream "^3.0.1"
|
||||
|
||||
bl@^4.0.1:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/bl/-/bl-4.0.2.tgz#52b71e9088515d0606d9dd9cc7aa48dc1f98e73a"
|
||||
integrity sha512-j4OH8f6Qg2bGuWfRiltT2HYGx0e1QcBTrK9KAHNMwMZdQnDZFk0ZSYIpADjYCB3U12nicC5tVJwSIhwOWjb4RQ==
|
||||
dependencies:
|
||||
buffer "^5.5.0"
|
||||
inherits "^2.0.4"
|
||||
readable-stream "^3.4.0"
|
||||
|
||||
blob@0.0.5:
|
||||
version "0.0.5"
|
||||
resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.5.tgz#d680eeef25f8cd91ad533f5b01eed48e64caf683"
|
||||
|
@ -8158,6 +8174,14 @@ buffer@^5.1.0, buffer@^5.2.0:
|
|||
base64-js "^1.0.2"
|
||||
ieee754 "^1.1.4"
|
||||
|
||||
buffer@^5.2.1, buffer@^5.5.0:
|
||||
version "5.6.0"
|
||||
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.6.0.tgz#a31749dc7d81d84db08abf937b6b8c4033f62786"
|
||||
integrity sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==
|
||||
dependencies:
|
||||
base64-js "^1.0.2"
|
||||
ieee754 "^1.1.4"
|
||||
|
||||
builtin-modules@^1.0.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f"
|
||||
|
@ -16649,7 +16673,7 @@ inflight@^1.0.4:
|
|||
once "^1.3.0"
|
||||
wrappy "1"
|
||||
|
||||
inherits@2, inherits@2.0.4, inherits@~2.0.3, inherits@~2.0.4:
|
||||
inherits@2, inherits@2.0.4, inherits@^2.0.4, inherits@~2.0.3, inherits@~2.0.4:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
|
@ -20773,6 +20797,11 @@ mixin-object@^2.0.1:
|
|||
for-in "^0.1.3"
|
||||
is-extendable "^0.1.1"
|
||||
|
||||
mkdirp-classic@^0.5.2:
|
||||
version "0.5.3"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113"
|
||||
integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==
|
||||
|
||||
mkdirp@0.5.1:
|
||||
version "0.5.1"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
|
||||
|
@ -23895,6 +23924,22 @@ puppeteer@^2.0.0:
|
|||
rimraf "^2.6.1"
|
||||
ws "^6.1.0"
|
||||
|
||||
puppeteer@^3.3.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-3.3.0.tgz#95839af9fdc0aa4de7e5ee073a4c0adeb9e2d3d7"
|
||||
integrity sha512-23zNqRltZ1PPoK28uRefWJ/zKb5Jhnzbbwbpcna2o5+QMn17F0khq5s1bdH3vPlyj+J36pubccR8wiNA/VE0Vw==
|
||||
dependencies:
|
||||
debug "^4.1.0"
|
||||
extract-zip "^2.0.0"
|
||||
https-proxy-agent "^4.0.0"
|
||||
mime "^2.0.3"
|
||||
progress "^2.0.1"
|
||||
proxy-from-env "^1.0.0"
|
||||
rimraf "^3.0.2"
|
||||
tar-fs "^2.0.0"
|
||||
unbzip2-stream "^1.3.3"
|
||||
ws "^7.2.3"
|
||||
|
||||
q@^1.1.2:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
|
||||
|
@ -26251,6 +26296,13 @@ rimraf@^2.5.4, rimraf@^2.7.1:
|
|||
dependencies:
|
||||
glob "^7.1.3"
|
||||
|
||||
rimraf@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
|
||||
integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
|
||||
dependencies:
|
||||
glob "^7.1.3"
|
||||
|
||||
rimraf@~2.0.2:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.0.3.tgz#f50a2965e7144e9afd998982f15df706730f56a9"
|
||||
|
@ -28598,6 +28650,16 @@ tar-fs@^1.16.3:
|
|||
pump "^1.0.0"
|
||||
tar-stream "^1.1.2"
|
||||
|
||||
tar-fs@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.0.tgz#d1cdd121ab465ee0eb9ccde2d35049d3f3daf0d5"
|
||||
integrity sha512-9uW5iDvrIMCVpvasdFHW0wJPez0K4JnMZtsuIeDI7HyMGJNxmDZDOCQROr7lXyS+iL/QMpj07qcjGYTSdRFXUg==
|
||||
dependencies:
|
||||
chownr "^1.1.1"
|
||||
mkdirp-classic "^0.5.2"
|
||||
pump "^3.0.0"
|
||||
tar-stream "^2.0.0"
|
||||
|
||||
tar-stream@^1.1.2, tar-stream@^1.5.2:
|
||||
version "1.5.5"
|
||||
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.5.5.tgz#5cad84779f45c83b1f2508d96b09d88c7218af55"
|
||||
|
@ -28608,6 +28670,17 @@ tar-stream@^1.1.2, tar-stream@^1.5.2:
|
|||
readable-stream "^2.0.0"
|
||||
xtend "^4.0.0"
|
||||
|
||||
tar-stream@^2.0.0:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.1.2.tgz#6d5ef1a7e5783a95ff70b69b97455a5968dc1325"
|
||||
integrity sha512-UaF6FoJ32WqALZGOIAApXx+OdxhekNMChu6axLJR85zMMjXKWFGjbIRe+J6P4UnRGg9rAwWvbTT0oI7hD/Un7Q==
|
||||
dependencies:
|
||||
bl "^4.0.1"
|
||||
end-of-stream "^1.4.1"
|
||||
fs-constants "^1.0.0"
|
||||
inherits "^2.0.3"
|
||||
readable-stream "^3.1.1"
|
||||
|
||||
tar-stream@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.1.0.tgz#d1aaa3661f05b38b5acc9b7020efdca5179a2cc3"
|
||||
|
@ -28897,7 +28970,7 @@ through2@~2.0.3:
|
|||
readable-stream "~2.3.6"
|
||||
xtend "~4.0.1"
|
||||
|
||||
through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6, through@~2.3.4, through@~2.3.6, through@~2.3.8:
|
||||
through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6, through@^2.3.8, through@~2.3.4, through@~2.3.6, through@~2.3.8:
|
||||
version "2.3.8"
|
||||
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
|
||||
integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
|
||||
|
@ -30091,6 +30164,14 @@ unbzip2-stream@^1.0.9:
|
|||
buffer "^3.0.1"
|
||||
through "^2.3.6"
|
||||
|
||||
unbzip2-stream@^1.3.3:
|
||||
version "1.4.2"
|
||||
resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.2.tgz#84eb9e783b186d8fb397515fbb656f312f1a7dbf"
|
||||
integrity sha512-pZMVAofMrrHX6Ik39hCk470kulCbmZ2SWfQLPmTWqfJV/oUm0gn1CblvHdUu4+54Je6Jq34x8kY6XjTy6dMkOg==
|
||||
dependencies:
|
||||
buffer "^5.2.1"
|
||||
through "^2.3.8"
|
||||
|
||||
unc-path-regex@^0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa"
|
||||
|
@ -32065,6 +32146,11 @@ ws@^7.0.0:
|
|||
dependencies:
|
||||
async-limiter "^1.0.0"
|
||||
|
||||
ws@^7.2.3:
|
||||
version "7.3.0"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-7.3.0.tgz#4b2f7f219b3d3737bc1a2fbf145d825b94d38ffd"
|
||||
integrity sha512-iFtXzngZVXPGgpTlP1rBqsUK82p9tKqsWRPg5L56egiljujJT3vGAYnHANvFxBieXrTFavhzhxW52jnaWV+w2w==
|
||||
|
||||
ws@~3.3.1:
|
||||
version "3.3.3"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue