diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_count_panel/index.test.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_count_panel/index.test.tsx index 80e5867aadc0c..6b0b0ed9a0e08 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_count_panel/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_count_panel/index.test.tsx @@ -60,7 +60,7 @@ jest.mock('../../../../common/components/visualization_actions/lens_embeddable') jest.mock('../../../../common/components/page/use_refetch_by_session'); jest.mock('../common/hooks', () => ({ useInspectButton: jest.fn(), - useStackByFields: jest.fn(), + useStackByFields: jest.fn().mockReturnValue(() => []), })); const mockUseIsExperimentalFeatureEnabled = useIsExperimentalFeatureEnabled as jest.Mock; const getMockUseIsExperimentalFeatureEnabled = diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/common/components.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/common/components.tsx index 085b66f249104..bf050c2eedab9 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/common/components.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/common/components.tsx @@ -98,7 +98,13 @@ export const StackByComboBox = React.forwardRef( return [{ label: selected, value: selected }]; }, [selected]); - const stackOptions = useStackByFields(useLensCompatibleFields); + const getExpensiveFields = useStackByFields(useLensCompatibleFields); + + const options = useMemo( + () => dropDownoptions ?? getExpensiveFields(), + [dropDownoptions, getExpensiveFields] + ); + const singleSelection = useMemo(() => { return { asPlainText: true }; }, []); @@ -115,7 +121,7 @@ export const StackByComboBox = React.forwardRef( singleSelection={singleSelection} isClearable={false} sortMatchesBy="startsWith" - options={dropDownoptions ?? stackOptions} + options={options} selectedOptions={selectedOptions} compressed onChange={onChange} diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/common/hooks.test.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/common/hooks.test.tsx index b0c75e5831ad2..fdbc2108e4d33 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/common/hooks.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/common/hooks.test.tsx @@ -124,11 +124,11 @@ describe('hooks', () => { {children} ); const { result, unmount } = renderHook(() => useStackByFields(), { wrapper }); - const aggregateableFields = result.current; + const aggregateableFields = result.current(); unmount(); - expect(aggregateableFields?.find((field) => field.label === 'agent.id')).toBeTruthy(); + expect(aggregateableFields!.find((field) => field.label === 'agent.id')).toBeTruthy(); expect( - aggregateableFields?.find((field) => field.label === 'nestedField.firstAttributes') + aggregateableFields!.find((field) => field.label === 'nestedField.firstAttributes') ).toBe(undefined); }); @@ -144,10 +144,10 @@ describe('hooks', () => { const { result, unmount } = renderHook(() => useStackByFields(useLensCompatibleFields), { wrapper, }); - const aggregateableFields = result.current; + const aggregateableFields = result.current(); unmount(); - expect(aggregateableFields?.find((field) => field.label === '@timestamp')).toBeUndefined(); - expect(aggregateableFields?.find((field) => field.label === '_id')).toBeUndefined(); + expect(aggregateableFields!.find((field) => field.label === '@timestamp')).toBeUndefined(); + expect(aggregateableFields!.find((field) => field.label === '_id')).toBeUndefined(); }); it('returns only Lens compatible fields (check if it is a nested field)', () => { @@ -162,7 +162,7 @@ describe('hooks', () => { const { result, unmount } = renderHook(() => useStackByFields(useLensCompatibleFields), { wrapper, }); - const aggregateableFields = result.current; + const aggregateableFields = result.current(); unmount(); expect(aggregateableFields).toHaveLength(0); }); diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/common/hooks.ts b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/common/hooks.ts index 86c8719053c81..9dbace9881c25 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/common/hooks.ts +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/common/hooks.ts @@ -5,12 +5,14 @@ * 2.0. */ -import { useEffect, useState, useMemo } from 'react'; +import { useCallback, useEffect } from 'react'; import { useLocation } from 'react-router-dom'; import type { EuiComboBoxOptionOption } from '@elastic/eui'; import type { IFieldSubTypeNested } from '@kbn/es-query'; import type { BrowserField } from '@kbn/timelines-plugin/common'; +import { i18n } from '@kbn/i18n'; +import { useAppToasts } from '../../../../common/hooks/use_app_toasts'; import type { GlobalTimeArgs } from '../../../../common/containers/use_global_time'; import { getScopeFromPath, useSourcererDataView } from '../../../../common/containers/sourcerer'; import { getAllFieldsByName } from '../../../../common/containers/source'; @@ -95,14 +97,22 @@ export function getAggregatableFields( export const useStackByFields = (useLensCompatibleFields?: boolean) => { const { pathname } = useLocation(); - + const { addError } = useAppToasts(); const { browserFields } = useSourcererDataView(getScopeFromPath(pathname)); - const allFields = useMemo(() => getAllFieldsByName(browserFields), [browserFields]); - const [stackByFieldOptions, setStackByFieldOptions] = useState(() => - getAggregatableFields(allFields, useLensCompatibleFields) - ); - useEffect(() => { - setStackByFieldOptions(getAggregatableFields(allFields, useLensCompatibleFields)); - }, [allFields, useLensCompatibleFields]); - return useMemo(() => stackByFieldOptions, [stackByFieldOptions]); + + return useCallback(() => { + try { + return getAggregatableFields(getAllFieldsByName(browserFields), useLensCompatibleFields); + } catch (err) { + addError(err, { + title: i18n.translate('xpack.securitySolution.useStackByFields.error.title', { + defaultMessage: 'Error fetching fields', + }), + toastMessage: i18n.translate('xpack.securitySolution.useStackByFields.error.toastMessage', { + defaultMessage: 'This error indicates an exceedingly large number of fields in an index', + }), + }); + return []; + } + }, [addError, browserFields, useLensCompatibleFields]); };