-
Notifications
You must be signed in to change notification settings - Fork 8.6k
[Streams] Add scalability performance journeys for Streams #252288
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 68 commits
4cb42e7
c635655
192ce2e
c404915
04eaa54
5fb6e44
93ea3ac
0b20355
aa4a44b
2237656
b2bca04
683ee05
4da18ab
3bd3ab2
1b5e465
926a52a
58ff17b
0d2dc9d
5ee3aac
087c18b
3d27e89
6f51503
1582f16
65905ca
87cbae6
a97ef99
d864305
be5b36d
eb90d6f
14a25ea
828b5eb
e644a4b
494043a
5385f72
38aeb1a
81e392e
026ceb9
dc5ba11
be144af
e23b011
ac71fd1
01e1267
96412a5
4ceb95f
3c4d895
fa0b385
7e0617b
61ac545
6f3841f
ae815aa
8cecc00
9e0a637
fe29aa8
fd1a689
5e4d806
3a43a94
3bd349d
6d47382
af717ea
5f9d0cd
b21a7ef
599ec21
21eecda
b3db365
cd8fd2e
eb8fb62
00ac6c1
442a790
340fe70
ba07441
16adcf1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| # yaml-language-server: $schema=https://gist.githubusercontent.com/elasticmachine/988b80dae436cafea07d9a4a460a011d/raw/rre.schema.json | ||
| apiVersion: backstage.io/v1alpha1 | ||
| kind: Resource | ||
| metadata: | ||
| name: bk-kibana-streams-performance | ||
| description: Runs Streams performance journeys at scale | ||
| links: | ||
| - url: 'https://buildkite.com/elastic/kibana-streams-performance' | ||
| title: Pipeline link | ||
| spec: | ||
| type: buildkite-pipeline | ||
| owner: 'group:obs-onboarding-team' | ||
| system: buildkite | ||
| implementation: | ||
| apiVersion: buildkite.elastic.dev/v1 | ||
| kind: Pipeline | ||
| metadata: | ||
| name: kibana / streams-performance | ||
| description: Runs Streams performance journeys at scale | ||
| spec: | ||
| env: | ||
| ELASTIC_SLACK_NOTIFICATIONS_ENABLED: 'false' | ||
| allow_rebuilds: true | ||
| branch_configuration: main | ||
| default_branch: main | ||
| repository: elastic/kibana | ||
| pipeline_file: .buildkite/pipelines/performance/streams_weekly.yml | ||
| provider_settings: | ||
| trigger_mode: none | ||
| build_branches: false | ||
| prefix_pull_request_fork_branch_names: true | ||
| publish_commit_status: false | ||
| skip_pull_request_builds_for_existing_commits: true | ||
| teams: | ||
| everyone: | ||
| access_level: BUILD_AND_READ | ||
| obs-onboarding-team: | ||
| access_level: MANAGE_BUILD_AND_READ | ||
| kibana-operations: | ||
| access_level: MANAGE_BUILD_AND_READ | ||
| appex-qa: | ||
| access_level: MANAGE_BUILD_AND_READ | ||
| kibana-tech-leads: | ||
| access_level: MANAGE_BUILD_AND_READ | ||
| schedules: | ||
| Weekly Streams performance: | ||
| cronline: 0 6 * * 1 Europe/Berlin | ||
| message: Weekly Streams performance | ||
| branch: main | ||
| tags: | ||
| - kibana | ||
| - performance | ||
| - streams |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| steps: | ||
| - label: ':male-mechanic::skin-tone-2: Pre-Build' | ||
| command: .buildkite/scripts/lifecycle/pre_build.sh | ||
| agents: | ||
| image: family/kibana-ubuntu-2404 | ||
| imageProject: elastic-images-prod | ||
| provider: gcp | ||
| machineType: n2-standard-2 | ||
|
|
||
| - wait | ||
|
|
||
| - label: ':building_construction: Build Kibana Distribution' | ||
| command: .buildkite/scripts/steps/build_kibana.sh | ||
| agents: | ||
| image: family/kibana-ubuntu-2404 | ||
| imageProject: elastic-images-prod | ||
| provider: gcp | ||
| machineType: n2-standard-8 | ||
| key: build | ||
| if: "build.env('KIBANA_BUILD_ID') == null || build.env('KIBANA_BUILD_ID') == ''" | ||
|
|
||
| - label: ':muscle: Streams Performance Tests' | ||
| command: .buildkite/scripts/steps/functional/performance_playwright.sh | ||
| env: | ||
| JOURNEYS_GROUP: streams | ||
| PERFORMANCE_ENABLE_TELEMETRY: true | ||
| agents: | ||
| queue: kb-static-scalability-2 | ||
| depends_on: build | ||
| key: tests | ||
| timeout_in_minutes: 180 | ||
|
|
||
| - label: ':chart_with_upwards_trend: Report performance metrics to ci-stats' | ||
| command: .buildkite/scripts/steps/functional/report_performance_metrics.sh | ||
| agents: | ||
| image: family/kibana-ubuntu-2404 | ||
| imageProject: elastic-images-prod | ||
| provider: gcp | ||
| localSsds: 1 | ||
| localSsdInterface: nvme | ||
| machineType: n2-standard-2 | ||
| depends_on: tests | ||
|
|
||
| - wait: ~ | ||
| continue_on_failure: true | ||
|
|
||
| - label: ':male_superhero::skin-tone-2: Post-Build' | ||
| command: .buildkite/scripts/lifecycle/post_build.sh | ||
| agents: | ||
| image: family/kibana-ubuntu-2404 | ||
| imageProject: elastic-images-prod | ||
| provider: gcp | ||
| machineType: n2-standard-2 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| /* | ||
| * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
| * or more contributor license agreements. Licensed under the Elastic License | ||
| * 2.0; you may not use this file except in compliance with the Elastic License | ||
| * 2.0. | ||
| */ | ||
|
|
||
| import type { FtrConfigProviderContext } from '@kbn/test'; | ||
|
|
||
| /** | ||
| * Extended FTR config for heavy Streams performance journeys (e.g. large wired hierarchy). | ||
| * Increases mochaOpts.timeout to 1 hour because beforeSteps runs inside Mocha's before() hook, | ||
| * meaning the entire data setup (batched content pack imports for 1000 wired children) is | ||
| * subject to this timeout. On CI bare metal workers the setup alone takes ~25-30 minutes. | ||
| * | ||
| */ | ||
| // eslint-disable-next-line import/no-default-export | ||
| export default async function ({ readConfigFile }: FtrConfigProviderContext) { | ||
|
Comment on lines
+17
to
+18
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major Move the default-export lint exception out of the file. Adding a new As per coding guidelines, "Never suppress linting errors with 🤖 Prompt for AI Agents |
||
| const baseConfig = await readConfigFile(require.resolve('./http2_config')); | ||
|
|
||
| return { | ||
| ...baseConfig.getAll(), | ||
| mochaOpts: { | ||
| ...baseConfig.get('mochaOpts'), | ||
| timeout: 3_600_000, // 1 hour | ||
| }, | ||
| }; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| /* | ||
| * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
| * or more contributor license agreements. Licensed under the Elastic License | ||
| * 2.0; you may not use this file except in compliance with the Elastic License | ||
| * 2.0. | ||
| */ | ||
|
|
||
| import { Journey } from '@kbn/journeys'; | ||
| import { subj } from '@kbn/test-subj-selector'; | ||
| import { setupDataQualityAtScale } from '../synthtrace_data/streams_data'; | ||
|
|
||
| export const journey = new Journey({ | ||
| ftrConfigPath: 'x-pack/performance/configs/streams_heavy_config.ts', | ||
| beforeSteps: async ({ kibanaServer, es, log }) => { | ||
| await setupDataQualityAtScale(kibanaServer, es, log); | ||
| }, | ||
| }) | ||
| .step('Go to stream detail page', async ({ page, kbnUrl }) => { | ||
| await page.goto(kbnUrl.get('/app/streams/logs.otel.child1')); | ||
| await page.waitForSelector(subj('wiredStreamBadge'), { timeout: 60000 }); | ||
| }) | ||
| .step('Navigate to Data Quality tab', async ({ page, kbnUrl }) => { | ||
| await page.goto(kbnUrl.get('/app/streams/logs.otel.child1/management/dataQuality')); | ||
| await page.waitForSelector(subj('datasetQualityDetailsSummaryKpiCard-Degraded documents'), { | ||
| timeout: 60000, | ||
| }); | ||
| }) | ||
| .step('Verify data quality metrics render', async ({ page }) => { | ||
| await page.waitForSelector(subj('datasetQualityDetailsSummaryKpiCard-Failed documents'), { | ||
| timeout: 60000, | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| /* | ||
| * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
| * or more contributor license agreements. Licensed under the Elastic License | ||
| * 2.0; you may not use this file except in compliance with the Elastic License | ||
| * 2.0. | ||
| */ | ||
|
|
||
| import { Journey } from '@kbn/journeys'; | ||
| import { subj } from '@kbn/test-subj-selector'; | ||
| import { setupFieldMappingAtScale } from '../synthtrace_data/streams_data'; | ||
|
|
||
| const getNewFieldName = (): string => { | ||
| const phase = (process.env.TEST_PERFORMANCE_PHASE ?? 'local') | ||
| .toLowerCase() | ||
| .replace(/[^a-z0-9_]+/g, '_'); | ||
|
|
||
| return `attributes.perf_scale_new_field_${phase}`; | ||
| }; | ||
|
|
||
| export const journey = new Journey({ | ||
| ftrConfigPath: 'x-pack/performance/configs/streams_heavy_config.ts', | ||
| beforeSteps: async ({ kibanaServer, log }) => { | ||
| await setupFieldMappingAtScale(kibanaServer, log); | ||
| }, | ||
| }) | ||
| .step('Go to stream schema page', async ({ page, kbnUrl }) => { | ||
| await page.goto(kbnUrl.get('/app/streams/logs.otel.child1/management/schema')); | ||
| await page.waitForSelector(subj('streamsAppContentAddFieldButton'), { timeout: 60000 }); | ||
| }) | ||
| .step('Open add field flyout', async ({ page }) => { | ||
| await page.click(subj('streamsAppContentAddFieldButton')); | ||
| await page.waitForSelector(subj('streamsAppSchemaEditorAddFieldFlyoutFieldName'), { | ||
| timeout: 30000, | ||
| }); | ||
| }) | ||
| .step('Configure new field mapping', async ({ page, inputDelays }) => { | ||
| const comboBox = page.locator(subj('streamsAppSchemaEditorAddFieldFlyoutFieldName')); | ||
| const comboInput = comboBox.locator('input[role="combobox"]'); | ||
| const fieldName = getNewFieldName(); | ||
| await comboInput.click(); | ||
| await comboInput.pressSequentially(fieldName, { | ||
| delay: inputDelays.TYPING, | ||
| timeout: 60000, | ||
| }); | ||
| await page.keyboard.press('Enter'); | ||
|
|
||
| await page.click(subj('streamsAppFieldFormTypeSelect')); | ||
| await page.click(subj('option-type-keyword')); | ||
| }) | ||
| .step('Add field mapping', async ({ page }) => { | ||
| await page.waitForSelector(`${subj('streamsAppSchemaEditorAddFieldButton')}:not([disabled])`, { | ||
| timeout: 30000, | ||
| }); | ||
| await page.click(subj('streamsAppSchemaEditorAddFieldButton')); | ||
| await page.waitForSelector(subj('streamsAppSchemaEditorAddFieldFlyoutCloseButton'), { | ||
| state: 'detached', | ||
| timeout: 30000, | ||
| }); | ||
| }) | ||
| .step('Review and submit field mapping', async ({ page }) => { | ||
| await page.waitForSelector(subj('streamsAppSchemaEditorReviewStagedChangesButton'), { | ||
| timeout: 60000, | ||
| }); | ||
| await page.click(subj('streamsAppSchemaEditorReviewStagedChangesButton')); | ||
| await page.waitForSelector(subj('streamsAppSchemaChangesReviewModalSubmitButton'), { | ||
| timeout: 60000, | ||
| }); | ||
| await page.click(subj('streamsAppSchemaChangesReviewModalSubmitButton')); | ||
| await page.waitForSelector(subj('streamsAppSchemaChangesReviewModalSubmitButton'), { | ||
| state: 'detached', | ||
| timeout: 30000, | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| /* | ||
| * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
| * or more contributor license agreements. Licensed under the Elastic License | ||
| * 2.0; you may not use this file except in compliance with the Elastic License | ||
| * 2.0. | ||
| */ | ||
|
|
||
| import { Journey } from '@kbn/journeys'; | ||
| import { subj } from '@kbn/test-subj-selector'; | ||
| import { setupListingPageData } from '../synthtrace_data/streams_data'; | ||
|
|
||
| const STREAMS_SEARCH_SELECTOR = 'input[aria-label="Search streams by name"]'; | ||
| const STREAMS_EXPAND_ALL_BUTTON = subj('streamsExpandAllButton'); | ||
| const STREAMS_COLLAPSE_ALL_BUTTON = subj('streamsCollapseAllButton'); | ||
| const CLASSIC_STREAM_TO_SEARCH = 'logs-perf-classic-00001'; | ||
|
|
||
| export const journey = new Journey({ | ||
| ftrConfigPath: 'x-pack/performance/configs/streams_heavy_config.ts', | ||
| beforeSteps: async ({ kibanaServer, es, log }) => { | ||
| await setupListingPageData(kibanaServer, es, log); | ||
| }, | ||
| }) | ||
| .step('Go to Streams listing page', async ({ page, kbnUrl }) => { | ||
| await page.goto(kbnUrl.get('/app/streams')); | ||
| await page.waitForSelector(subj('streamsTable'), { timeout: 120000 }); | ||
| }) | ||
| .step('Search for a classic stream', async ({ page, inputDelays }) => { | ||
| const searchBox = page.locator(STREAMS_SEARCH_SELECTOR).first(); | ||
| await searchBox.waitFor({ state: 'visible', timeout: 60000 }); | ||
| await searchBox.fill(''); | ||
| await searchBox.pressSequentially(CLASSIC_STREAM_TO_SEARCH, { | ||
| delay: inputDelays.TYPING, | ||
| timeout: 120000, | ||
| }); | ||
| await page.waitForSelector(subj(`streamsNameLink-${CLASSIC_STREAM_TO_SEARCH}`), { | ||
| timeout: 120000, | ||
| }); | ||
| }) | ||
| .step('Clear search and expand all streams', async ({ page }) => { | ||
| const searchBox = page.locator(STREAMS_SEARCH_SELECTOR).first(); | ||
| await searchBox.waitFor({ state: 'visible', timeout: 60000 }); | ||
| await searchBox.fill(''); | ||
|
|
||
| const expandAllButton = page.locator(STREAMS_EXPAND_ALL_BUTTON).first(); | ||
| const collapseAllButton = page.locator(STREAMS_COLLAPSE_ALL_BUTTON).first(); | ||
|
|
||
| if (await expandAllButton.isVisible().catch(() => false)) { | ||
| await expandAllButton.click(); | ||
| } else { | ||
| await collapseAllButton.waitFor({ state: 'visible', timeout: 60000 }); | ||
| await collapseAllButton.click(); | ||
| await expandAllButton.waitFor({ state: 'visible', timeout: 60000 }); | ||
| await expandAllButton.click(); | ||
| } | ||
|
|
||
| // Wait for the expand-all action to settle (button state swap). | ||
| await collapseAllButton.waitFor({ state: 'visible', timeout: 60000 }); | ||
| }) | ||
| .step('Collapse all streams', async ({ page }) => { | ||
| const collapseAllButton = page.locator(STREAMS_COLLAPSE_ALL_BUTTON).first(); | ||
| await collapseAllButton.waitFor({ state: 'visible', timeout: 60000 }); | ||
| await collapseAllButton.click(); | ||
| const expandAllButton = page.locator(STREAMS_EXPAND_ALL_BUTTON).first(); | ||
| await expandAllButton.waitFor({ state: 'visible', timeout: 60000 }); | ||
| }) | ||
| .step('Navigate to a stream detail page', async ({ page, inputDelays }) => { | ||
| // logs.otel can be paginated away. Filter to bring it into view. | ||
| const searchBox = page.locator(STREAMS_SEARCH_SELECTOR).first(); | ||
| await searchBox.waitFor({ state: 'visible', timeout: 60000 }); | ||
| await searchBox.fill(''); | ||
| await searchBox.pressSequentially('logs.otel', { | ||
| delay: inputDelays.TYPING, | ||
| timeout: 60000, | ||
| }); | ||
|
|
||
| const logsOtelExpand = page.locator(subj('expandButton-logs.otel')); | ||
| await logsOtelExpand.waitFor({ state: 'visible', timeout: 120000 }); | ||
| await logsOtelExpand.click(); | ||
|
|
||
| const streamLink = page.locator(subj('streamsNameLink-logs.otel.child1')); | ||
| await streamLink.waitFor({ state: 'visible', timeout: 60000 }); | ||
| await streamLink.click(); | ||
| await page.waitForSelector(subj('wiredStreamBadge'), { timeout: 60000 }); | ||
| }); |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don’t disable the lightweight Streams journeys here.
This block currently moves all Streams journeys out of the regular stateful CI path, but the PR goal says only
streams_wired_hierarchy.tsshould be scheduled-pipeline-only. Keepingstreams_data_quality.ts,streams_field_mapping.ts,streams_listing_page.ts,streams_processing_step.ts, andstreams_retention.tsindisabledwill drop the PR-CI coverage you’re adding.Suggested update
🤖 Prompt for AI Agents
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can I get some help in understanding - won't this mean we'll always run this config with other ftrs? (cc: @dmlemeshko )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.