Skip to content

Commit

Permalink
[ML] Transforms: Add performance journey for transform wizard source …
Browse files Browse the repository at this point in the history
…index loading. (#160837)

Add a performance journey for transform wizard source index loading.
  • Loading branch information
walterra authored Jun 30, 2023
1 parent 4fb883a commit a8e07e8
Show file tree
Hide file tree
Showing 9 changed files with 70 additions and 9 deletions.
1 change: 1 addition & 0 deletions .buildkite/ftr_configs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,7 @@ enabled:
- x-pack/performance/journeys/flight_dashboard.ts
- x-pack/performance/journeys/login.ts
- x-pack/performance/journeys/many_fields_discover.ts
- x-pack/performance/journeys/many_fields_transform.ts
- x-pack/performance/journeys/promotion_tracking_dashboard.ts
- x-pack/performance/journeys/web_logs_dashboard.ts
- x-pack/performance/journeys/data_stress_test_lens.ts
Expand Down
4 changes: 2 additions & 2 deletions dev_docs/tutorials/performance/adding_performance_journey.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ In order to achieve our goal of creating best user experience in Kibana, it is i
To make things easier, we introduced performance journeys, that mimics end-user experience with Kibana.

Journey runs a flow of user interactions with Kibana in a browser and collects APM metrics for both server and client-side.
It is possible to instrument Kibana with [custom performance metrics](https://docs.elastic.dev/kibana-dev-docs/tutorials/performance/adding_custom_performance_metrics),
It is possible to instrument Kibana with [custom performance metrics](https://docs.elastic.dev/kibana-dev-docs/tutorial/performance/adding_custom_performance_metrics),
that will provide more detailed information about feature performance.

Journeys core is [kbn-journeys](packages/kbn-journeys/README.mdx) package. It is a function test by design and is powered
Expand Down Expand Up @@ -61,7 +61,7 @@ Scripts steps include:

You can skip warmup phase for debug purpose by using `--skip-warmup` flag

Since the tests are run on a local machine, there is also realistic throttling applied to the network to
Since the tests are run on a local machine, there is also realistic throttling applied to the network to
simulate real life internet connection. This means that all requests have a fixed latency and limited bandwidth.

### Benchmarking performance on CI
Expand Down
5 changes: 2 additions & 3 deletions packages/kbn-journeys/journey/journey_ftr_harness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,9 +240,8 @@ export class JourneyFtrHarness {
return await block();
}

const span = this.apm?.startSpan(name, type ?? null, {
childOf: this.currentTransaction,
});
const span = this.currentTransaction.startSpan(name, type ?? null);

if (!span) {
return await block();
}
Expand Down
32 changes: 32 additions & 0 deletions x-pack/performance/journeys/many_fields_transform.ts
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 { waitForChrome } from '../utils';

export const journey = new Journey({
kbnArchives: ['test/functional/fixtures/kbn_archiver/many_fields_data_view'],
esArchives: ['test/functional/fixtures/es_archiver/many_fields'],
})
.step('Go to Transforms', async ({ page, kbnUrl }) => {
await page.goto(kbnUrl.get(`app/management/data/transform`));
await waitForChrome(page);
await page.waitForSelector(subj('transformCreateFirstButton'));
await page.waitForSelector(subj('globalLoadingIndicator-hidden'));
})
.step('Go to data view selection', async ({ page }) => {
const createButtons = page.locator(subj('transformCreateFirstButton'));
await createButtons.first().click();
await page.waitForSelector(subj('savedObjectsFinderTable'));
})
.step('Go to Transform Wizard', async ({ page }) => {
await page.click(subj('savedObjectTitleindices-stats*'));
// Extended the timeout, this one tracks a known issue with slow data grid performance with many fields
await page.waitForSelector(subj('transformIndexPreview loaded'), { timeout: 120000 });
await page.waitForSelector(subj('globalLoadingIndicator-hidden'), { timeout: 120000 });
});
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ dataStart.search.search = jest.fn(({ params }: IKibanaSearchRequest) => {
}) as ISearchGeneric;

const appDependencies: AppDependencies = {
analytics: coreStart.analytics,
application: coreStart.application,
charts: chartPluginMock.createStartContract(),
chrome: coreStart.chrome,
Expand Down
4 changes: 3 additions & 1 deletion x-pack/plugins/transform/public/app/app_dependencies.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

import type {
AnalyticsServiceStart,
ApplicationStart,
ChromeStart,
DocLinksStart,
Expand All @@ -15,12 +16,12 @@ import type {
NotificationsStart,
OverlayStart,
SavedObjectsStart,
ScopedHistory,
ThemeServiceStart,
} from '@kbn/core/public';
import type { SavedObjectsStart as SavedObjectsPluginStart } from '@kbn/saved-objects-plugin/public';
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public';
import type { ScopedHistory } from '@kbn/core/public';
import type { SharePluginStart } from '@kbn/share-plugin/public';
import type { SpacesPluginStart } from '@kbn/spaces-plugin/public';
import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public';
Expand All @@ -38,6 +39,7 @@ import type { SettingsStart } from '@kbn/core-ui-settings-browser';
import type { GetMlSharedImportsReturnType } from '../shared_imports';

export interface AppDependencies {
analytics: AnalyticsServiceStart;
application: ApplicationStart;
charts: ChartsPluginStart;
chrome: ChromeStart;
Expand Down
27 changes: 25 additions & 2 deletions x-pack/plugins/transform/public/app/hooks/use_index_data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
* 2.0.
*/

import { useEffect, useMemo, useState } from 'react';
import { useEffect, useMemo, useRef, useState } from 'react';

import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import type { EuiDataGridColumn } from '@elastic/eui';

import { reportPerformanceMetricEvent } from '@kbn/ebt-tools';
import { isRuntimeMappings } from '@kbn/ml-runtime-field-utils';
import { buildBaseFilterCriteria } from '@kbn/ml-query-utils';
import {
Expand Down Expand Up @@ -39,7 +40,7 @@ import {
import { getErrorMessage } from '../../../common/utils/errors';

import { isDefaultQuery, matchAllQuery, TransformConfigQuery } from '../common';
import { useToastNotifications } from '../app_dependencies';
import { useToastNotifications, useAppDependencies } from '../app_dependencies';
import type { StepDefineExposedState } from '../sections/create_transform/components/step_define/common';

import { SearchItems } from './use_search_items';
Expand All @@ -52,6 +53,12 @@ export const useIndexData = (
combinedRuntimeMappings?: StepDefineExposedState['runtimeMappings'],
timeRangeMs?: TimeRangeMs
): UseIndexDataReturnType => {
const { analytics } = useAppDependencies();

// Store the performance metric's start time using a ref
// to be able to track it across rerenders.
const loadIndexDataStartTime = useRef<number | undefined>(window.performance.now());

const indexPattern = useMemo(() => dataView.getIndexPattern(), [dataView]);

const api = useApi();
Expand Down Expand Up @@ -315,6 +322,22 @@ export const useIndexData = (

const renderCellValue = useRenderCellValue(dataView, pagination, tableItems);

if (
dataGrid.status === INDEX_STATUS.LOADED &&
dataViewFields !== undefined &&
loadIndexDataStartTime.current !== undefined
) {
const loadIndexDataDuration = window.performance.now() - loadIndexDataStartTime.current;

// Set this to undefined so reporting the metric gets triggered only once.
loadIndexDataStartTime.current = undefined;

reportPerformanceMetricEvent(analytics, {
eventName: 'transformLoadIndexPreview',
duration: loadIndexDataDuration,
});
}

return {
...dataGrid,
renderCellValue,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export async function mountManagementSection(
const startServices = await getStartServices();
const [core, plugins] = startServices;
const {
analytics,
application,
chrome,
docLinks,
Expand Down Expand Up @@ -61,6 +62,7 @@ export async function mountManagementSection(

// AppCore/AppPlugins to be passed on as React context
const appDependencies: AppDependencies = {
analytics,
application,
chrome,
data,
Expand Down
3 changes: 2 additions & 1 deletion x-pack/plugins/transform/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@
"@kbn/ml-runtime-field-utils",
"@kbn/ml-date-utils",
"@kbn/saved-search-plugin",
"@kbn/unified-field-list"
"@kbn/unified-field-list",
"@kbn/ebt-tools"
],
"exclude": [
"target/**/*",
Expand Down

0 comments on commit a8e07e8

Please sign in to comment.