From 37365bfb51daf84aa5a654a1e691afb22e687e13 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Tue, 12 May 2020 16:53:19 +0300 Subject: [PATCH 01/32] performance_tests: draft version --- package.json | 2 + packages/kbn-test/src/index.ts | 3 + scripts/performance_tests.js | 21 ++++++ src/dev/performance/index.ts | 71 +++++++++++++++++++ src/dev/performance/tests/navigation.ts | 81 ++++++++++++++++++++++ yarn.lock | 90 ++++++++++++++++++++++++- 6 files changed, 266 insertions(+), 2 deletions(-) create mode 100644 scripts/performance_tests.js create mode 100644 src/dev/performance/index.ts create mode 100644 src/dev/performance/tests/navigation.ts diff --git a/package.json b/package.json index 0c83cb429b651e..93bfcfee0a8805 100644 --- a/package.json +++ b/package.json @@ -370,6 +370,7 @@ "@types/pngjs": "^3.3.2", "@types/podium": "^1.0.0", "@types/prop-types": "^15.5.3", + "@types/puppeteer": "^2.1.0", "@types/reach__router": "^1.2.6", "@types/react": "^16.9.19", "@types/react-dom": "^16.9.5", @@ -483,6 +484,7 @@ "postcss-url": "^8.0.0", "prettier": "^1.19.1", "proxyquire": "1.8.0", + "puppeteer": "^3.0.4", "react-popper-tooltip": "^2.10.1", "react-textarea-autosize": "^7.1.2", "regenerate": "^1.4.0", diff --git a/packages/kbn-test/src/index.ts b/packages/kbn-test/src/index.ts index 57cdc8ffd494f3..1c0f297ae96e54 100644 --- a/packages/kbn-test/src/index.ts +++ b/packages/kbn-test/src/index.ts @@ -42,6 +42,9 @@ export { kbnTestConfig, kibanaServerTestUser, kibanaTestUser, adminTestUser } fr // @ts-ignore not typed yet export { setupUsers, DEFAULT_SUPERUSER_PASS } from './functional_tests/lib/auth'; +// @ts-ignore not typed yet +export { runElasticsearch, runKibanaServer } from './functional_tests/lib'; + // @ts-ignore not typed yet export { readConfigFile } from './functional_test_runner/lib/config/read_config_file'; diff --git a/scripts/performance_tests.js b/scripts/performance_tests.js new file mode 100644 index 00000000000000..0df97612e962a0 --- /dev/null +++ b/scripts/performance_tests.js @@ -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('../src/dev/performance').runTestsCli(); diff --git a/src/dev/performance/index.ts b/src/dev/performance/index.ts new file mode 100644 index 00000000000000..2c04a4d353a205 --- /dev/null +++ b/src/dev/performance/index.ts @@ -0,0 +1,71 @@ +/* + * 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 { resolve } from 'path'; +import * as Fs from 'fs'; +import { withProcRunner, ToolingLog, REPO_ROOT } from '@kbn/dev-utils'; +import { readConfigFile, runElasticsearch, runKibanaServer } from '@kbn/test'; +import { navigateToKibana } from './tests/navigation'; +// @ts-ignore not TS yet +import getUrl from '../../test_utils/get_url'; + +const configPath = resolve(REPO_ROOT, 'x-pack/test/functional/config.js'); +const statsPath = resolve(REPO_ROOT, 'target/performance_stats'); + +export async function runTestsCli() { + const log = new ToolingLog({ + level: 'debug', + writeTo: process.stdout, + }); + + const opts = { + log, + }; + + let results; + + await withProcRunner(log, async procs => { + const config = await readConfigFile(log, configPath); + + const appConfig = { + url: getUrl.baseUrl(config.get('servers.kibana')), + login: config.get('servers.kibana.username'), + password: config.get('servers.kibana.password'), + }; + + let es; + try { + es = await runElasticsearch({ config, options: opts }); + await runKibanaServer({ procs, config, options: opts }); + // run tests here + results = await navigateToKibana(log, appConfig); + } finally { + try { + await procs.stop('kibana'); + } finally { + if (es) { + await es.cleanup(); + } + } + } + }); + + Fs.mkdirSync(statsPath, { recursive: true }); + Fs.writeFileSync(resolve(statsPath, 'login_page.json'), JSON.stringify(results, null, 2)); +} diff --git a/src/dev/performance/tests/navigation.ts b/src/dev/performance/tests/navigation.ts new file mode 100644 index 00000000000000..d3e649422f7ae2 --- /dev/null +++ b/src/dev/performance/tests/navigation.ts @@ -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 _ from 'lodash'; +import puppeteer from 'puppeteer'; +import { ToolingLog, REPO_ROOT } from '@kbn/dev-utils'; +import { resolve } from 'path'; + +const statsPath = resolve(REPO_ROOT, 'target/performance_stats'); + +export async function navigateToKibana( + log: ToolingLog, + appConfig: { url: string; login: string; password: string } +) { + const browser = await puppeteer.launch({ headless: false }); + const results: Array<{ url: any; time: any; size: string; eventSize: string }> = []; + const page = await browser.newPage(); + + const client = await page.target().createCDPSession(); + await client.send('Network.enable'); + await client.send('Performance.enable'); + await page.tracing.start({ path: resolve(statsPath, 'trace.json') }); + const devToolsResponses = new Map(); + + client.on('Network.responseReceived', event => { + devToolsResponses.set(event.requestId, event.response); + }); + + client.on('Network.loadingFinished', event => { + const response = devToolsResponses.get(event.requestId); + + if (/^.*.[js|css]$/.test(response.url)) { + const encodedBodyLength = event.encodedDataLength - response.encodedDataLength; + results.push({ + url: response.url, + time: response.timing ? response.timing.requestTime : 0, + size: (encodedBodyLength / 1024).toFixed(1), + eventSize: (event.encodedDataLength / 1024).toFixed(1), + }); + } + }); + + client.on( + 'Network.responseReceived', + async ({ requestId, loaderId, timestamp, type, response, frameId }: any) => { + log.debug(response.url); + } + ); + + page.setDefaultNavigationTimeout(0); + log.debug(`goto ${appConfig.url}`); + await page.goto(appConfig.url, { + waitUntil: 'networkidle0', + }); + log.debug(`log in to the app..`); + await page.type('[data-test-subj="loginUsername"]', appConfig.login); + await page.type('[data-test-subj="loginPassword"]', appConfig.password); + await page.click('[data-test-subj="loginSubmit"]'); + await page.waitForNavigation({ waitUntil: 'networkidle0' }); + + await page.tracing.stop(); + await browser.close(); + + return results; +} diff --git a/yarn.lock b/yarn.lock index 8b16bac98e8951..e664c572d7d430 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4606,6 +4606,13 @@ dependencies: "@types/node" "*" +"@types/puppeteer@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@types/puppeteer/-/puppeteer-2.1.0.tgz#31367580654632f87f86df565f1bde0533577401" + integrity sha512-QIRQXl0VaSgnwOZ1LwxD321Tfb1jLOzCWuF2BrwjEkWq2IhxSicPOddUywLV7dRSO6mcU4sWKRdoGdci6gk0Aw== + 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" @@ -7629,6 +7636,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" @@ -8150,6 +8166,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" @@ -16646,7 +16670,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== @@ -20818,6 +20842,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" @@ -23956,6 +23985,22 @@ puppeteer@^2.0.0: rimraf "^2.6.1" ws "^6.1.0" +puppeteer@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-3.0.4.tgz#f445aae0a6732c65bbb90e963dcd6fd8fde0d780" + integrity sha512-1QEb4tJXXbNId7WSHlcDkS3B4GklTIebKn8Y9D6B7tAdUjQncb+8QlTjbQsAgGX5dhRG32Qycuk5XKzJgLs0sg== + 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" @@ -26312,6 +26357,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" @@ -28681,6 +28733,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" @@ -28691,6 +28753,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" @@ -28989,7 +29062,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= @@ -30183,6 +30256,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" @@ -32156,6 +32237,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" From ba5f384b96d535d268a477c9ae80534718fb712c Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Thu, 14 May 2020 18:44:26 +0200 Subject: [PATCH 02/32] update cli runner and script --- src/dev/performance/index.ts | 68 +++++++++----------- src/dev/performance/tests/navigation.ts | 83 ++++++++++++++----------- 2 files changed, 75 insertions(+), 76 deletions(-) diff --git a/src/dev/performance/index.ts b/src/dev/performance/index.ts index 2c04a4d353a205..a9d543607a4f8e 100644 --- a/src/dev/performance/index.ts +++ b/src/dev/performance/index.ts @@ -19,8 +19,8 @@ import { resolve } from 'path'; import * as Fs from 'fs'; -import { withProcRunner, ToolingLog, REPO_ROOT } from '@kbn/dev-utils'; -import { readConfigFile, runElasticsearch, runKibanaServer } from '@kbn/test'; +import { REPO_ROOT, run, createFlagError } from '@kbn/dev-utils'; +import { readConfigFile } from '@kbn/test'; import { navigateToKibana } from './tests/navigation'; // @ts-ignore not TS yet import getUrl from '../../test_utils/get_url'; @@ -28,44 +28,34 @@ import getUrl from '../../test_utils/get_url'; const configPath = resolve(REPO_ROOT, 'x-pack/test/functional/config.js'); const statsPath = resolve(REPO_ROOT, 'target/performance_stats'); -export async function runTestsCli() { - const log = new ToolingLog({ - level: 'debug', - writeTo: process.stdout, - }); +export function runTestsCli() { + run( + async ({ flags, log }) => { + const config = await readConfigFile(log, configPath); - const opts = { - log, - }; - - let results; - - await withProcRunner(log, async procs => { - const config = await readConfigFile(log, configPath); - - const appConfig = { - url: getUrl.baseUrl(config.get('servers.kibana')), - login: config.get('servers.kibana.username'), - password: config.get('servers.kibana.password'), - }; - - let es; - try { - es = await runElasticsearch({ config, options: opts }); - await runKibanaServer({ procs, config, options: opts }); - // run tests here - results = await navigateToKibana(log, appConfig); - } finally { - try { - await procs.stop('kibana'); - } finally { - if (es) { - await es.cleanup(); - } + const kibanaUrl = flags['kibana-url']; + if (!kibanaUrl || typeof kibanaUrl !== 'string') { + throw createFlagError('Expect --kibana-url to be a string'); } - } - }); - Fs.mkdirSync(statsPath, { recursive: true }); - Fs.writeFileSync(resolve(statsPath, 'login_page.json'), JSON.stringify(results, null, 2)); + const appConfig = { + url: kibanaUrl, + login: config.get('servers.kibana.username'), + password: config.get('servers.kibana.password'), + }; + + const results = await navigateToKibana(log, appConfig); + + Fs.mkdirSync(statsPath, { recursive: true }); + Fs.writeFileSync(resolve(statsPath, 'login_page.json'), JSON.stringify(results, null, 2)); + }, + { + flags: { + string: ['kibana-url'], + help: ` + --kibana-url Url for Kibana we should connect to, + `, + }, + } + ); } diff --git a/src/dev/performance/tests/navigation.ts b/src/dev/performance/tests/navigation.ts index d3e649422f7ae2..c3f0bfdd8f6d24 100644 --- a/src/dev/performance/tests/navigation.ts +++ b/src/dev/performance/tests/navigation.ts @@ -30,51 +30,60 @@ export async function navigateToKibana( ) { const browser = await puppeteer.launch({ headless: false }); const results: Array<{ url: any; time: any; size: string; eventSize: string }> = []; - const page = await browser.newPage(); - - const client = await page.target().createCDPSession(); - await client.send('Network.enable'); - await client.send('Performance.enable'); - await page.tracing.start({ path: resolve(statsPath, 'trace.json') }); const devToolsResponses = new Map(); - client.on('Network.responseReceived', event => { - devToolsResponses.set(event.requestId, event.response); - }); + for (const url of ['/login', '/app/kibana', '/app/graph']) { + const page = await browser.newPage(); + page.setDefaultNavigationTimeout(0); + const frameResponses = new Map(); + devToolsResponses.set(url, frameResponses); - client.on('Network.loadingFinished', event => { - const response = devToolsResponses.get(event.requestId); + const client = await page.target().createCDPSession(); + await client.send('Network.enable'); - if (/^.*.[js|css]$/.test(response.url)) { - const encodedBodyLength = event.encodedDataLength - response.encodedDataLength; - results.push({ - url: response.url, - time: response.timing ? response.timing.requestTime : 0, - size: (encodedBodyLength / 1024).toFixed(1), - eventSize: (event.encodedDataLength / 1024).toFixed(1), - }); - } - }); + client.on('Network.responseReceived', event => { + frameResponses.set(event.requestId, { responseRecieved: event }); + }); + + client.on('Network.loadingFinished', event => { + frameResponses.get(event.requestId).loadingFinished = event; + + // if (/^.*.[js|css]$/.test(response.url)) { + // const encodedBodyLength = event.encodedDataLength - response.encodedDataLength; + // results.push({ + // url: response.url, + // time: response.timing ? response.timing.requestTime : 0, + // size: (encodedBodyLength / 1024).toFixed(1), + // eventSize: (event.encodedDataLength / 1024).toFixed(1), + // }); + // } + }); + + client.on( + 'Network.responseReceived', + async ({ requestId, loaderId, timestamp, type, response, frameId }: any) => { + log.debug(response.url); + } + ); + + const fullURL = appConfig.url + url; + log.debug(`goto ${fullURL}`); + await page.goto(fullURL, { + waitUntil: 'networkidle0', + }); - client.on( - 'Network.responseReceived', - async ({ requestId, loaderId, timestamp, type, response, frameId }: any) => { - log.debug(response.url); + if (url === '/login') { + log.debug(`log in to the app..`); + await page.type('[data-test-subj="loginUsername"]', appConfig.login); + await page.type('[data-test-subj="loginPassword"]', appConfig.password); + await page.click('[data-test-subj="loginSubmit"]'); + await page.waitForNavigation({ waitUntil: 'networkidle0' }); } - ); - page.setDefaultNavigationTimeout(0); - log.debug(`goto ${appConfig.url}`); - await page.goto(appConfig.url, { - waitUntil: 'networkidle0', - }); - log.debug(`log in to the app..`); - await page.type('[data-test-subj="loginUsername"]', appConfig.login); - await page.type('[data-test-subj="loginPassword"]', appConfig.password); - await page.click('[data-test-subj="loginSubmit"]'); - await page.waitForNavigation({ waitUntil: 'networkidle0' }); + await page.close(); + // clear dev tools responses + } - await page.tracing.stop(); await browser.close(); return results; From 8e9f0b1dadb967a13451abf3a20085f76b8d21bf Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Tue, 19 May 2020 11:29:00 +0200 Subject: [PATCH 03/32] ingest metrics --- src/dev/performance/event.ts | 34 +++++++++ src/dev/performance/index.ts | 26 ++++--- src/dev/performance/ingest_metrics.ts | 71 +++++++++++++++++++ src/dev/performance/{tests => }/navigation.ts | 57 +++++++-------- 4 files changed, 146 insertions(+), 42 deletions(-) create mode 100644 src/dev/performance/event.ts create mode 100644 src/dev/performance/ingest_metrics.ts rename src/dev/performance/{tests => }/navigation.ts (59%) diff --git a/src/dev/performance/event.ts b/src/dev/performance/event.ts new file mode 100644 index 00000000000000..0b7afc1e977599 --- /dev/null +++ b/src/dev/performance/event.ts @@ -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; + timestamp: number; + type: string; +} + +export interface LoadingFinishedEvent { + encodedDataLength: number; + requestId: string; + shouldReportCorbBlocking: boolean; + timestamp: number; +} diff --git a/src/dev/performance/index.ts b/src/dev/performance/index.ts index a9d543607a4f8e..1dbdbb92fe43d7 100644 --- a/src/dev/performance/index.ts +++ b/src/dev/performance/index.ts @@ -18,15 +18,14 @@ */ import { resolve } from 'path'; -import * as Fs from 'fs'; import { REPO_ROOT, run, createFlagError } from '@kbn/dev-utils'; import { readConfigFile } from '@kbn/test'; -import { navigateToKibana } from './tests/navigation'; +import { navigateToApp } from './navigation'; +import { ingestPerformanceMetrics } from './ingest_metrics'; // @ts-ignore not TS yet import getUrl from '../../test_utils/get_url'; const configPath = resolve(REPO_ROOT, 'x-pack/test/functional/config.js'); -const statsPath = resolve(REPO_ROOT, 'target/performance_stats'); export function runTestsCli() { run( @@ -38,22 +37,27 @@ export function runTestsCli() { throw createFlagError('Expect --kibana-url to be a string'); } - const appConfig = { - url: kibanaUrl, - login: config.get('servers.kibana.username'), - password: config.get('servers.kibana.password'), - }; + const headless = !flags.head; - const results = await navigateToKibana(log, appConfig); + const options = { + headless, + appConfig: { + url: kibanaUrl, + login: config.get('servers.kibana.username'), + password: config.get('servers.kibana.password'), + }, + }; - Fs.mkdirSync(statsPath, { recursive: true }); - Fs.writeFileSync(resolve(statsPath, 'login_page.json'), JSON.stringify(results, null, 2)); + const responses = await navigateToApp(log, options); + ingestPerformanceMetrics(log, responses); }, { flags: { string: ['kibana-url'], + boolean: ['head'], help: ` --kibana-url Url for Kibana we should connect to, + --head Run pupeteer with graphical user interface, `, }, } diff --git a/src/dev/performance/ingest_metrics.ts b/src/dev/performance/ingest_metrics.ts new file mode 100644 index 00000000000000..c7b082daefab6a --- /dev/null +++ b/src/dev/performance/ingest_metrics.ts @@ -0,0 +1,71 @@ +/* + * 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 { CiStatsReporter, ToolingLog } from '@kbn/dev-utils'; +import { LoadingFinishedEvent, ResponseReceivedEvent } from './event'; + +export function ingestPerformanceMetrics( + log: ToolingLog, + responses: Map< + string, + Map + > +) { + const uniqueRequests = new Map>(); + + for (const [path, frameResponses] of responses) { + for (const [, response] of frameResponses) { + const url: string = response.responseRecieved.response.url; + const encodedBodyLength: number = + response.loadingFinished.encodedDataLength - + response.responseRecieved.response.encodedDataLength; + if (uniqueRequests.has(url)) { + uniqueRequests.set( + url, + [{ path, encodedBodyLength }].concat(uniqueRequests.get(url) || []) + ); + } else { + uniqueRequests.set(url, [{ path, encodedBodyLength }]); + } + } + } + + const metrics = []; + + for (const [path, array] of uniqueRequests) { + if (array.length > 1) { + const avgSize = Math.round( + array.map((i: any) => i.encodedBodyLength).reduce((acc, value) => acc + value) / + array.length + ); + metrics.push({ path, encodedBodyLength: avgSize }); + } + } + + const reporter = CiStatsReporter.fromEnv(log); + metrics.map(asset => { + reporter.metrics([ + { + group: 'Asset size', + id: asset.path, + value: asset.encodedBodyLength, + }, + ]); + }); +} diff --git a/src/dev/performance/tests/navigation.ts b/src/dev/performance/navigation.ts similarity index 59% rename from src/dev/performance/tests/navigation.ts rename to src/dev/performance/navigation.ts index c3f0bfdd8f6d24..18e75401543857 100644 --- a/src/dev/performance/tests/navigation.ts +++ b/src/dev/performance/navigation.ts @@ -19,21 +19,34 @@ import _ from 'lodash'; import puppeteer from 'puppeteer'; -import { ToolingLog, REPO_ROOT } from '@kbn/dev-utils'; -import { resolve } from 'path'; +import { ToolingLog } from '@kbn/dev-utils'; +import { LoadingFinishedEvent, ResponseReceivedEvent } from './event'; -const statsPath = resolve(REPO_ROOT, 'target/performance_stats'); - -export async function navigateToKibana( +export async function navigateToApp( log: ToolingLog, - appConfig: { url: string; login: string; password: string } + options: { headless: boolean; appConfig: { url: string; login: string; password: string } } ) { - const browser = await puppeteer.launch({ headless: false }); - const results: Array<{ url: any; time: any; size: string; eventSize: string }> = []; - const devToolsResponses = new Map(); + const { headless, appConfig } = options; + const browser = await puppeteer.launch({ headless }); + const devToolsResponses = new Map(); + const apps = [ + 'kibana', + 'graph', + 'logs', + 'canvas', + 'maps', + 'timelion', + 'metrics', + 'apm', + 'uptime', + 'siem', + 'dev_tools', + 'monitoring', + ].map(app => `/app/${app}`); - for (const url of ['/login', '/app/kibana', '/app/graph']) { + for (const url of ['/login', ...apps]) { const page = await browser.newPage(); + page.setCacheEnabled(false); page.setDefaultNavigationTimeout(0); const frameResponses = new Map(); devToolsResponses.set(url, frameResponses); @@ -41,31 +54,14 @@ export async function navigateToKibana( const client = await page.target().createCDPSession(); await client.send('Network.enable'); - client.on('Network.responseReceived', event => { + client.on('Network.responseReceived', (event: ResponseReceivedEvent) => { frameResponses.set(event.requestId, { responseRecieved: event }); }); - client.on('Network.loadingFinished', event => { + client.on('Network.loadingFinished', (event: LoadingFinishedEvent) => { frameResponses.get(event.requestId).loadingFinished = event; - - // if (/^.*.[js|css]$/.test(response.url)) { - // const encodedBodyLength = event.encodedDataLength - response.encodedDataLength; - // results.push({ - // url: response.url, - // time: response.timing ? response.timing.requestTime : 0, - // size: (encodedBodyLength / 1024).toFixed(1), - // eventSize: (event.encodedDataLength / 1024).toFixed(1), - // }); - // } }); - client.on( - 'Network.responseReceived', - async ({ requestId, loaderId, timestamp, type, response, frameId }: any) => { - log.debug(response.url); - } - ); - const fullURL = appConfig.url + url; log.debug(`goto ${fullURL}`); await page.goto(fullURL, { @@ -81,10 +77,9 @@ export async function navigateToKibana( } await page.close(); - // clear dev tools responses } await browser.close(); - return results; + return devToolsResponses; } From d4e2f0cda8698b93040cb2654c00f832ba74d57c Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Tue, 19 May 2020 14:48:32 +0200 Subject: [PATCH 04/32] save asset type for plugins --- src/dev/performance/ingest_metrics.ts | 35 +++++++++++++++++++++------ 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/src/dev/performance/ingest_metrics.ts b/src/dev/performance/ingest_metrics.ts index c7b082daefab6a..3e0942be9d98c8 100644 --- a/src/dev/performance/ingest_metrics.ts +++ b/src/dev/performance/ingest_metrics.ts @@ -27,7 +27,10 @@ export function ingestPerformanceMetrics( Map > ) { - const uniqueRequests = new Map>(); + const uniqueRequests = new Map< + string, + Array<{ path: string; encodedBodyLength: number; plugin?: string; type?: string }> + >(); for (const [path, frameResponses] of responses) { for (const [, response] of frameResponses) { @@ -46,15 +49,33 @@ export function ingestPerformanceMetrics( } } - const metrics = []; + const metrics = Array<{ + url: string; + encodedBodyLength: number; + plugin?: string; + type?: string; + }>(); - for (const [path, array] of uniqueRequests) { - if (array.length > 1) { - const avgSize = Math.round( + for (const [url, array] of uniqueRequests) { + const isPlugin = url.endsWith('.plugin.js'); + if (isPlugin) { + const type = url.match(/.*\/\d+.plugin.js$/) ? 'lazy' : 'entry'; + const results = url.match(/(?<=plugin\/)(.*)(?=\/)/); + const plugin = results ? results[0] : url; + const encodedBodyLength = Math.round( array.map((i: any) => i.encodedBodyLength).reduce((acc, value) => acc + value) / array.length ); - metrics.push({ path, encodedBodyLength: avgSize }); + + metrics.push({ url, plugin, type, encodedBodyLength }); + } else { + if (array.length > 1) { + const encodedBodyLength = Math.round( + array.map((i: any) => i.encodedBodyLength).reduce((acc, value) => acc + value) / + array.length + ); + metrics.push({ url, encodedBodyLength }); + } } } @@ -63,7 +84,7 @@ export function ingestPerformanceMetrics( reporter.metrics([ { group: 'Asset size', - id: asset.path, + id: asset.url, value: asset.encodedBodyLength, }, ]); From fc06477939717a2991e8f67a3011c82a1c9f1f40 Mon Sep 17 00:00:00 2001 From: Dmitry Lemeshko Date: Tue, 19 May 2020 19:17:01 +0200 Subject: [PATCH 05/32] Update src/dev/performance/ingest_metrics.ts Co-authored-by: Spencer --- src/dev/performance/ingest_metrics.ts | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/dev/performance/ingest_metrics.ts b/src/dev/performance/ingest_metrics.ts index 3e0942be9d98c8..1798191ce0a2b6 100644 --- a/src/dev/performance/ingest_metrics.ts +++ b/src/dev/performance/ingest_metrics.ts @@ -80,13 +80,9 @@ export function ingestPerformanceMetrics( } const reporter = CiStatsReporter.fromEnv(log); - metrics.map(asset => { - reporter.metrics([ - { - group: 'Asset size', - id: asset.url, - value: asset.encodedBodyLength, - }, - ]); - }); + await reporter.metrics(metrics.map(asset => ({ + group: 'Asset size', + id: asset.url, + value: asset.encodedBodyLength, + }))); } From 1551910dc2a6865762e8a9db187398ac8cdbc264 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Thu, 28 May 2020 18:34:58 +0200 Subject: [PATCH 06/32] follow review comments --- ...e_tests.js => report_page_load_metrics.js} | 2 +- .../event.ts | 0 .../index.ts | 2 +- .../ingest_metrics.ts | 42 +++++++----------- .../navigation.ts | 18 +++----- x-pack/test/page_load_metrics/config.ts | 44 +++++++++++++++++++ x-pack/test/page_load_metrics/runner.ts | 31 +++++++++++++ 7 files changed, 99 insertions(+), 40 deletions(-) rename scripts/{performance_tests.js => report_page_load_metrics.js} (93%) rename src/dev/{performance => loading_time_performance}/event.ts (100%) rename src/dev/{performance => loading_time_performance}/index.ts (96%) rename src/dev/{performance => loading_time_performance}/ingest_metrics.ts (73%) rename src/dev/{performance => loading_time_performance}/navigation.ts (93%) create mode 100644 x-pack/test/page_load_metrics/config.ts create mode 100644 x-pack/test/page_load_metrics/runner.ts diff --git a/scripts/performance_tests.js b/scripts/report_page_load_metrics.js similarity index 93% rename from scripts/performance_tests.js rename to scripts/report_page_load_metrics.js index 0df97612e962a0..10bb34c7ec24f9 100644 --- a/scripts/performance_tests.js +++ b/scripts/report_page_load_metrics.js @@ -18,4 +18,4 @@ */ require('../src/setup_node_env'); -require('../src/dev/performance').runTestsCli(); +require('../src/dev/loading_time_performance').runTestsCli(); diff --git a/src/dev/performance/event.ts b/src/dev/loading_time_performance/event.ts similarity index 100% rename from src/dev/performance/event.ts rename to src/dev/loading_time_performance/event.ts diff --git a/src/dev/performance/index.ts b/src/dev/loading_time_performance/index.ts similarity index 96% rename from src/dev/performance/index.ts rename to src/dev/loading_time_performance/index.ts index 1dbdbb92fe43d7..4a1dd427a1d5b4 100644 --- a/src/dev/performance/index.ts +++ b/src/dev/loading_time_performance/index.ts @@ -25,7 +25,7 @@ import { ingestPerformanceMetrics } from './ingest_metrics'; // @ts-ignore not TS yet import getUrl from '../../test_utils/get_url'; -const configPath = resolve(REPO_ROOT, 'x-pack/test/functional/config.js'); +const configPath = resolve(REPO_ROOT, 'x-pack/test/page_load_metrics/config.ts'); export function runTestsCli() { run( diff --git a/src/dev/performance/ingest_metrics.ts b/src/dev/loading_time_performance/ingest_metrics.ts similarity index 73% rename from src/dev/performance/ingest_metrics.ts rename to src/dev/loading_time_performance/ingest_metrics.ts index 3e0942be9d98c8..6916b0260cde46 100644 --- a/src/dev/performance/ingest_metrics.ts +++ b/src/dev/loading_time_performance/ingest_metrics.ts @@ -52,41 +52,31 @@ export function ingestPerformanceMetrics( const metrics = Array<{ url: string; encodedBodyLength: number; - plugin?: string; - type?: string; }>(); for (const [url, array] of uniqueRequests) { - const isPlugin = url.endsWith('.plugin.js'); - if (isPlugin) { - const type = url.match(/.*\/\d+.plugin.js$/) ? 'lazy' : 'entry'; - const results = url.match(/(?<=plugin\/)(.*)(?=\/)/); - const plugin = results ? results[0] : url; + // ignore lazy loaded plugins + if (url.match(/.*\/\d+.plugin.js$/)) { + continue; + } + + // get all entry plugins and repeatable assets + if (url.endsWith('.plugin.js') || array.length > 1) { const encodedBodyLength = Math.round( array.map((i: any) => i.encodedBodyLength).reduce((acc, value) => acc + value) / array.length ); - - metrics.push({ url, plugin, type, encodedBodyLength }); - } else { - if (array.length > 1) { - const encodedBodyLength = Math.round( - array.map((i: any) => i.encodedBodyLength).reduce((acc, value) => acc + value) / - array.length - ); - metrics.push({ url, encodedBodyLength }); - } + metrics.push({ url, encodedBodyLength }); } } const reporter = CiStatsReporter.fromEnv(log); - metrics.map(asset => { - reporter.metrics([ - { - group: 'Asset size', - id: asset.url, - value: asset.encodedBodyLength, - }, - ]); - }); + + reporter.metrics( + metrics.map((asset) => ({ + group: 'Asset size', + id: asset.url, + value: asset.encodedBodyLength, + })) + ); } diff --git a/src/dev/performance/navigation.ts b/src/dev/loading_time_performance/navigation.ts similarity index 93% rename from src/dev/performance/navigation.ts rename to src/dev/loading_time_performance/navigation.ts index 18e75401543857..134f7bd5f2465f 100644 --- a/src/dev/performance/navigation.ts +++ b/src/dev/loading_time_performance/navigation.ts @@ -31,18 +31,12 @@ export async function navigateToApp( const devToolsResponses = new Map(); const apps = [ 'kibana', - 'graph', - 'logs', - 'canvas', - 'maps', - 'timelion', - 'metrics', - 'apm', - 'uptime', - 'siem', - 'dev_tools', - 'monitoring', - ].map(app => `/app/${app}`); + 'canvas', // +1 + 'maps', // +16 + 'timelion', // +1 + 'apm', // +1 + 'uptime', // +1 + ].map((app) => `/app/${app}`); for (const url of ['/login', ...apps]) { const page = await browser.newPage(); diff --git a/x-pack/test/page_load_metrics/config.ts b/x-pack/test/page_load_metrics/config.ts new file mode 100644 index 00000000000000..620917cc03dba8 --- /dev/null +++ b/x-pack/test/page_load_metrics/config.ts @@ -0,0 +1,44 @@ +/* + * 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('../../../test/functional/es_archives'), + }, + + esTestCluster: { + ...xpackFunctionalTestsConfig.get('esTestCluster'), + serverArgs: [ + ...xpackFunctionalTestsConfig.get('esTestCluster.serverArgs'), + // define custom es server here + // API Keys is enabled at the top level + // 'xpack.security.enabled=true', + ], + }, + + kbnTestServer: { + ...xpackFunctionalTestsConfig.get('kbnTestServer'), + serverArgs: [...xpackFunctionalTestsConfig.get('kbnTestServer.serverArgs')], + }, + }; +} diff --git a/x-pack/test/page_load_metrics/runner.ts b/x-pack/test/page_load_metrics/runner.ts new file mode 100644 index 00000000000000..63b0803e88e71b --- /dev/null +++ b/x-pack/test/page_load_metrics/runner.ts @@ -0,0 +1,31 @@ +/* + * 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 Url from 'url'; + +import { withProcRunner } from '@kbn/dev-utils'; +import { FtrProviderContext } from './../functional/ftr_provider_context'; +import { navigateToApp } from './../../../src/dev/loading_time_performance/navigation'; +import { ingestPerformanceMetrics } from './../../../src/dev/loading_time_performance/ingest_metrics'; + +export async function PuppeteerTestRunner({ getService }: FtrProviderContext) { + const log = getService('log'); + const config = getService('config'); + + const options = { + headless: false, + appConfig: { + url: Url.format(config.get('servers.kibana')), + login: config.get('servers.kibana.username'), + password: config.get('servers.kibana.password'), + }, + }; + + await withProcRunner(log, async () => { + const responses = await navigateToApp(log, options); + ingestPerformanceMetrics(log, responses); + }); +} From bebd18912bf7f2cd50823a1a9f4bfa3de99a7676 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Fri, 29 May 2020 00:11:34 +0200 Subject: [PATCH 07/32] fix size calc, add FTR config, move src to kbn/test --- Jenkinsfile | 1 + package.json | 2 - packages/kbn-test/package.json | 2 + packages/kbn-test/src/index.ts | 2 + .../capture_page_load_metrics.ts | 81 + .../kbn-test/src/page_load_metrics/cli.ts | 51 +- .../kbn-test/src/page_load_metrics}/event.ts | 7 + .../kbn-test/src/page_load_metrics/index.ts | 21 + .../src/page_load_metrics/navigation.ts | 127 + ...e_load_metrics.js => page_load_metrics.js} | 2 +- .../ingest_metrics.ts | 82 - .../loading_time_performance/navigation.ts | 79 - .../jenkins_xpack_page_load_metrics.sh | 9 + x-pack/test/page_load_metrics/config.ts | 9 +- .../es_archives/default/data.json.gz | Bin 0 -> 1812 bytes .../es_archives/default/mappings.json | 2402 +++++++++++++++++ x-pack/test/page_load_metrics/runner.ts | 27 +- yarn.lock | 32 +- 18 files changed, 2715 insertions(+), 221 deletions(-) create mode 100644 packages/kbn-test/src/page_load_metrics/capture_page_load_metrics.ts rename src/dev/loading_time_performance/index.ts => packages/kbn-test/src/page_load_metrics/cli.ts (53%) rename {src/dev/loading_time_performance => packages/kbn-test/src/page_load_metrics}/event.ts (89%) create mode 100644 packages/kbn-test/src/page_load_metrics/index.ts create mode 100644 packages/kbn-test/src/page_load_metrics/navigation.ts rename scripts/{report_page_load_metrics.js => page_load_metrics.js} (93%) delete mode 100644 src/dev/loading_time_performance/ingest_metrics.ts delete mode 100644 src/dev/loading_time_performance/navigation.ts create mode 100644 test/scripts/jenkins_xpack_page_load_metrics.sh create mode 100644 x-pack/test/page_load_metrics/es_archives/default/data.json.gz create mode 100644 x-pack/test/page_load_metrics/es_archives/default/mappings.json diff --git a/Jenkinsfile b/Jenkinsfile index f435b18c6d824e..f44e3501f44387 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -41,6 +41,7 @@ kibanaPipeline(timeoutMinutes: 155, 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) diff --git a/package.json b/package.json index 0a47719c86ff0c..2dca52121d056a 100644 --- a/package.json +++ b/package.json @@ -371,7 +371,6 @@ "@types/pngjs": "^3.3.2", "@types/podium": "^1.0.0", "@types/prop-types": "^15.5.3", - "@types/puppeteer": "^2.1.0", "@types/reach__router": "^1.2.6", "@types/react": "^16.9.19", "@types/react-dom": "^16.9.5", @@ -485,7 +484,6 @@ "postcss-url": "^8.0.0", "prettier": "^2.0.5", "proxyquire": "1.8.0", - "puppeteer": "^3.0.4", "react-popper-tooltip": "^2.10.1", "react-textarea-autosize": "^7.1.2", "regenerate": "^1.4.0", diff --git a/packages/kbn-test/package.json b/packages/kbn-test/package.json index 0ab0048619358b..7de4c2adb03096 100644 --- a/packages/kbn-test/package.json +++ b/packages/kbn-test/package.json @@ -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": "^2.1.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.1.0", "strip-ansi": "^5.2.0", "rxjs": "^6.5.3", "tar-fs": "^1.16.3", diff --git a/packages/kbn-test/src/index.ts b/packages/kbn-test/src/index.ts index 585ce8181df5f4..0bc7cc664df68f 100644 --- a/packages/kbn-test/src/index.ts +++ b/packages/kbn-test/src/index.ts @@ -58,3 +58,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'; diff --git a/packages/kbn-test/src/page_load_metrics/capture_page_load_metrics.ts b/packages/kbn-test/src/page_load_metrics/capture_page_load_metrics.ts new file mode 100644 index 00000000000000..2b7a42dc194164 --- /dev/null +++ b/packages/kbn-test/src/page_load_metrics/capture_page_load_metrics.ts @@ -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(); + + 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); + 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: 'Asset size', id: url, value: measurements[0] }; + }); +} diff --git a/src/dev/loading_time_performance/index.ts b/packages/kbn-test/src/page_load_metrics/cli.ts similarity index 53% rename from src/dev/loading_time_performance/index.ts rename to packages/kbn-test/src/page_load_metrics/cli.ts index 4a1dd427a1d5b4..14f2d2f17c37a0 100644 --- a/src/dev/loading_time_performance/index.ts +++ b/packages/kbn-test/src/page_load_metrics/cli.ts @@ -17,47 +17,56 @@ * under the License. */ -import { resolve } from 'path'; -import { REPO_ROOT, run, createFlagError } from '@kbn/dev-utils'; -import { readConfigFile } from '@kbn/test'; -import { navigateToApp } from './navigation'; -import { ingestPerformanceMetrics } from './ingest_metrics'; -// @ts-ignore not TS yet -import getUrl from '../../test_utils/get_url'; +import Url from 'url'; -const configPath = resolve(REPO_ROOT, 'x-pack/test/page_load_metrics/config.ts'); +import { run, createFlagError } from '@kbn/dev-utils'; +import { capturePageLoadMetrics } from './capture_page_load_metrics'; -export function runTestsCli() { +export function runPageLoadMetricsCli() { run( async ({ flags, log }) => { - const config = await readConfigFile(log, configPath); - 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 options = { + const metrics = await capturePageLoadMetrics(log, { headless, appConfig: { url: kibanaUrl, - login: config.get('servers.kibana.username'), - password: config.get('servers.kibana.password'), + username, + password, }, - }; - - const responses = await navigateToApp(log, options); - ingestPerformanceMetrics(log, responses); + }); + 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'], + string: ['kibana-url', 'username', 'password'], boolean: ['head'], + default: { username: 'elastic', password: 'changeme', debug: true }, help: ` - --kibana-url Url for Kibana we should connect to, - --head Run pupeteer with graphical user interface, + --kibana-url Url for Kibana we should connect to, can include login info + --head Run pupeteer with graphical user interface + --username Set username, defaults to 'elastic' + --password Set password, defaults to 'changeme' `, }, } diff --git a/src/dev/loading_time_performance/event.ts b/packages/kbn-test/src/page_load_metrics/event.ts similarity index 89% rename from src/dev/loading_time_performance/event.ts rename to packages/kbn-test/src/page_load_metrics/event.ts index 0b7afc1e977599..71dc2343e2219d 100644 --- a/src/dev/loading_time_performance/event.ts +++ b/packages/kbn-test/src/page_load_metrics/event.ts @@ -32,3 +32,10 @@ export interface LoadingFinishedEvent { shouldReportCorbBlocking: boolean; timestamp: number; } + +export interface DataReceivedEvent { + encodedDataLength: number; + dataLength: number; + requestId: string; + timestamp: number; +} diff --git a/packages/kbn-test/src/page_load_metrics/index.ts b/packages/kbn-test/src/page_load_metrics/index.ts new file mode 100644 index 00000000000000..4309d558518a60 --- /dev/null +++ b/packages/kbn-test/src/page_load_metrics/index.ts @@ -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'; diff --git a/packages/kbn-test/src/page_load_metrics/navigation.ts b/packages/kbn-test/src/page_load_metrics/navigation.ts new file mode 100644 index 00000000000000..1fef99d0137c49 --- /dev/null +++ b/packages/kbn-test/src/page_load_metrics/navigation.ts @@ -0,0 +1,127 @@ +/* + * 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 _ from 'lodash'; +import puppeteer from 'puppeteer'; +import { ToolingLog } from '@kbn/dev-utils'; +import { ResponseReceivedEvent, DataReceivedEvent } from './event'; + +export interface NavigationOptions { + headless: boolean; + appConfig: { url: string; username: string; password: string }; +} + +export type NavigationResults = Map>; + +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, options: NavigationOptions) { + const baseUrl = Url.parse(options.appConfig.url); + return Url.format({ + protocol: baseUrl.protocol, + hostname: baseUrl.hostname, + port: baseUrl.port, + pathname: joinPath(baseUrl.pathname || '', path), + }); +} + +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); + 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 }); + const devToolsResponses: NavigationResults = new Map(); + const paths = [ + '/app/discover', + '/app/home', + '/app/canvas', // +1 + '/app/maps', // +16 + '/app/timelion', // +1 + '/app/apm', // +1 + '/app/uptime', // +1 + ]; + + await loginToKibana(log, browser, options); + + await Promise.all( + paths.map(async (path) => { + const page = await browser.newPage(); + page.setCacheEnabled(false); + page.setDefaultNavigationTimeout(0); + const frameResponses = new Map(); + devToolsResponses.set(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(path, options); + log.debug(`goto ${url}`); + await page.goto(url, { + waitUntil: 'networkidle0', + }); + + await page.close(); + }) + ); + + await browser.close(); + + return devToolsResponses; +} diff --git a/scripts/report_page_load_metrics.js b/scripts/page_load_metrics.js similarity index 93% rename from scripts/report_page_load_metrics.js rename to scripts/page_load_metrics.js index 10bb34c7ec24f9..37500c26e0b20b 100644 --- a/scripts/report_page_load_metrics.js +++ b/scripts/page_load_metrics.js @@ -18,4 +18,4 @@ */ require('../src/setup_node_env'); -require('../src/dev/loading_time_performance').runTestsCli(); +require('@kbn/test').runPageLoadMetricsCli(); diff --git a/src/dev/loading_time_performance/ingest_metrics.ts b/src/dev/loading_time_performance/ingest_metrics.ts deleted file mode 100644 index 6916b0260cde46..00000000000000 --- a/src/dev/loading_time_performance/ingest_metrics.ts +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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 { CiStatsReporter, ToolingLog } from '@kbn/dev-utils'; -import { LoadingFinishedEvent, ResponseReceivedEvent } from './event'; - -export function ingestPerformanceMetrics( - log: ToolingLog, - responses: Map< - string, - Map - > -) { - const uniqueRequests = new Map< - string, - Array<{ path: string; encodedBodyLength: number; plugin?: string; type?: string }> - >(); - - for (const [path, frameResponses] of responses) { - for (const [, response] of frameResponses) { - const url: string = response.responseRecieved.response.url; - const encodedBodyLength: number = - response.loadingFinished.encodedDataLength - - response.responseRecieved.response.encodedDataLength; - if (uniqueRequests.has(url)) { - uniqueRequests.set( - url, - [{ path, encodedBodyLength }].concat(uniqueRequests.get(url) || []) - ); - } else { - uniqueRequests.set(url, [{ path, encodedBodyLength }]); - } - } - } - - const metrics = Array<{ - url: string; - encodedBodyLength: number; - }>(); - - for (const [url, array] of uniqueRequests) { - // ignore lazy loaded plugins - if (url.match(/.*\/\d+.plugin.js$/)) { - continue; - } - - // get all entry plugins and repeatable assets - if (url.endsWith('.plugin.js') || array.length > 1) { - const encodedBodyLength = Math.round( - array.map((i: any) => i.encodedBodyLength).reduce((acc, value) => acc + value) / - array.length - ); - metrics.push({ url, encodedBodyLength }); - } - } - - const reporter = CiStatsReporter.fromEnv(log); - - reporter.metrics( - metrics.map((asset) => ({ - group: 'Asset size', - id: asset.url, - value: asset.encodedBodyLength, - })) - ); -} diff --git a/src/dev/loading_time_performance/navigation.ts b/src/dev/loading_time_performance/navigation.ts deleted file mode 100644 index 134f7bd5f2465f..00000000000000 --- a/src/dev/loading_time_performance/navigation.ts +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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 _ from 'lodash'; -import puppeteer from 'puppeteer'; -import { ToolingLog } from '@kbn/dev-utils'; -import { LoadingFinishedEvent, ResponseReceivedEvent } from './event'; - -export async function navigateToApp( - log: ToolingLog, - options: { headless: boolean; appConfig: { url: string; login: string; password: string } } -) { - const { headless, appConfig } = options; - const browser = await puppeteer.launch({ headless }); - const devToolsResponses = new Map(); - const apps = [ - 'kibana', - 'canvas', // +1 - 'maps', // +16 - 'timelion', // +1 - 'apm', // +1 - 'uptime', // +1 - ].map((app) => `/app/${app}`); - - for (const url of ['/login', ...apps]) { - const page = await browser.newPage(); - page.setCacheEnabled(false); - page.setDefaultNavigationTimeout(0); - const frameResponses = new Map(); - devToolsResponses.set(url, frameResponses); - - const client = await page.target().createCDPSession(); - await client.send('Network.enable'); - - client.on('Network.responseReceived', (event: ResponseReceivedEvent) => { - frameResponses.set(event.requestId, { responseRecieved: event }); - }); - - client.on('Network.loadingFinished', (event: LoadingFinishedEvent) => { - frameResponses.get(event.requestId).loadingFinished = event; - }); - - const fullURL = appConfig.url + url; - log.debug(`goto ${fullURL}`); - await page.goto(fullURL, { - waitUntil: 'networkidle0', - }); - - if (url === '/login') { - log.debug(`log in to the app..`); - await page.type('[data-test-subj="loginUsername"]', appConfig.login); - await page.type('[data-test-subj="loginPassword"]', appConfig.password); - await page.click('[data-test-subj="loginSubmit"]'); - await page.waitForNavigation({ waitUntil: 'networkidle0' }); - } - - await page.close(); - } - - await browser.close(); - - return devToolsResponses; -} diff --git a/test/scripts/jenkins_xpack_page_load_metrics.sh b/test/scripts/jenkins_xpack_page_load_metrics.sh new file mode 100644 index 00000000000000..679f0b8d2ddc59 --- /dev/null +++ b/test/scripts/jenkins_xpack_page_load_metrics.sh @@ -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; diff --git a/x-pack/test/page_load_metrics/config.ts b/x-pack/test/page_load_metrics/config.ts index 620917cc03dba8..3ebbd89e78ec68 100644 --- a/x-pack/test/page_load_metrics/config.ts +++ b/x-pack/test/page_load_metrics/config.ts @@ -23,17 +23,12 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { testRunner: PuppeteerTestRunner, esArchiver: { - directory: resolve('../../../test/functional/es_archives'), + directory: resolve(__dirname, 'es_archives'), }, esTestCluster: { ...xpackFunctionalTestsConfig.get('esTestCluster'), - serverArgs: [ - ...xpackFunctionalTestsConfig.get('esTestCluster.serverArgs'), - // define custom es server here - // API Keys is enabled at the top level - // 'xpack.security.enabled=true', - ], + serverArgs: [...xpackFunctionalTestsConfig.get('esTestCluster.serverArgs')], }, kbnTestServer: { diff --git a/x-pack/test/page_load_metrics/es_archives/default/data.json.gz b/x-pack/test/page_load_metrics/es_archives/default/data.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..5a5290ddf64478d0dfd175e7b91ad91efa5c61ff GIT binary patch literal 1812 zcmV+v2kZDBiwFP!000026YW~vQ`ODC%jnK86-Mz#En8LuAk1&$c@Sdr*$gngb#vtbu z4|0y!F`|bstBi{A2y%F$II=yGr+i^ta+r(+5$sl}3B0bO;#5*g#M|-=9VP4xg`Ch& zaEfTH#Oe#NoOdeR+H~#{S+P?ivcTwAco@-?ea3wJ9+7>F;%Ke|*f9B+;FNFm#>p6F zXyqF+5Kak)aor$8oa1!F79)U-$(0CoIcc5@ z5Iq|133-c^FUmJ5{n6&PuKza_q%H#s9K&9AAPEOb9g00;(f4#&pph%vS)ujNZIod5BWn)66 zu-^d~3f{+FKE`=rbC8#QcqIxn0ZAUVZ#){R2-Gxcvcs5dj_z&j-j2vA*6WrR+}hmxUBxKYY*?~Q!IEcl~gLGCL&(eXIiJ* z7w4o>rd?Y=d%s?yRZw-Z;?NP%oWBFGgfRY-^OQdc@l|9W$-64trypX&jR z&h_1MWrZRzu~^cPq9La4X$AS~Y~qEWs-+`nK>RL}DiR~Uy2_O#1Zg;yX;TnYhCbKf zXhhKn@+y@g810K>@s5ON(q(MU<#xBKp){(glEvH~q9+RpMO8hE$XB#&)R_|(^qG?z zE2QG1s!^F(b=`d6;>RdkXxIqkV#bfact}Vy9XYz@kEP<4o)kKEFVXah(1t7fZt|0R zbT-8D!D*qC&^rcDhbZ2!dS;O0IQlzJ1ho%}UT#*T5&g zjtfLUG7=;I_~_)cs4{*%+ewB}DKN`^{%_Msse`8S)b8w+tn8nWXYp#!M7a$jgfzn9 zpn~~yv9F?ZkXdd=nO#U!sZv}V2Q?z^#*Jv9Gi9j_rpV%IvuOPO&Z?(sgU$Wr#Iiwz z;t^gvr#@4o>XDSeywn_{)DDW>E-#9gn%<%~Uf=aZsk-=Dc&$)-cROAQybctXKc(yjH$Qj8}|6FTDGMGLRD*<2| zi`J&6ri#?Aq%mXxOs7G~*~RgsQtQ{iFq5#L3zrRTb!kOx5i1hPd}G?2Qy3={)iYuE zI}(*dFqm?ssR_K6d6SJr5VO^m84WrOIhviFmYkNvwHYb+Mg}aX^F+OfyZ*LpMUof( z<|*QffuWDc66qV9z-1!q3?M^G^pr&C8(Si0Q$ALqStZkaFs&gboq|PuuOeiZ?J_$j z9(Q7I~?F%)%qZ@4i4F$~dLBKfN+EJF(Sjfsn zv`L29YbYb5MA*T^_KYSiKsOxIY?@S7Ze?pF*iA8?6n8Y+@^_n*UG2XXBwM!xTfQM% zhU|xYgf-rFzI-_NtN(HTpEG>wf$KAS>6jt!yjGtuhD2sbeE?}ijsE~&R^>A`FaQ8s CuYsii literal 0 HcmV?d00001 diff --git a/x-pack/test/page_load_metrics/es_archives/default/mappings.json b/x-pack/test/page_load_metrics/es_archives/default/mappings.json new file mode 100644 index 00000000000000..c36f9576c4df12 --- /dev/null +++ b/x-pack/test/page_load_metrics/es_archives/default/mappings.json @@ -0,0 +1,2402 @@ +{ + "type": "index", + "value": { + "aliases": { + ".kibana": { + } + }, + "index": ".kibana_1", + "mappings": { + "_meta": { + "migrationMappingPropertyHashes": { + "action": "6e96ac5e648f57523879661ea72525b7", + "action_task_params": "a9d49f184ee89641044be0ca2950fa3a", + "alert": "7b44fba6773e37c806ce290ea9b7024e", + "apm-indices": "9bb9b2bf1fa636ed8619cbab5ce6a1dd", + "apm-telemetry": "3525d7c22c42bc80f5e6e9cb3f2b26a2", + "application_usage_totals": "c897e4310c5f24b07caaff3db53ae2c1", + "application_usage_transactional": "965839e75f809fefe04f92dc4d99722a", + "canvas-element": "7390014e1091044523666d97247392fc", + "canvas-workpad": "b0a1706d356228dbdcb4a17e6b9eb231", + "cases": "32aa96a6d3855ddda53010ae2048ac22", + "cases-comments": "c2061fb929f585df57425102fa928b4b", + "cases-configure": "42711cbb311976c0687853f4c1354572", + "cases-user-actions": "32277330ec6b721abe3b846cfd939a71", + "config": "ae24d22d5986d04124cc6568f771066f", + "dashboard": "d00f614b29a80360e1190193fd333bab", + "file-upload-telemetry": "0ed4d3e1983d1217a30982630897092e", + "graph-workspace": "cd7ba1330e6682e9cc00b78850874be1", + "index-pattern": "66eccb05066c5a89924f48a9e9736499", + "infrastructure-ui-source": "ddc0ecb18383f6b26101a2fadb2dab0c", + "inventory-view": "88fc7e12fd1b45b6f0787323ce4f18d2", + "kql-telemetry": "d12a98a6f19a2d273696597547e064ee", + "lens": "21c3ea0763beb1ecb0162529706b88c5", + "lens-ui-telemetry": "509bfa5978586998e05f9e303c07a327", + "map": "23d7aa4a720d4938ccde3983f87bd58d", + "maps-telemetry": "bfd39d88aadadb4be597ea984d433dbe", + "metrics-explorer-view": "428e319af3e822c80a84cf87123ca35c", + "migrationVersion": "4a1746014a75ade3a714e1db5763276f", + "ml-telemetry": "257fd1d4b4fdbb9cb4b8a3b27da201e9", + "namespace": "2f4316de49999235636386fe51dc06c1", + "namespaces": "2f4316de49999235636386fe51dc06c1", + "query": "11aaeb7f5f7fa5bb43f25e18ce26e7d9", + "references": "7997cf5a56cc02bdc9c93361bde732b0", + "sample-data-telemetry": "7d3cfeb915303c9641c59681967ffeb4", + "search": "181661168bbadd1eff5902361e2a0d5c", + "space": "c5ca8acafa0beaa4d08d014a97b6bc6b", + "telemetry": "36a616f7026dfa617d6655df850fe16d", + "timelion-sheet": "9a2a2748877c7a7b582fef201ab1d4cf", + "tsvb-validation-telemetry": "3a37ef6c8700ae6fc97d5c7da00e9215", + "type": "2f4316de49999235636386fe51dc06c1", + "ui-metric": "0d409297dc5ebe1e3a1da691c6ee32e3", + "updated_at": "00da57df13e94e9d98437d13ace4bfe0", + "upgrade-assistant-reindex-operation": "296a89039fc4260292be36b1b005d8f2", + "upgrade-assistant-telemetry": "56702cec857e0a9dacfb696655b4ff7b", + "uptime-dynamic-settings": "fcdb453a30092f022f2642db29523d80", + "url": "b675c3be8d76ecf029294d51dc7ec65d", + "visualization": "52d7a13ad68a150c4525b292d23e12cc" + } + }, + "dynamic": "strict", + "properties": { + "action": { + "properties": { + "actionTypeId": { + "type": "keyword" + }, + "config": { + "enabled": false, + "type": "object" + }, + "name": { + "fields": { + "keyword": { + "type": "keyword" + } + }, + "type": "text" + }, + "secrets": { + "type": "binary" + } + } + }, + "action_task_params": { + "properties": { + "actionId": { + "type": "keyword" + }, + "apiKey": { + "type": "binary" + }, + "params": { + "enabled": false, + "type": "object" + } + } + }, + "alert": { + "properties": { + "actions": { + "properties": { + "actionRef": { + "type": "keyword" + }, + "actionTypeId": { + "type": "keyword" + }, + "group": { + "type": "keyword" + }, + "params": { + "enabled": false, + "type": "object" + } + }, + "type": "nested" + }, + "alertTypeId": { + "type": "keyword" + }, + "apiKey": { + "type": "binary" + }, + "apiKeyOwner": { + "type": "keyword" + }, + "consumer": { + "type": "keyword" + }, + "createdAt": { + "type": "date" + }, + "createdBy": { + "type": "keyword" + }, + "enabled": { + "type": "boolean" + }, + "muteAll": { + "type": "boolean" + }, + "mutedInstanceIds": { + "type": "keyword" + }, + "name": { + "fields": { + "keyword": { + "type": "keyword" + } + }, + "type": "text" + }, + "params": { + "enabled": false, + "type": "object" + }, + "schedule": { + "properties": { + "interval": { + "type": "keyword" + } + } + }, + "scheduledTaskId": { + "type": "keyword" + }, + "tags": { + "type": "keyword" + }, + "throttle": { + "type": "keyword" + }, + "updatedBy": { + "type": "keyword" + } + } + }, + "apm-indices": { + "properties": { + "apm_oss": { + "properties": { + "errorIndices": { + "type": "keyword" + }, + "metricsIndices": { + "type": "keyword" + }, + "onboardingIndices": { + "type": "keyword" + }, + "sourcemapIndices": { + "type": "keyword" + }, + "spanIndices": { + "type": "keyword" + }, + "transactionIndices": { + "type": "keyword" + } + } + } + } + }, + "apm-telemetry": { + "properties": { + "agents": { + "properties": { + "dotnet": { + "properties": { + "agent": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "language": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "runtime": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } + }, + "go": { + "properties": { + "agent": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "language": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "runtime": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } + }, + "java": { + "properties": { + "agent": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "language": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "runtime": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } + }, + "js-base": { + "properties": { + "agent": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "language": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "runtime": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } + }, + "nodejs": { + "properties": { + "agent": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "language": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "runtime": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } + }, + "python": { + "properties": { + "agent": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "language": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "runtime": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } + }, + "ruby": { + "properties": { + "agent": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "language": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "runtime": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } + }, + "rum-js": { + "properties": { + "agent": { + "properties": { + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "service": { + "properties": { + "framework": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "language": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "runtime": { + "properties": { + "composite": { + "ignore_above": 1024, + "type": "keyword" + }, + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "version": { + "ignore_above": 1024, + "type": "keyword" + } + } + } + } + } + } + } + } + }, + "cardinality": { + "properties": { + "transaction": { + "properties": { + "name": { + "properties": { + "all_agents": { + "properties": { + "1d": { + "type": "long" + } + } + }, + "rum": { + "properties": { + "1d": { + "type": "long" + } + } + } + } + } + } + }, + "user_agent": { + "properties": { + "original": { + "properties": { + "all_agents": { + "properties": { + "1d": { + "type": "long" + } + } + }, + "rum": { + "properties": { + "1d": { + "type": "long" + } + } + } + } + } + } + } + } + }, + "counts": { + "properties": { + "agent_configuration": { + "properties": { + "all": { + "type": "long" + } + } + }, + "error": { + "properties": { + "1d": { + "type": "long" + }, + "all": { + "type": "long" + } + } + }, + "max_error_groups_per_service": { + "properties": { + "1d": { + "type": "long" + } + } + }, + "max_transaction_groups_per_service": { + "properties": { + "1d": { + "type": "long" + } + } + }, + "metric": { + "properties": { + "1d": { + "type": "long" + }, + "all": { + "type": "long" + } + } + }, + "onboarding": { + "properties": { + "1d": { + "type": "long" + }, + "all": { + "type": "long" + } + } + }, + "services": { + "properties": { + "1d": { + "type": "long" + } + } + }, + "sourcemap": { + "properties": { + "1d": { + "type": "long" + }, + "all": { + "type": "long" + } + } + }, + "span": { + "properties": { + "1d": { + "type": "long" + }, + "all": { + "type": "long" + } + } + }, + "traces": { + "properties": { + "1d": { + "type": "long" + } + } + }, + "transaction": { + "properties": { + "1d": { + "type": "long" + }, + "all": { + "type": "long" + } + } + } + } + }, + "has_any_services": { + "type": "boolean" + }, + "indices": { + "properties": { + "all": { + "properties": { + "total": { + "properties": { + "docs": { + "properties": { + "count": { + "type": "long" + } + } + }, + "store": { + "properties": { + "size_in_bytes": { + "type": "long" + } + } + } + } + } + } + }, + "shards": { + "properties": { + "total": { + "type": "long" + } + } + } + } + }, + "integrations": { + "properties": { + "ml": { + "properties": { + "all_jobs_count": { + "type": "long" + } + } + } + } + }, + "retainment": { + "properties": { + "error": { + "properties": { + "ms": { + "type": "long" + } + } + }, + "metric": { + "properties": { + "ms": { + "type": "long" + } + } + }, + "onboarding": { + "properties": { + "ms": { + "type": "long" + } + } + }, + "span": { + "properties": { + "ms": { + "type": "long" + } + } + }, + "transaction": { + "properties": { + "ms": { + "type": "long" + } + } + } + } + }, + "services_per_agent": { + "properties": { + "dotnet": { + "null_value": 0, + "type": "long" + }, + "go": { + "null_value": 0, + "type": "long" + }, + "java": { + "null_value": 0, + "type": "long" + }, + "js-base": { + "null_value": 0, + "type": "long" + }, + "nodejs": { + "null_value": 0, + "type": "long" + }, + "python": { + "null_value": 0, + "type": "long" + }, + "ruby": { + "null_value": 0, + "type": "long" + }, + "rum-js": { + "null_value": 0, + "type": "long" + } + } + }, + "tasks": { + "properties": { + "agent_configuration": { + "properties": { + "took": { + "properties": { + "ms": { + "type": "long" + } + } + } + } + }, + "agents": { + "properties": { + "took": { + "properties": { + "ms": { + "type": "long" + } + } + } + } + }, + "cardinality": { + "properties": { + "took": { + "properties": { + "ms": { + "type": "long" + } + } + } + } + }, + "groupings": { + "properties": { + "took": { + "properties": { + "ms": { + "type": "long" + } + } + } + } + }, + "indices_stats": { + "properties": { + "took": { + "properties": { + "ms": { + "type": "long" + } + } + } + } + }, + "integrations": { + "properties": { + "took": { + "properties": { + "ms": { + "type": "long" + } + } + } + } + }, + "processor_events": { + "properties": { + "took": { + "properties": { + "ms": { + "type": "long" + } + } + } + } + }, + "services": { + "properties": { + "took": { + "properties": { + "ms": { + "type": "long" + } + } + } + } + }, + "versions": { + "properties": { + "took": { + "properties": { + "ms": { + "type": "long" + } + } + } + } + } + } + }, + "version": { + "properties": { + "apm_server": { + "properties": { + "major": { + "type": "long" + }, + "minor": { + "type": "long" + }, + "patch": { + "type": "long" + } + } + } + } + } + } + }, + "application_usage_totals": { + "properties": { + "appId": { + "type": "keyword" + }, + "minutesOnScreen": { + "type": "float" + }, + "numberOfClicks": { + "type": "long" + } + } + }, + "application_usage_transactional": { + "properties": { + "appId": { + "type": "keyword" + }, + "minutesOnScreen": { + "type": "float" + }, + "numberOfClicks": { + "type": "long" + }, + "timestamp": { + "type": "date" + } + } + }, + "canvas-element": { + "dynamic": "false", + "properties": { + "@created": { + "type": "date" + }, + "@timestamp": { + "type": "date" + }, + "content": { + "type": "text" + }, + "help": { + "type": "text" + }, + "image": { + "type": "text" + }, + "name": { + "fields": { + "keyword": { + "type": "keyword" + } + }, + "type": "text" + } + } + }, + "canvas-workpad": { + "dynamic": "false", + "properties": { + "@created": { + "type": "date" + }, + "@timestamp": { + "type": "date" + }, + "name": { + "fields": { + "keyword": { + "type": "keyword" + } + }, + "type": "text" + } + } + }, + "cases": { + "properties": { + "closed_at": { + "type": "date" + }, + "closed_by": { + "properties": { + "email": { + "type": "keyword" + }, + "full_name": { + "type": "keyword" + }, + "username": { + "type": "keyword" + } + } + }, + "connector_id": { + "type": "keyword" + }, + "created_at": { + "type": "date" + }, + "created_by": { + "properties": { + "email": { + "type": "keyword" + }, + "full_name": { + "type": "keyword" + }, + "username": { + "type": "keyword" + } + } + }, + "description": { + "type": "text" + }, + "external_service": { + "properties": { + "connector_id": { + "type": "keyword" + }, + "connector_name": { + "type": "keyword" + }, + "external_id": { + "type": "keyword" + }, + "external_title": { + "type": "text" + }, + "external_url": { + "type": "text" + }, + "pushed_at": { + "type": "date" + }, + "pushed_by": { + "properties": { + "email": { + "type": "keyword" + }, + "full_name": { + "type": "keyword" + }, + "username": { + "type": "keyword" + } + } + } + } + }, + "status": { + "type": "keyword" + }, + "tags": { + "type": "keyword" + }, + "title": { + "type": "keyword" + }, + "updated_at": { + "type": "date" + }, + "updated_by": { + "properties": { + "email": { + "type": "keyword" + }, + "full_name": { + "type": "keyword" + }, + "username": { + "type": "keyword" + } + } + } + } + }, + "cases-comments": { + "properties": { + "comment": { + "type": "text" + }, + "created_at": { + "type": "date" + }, + "created_by": { + "properties": { + "email": { + "type": "keyword" + }, + "full_name": { + "type": "keyword" + }, + "username": { + "type": "keyword" + } + } + }, + "pushed_at": { + "type": "date" + }, + "pushed_by": { + "properties": { + "email": { + "type": "keyword" + }, + "full_name": { + "type": "keyword" + }, + "username": { + "type": "keyword" + } + } + }, + "updated_at": { + "type": "date" + }, + "updated_by": { + "properties": { + "email": { + "type": "keyword" + }, + "full_name": { + "type": "keyword" + }, + "username": { + "type": "keyword" + } + } + } + } + }, + "cases-configure": { + "properties": { + "closure_type": { + "type": "keyword" + }, + "connector_id": { + "type": "keyword" + }, + "connector_name": { + "type": "keyword" + }, + "created_at": { + "type": "date" + }, + "created_by": { + "properties": { + "email": { + "type": "keyword" + }, + "full_name": { + "type": "keyword" + }, + "username": { + "type": "keyword" + } + } + }, + "updated_at": { + "type": "date" + }, + "updated_by": { + "properties": { + "email": { + "type": "keyword" + }, + "full_name": { + "type": "keyword" + }, + "username": { + "type": "keyword" + } + } + } + } + }, + "cases-user-actions": { + "properties": { + "action": { + "type": "keyword" + }, + "action_at": { + "type": "date" + }, + "action_by": { + "properties": { + "email": { + "type": "keyword" + }, + "full_name": { + "type": "keyword" + }, + "username": { + "type": "keyword" + } + } + }, + "action_field": { + "type": "keyword" + }, + "new_value": { + "type": "text" + }, + "old_value": { + "type": "text" + } + } + }, + "config": { + "dynamic": "true", + "properties": { + "buildNum": { + "type": "keyword" + }, + "defaultIndex": { + "fields": { + "keyword": { + "ignore_above": 256, + "type": "keyword" + } + }, + "type": "text" + } + } + }, + "dashboard": { + "properties": { + "description": { + "type": "text" + }, + "hits": { + "type": "integer" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "optionsJSON": { + "type": "text" + }, + "panelsJSON": { + "type": "text" + }, + "refreshInterval": { + "properties": { + "display": { + "type": "keyword" + }, + "pause": { + "type": "boolean" + }, + "section": { + "type": "integer" + }, + "value": { + "type": "integer" + } + } + }, + "timeFrom": { + "type": "keyword" + }, + "timeRestore": { + "type": "boolean" + }, + "timeTo": { + "type": "keyword" + }, + "title": { + "type": "text" + }, + "version": { + "type": "integer" + } + } + }, + "file-upload-telemetry": { + "properties": { + "filesUploadedTotalCount": { + "type": "long" + } + } + }, + "graph-workspace": { + "properties": { + "description": { + "type": "text" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "numLinks": { + "type": "integer" + }, + "numVertices": { + "type": "integer" + }, + "title": { + "type": "text" + }, + "version": { + "type": "integer" + }, + "wsState": { + "type": "text" + } + } + }, + "index-pattern": { + "properties": { + "fieldFormatMap": { + "type": "text" + }, + "fields": { + "type": "text" + }, + "intervalName": { + "type": "keyword" + }, + "notExpandable": { + "type": "boolean" + }, + "sourceFilters": { + "type": "text" + }, + "timeFieldName": { + "type": "keyword" + }, + "title": { + "type": "text" + }, + "type": { + "type": "keyword" + }, + "typeMeta": { + "type": "keyword" + } + } + }, + "infrastructure-ui-source": { + "properties": { + "description": { + "type": "text" + }, + "fields": { + "properties": { + "container": { + "type": "keyword" + }, + "host": { + "type": "keyword" + }, + "pod": { + "type": "keyword" + }, + "tiebreaker": { + "type": "keyword" + }, + "timestamp": { + "type": "keyword" + } + } + }, + "logAlias": { + "type": "keyword" + }, + "logColumns": { + "properties": { + "fieldColumn": { + "properties": { + "field": { + "type": "keyword" + }, + "id": { + "type": "keyword" + } + } + }, + "messageColumn": { + "properties": { + "id": { + "type": "keyword" + } + } + }, + "timestampColumn": { + "properties": { + "id": { + "type": "keyword" + } + } + } + }, + "type": "nested" + }, + "metricAlias": { + "type": "keyword" + }, + "name": { + "type": "text" + } + } + }, + "inventory-view": { + "properties": { + "accountId": { + "type": "keyword" + }, + "autoBounds": { + "type": "boolean" + }, + "autoReload": { + "type": "boolean" + }, + "boundsOverride": { + "properties": { + "max": { + "type": "integer" + }, + "min": { + "type": "integer" + } + } + }, + "customMetrics": { + "properties": { + "aggregation": { + "type": "keyword" + }, + "field": { + "type": "keyword" + }, + "id": { + "type": "keyword" + }, + "label": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + }, + "type": "nested" + }, + "customOptions": { + "properties": { + "field": { + "type": "keyword" + }, + "text": { + "type": "keyword" + } + }, + "type": "nested" + }, + "filterQuery": { + "properties": { + "expression": { + "type": "keyword" + }, + "kind": { + "type": "keyword" + } + } + }, + "groupBy": { + "properties": { + "field": { + "type": "keyword" + }, + "label": { + "type": "keyword" + } + }, + "type": "nested" + }, + "legend": { + "properties": { + "palette": { + "type": "keyword" + }, + "reverseColors": { + "type": "boolean" + }, + "steps": { + "type": "long" + } + } + }, + "metric": { + "properties": { + "aggregation": { + "type": "keyword" + }, + "field": { + "type": "keyword" + }, + "id": { + "type": "keyword" + }, + "label": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + } + }, + "name": { + "type": "keyword" + }, + "nodeType": { + "type": "keyword" + }, + "region": { + "type": "keyword" + }, + "sort": { + "properties": { + "by": { + "type": "keyword" + }, + "direction": { + "type": "keyword" + } + } + }, + "time": { + "type": "long" + }, + "view": { + "type": "keyword" + } + } + }, + "kql-telemetry": { + "properties": { + "optInCount": { + "type": "long" + }, + "optOutCount": { + "type": "long" + } + } + }, + "lens": { + "properties": { + "expression": { + "index": false, + "type": "keyword" + }, + "state": { + "type": "flattened" + }, + "title": { + "type": "text" + }, + "visualizationType": { + "type": "keyword" + } + } + }, + "lens-ui-telemetry": { + "properties": { + "count": { + "type": "integer" + }, + "date": { + "type": "date" + }, + "name": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + } + }, + "map": { + "properties": { + "bounds": { + "type": "geo_shape" + }, + "description": { + "type": "text" + }, + "layerListJSON": { + "type": "text" + }, + "mapStateJSON": { + "type": "text" + }, + "title": { + "type": "text" + }, + "uiStateJSON": { + "type": "text" + }, + "version": { + "type": "integer" + } + } + }, + "maps-telemetry": { + "properties": { + "attributesPerMap": { + "properties": { + "dataSourcesCount": { + "properties": { + "avg": { + "type": "long" + }, + "max": { + "type": "long" + }, + "min": { + "type": "long" + } + } + }, + "emsVectorLayersCount": { + "dynamic": "true", + "type": "object" + }, + "layerTypesCount": { + "dynamic": "true", + "type": "object" + }, + "layersCount": { + "properties": { + "avg": { + "type": "long" + }, + "max": { + "type": "long" + }, + "min": { + "type": "long" + } + } + } + } + }, + "indexPatternsWithGeoFieldCount": { + "type": "long" + }, + "indexPatternsWithGeoPointFieldCount": { + "type": "long" + }, + "indexPatternsWithGeoShapeFieldCount": { + "type": "long" + }, + "mapsTotalCount": { + "type": "long" + }, + "settings": { + "properties": { + "showMapVisualizationTypes": { + "type": "boolean" + } + } + }, + "timeCaptured": { + "type": "date" + } + } + }, + "metrics-explorer-view": { + "properties": { + "chartOptions": { + "properties": { + "stack": { + "type": "boolean" + }, + "type": { + "type": "keyword" + }, + "yAxisMode": { + "type": "keyword" + } + } + }, + "currentTimerange": { + "properties": { + "from": { + "type": "keyword" + }, + "interval": { + "type": "keyword" + }, + "to": { + "type": "keyword" + } + } + }, + "name": { + "type": "keyword" + }, + "options": { + "properties": { + "aggregation": { + "type": "keyword" + }, + "filterQuery": { + "type": "keyword" + }, + "forceInterval": { + "type": "boolean" + }, + "groupBy": { + "type": "keyword" + }, + "limit": { + "type": "integer" + }, + "metrics": { + "properties": { + "aggregation": { + "type": "keyword" + }, + "color": { + "type": "keyword" + }, + "field": { + "type": "keyword" + }, + "label": { + "type": "keyword" + } + }, + "type": "nested" + } + } + } + } + }, + "migrationVersion": { + "dynamic": "true", + "properties": { + "index-pattern": { + "fields": { + "keyword": { + "ignore_above": 256, + "type": "keyword" + } + }, + "type": "text" + }, + "space": { + "fields": { + "keyword": { + "ignore_above": 256, + "type": "keyword" + } + }, + "type": "text" + } + } + }, + "ml-telemetry": { + "properties": { + "file_data_visualizer": { + "properties": { + "index_creation_count": { + "type": "long" + } + } + } + } + }, + "namespace": { + "type": "keyword" + }, + "namespaces": { + "type": "keyword" + }, + "query": { + "properties": { + "description": { + "type": "text" + }, + "filters": { + "enabled": false, + "type": "object" + }, + "query": { + "properties": { + "language": { + "type": "keyword" + }, + "query": { + "index": false, + "type": "keyword" + } + } + }, + "timefilter": { + "enabled": false, + "type": "object" + }, + "title": { + "type": "text" + } + } + }, + "references": { + "properties": { + "id": { + "type": "keyword" + }, + "name": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + }, + "type": "nested" + }, + "sample-data-telemetry": { + "properties": { + "installCount": { + "type": "long" + }, + "unInstallCount": { + "type": "long" + } + } + }, + "search": { + "properties": { + "columns": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "hits": { + "type": "integer" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "sort": { + "type": "keyword" + }, + "title": { + "type": "text" + }, + "version": { + "type": "integer" + } + } + }, + "space": { + "properties": { + "_reserved": { + "type": "boolean" + }, + "color": { + "type": "keyword" + }, + "description": { + "type": "text" + }, + "disabledFeatures": { + "type": "keyword" + }, + "imageUrl": { + "index": false, + "type": "text" + }, + "initials": { + "type": "keyword" + }, + "name": { + "fields": { + "keyword": { + "ignore_above": 2048, + "type": "keyword" + } + }, + "type": "text" + } + } + }, + "telemetry": { + "properties": { + "allowChangingOptInStatus": { + "type": "boolean" + }, + "enabled": { + "type": "boolean" + }, + "lastReported": { + "type": "date" + }, + "lastVersionChecked": { + "type": "keyword" + }, + "reportFailureCount": { + "type": "integer" + }, + "reportFailureVersion": { + "type": "keyword" + }, + "sendUsageFrom": { + "type": "keyword" + }, + "userHasSeenNotice": { + "type": "boolean" + } + } + }, + "timelion-sheet": { + "properties": { + "description": { + "type": "text" + }, + "hits": { + "type": "integer" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "timelion_chart_height": { + "type": "integer" + }, + "timelion_columns": { + "type": "integer" + }, + "timelion_interval": { + "type": "keyword" + }, + "timelion_other_interval": { + "type": "keyword" + }, + "timelion_rows": { + "type": "integer" + }, + "timelion_sheet": { + "type": "text" + }, + "title": { + "type": "text" + }, + "version": { + "type": "integer" + } + } + }, + "tsvb-validation-telemetry": { + "properties": { + "failedRequests": { + "type": "long" + } + } + }, + "type": { + "type": "keyword" + }, + "ui-metric": { + "properties": { + "count": { + "type": "integer" + } + } + }, + "updated_at": { + "type": "date" + }, + "upgrade-assistant-reindex-operation": { + "properties": { + "errorMessage": { + "type": "keyword" + }, + "indexName": { + "type": "keyword" + }, + "lastCompletedStep": { + "type": "integer" + }, + "locked": { + "type": "date" + }, + "newIndexName": { + "type": "keyword" + }, + "reindexOptions": { + "properties": { + "openAndClose": { + "type": "boolean" + }, + "queueSettings": { + "properties": { + "queuedAt": { + "type": "long" + }, + "startedAt": { + "type": "long" + } + } + } + } + }, + "reindexTaskId": { + "type": "keyword" + }, + "reindexTaskPercComplete": { + "type": "float" + }, + "runningReindexCount": { + "type": "integer" + }, + "status": { + "type": "integer" + } + } + }, + "upgrade-assistant-telemetry": { + "properties": { + "features": { + "properties": { + "deprecation_logging": { + "properties": { + "enabled": { + "null_value": true, + "type": "boolean" + } + } + } + } + }, + "ui_open": { + "properties": { + "cluster": { + "null_value": 0, + "type": "long" + }, + "indices": { + "null_value": 0, + "type": "long" + }, + "overview": { + "null_value": 0, + "type": "long" + } + } + }, + "ui_reindex": { + "properties": { + "close": { + "null_value": 0, + "type": "long" + }, + "open": { + "null_value": 0, + "type": "long" + }, + "start": { + "null_value": 0, + "type": "long" + }, + "stop": { + "null_value": 0, + "type": "long" + } + } + } + } + }, + "uptime-dynamic-settings": { + "properties": { + "certAgeThreshold": { + "type": "long" + }, + "certExpirationThreshold": { + "type": "long" + }, + "heartbeatIndices": { + "type": "keyword" + } + } + }, + "url": { + "properties": { + "accessCount": { + "type": "long" + }, + "accessDate": { + "type": "date" + }, + "createDate": { + "type": "date" + }, + "url": { + "fields": { + "keyword": { + "type": "keyword" + } + }, + "type": "text" + } + } + }, + "visualization": { + "properties": { + "description": { + "type": "text" + }, + "kibanaSavedObjectMeta": { + "properties": { + "searchSourceJSON": { + "type": "text" + } + } + }, + "savedSearchRefName": { + "type": "keyword" + }, + "title": { + "type": "text" + }, + "uiStateJSON": { + "type": "text" + }, + "version": { + "type": "integer" + }, + "visState": { + "type": "text" + } + } + } + } + }, + "settings": { + "index": { + "auto_expand_replicas": "0-1", + "number_of_replicas": "0", + "number_of_shards": "1" + } + } + } +} + +{ + "type": "index", + "value": { + "aliases": { + }, + "index": "test", + "mappings": { + "properties": { + "foo": { + "fields": { + "keyword": { + "ignore_above": 256, + "type": "keyword" + } + }, + "type": "text" + } + } + }, + "settings": { + "index": { + "number_of_replicas": "1", + "number_of_shards": "1" + } + } + } +} \ No newline at end of file diff --git a/x-pack/test/page_load_metrics/runner.ts b/x-pack/test/page_load_metrics/runner.ts index 63b0803e88e71b..42b3c46938c229 100644 --- a/x-pack/test/page_load_metrics/runner.ts +++ b/x-pack/test/page_load_metrics/runner.ts @@ -4,28 +4,29 @@ * you may not use this file except in compliance with the Elastic License. */ -import Url from 'url'; +import { CiStatsReporter } from '@kbn/dev-utils'; + +// @ts-ignore not TS yet +import getUrl from '../../../src/test_utils/get_url'; -import { withProcRunner } from '@kbn/dev-utils'; import { FtrProviderContext } from './../functional/ftr_provider_context'; -import { navigateToApp } from './../../../src/dev/loading_time_performance/navigation'; -import { ingestPerformanceMetrics } from './../../../src/dev/loading_time_performance/ingest_metrics'; +import { capturePageLoadMetrics } from './../../../src/dev/page_load_metrics'; export async function PuppeteerTestRunner({ getService }: FtrProviderContext) { const log = getService('log'); const config = getService('config'); + const esArchiver = getService('esArchiver'); - const options = { - headless: false, + await esArchiver.load('default'); + const metrics = await capturePageLoadMetrics(log, { + headless: true, appConfig: { - url: Url.format(config.get('servers.kibana')), - login: config.get('servers.kibana.username'), + url: getUrl.baseUrl(config.get('servers.kibana')), + username: config.get('servers.kibana.username'), password: config.get('servers.kibana.password'), }, - }; - - await withProcRunner(log, async () => { - const responses = await navigateToApp(log, options); - ingestPerformanceMetrics(log, responses); }); + const reporter = CiStatsReporter.fromEnv(log); + + await reporter.metrics(metrics); } diff --git a/yarn.lock b/yarn.lock index ffdc8900ba1cef..1ee2b98319edec 100644 --- a/yarn.lock +++ b/yarn.lock @@ -23985,6 +23985,22 @@ puppeteer-core@^1.19.0: rimraf "^2.6.1" ws "^6.1.0" +puppeteer@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-3.1.0.tgz#d44efdc5410809025f38bca2de106c3ae5c85a52" + integrity sha512-jLa9sqdVx0tPnr2FcwAq+8DSjGhSM4YpkwOf3JE22Ycyqm71SW7B5uGfTyMGFoLCmbCozbLZclCjasPb0flTRw== + 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" + puppeteer@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-2.1.1.tgz#ccde47c2a688f131883b50f2d697bd25189da27e" @@ -24001,22 +24017,6 @@ puppeteer@^2.0.0: rimraf "^2.6.1" ws "^6.1.0" -puppeteer@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-3.0.4.tgz#f445aae0a6732c65bbb90e963dcd6fd8fde0d780" - integrity sha512-1QEb4tJXXbNId7WSHlcDkS3B4GklTIebKn8Y9D6B7tAdUjQncb+8QlTjbQsAgGX5dhRG32Qycuk5XKzJgLs0sg== - 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" From 4aa25a65920a15057fd82e671d04b596705884e5 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Fri, 29 May 2020 00:26:21 +0200 Subject: [PATCH 08/32] fix import, remove unused interface --- packages/kbn-test/src/page_load_metrics/event.ts | 7 ------- x-pack/test/page_load_metrics/runner.ts | 3 +-- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/packages/kbn-test/src/page_load_metrics/event.ts b/packages/kbn-test/src/page_load_metrics/event.ts index 71dc2343e2219d..481954bbf672e2 100644 --- a/packages/kbn-test/src/page_load_metrics/event.ts +++ b/packages/kbn-test/src/page_load_metrics/event.ts @@ -26,13 +26,6 @@ export interface ResponseReceivedEvent { type: string; } -export interface LoadingFinishedEvent { - encodedDataLength: number; - requestId: string; - shouldReportCorbBlocking: boolean; - timestamp: number; -} - export interface DataReceivedEvent { encodedDataLength: number; dataLength: number; diff --git a/x-pack/test/page_load_metrics/runner.ts b/x-pack/test/page_load_metrics/runner.ts index 42b3c46938c229..a411073aca2c50 100644 --- a/x-pack/test/page_load_metrics/runner.ts +++ b/x-pack/test/page_load_metrics/runner.ts @@ -5,12 +5,11 @@ */ 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'; -import { capturePageLoadMetrics } from './../../../src/dev/page_load_metrics'; export async function PuppeteerTestRunner({ getService }: FtrProviderContext) { const log = getService('log'); From d9133d3a8e60022d8e4c27bd6a28665b822bfa31 Mon Sep 17 00:00:00 2001 From: Dmitry Lemeshko Date: Fri, 29 May 2020 07:15:07 +0200 Subject: [PATCH 09/32] Update packages/kbn-test/src/page_load_metrics/capture_page_load_metrics.ts Co-authored-by: Spencer --- .../kbn-test/src/page_load_metrics/capture_page_load_metrics.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kbn-test/src/page_load_metrics/capture_page_load_metrics.ts b/packages/kbn-test/src/page_load_metrics/capture_page_load_metrics.ts index 2b7a42dc194164..279788f8fcd957 100644 --- a/packages/kbn-test/src/page_load_metrics/capture_page_load_metrics.ts +++ b/packages/kbn-test/src/page_load_metrics/capture_page_load_metrics.ts @@ -76,6 +76,6 @@ export async function capturePageLoadMetrics(log: ToolingLog, options: Navigatio return true; }) .map(([url, measurements]) => { - return { group: 'Asset size', id: url, value: measurements[0] }; + return { group: 'page load asset size', id: url, value: measurements[0] }; }); } From 1d4cb3471bfbd6c81d6160ae185e800b9fa91ed6 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Fri, 29 May 2020 07:25:44 +0200 Subject: [PATCH 10/32] start chromium with no-sandbox --- packages/kbn-test/src/page_load_metrics/navigation.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kbn-test/src/page_load_metrics/navigation.ts b/packages/kbn-test/src/page_load_metrics/navigation.ts index 1fef99d0137c49..41075503560184 100644 --- a/packages/kbn-test/src/page_load_metrics/navigation.ts +++ b/packages/kbn-test/src/page_load_metrics/navigation.ts @@ -70,7 +70,7 @@ async function loginToKibana( } export async function navigateToApps(log: ToolingLog, options: NavigationOptions) { - const browser = await puppeteer.launch({ headless: options.headless }); + const browser = await puppeteer.launch({ headless: options.headless, args: ['--no-sandbox'] }); const devToolsResponses: NavigationResults = new Map(); const paths = [ '/app/discover', From f379b60d0f38a44f6e3d9b2d106fbb94140163ac Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Fri, 29 May 2020 09:29:32 +0200 Subject: [PATCH 11/32] add logging --- packages/kbn-test/src/page_load_metrics/cli.ts | 1 + x-pack/test/page_load_metrics/runner.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/kbn-test/src/page_load_metrics/cli.ts b/packages/kbn-test/src/page_load_metrics/cli.ts index 14f2d2f17c37a0..fd10b24cc23d3f 100644 --- a/packages/kbn-test/src/page_load_metrics/cli.ts +++ b/packages/kbn-test/src/page_load_metrics/cli.ts @@ -25,6 +25,7 @@ import { capturePageLoadMetrics } from './capture_page_load_metrics'; export function runPageLoadMetricsCli() { run( async ({ flags, log }) => { + log.info('!!! Do not forget to load data with index pattern !!!'); const kibanaUrl = flags['kibana-url']; if (!kibanaUrl || typeof kibanaUrl !== 'string') { throw createFlagError('Expect --kibana-url to be a string'); diff --git a/x-pack/test/page_load_metrics/runner.ts b/x-pack/test/page_load_metrics/runner.ts index a411073aca2c50..9d56f0ee139ec9 100644 --- a/x-pack/test/page_load_metrics/runner.ts +++ b/x-pack/test/page_load_metrics/runner.ts @@ -27,5 +27,6 @@ export async function PuppeteerTestRunner({ getService }: FtrProviderContext) { }); const reporter = CiStatsReporter.fromEnv(log); + log.debug('Report page load asset size'); await reporter.metrics(metrics); } From 34047f720b482b7dd71eca216f9824a9e23c1f96 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Fri, 29 May 2020 16:19:57 +0200 Subject: [PATCH 12/32] check page contains expected element, cut apps to 5 --- .../kbn-test/src/page_load_metrics/cli.ts | 1 - .../src/page_load_metrics/navigation.ts | 25 +++++++++++-------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/packages/kbn-test/src/page_load_metrics/cli.ts b/packages/kbn-test/src/page_load_metrics/cli.ts index fd10b24cc23d3f..14f2d2f17c37a0 100644 --- a/packages/kbn-test/src/page_load_metrics/cli.ts +++ b/packages/kbn-test/src/page_load_metrics/cli.ts @@ -25,7 +25,6 @@ import { capturePageLoadMetrics } from './capture_page_load_metrics'; export function runPageLoadMetricsCli() { run( async ({ flags, log }) => { - log.info('!!! Do not forget to load data with index pattern !!!'); const kibanaUrl = flags['kibana-url']; if (!kibanaUrl || typeof kibanaUrl !== 'string') { throw createFlagError('Expect --kibana-url to be a string'); diff --git a/packages/kbn-test/src/page_load_metrics/navigation.ts b/packages/kbn-test/src/page_load_metrics/navigation.ts index 41075503560184..29aa76ae313b08 100644 --- a/packages/kbn-test/src/page_load_metrics/navigation.ts +++ b/packages/kbn-test/src/page_load_metrics/navigation.ts @@ -72,25 +72,23 @@ async function loginToKibana( 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 paths = [ - '/app/discover', - '/app/home', - '/app/canvas', // +1 - '/app/maps', // +16 - '/app/timelion', // +1 - '/app/apm', // +1 - '/app/uptime', // +1 + const apps = [ + { path: '/app/discover', locator: '[data-test-subj="discover-sidebar"]' }, + { path: '/app/home', locator: '[data-test-subj="homeApp"]' }, + { path: '/app/canvas', locator: '[data-test-subj="create-workpad-button"]' }, + { path: '/app/maps', locator: '[data-test-subj="mapsFullScreenMode"]' }, + { path: '/app/apm', locator: '[data-test-subj="apmMainContainer"]' }, ]; await loginToKibana(log, browser, options); await Promise.all( - paths.map(async (path) => { + apps.map(async (app) => { const page = await browser.newPage(); page.setCacheEnabled(false); page.setDefaultNavigationTimeout(0); const frameResponses = new Map(); - devToolsResponses.set(path, frameResponses); + devToolsResponses.set(app.path, frameResponses); const client = await page.target().createCDPSession(); await client.send('Network.enable'); @@ -111,12 +109,17 @@ export async function navigateToApps(log: ToolingLog, options: NavigationOptions getRequestData(event.requestId).dataLength += event.dataLength; }); - const url = createUrl(path, options); + const url = createUrl(app.path, options); log.debug(`goto ${url}`); await page.goto(url, { waitUntil: 'networkidle0', }); + await page.waitForSelector(app.locator, { timeout: 30000 }).catch((err) => { + log.error(`Page '${app.path}' was not loaded properly, current ulr: ${page.url()}`); + throw err; + }); + await page.close(); }) ); From ffb7da95b16b53d16c810c1d665e49273d7ccac4 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Fri, 29 May 2020 17:43:04 +0200 Subject: [PATCH 13/32] fix locator & typo --- packages/kbn-test/src/page_load_metrics/navigation.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/kbn-test/src/page_load_metrics/navigation.ts b/packages/kbn-test/src/page_load_metrics/navigation.ts index 29aa76ae313b08..193edf93f1b8fc 100644 --- a/packages/kbn-test/src/page_load_metrics/navigation.ts +++ b/packages/kbn-test/src/page_load_metrics/navigation.ts @@ -76,7 +76,7 @@ export async function navigateToApps(log: ToolingLog, options: NavigationOptions { path: '/app/discover', locator: '[data-test-subj="discover-sidebar"]' }, { path: '/app/home', locator: '[data-test-subj="homeApp"]' }, { path: '/app/canvas', locator: '[data-test-subj="create-workpad-button"]' }, - { path: '/app/maps', locator: '[data-test-subj="mapsFullScreenMode"]' }, + { path: '/app/maps', locator: '[data-test-subj="newMapLink"]' }, { path: '/app/apm', locator: '[data-test-subj="apmMainContainer"]' }, ]; @@ -116,7 +116,7 @@ export async function navigateToApps(log: ToolingLog, options: NavigationOptions }); await page.waitForSelector(app.locator, { timeout: 30000 }).catch((err) => { - log.error(`Page '${app.path}' was not loaded properly, current ulr: ${page.url()}`); + log.error(`Page '${app.path}' was not loaded properly, current url: ${page.url()}`); throw err; }); From 45549406554f5a1c26da687b0bbb2c33e43bb506 Mon Sep 17 00:00:00 2001 From: Dmitry Lemeshko Date: Tue, 2 Jun 2020 11:59:21 +0200 Subject: [PATCH 14/32] Update packages/kbn-test/src/page_load_metrics/navigation.ts Co-authored-by: Spencer --- .../src/page_load_metrics/navigation.ts | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/packages/kbn-test/src/page_load_metrics/navigation.ts b/packages/kbn-test/src/page_load_metrics/navigation.ts index 193edf93f1b8fc..4e4be9fb9df601 100644 --- a/packages/kbn-test/src/page_load_metrics/navigation.ts +++ b/packages/kbn-test/src/page_load_metrics/navigation.ts @@ -115,9 +115,22 @@ export async function navigateToApps(log: ToolingLog, options: NavigationOptions waitUntil: 'networkidle0', }); - await page.waitForSelector(app.locator, { timeout: 30000 }).catch((err) => { - log.error(`Page '${app.path}' was not loaded properly, current url: ${page.url()}`); - throw err; + 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; + } + + throw err; + } }); await page.close(); From 060a844e4ac6802451e5239136a766f1f5c69a90 Mon Sep 17 00:00:00 2001 From: Mikhail Shustov Date: Tue, 2 Jun 2020 18:14:54 +0200 Subject: [PATCH 15/32] Update navigation.ts --- .../kbn-test/src/page_load_metrics/navigation.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/kbn-test/src/page_load_metrics/navigation.ts b/packages/kbn-test/src/page_load_metrics/navigation.ts index 4e4be9fb9df601..fbae858b31c5ce 100644 --- a/packages/kbn-test/src/page_load_metrics/navigation.ts +++ b/packages/kbn-test/src/page_load_metrics/navigation.ts @@ -115,23 +115,23 @@ export async function navigateToApps(log: ToolingLog, options: NavigationOptions waitUntil: 'networkidle0', }); - let readyAttempt = 0 - let selectorFound = false + let readyAttempt = 0; + let selectorFound = false; while (!selectorFound) { - readyAttempt += 1 + 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; } - + throw err; } - }); + } await page.close(); }) From c18ce02c85da5a9ed458175e90fe6590482d0697 Mon Sep 17 00:00:00 2001 From: Mikhail Shustov Date: Tue, 2 Jun 2020 18:32:20 +0200 Subject: [PATCH 16/32] Update navigation.ts --- packages/kbn-test/src/page_load_metrics/navigation.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/kbn-test/src/page_load_metrics/navigation.ts b/packages/kbn-test/src/page_load_metrics/navigation.ts index fbae858b31c5ce..32ba90b4c62b78 100644 --- a/packages/kbn-test/src/page_load_metrics/navigation.ts +++ b/packages/kbn-test/src/page_load_metrics/navigation.ts @@ -121,15 +121,19 @@ export async function navigateToApps(log: ToolingLog, options: NavigationOptions readyAttempt += 1; try { await page.waitForSelector(app.locator, { timeout: 5000 }); - selectorFound = true + selectorFound = true; } catch (error) { - log.error(`Page '${app.path}' was not loaded properly, unable to find '${app.locator}', url: ${page.url()}`); + log.error( + `Page '${app.path}' was not loaded properly, unable to find '${ + app.locator + }', url: ${page.url()}` + ); if (readyAttempt < 6) { continue; } - throw err; + throw error; } } From b15ce8c27e28f822f59b85a37f216e90f767dc78 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Wed, 3 Jun 2020 11:50:21 +0200 Subject: [PATCH 17/32] bump puppeteer version --- packages/kbn-test/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/kbn-test/package.json b/packages/kbn-test/package.json index 7de4c2adb03096..8e2fd1c9182ff7 100644 --- a/packages/kbn-test/package.json +++ b/packages/kbn-test/package.json @@ -14,7 +14,7 @@ "@kbn/babel-preset": "1.0.0", "@kbn/dev-utils": "1.0.0", "@types/parse-link-header": "^1.0.0", - "@types/puppeteer": "^2.1.0", + "@types/puppeteer": "^3.0.0", "@types/strip-ansi": "^5.2.1", "@types/xml2js": "^0.4.5", "diff": "^4.0.1" @@ -26,7 +26,7 @@ "getopts": "^2.2.4", "glob": "^7.1.2", "parse-link-header": "^1.0.1", - "puppeteer": "3.1.0", + "puppeteer": "^3.3.0", "strip-ansi": "^5.2.0", "rxjs": "^6.5.3", "tar-fs": "^1.16.3", From 8a7cc12d395ffaff4f4bba44aa41a3cd2e1d1d45 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Wed, 3 Jun 2020 11:51:00 +0200 Subject: [PATCH 18/32] fix typo --- packages/kbn-test/src/page_load_metrics/cli.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kbn-test/src/page_load_metrics/cli.ts b/packages/kbn-test/src/page_load_metrics/cli.ts index 14f2d2f17c37a0..e7fc1b2725403e 100644 --- a/packages/kbn-test/src/page_load_metrics/cli.ts +++ b/packages/kbn-test/src/page_load_metrics/cli.ts @@ -64,7 +64,7 @@ export function runPageLoadMetricsCli() { default: { username: 'elastic', password: 'changeme', debug: true }, help: ` --kibana-url Url for Kibana we should connect to, can include login info - --head Run pupeteer with graphical user interface + --head Run puppeteer with graphical user interface --username Set username, defaults to 'elastic' --password Set password, defaults to 'changeme' `, From da9a923236d19b73baa338d806fac9d1cc7ce9d3 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Wed, 3 Jun 2020 11:59:57 +0200 Subject: [PATCH 19/32] update navigation script --- packages/kbn-test/src/page_load_metrics/navigation.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/kbn-test/src/page_load_metrics/navigation.ts b/packages/kbn-test/src/page_load_metrics/navigation.ts index 32ba90b4c62b78..d7f7e543fa5a16 100644 --- a/packages/kbn-test/src/page_load_metrics/navigation.ts +++ b/packages/kbn-test/src/page_load_metrics/navigation.ts @@ -41,8 +41,8 @@ function joinPath(pathA: string, pathB: string) { }`; } -export function createUrl(path: string, options: NavigationOptions) { - const baseUrl = Url.parse(options.appConfig.url); +export function createUrl(path: string, url: string) { + const baseUrl = Url.parse(url); return Url.format({ protocol: baseUrl.protocol, hostname: baseUrl.hostname, @@ -58,7 +58,7 @@ async function loginToKibana( ) { log.debug(`log in to the app..`); const page = await browser.newPage(); - const loginUrl = createUrl('/login', options); + const loginUrl = createUrl('/login', options.appConfig.url); await page.goto(loginUrl, { waitUntil: 'networkidle0', }); @@ -109,7 +109,7 @@ export async function navigateToApps(log: ToolingLog, options: NavigationOptions getRequestData(event.requestId).dataLength += event.dataLength; }); - const url = createUrl(app.path, options); + const url = createUrl(app.path, options.appConfig.url); log.debug(`goto ${url}`); await page.goto(url, { waitUntil: 'networkidle0', From bd6c908fdc802f161dd3e542dd60fb5b2c6ed7a7 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Wed, 3 Jun 2020 12:00:40 +0200 Subject: [PATCH 20/32] update config file --- x-pack/test/page_load_metrics/config.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/test/page_load_metrics/config.ts b/x-pack/test/page_load_metrics/config.ts index 3ebbd89e78ec68..11752d71e9578b 100644 --- a/x-pack/test/page_load_metrics/config.ts +++ b/x-pack/test/page_load_metrics/config.ts @@ -33,7 +33,6 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { kbnTestServer: { ...xpackFunctionalTestsConfig.get('kbnTestServer'), - serverArgs: [...xpackFunctionalTestsConfig.get('kbnTestServer.serverArgs')], }, }; } From bf8a0a8b6cdab8cfa3e96c394242f149142891ac Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Wed, 3 Jun 2020 12:01:11 +0200 Subject: [PATCH 21/32] update yarn.lock --- yarn.lock | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/yarn.lock b/yarn.lock index 4d08df09669515..104365c31a1478 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4635,10 +4635,10 @@ dependencies: "@types/node" "*" -"@types/puppeteer@^2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@types/puppeteer/-/puppeteer-2.1.0.tgz#31367580654632f87f86df565f1bde0533577401" - integrity sha512-QIRQXl0VaSgnwOZ1LwxD321Tfb1jLOzCWuF2BrwjEkWq2IhxSicPOddUywLV7dRSO6mcU4sWKRdoGdci6gk0Aw== +"@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" "*" @@ -23985,22 +23985,6 @@ puppeteer-core@^1.19.0: rimraf "^2.6.1" ws "^6.1.0" -puppeteer@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-3.1.0.tgz#d44efdc5410809025f38bca2de106c3ae5c85a52" - integrity sha512-jLa9sqdVx0tPnr2FcwAq+8DSjGhSM4YpkwOf3JE22Ycyqm71SW7B5uGfTyMGFoLCmbCozbLZclCjasPb0flTRw== - 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" - puppeteer@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-2.1.1.tgz#ccde47c2a688f131883b50f2d697bd25189da27e" @@ -24017,6 +24001,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" From f848c4eead2149984ed9d438e07d86bb98b6168f Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Wed, 3 Jun 2020 16:37:20 +0200 Subject: [PATCH 22/32] fix --- .../kbn-test/src/page_load_metrics/capture_page_load_metrics.ts | 2 +- packages/kbn-test/src/page_load_metrics/navigation.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/kbn-test/src/page_load_metrics/capture_page_load_metrics.ts b/packages/kbn-test/src/page_load_metrics/capture_page_load_metrics.ts index 279788f8fcd957..013d49a29a51cf 100644 --- a/packages/kbn-test/src/page_load_metrics/capture_page_load_metrics.ts +++ b/packages/kbn-test/src/page_load_metrics/capture_page_load_metrics.ts @@ -42,7 +42,7 @@ export async function capturePageLoadMetrics(log: ToolingLog, options: Navigatio return Array.from(assetSizeMeasurements.entries()) .map(([url, measurements]) => { - const baseUrl = createUrl('/', options); + 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), '') diff --git a/packages/kbn-test/src/page_load_metrics/navigation.ts b/packages/kbn-test/src/page_load_metrics/navigation.ts index d7f7e543fa5a16..6d81a7898eef0a 100644 --- a/packages/kbn-test/src/page_load_metrics/navigation.ts +++ b/packages/kbn-test/src/page_load_metrics/navigation.ts @@ -76,7 +76,7 @@ export async function navigateToApps(log: ToolingLog, options: NavigationOptions { path: '/app/discover', locator: '[data-test-subj="discover-sidebar"]' }, { path: '/app/home', locator: '[data-test-subj="homeApp"]' }, { path: '/app/canvas', locator: '[data-test-subj="create-workpad-button"]' }, - { path: '/app/maps', locator: '[data-test-subj="newMapLink"]' }, + { path: '/app/maps', locator: '[data-test-subj="mapContainer"]' }, { path: '/app/apm', locator: '[data-test-subj="apmMainContainer"]' }, ]; From 7b0401485eea321d1259edd257827bb96e1dd53d Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Wed, 3 Jun 2020 22:46:49 +0200 Subject: [PATCH 23/32] take screenshot on failure --- .../kbn-test/src/page_load_metrics/navigation.ts | 14 +++++++++++++- x-pack/.gitignore | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/kbn-test/src/page_load_metrics/navigation.ts b/packages/kbn-test/src/page_load_metrics/navigation.ts index 6d81a7898eef0a..b7cddc740c56b1 100644 --- a/packages/kbn-test/src/page_load_metrics/navigation.ts +++ b/packages/kbn-test/src/page_load_metrics/navigation.ts @@ -17,12 +17,16 @@ * under the License. */ +import Fs from 'fs'; import Url from 'url'; import _ from 'lodash'; import puppeteer from 'puppeteer'; -import { ToolingLog } from '@kbn/dev-utils'; +import { resolve } from 'path'; +import { ToolingLog, REPO_ROOT } from '@kbn/dev-utils'; import { ResponseReceivedEvent, DataReceivedEvent } from './event'; +const failureDir = resolve(REPO_ROOT, 'x-pack/test/page_load_metrics/screenshots/failure'); + export interface NavigationOptions { headless: boolean; appConfig: { url: string; username: string; password: string }; @@ -133,6 +137,14 @@ export async function navigateToApps(log: ToolingLog, options: NavigationOptions continue; } + await page.bringToFront(); + Fs.mkdirSync(failureDir, { recursive: true }); + await page.screenshot({ + path: resolve(failureDir, `${app.path.replace('/', '_')}_navigation.png`), + type: 'png', + fullPage: true, + }); + throw error; } } diff --git a/x-pack/.gitignore b/x-pack/.gitignore index 6bac5e181861da..d6316346900cbe 100644 --- a/x-pack/.gitignore +++ b/x-pack/.gitignore @@ -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/ From f4401437c060cbe2502901458d4f209933976476 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Thu, 4 Jun 2020 09:13:22 +0200 Subject: [PATCH 24/32] update screenshot title --- packages/kbn-test/src/page_load_metrics/navigation.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kbn-test/src/page_load_metrics/navigation.ts b/packages/kbn-test/src/page_load_metrics/navigation.ts index b7cddc740c56b1..ba4b414ffa51b8 100644 --- a/packages/kbn-test/src/page_load_metrics/navigation.ts +++ b/packages/kbn-test/src/page_load_metrics/navigation.ts @@ -140,7 +140,7 @@ export async function navigateToApps(log: ToolingLog, options: NavigationOptions await page.bringToFront(); Fs.mkdirSync(failureDir, { recursive: true }); await page.screenshot({ - path: resolve(failureDir, `${app.path.replace('/', '_')}_navigation.png`), + path: resolve(failureDir, `${app.path.split('/').join('_')}_navigation.png`), type: 'png', fullPage: true, }); From 6b3e7fa8aa647b055336b996ff1719009f8700a2 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Thu, 4 Jun 2020 15:35:05 +0200 Subject: [PATCH 25/32] fix screenshot saving and error --- .../src/page_load_metrics/navigation.ts | 20 +++++++++++++------ x-pack/test/page_load_metrics/runner.ts | 3 +++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/packages/kbn-test/src/page_load_metrics/navigation.ts b/packages/kbn-test/src/page_load_metrics/navigation.ts index ba4b414ffa51b8..9b78db0f449993 100644 --- a/packages/kbn-test/src/page_load_metrics/navigation.ts +++ b/packages/kbn-test/src/page_load_metrics/navigation.ts @@ -22,14 +22,13 @@ import Url from 'url'; import _ from 'lodash'; import puppeteer from 'puppeteer'; import { resolve } from 'path'; -import { ToolingLog, REPO_ROOT } from '@kbn/dev-utils'; +import { ToolingLog } from '@kbn/dev-utils'; import { ResponseReceivedEvent, DataReceivedEvent } from './event'; -const failureDir = resolve(REPO_ROOT, 'x-pack/test/page_load_metrics/screenshots/failure'); - export interface NavigationOptions { headless: boolean; appConfig: { url: string; username: string; password: string }; + screenshotsDir?: string; } export type NavigationResults = Map>; @@ -137,15 +136,24 @@ export async function navigateToApps(log: ToolingLog, options: NavigationOptions continue; } - await page.bringToFront(); + const failureDir = options.screenshotsDir + ? resolve(options.screenshotsDir, 'failure') + : resolve(__dirname, 'screenshots/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: resolve(failureDir, `${app.path.split('/').join('_')}_navigation.png`), + path: screenshotPath, type: 'png', fullPage: true, }); + log.debug(`Saving screenshot to ${screenshotPath}`); - throw error; + throw new Error(`Page load timeout: ${app.path} not loaded after 30 seconds`); } } diff --git a/x-pack/test/page_load_metrics/runner.ts b/x-pack/test/page_load_metrics/runner.ts index 9d56f0ee139ec9..82a281eb58f04d 100644 --- a/x-pack/test/page_load_metrics/runner.ts +++ b/x-pack/test/page_load_metrics/runner.ts @@ -16,6 +16,8 @@ export async function PuppeteerTestRunner({ getService }: FtrProviderContext) { const config = getService('config'); const esArchiver = getService('esArchiver'); + const screenshotsDir = config.get('screenshots.directory'); + await esArchiver.load('default'); const metrics = await capturePageLoadMetrics(log, { headless: true, @@ -24,6 +26,7 @@ export async function PuppeteerTestRunner({ getService }: FtrProviderContext) { username: config.get('servers.kibana.username'), password: config.get('servers.kibana.password'), }, + screenshotsDir, }); const reporter = CiStatsReporter.fromEnv(log); From 3007539a696234b9b8a09d8705d6521dbbe06ff1 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Thu, 4 Jun 2020 15:39:16 +0200 Subject: [PATCH 26/32] invalid locator --- packages/kbn-test/src/page_load_metrics/navigation.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kbn-test/src/page_load_metrics/navigation.ts b/packages/kbn-test/src/page_load_metrics/navigation.ts index 9b78db0f449993..9a6f21ccf9662e 100644 --- a/packages/kbn-test/src/page_load_metrics/navigation.ts +++ b/packages/kbn-test/src/page_load_metrics/navigation.ts @@ -79,7 +79,7 @@ export async function navigateToApps(log: ToolingLog, options: NavigationOptions { path: '/app/discover', locator: '[data-test-subj="discover-sidebar"]' }, { path: '/app/home', locator: '[data-test-subj="homeApp"]' }, { path: '/app/canvas', locator: '[data-test-subj="create-workpad-button"]' }, - { path: '/app/maps', locator: '[data-test-subj="mapContainer"]' }, + { path: '/app/maps', locator: '[data-test-subj="XYZmapContainer"]' }, { path: '/app/apm', locator: '[data-test-subj="apmMainContainer"]' }, ]; From 19979b54bf96854db956e6627e532e56e09e37f7 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Thu, 4 Jun 2020 17:32:07 +0200 Subject: [PATCH 27/32] Revert "invalid locator" This reverts commit 3007539a696234b9b8a09d8705d6521dbbe06ff1. --- packages/kbn-test/src/page_load_metrics/navigation.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kbn-test/src/page_load_metrics/navigation.ts b/packages/kbn-test/src/page_load_metrics/navigation.ts index 9a6f21ccf9662e..9b78db0f449993 100644 --- a/packages/kbn-test/src/page_load_metrics/navigation.ts +++ b/packages/kbn-test/src/page_load_metrics/navigation.ts @@ -79,7 +79,7 @@ export async function navigateToApps(log: ToolingLog, options: NavigationOptions { path: '/app/discover', locator: '[data-test-subj="discover-sidebar"]' }, { path: '/app/home', locator: '[data-test-subj="homeApp"]' }, { path: '/app/canvas', locator: '[data-test-subj="create-workpad-button"]' }, - { path: '/app/maps', locator: '[data-test-subj="XYZmapContainer"]' }, + { path: '/app/maps', locator: '[data-test-subj="mapContainer"]' }, { path: '/app/apm', locator: '[data-test-subj="apmMainContainer"]' }, ]; From 6cfa219140c2ebad07b02e5f05abd245662b2c59 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Thu, 4 Jun 2020 17:41:25 +0200 Subject: [PATCH 28/32] run script in a loop 10 times --- .../src/page_load_metrics/capture_page_load_metrics.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/kbn-test/src/page_load_metrics/capture_page_load_metrics.ts b/packages/kbn-test/src/page_load_metrics/capture_page_load_metrics.ts index 013d49a29a51cf..4f02fb23e748dc 100644 --- a/packages/kbn-test/src/page_load_metrics/capture_page_load_metrics.ts +++ b/packages/kbn-test/src/page_load_metrics/capture_page_load_metrics.ts @@ -21,7 +21,15 @@ 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); + let responsesByPageView = []; + log.debug(`Running script in a loop`); + for (let i = 1; i <= 10; i++) { + try { + responsesByPageView = await navigateToApps(log, options); + } catch (err) { + log.error(`iteration ${i} failed: ${err}`); + } + } const assetSizeMeasurements = new Map(); From 1421388d49fd1ace8cd57bd4ac3b1733529dcebe Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Thu, 4 Jun 2020 19:34:15 +0200 Subject: [PATCH 29/32] Revert "run script in a loop 10 times" This reverts commit 6cfa219140c2ebad07b02e5f05abd245662b2c59. --- .../src/page_load_metrics/capture_page_load_metrics.ts | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/packages/kbn-test/src/page_load_metrics/capture_page_load_metrics.ts b/packages/kbn-test/src/page_load_metrics/capture_page_load_metrics.ts index 4f02fb23e748dc..013d49a29a51cf 100644 --- a/packages/kbn-test/src/page_load_metrics/capture_page_load_metrics.ts +++ b/packages/kbn-test/src/page_load_metrics/capture_page_load_metrics.ts @@ -21,15 +21,7 @@ import { ToolingLog } from '@kbn/dev-utils'; import { NavigationOptions, createUrl, navigateToApps } from './navigation'; export async function capturePageLoadMetrics(log: ToolingLog, options: NavigationOptions) { - let responsesByPageView = []; - log.debug(`Running script in a loop`); - for (let i = 1; i <= 10; i++) { - try { - responsesByPageView = await navigateToApps(log, options); - } catch (err) { - log.error(`iteration ${i} failed: ${err}`); - } - } + const responsesByPageView = await navigateToApps(log, options); const assetSizeMeasurements = new Map(); From a19828ffc5b534f694095b9dc326a792fc6cd8f7 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Thu, 4 Jun 2020 20:12:39 +0200 Subject: [PATCH 30/32] path config value directly --- x-pack/test/page_load_metrics/runner.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/x-pack/test/page_load_metrics/runner.ts b/x-pack/test/page_load_metrics/runner.ts index 82a281eb58f04d..05f293730f843a 100644 --- a/x-pack/test/page_load_metrics/runner.ts +++ b/x-pack/test/page_load_metrics/runner.ts @@ -16,8 +16,6 @@ export async function PuppeteerTestRunner({ getService }: FtrProviderContext) { const config = getService('config'); const esArchiver = getService('esArchiver'); - const screenshotsDir = config.get('screenshots.directory'); - await esArchiver.load('default'); const metrics = await capturePageLoadMetrics(log, { headless: true, @@ -26,7 +24,7 @@ export async function PuppeteerTestRunner({ getService }: FtrProviderContext) { username: config.get('servers.kibana.username'), password: config.get('servers.kibana.password'), }, - screenshotsDir, + screenshotsDir: config.get('screenshots.directory'), }); const reporter = CiStatsReporter.fromEnv(log); From fec3c4ef864193579f9daf92bb793a1deb2995c0 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Fri, 5 Jun 2020 14:30:39 +0200 Subject: [PATCH 31/32] fix screenshots directory setup --- .../kbn-test/src/page_load_metrics/cli.ts | 20 +++++++++++++++++-- .../src/page_load_metrics/navigation.ts | 6 ++---- x-pack/test/page_load_metrics/config.ts | 4 ++++ 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/packages/kbn-test/src/page_load_metrics/cli.ts b/packages/kbn-test/src/page_load_metrics/cli.ts index e7fc1b2725403e..95421384c79cb0 100644 --- a/packages/kbn-test/src/page_load_metrics/cli.ts +++ b/packages/kbn-test/src/page_load_metrics/cli.ts @@ -20,8 +20,11 @@ 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 }) => { @@ -44,6 +47,12 @@ export function runPageLoadMetricsCli() { 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: { @@ -51,6 +60,7 @@ export function runPageLoadMetricsCli() { username, password, }, + screenshotsDir, }); for (const metric of metrics) { log.info(`${metric.id}: ${metric.value}`); @@ -59,14 +69,20 @@ export function runPageLoadMetricsCli() { { description: `Loads several pages with Puppeteer to capture the size of assets`, flags: { - string: ['kibana-url', 'username', 'password'], + string: ['kibana-url', 'username', 'password', 'screenshotsDir'], boolean: ['head'], - default: { username: 'elastic', password: 'changeme', debug: true }, + 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}' `, }, } diff --git a/packages/kbn-test/src/page_load_metrics/navigation.ts b/packages/kbn-test/src/page_load_metrics/navigation.ts index 9b78db0f449993..4884ad82f75b32 100644 --- a/packages/kbn-test/src/page_load_metrics/navigation.ts +++ b/packages/kbn-test/src/page_load_metrics/navigation.ts @@ -28,7 +28,7 @@ import { ResponseReceivedEvent, DataReceivedEvent } from './event'; export interface NavigationOptions { headless: boolean; appConfig: { url: string; username: string; password: string }; - screenshotsDir?: string; + screenshotsDir: string; } export type NavigationResults = Map>; @@ -136,9 +136,7 @@ export async function navigateToApps(log: ToolingLog, options: NavigationOptions continue; } - const failureDir = options.screenshotsDir - ? resolve(options.screenshotsDir, 'failure') - : resolve(__dirname, 'screenshots/failure'); + const failureDir = resolve(options.screenshotsDir, 'failure'); const screenshotPath = resolve( failureDir, `${app.path.slice(1).split('/').join('_')}_navigation.png` diff --git a/x-pack/test/page_load_metrics/config.ts b/x-pack/test/page_load_metrics/config.ts index 11752d71e9578b..641099ff8e9346 100644 --- a/x-pack/test/page_load_metrics/config.ts +++ b/x-pack/test/page_load_metrics/config.ts @@ -26,6 +26,10 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { directory: resolve(__dirname, 'es_archives'), }, + screenshots: { + directory: resolve(__dirname, 'screenshots'), + }, + esTestCluster: { ...xpackFunctionalTestsConfig.get('esTestCluster'), serverArgs: [...xpackFunctionalTestsConfig.get('esTestCluster.serverArgs')], From d6ee29b7ef15670ba96212b13fbd4977a1a3ab67 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Fri, 5 Jun 2020 14:49:47 +0200 Subject: [PATCH 32/32] update maps locator, common for landing and new map --- packages/kbn-test/src/page_load_metrics/navigation.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kbn-test/src/page_load_metrics/navigation.ts b/packages/kbn-test/src/page_load_metrics/navigation.ts index 4884ad82f75b32..21dc681951b212 100644 --- a/packages/kbn-test/src/page_load_metrics/navigation.ts +++ b/packages/kbn-test/src/page_load_metrics/navigation.ts @@ -79,7 +79,7 @@ export async function navigateToApps(log: ToolingLog, options: NavigationOptions { path: '/app/discover', locator: '[data-test-subj="discover-sidebar"]' }, { path: '/app/home', locator: '[data-test-subj="homeApp"]' }, { path: '/app/canvas', locator: '[data-test-subj="create-workpad-button"]' }, - { path: '/app/maps', locator: '[data-test-subj="mapContainer"]' }, + { path: '/app/maps', locator: '[title="Maps"]' }, { path: '/app/apm', locator: '[data-test-subj="apmMainContainer"]' }, ];