From 60858f682deb8b1090bb4c417407889b21d686ec Mon Sep 17 00:00:00 2001 From: Luke Gmys <11671118+lgestc@users.noreply.github.com> Date: Wed, 2 Jul 2025 14:14:35 +0200 Subject: [PATCH 1/3] [Security Solution][Sourcerer] Replace unnecessary useDataViewSpec calls (#224831) ## Summary As useDataViewSpec uses are expensive (due to toSpec method in the data view implementation), this PR adds in an optional switch to the hook and actually replaces it where we only need the data view id and not the full spec. ### Testing Set the FF, ``` xpack.securitySolution.enableExperimental: ['newDataViewPickerEnabled'] ``` verify that the app still works correctly (timelines) ### Checklist Check the PR satisfies following conditions. Reviewers should verify this PR satisfies this list as well. - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios (cherry picked from commit 711ab70b3770addcba8fa66b28af65ceda11e5e3) --- .../assistant/send_to_timeline/index.tsx | 6 +++--- .../components/data_view_picker/index.test.tsx | 12 ++++++------ .../components/data_view_picker/index.tsx | 18 ++++++++++++------ .../hooks/use_data_view_spec.ts | 8 +++++--- .../timelines/hooks/use_create_timeline.tsx | 10 ++++------ 5 files changed, 30 insertions(+), 24 deletions(-) diff --git a/x-pack/solutions/security/plugins/security_solution/public/assistant/send_to_timeline/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/assistant/send_to_timeline/index.tsx index 0968bc4a4fe21..4c906bb93154d 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/assistant/send_to_timeline/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/assistant/send_to_timeline/index.tsx @@ -39,7 +39,7 @@ import { useSourcererDataView } from '../../sourcerer/containers'; import { useDiscoverState } from '../../timelines/components/timeline/tabs/esql/use_discover_state'; import { useKibana } from '../../common/lib/kibana'; import { useIsExperimentalFeatureEnabled } from '../../common/hooks/use_experimental_features'; -import { useDataViewSpec } from '../../data_view_manager/hooks/use_data_view_spec'; +import { useDataView } from '../../data_view_manager/hooks/use_data_view'; export interface SendToTimelineButtonProps { asEmptyButton: boolean; @@ -67,10 +67,10 @@ export const SendToTimelineButton: FC ({ useUpdateUrlParam: jest.fn(), })); -jest.mock('../../hooks/use_data_view_spec', () => ({ - useDataViewSpec: jest.fn(), +jest.mock('../../hooks/use_data_view', () => ({ + useDataView: jest.fn(), })); jest.mock('../../hooks/use_select_data_view', () => ({ @@ -79,11 +79,11 @@ describe('DataViewPicker', () => { beforeEach(() => { jest.mocked(useUpdateUrlParam).mockReturnValue(jest.fn()); - jest.mocked(useDataViewSpec).mockReturnValue({ - dataViewSpec: { + jest.mocked(useDataView).mockReturnValue({ + dataView: { id: DEFAULT_SECURITY_SOLUTION_DATA_VIEW_ID, name: 'Default Security Data View', - }, + } as unknown as DataView, status: 'ready', }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/data_view_manager/components/data_view_picker/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/data_view_manager/components/data_view_picker/index.tsx index 44d673c70efab..da54dc8b05243 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/data_view_manager/components/data_view_picker/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/data_view_manager/components/data_view_picker/index.tsx @@ -14,15 +14,15 @@ import type { SourcererUrlState } from '../../../sourcerer/store/model'; import { useUpdateUrlParam } from '../../../common/utils/global_query_string'; import { URL_PARAM_KEY } from '../../../common/hooks/use_url_state'; import { useKibana } from '../../../common/lib/kibana'; -import { useDataViewSpec } from '../../hooks/use_data_view_spec'; import { sharedStateSelector } from '../../redux/selectors'; import { sharedDataViewManagerSlice } from '../../redux/slices'; import { useSelectDataView } from '../../hooks/use_select_data_view'; import { DataViewManagerScopeName } from '../../constants'; import { useManagedDataViews } from '../../hooks/use_managed_data_views'; import { useSavedDataViews } from '../../hooks/use_saved_data_views'; -import { LOADING } from './translations'; +import { DEFAULT_SECURITY_DATA_VIEW, LOADING } from './translations'; import { DATA_VIEW_PICKER_TEST_ID } from './constants'; +import { useDataView } from '../../hooks/use_data_view'; interface DataViewPickerProps { /** @@ -55,7 +55,7 @@ export const DataViewPicker = memo(({ scope, onClosePopover, disabled }: DataVie const closeDataViewEditor = useRef<() => void | undefined>(); const closeFieldEditor = useRef<() => void | undefined>(); - const { dataViewSpec, status } = useDataViewSpec(scope); + const { dataView, status } = useDataView(scope); const { adhocDataViews: adhocDataViewSpecs, defaultDataViewId } = useSelector(sharedStateSelector); @@ -69,7 +69,7 @@ export const DataViewPicker = memo(({ scope, onClosePopover, disabled }: DataVie const isDefaultSourcerer = scope === DataViewManagerScopeName.default; const updateUrlParam = useUpdateUrlParam(URL_PARAM_KEY.sourcerer); - const dataViewId = dataViewSpec?.id; + const dataViewId = dataView?.id; // NOTE: this function is called in response to user interaction with the picker, // hence - it is the only place where we should update the url param for the data view selection. @@ -154,10 +154,16 @@ export const DataViewPicker = memo(({ scope, onClosePopover, disabled }: DataVie return { label: LOADING }; } + if (dataView?.id === defaultDataViewId) { + return { + label: DEFAULT_SECURITY_DATA_VIEW, + }; + } + return { - label: dataViewSpec?.name || dataViewSpec?.id || 'Data view', + label: dataView?.name || dataView?.id || 'Data view', }; - }, [dataViewSpec?.name, dataViewSpec?.id, status]); + }, [dataView?.id, dataView?.name, defaultDataViewId, status]); return (
diff --git a/x-pack/solutions/security/plugins/security_solution/public/data_view_manager/hooks/use_data_view_spec.ts b/x-pack/solutions/security/plugins/security_solution/public/data_view_manager/hooks/use_data_view_spec.ts index a89524559c25d..5f6febb770ebe 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/data_view_manager/hooks/use_data_view_spec.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/data_view_manager/hooks/use_data_view_spec.ts @@ -23,9 +23,11 @@ export interface UseDataViewSpecResult { /** * Returns an object with the dataViewSpec and status values for the given scopeName. + * IMPORTANT: If fields are not required, make sure to pass `includeFields = false`. */ export const useDataViewSpec = ( - scopeName: DataViewManagerScopeName = DataViewManagerScopeName.default + scopeName: DataViewManagerScopeName = DataViewManagerScopeName.default, + includeFields = true ): UseDataViewSpecResult => { const { dataView, status } = useDataView(scopeName); @@ -42,6 +44,6 @@ export const useDataViewSpec = ( }; } - return { dataViewSpec: dataView?.toSpec?.(), status }; - }, [dataView, status]); + return { dataViewSpec: dataView?.toSpec?.(includeFields), status }; + }, [dataView, includeFields, status]); }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/hooks/use_create_timeline.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/hooks/use_create_timeline.tsx index 653c3943efd85..955cbac9abd6a 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/hooks/use_create_timeline.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/hooks/use_create_timeline.tsx @@ -21,11 +21,11 @@ import { defaultUdtHeaders } from '../components/timeline/body/column_headers/de import { timelineDefaults } from '../store/defaults'; import { useSelectDataView } from '../../data_view_manager/hooks/use_select_data_view'; import { DataViewManagerScopeName } from '../../data_view_manager/constants'; -import { useDataViewSpec } from '../../data_view_manager/hooks/use_data_view_spec'; import { useSelectedPatterns } from '../../data_view_manager/hooks/use_selected_patterns'; import { sourcererActions, sourcererSelectors } from '../../sourcerer/store'; import { SourcererScopeName } from '../../sourcerer/store/model'; import { useEnableExperimental } from '../../common/hooks/use_experimental_features'; +import { useDataView } from '../../data_view_manager/hooks/use_data_view'; export interface UseCreateTimelineParams { /** @@ -59,14 +59,12 @@ export const useCreateTimeline = ({ ) ?? { id: '', patternList: [] }; const { newDataViewPickerEnabled } = useEnableExperimental(); - const { dataViewSpec: experimentalDataViewSpec } = useDataViewSpec( - DataViewManagerScopeName.default - ); + const { dataView: experimentalDataView } = useDataView(DataViewManagerScopeName.default); const experimentalSelectedPatterns = useSelectedPatterns(DataViewManagerScopeName.default); const dataViewId = useMemo( - () => (newDataViewPickerEnabled ? experimentalDataViewSpec.id ?? '' : oldDataViewId), - [experimentalDataViewSpec.id, newDataViewPickerEnabled, oldDataViewId] + () => (newDataViewPickerEnabled ? experimentalDataView?.id ?? '' : oldDataViewId), + [experimentalDataView?.id, newDataViewPickerEnabled, oldDataViewId] ); const selectedPatterns = useMemo( () => (newDataViewPickerEnabled ? experimentalSelectedPatterns : oldSelectedPatterns), From 57693e2662f1a7e3e960cd9ef791ed796497409b Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Tue, 15 Jul 2025 09:40:19 +0000 Subject: [PATCH 2/3] [CI] Auto-commit changed files from 'node scripts/eslint_all_files --no-cache --fix' --- .../public/timelines/hooks/use_create_timeline.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/hooks/use_create_timeline.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/hooks/use_create_timeline.tsx index c46da43d52e43..3da8813653b46 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/hooks/use_create_timeline.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/hooks/use_create_timeline.tsx @@ -21,10 +21,8 @@ import { defaultUdtHeaders } from '../components/timeline/body/column_headers/de import { timelineDefaults } from '../store/defaults'; import { useSelectDataView } from '../../data_view_manager/hooks/use_select_data_view'; import { DataViewManagerScopeName } from '../../data_view_manager/constants'; -import { useSelectedPatterns } from '../../data_view_manager/hooks/use_selected_patterns'; import { sourcererActions, sourcererSelectors } from '../../sourcerer/store'; import { SourcererScopeName } from '../../sourcerer/store/model'; -import { useDataView } from '../../data_view_manager/hooks/use_data_view'; import { useEnableExperimental } from '../../common/hooks/use_experimental_features'; import { useSecurityDefaultPatterns } from '../../data_view_manager/hooks/use_security_default_patterns'; From 56f37cdbdf21dc1d05837f7d854617c72e296d59 Mon Sep 17 00:00:00 2001 From: Luke Gmys <11671118+lgestc@users.noreply.github.com> Date: Tue, 15 Jul 2025 15:43:08 +0200 Subject: [PATCH 3/3] Update index.tsx --- .../data_view_manager/components/data_view_picker/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/solutions/security/plugins/security_solution/public/data_view_manager/components/data_view_picker/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/data_view_manager/components/data_view_picker/index.tsx index 945a7195bc9f3..40513f0af7a46 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/data_view_manager/components/data_view_picker/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/data_view_manager/components/data_view_picker/index.tsx @@ -23,6 +23,7 @@ import { useSavedDataViews } from '../../hooks/use_saved_data_views'; import { DEFAULT_SECURITY_DATA_VIEW, LOADING } from './translations'; import { DATA_VIEW_PICKER_TEST_ID } from './constants'; import { useDataView } from '../../hooks/use_data_view'; +import { browserFieldsManager } from '../../utils/security_browser_fields_manager'; interface DataViewPickerProps { /**