From 5b17da98c227b34f36acaa6a739b9672ae6b50ba Mon Sep 17 00:00:00 2001 From: Michael Olorunnisola Date: Mon, 14 Jul 2025 21:41:03 -0400 Subject: [PATCH 1/4] [Investigations][DataViews] - Remove non-performant toSpec usage (#225726) ## Summary This PR looks to improve the performance of the application by using `DataView` in place of `DataViewSpec`. The currently used `DataViewSpec` turns out to not be performant at scale because it lacks caching, and performs quite a few nested iterations in the [DataView.toSpec](https://github.com/elastic/kibana/blob/27183690142a5590b4ad72d060c43cad869f3f3c/src/platform/plugins/shared/data_views/common/data_views/data_view.ts#L147) call as seen [here](https://github.com/elastic/kibana/blob/27183690142a5590b4ad72d060c43cad869f3f3c/src/platform/plugins/shared/data_views/common/data_views/abstract_data_views.ts#L391-L422), [here](https://github.com/elastic/kibana/blob/27183690142a5590b4ad72d060c43cad869f3f3c/src/platform/plugins/shared/data_views/common/fields/field_list.ts#L157-L159), and finally [here](https://github.com/elastic/kibana/blob/27183690142a5590b4ad72d060c43cad869f3f3c/src/platform/plugins/shared/data_views/common/fields/data_view_field.ts#L438-L440). While this may not be a significant issue at a few thousand fields, this does not scale well as the number of fields reaches the tens/hundreds of thousands. This PR makes the change to rely on the DataView instance directly, which is cached in memory. These performance impacts aren't seen currently as the new framework is currently disabled behind the below feature flag. ** Relevant configurations ** `xpack.securitySolution.enableExperimental: ['newDataViewPickerEnabled']` --------- Co-authored-by: PhilippeOberti (cherry picked from commit 6294df62575ad73f5feb5a20142b5e1fc49c3dbe) # Conflicts: # x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/index.tsx # x-pack/solutions/security/plugins/security_solution/public/dashboards/pages/details/index.tsx # x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx # x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/additional_toolbar_controls.tsx # x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/index.tsx # x-pack/solutions/security/plugins/security_solution/public/detections/pages/alerts/detection_engine.tsx # x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/risk_score_management/risk_score_preview_section.tsx # x-pack/solutions/security/plugins/security_solution/public/entity_analytics/components/top_risk_score_contributors_alerts/index.tsx # x-pack/solutions/security/plugins/security_solution/public/entity_analytics/pages/entity_analytics_privileged_user_monitoring_page.tsx # x-pack/solutions/security/plugins/security_solution/public/explore/hosts/pages/details/index.tsx # x-pack/solutions/security/plugins/security_solution/public/explore/hosts/pages/hosts.tsx # x-pack/solutions/security/plugins/security_solution/public/explore/network/pages/network.tsx # x-pack/solutions/security/plugins/security_solution/public/explore/users/pages/details/index.tsx --- .../top_values_popover/top_values_popover.tsx | 8 ++-- .../assistant/send_to_timeline/index.tsx | 4 +- .../public/attack_discovery/pages/index.tsx | 14 ++---- .../schedule/create_flyout/index.tsx | 7 ++- .../schedule/details_flyout/index.tsx | 13 +++-- .../schedule/utils/convert_form_data.test.ts | 4 +- .../schedule/utils/convert_form_data.ts | 6 ++- .../common/components/cell_actions/index.tsx | 6 +-- .../common/components/events_viewer/index.tsx | 35 +++++++++----- .../markdown_editor/plugins/insight/index.tsx | 17 ++++--- .../plugins/insight/use_insight_query.ts | 20 +++++--- .../common/components/top_n/index.test.tsx | 4 +- .../public/common/components/top_n/index.tsx | 8 +++- .../common/components/top_n/top_n.test.tsx | 6 ++- .../public/common/components/top_n/top_n.tsx | 5 +- .../use_lens_attributes.tsx | 6 +-- .../public/common/lib/kuery/index.test.ts | 5 +- .../public/common/lib/kuery/index.ts | 26 +++++++--- .../public/dashboards/pages/details/index.tsx | 12 ++--- .../execution_log_table.tsx | 20 +++++--- .../pages/rule_details/index.tsx | 14 +++--- .../components/alert_summary/table/table.tsx | 3 +- .../alert_summary/table/table_section.tsx | 3 +- .../additional_toolbar_controls.tsx | 17 +++---- .../alerts_table/alerts_grouping.tsx | 47 +++++++++++++++---- .../alerts_table/alerts_sub_grouping.tsx | 16 ++++--- .../components/alerts_table/index.tsx | 30 ++++++++---- .../use_add_bulk_to_timeline.tsx | 32 ++++++++----- .../detection_engine_filters.test.tsx | 4 +- .../detection_engine_filters.tsx | 6 +-- .../rules/use_rule_from_timeline.tsx | 4 +- .../use_cell_actions.tsx | 6 +-- .../pages/alerts/detection_engine.tsx | 27 ++++++----- .../risk_score_preview_section.tsx | 6 +-- .../index.tsx | 13 ++--- .../pages/entity_analytics_dashboard.tsx | 12 ++--- .../hosts/pages/details/details_tabs.test.tsx | 31 ------------ .../hosts/pages/details/details_tabs.tsx | 10 +--- .../explore/hosts/pages/details/index.tsx | 24 ++++++---- .../public/explore/hosts/pages/hosts.tsx | 24 ++++++---- .../explore/network/pages/details/index.tsx | 34 ++++++++++---- .../navigation/countries_query_tab_body.tsx | 1 - .../pages/navigation/network_routes.tsx | 8 +--- .../explore/network/pages/navigation/types.ts | 4 -- .../public/explore/network/pages/network.tsx | 42 ++++++++++------- .../explore/users/pages/details/index.tsx | 31 ++++++++---- .../explore/users/pages/details/types.ts | 2 - .../public/explore/users/pages/users.tsx | 24 ++++++---- .../components/network_details.tsx | 24 +++++----- .../components/event_counts/index.test.tsx | 2 + .../components/event_counts/index.tsx | 9 +++- .../components/events_by_dataset/index.tsx | 13 +++-- .../overview/pages/detection_response.tsx | 12 ++--- .../public/overview/pages/overview.tsx | 18 +++---- .../controls/sourcerer_selection.test.tsx | 13 ++--- .../use_get_sourcerer_data_view.tsx | 6 ++- .../components/modal/header/index.tsx | 27 ++++++----- .../components/open_timeline/index.tsx | 8 ++-- .../timelines/components/timeline/index.tsx | 9 ++-- .../components/timeline/kpi/kpi_container.tsx | 24 ++++++---- .../timeline/query_bar/eql/index.tsx | 31 +++++------- .../components/timeline/query_bar/index.tsx | 28 +++++------ .../components/timeline/tabs/eql/index.tsx | 22 ++++----- .../components/timeline/tabs/esql/index.tsx | 18 +++---- .../components/timeline/tabs/pinned/index.tsx | 24 ++++++---- .../timeline/tabs/query/events_count.tsx | 14 +++++- .../components/timeline/tabs/query/index.tsx | 40 +++++++++------- 67 files changed, 592 insertions(+), 451 deletions(-) diff --git a/x-pack/solutions/security/plugins/security_solution/public/app/components/top_values_popover/top_values_popover.tsx b/x-pack/solutions/security/plugins/security_solution/public/app/components/top_values_popover/top_values_popover.tsx index 8d55928e4da35..b27f9abd0a97a 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/app/components/top_values_popover/top_values_popover.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/app/components/top_values_popover/top_values_popover.tsx @@ -14,7 +14,7 @@ import { StatefulTopN } from '../../../common/components/top_n'; import { getScopeFromPath } from '../../../sourcerer/containers/sourcerer_paths'; import { useSourcererDataView } from '../../../sourcerer/containers'; import { useKibana } from '../../../common/lib/kibana'; -import { useDataViewSpec } from '../../../data_view_manager/hooks/use_data_view_spec'; +import { useDataView } from '../../../data_view_manager/hooks/use_data_view'; import { useBrowserFields } from '../../../data_view_manager/hooks/use_browser_fields'; export const TopValuesPopover = React.memo(() => { @@ -25,10 +25,9 @@ export const TopValuesPopover = React.memo(() => { const newDataViewPickerEnabled = useIsExperimentalFeatureEnabled('newDataViewPickerEnabled'); - const { dataViewSpec } = useDataViewSpec(sourcererScope); + const { dataView: experimentalDataView } = useDataView(sourcererScope); const experimentalBrowserFields = useBrowserFields(sourcererScope); - const sourcererDataView = newDataViewPickerEnabled ? dataViewSpec : oldSourcererDataView; const browserFields = newDataViewPickerEnabled ? experimentalBrowserFields : oldBrowserFields; const { @@ -57,7 +56,8 @@ export const TopValuesPopover = React.memo(() => { field={data.fieldName} scopeId={data.scopeId} toggleTopN={onClose} - dataViewSpec={sourcererDataView} + dataView={experimentalDataView} + dataViewSpec={oldSourcererDataView} browserFields={browserFields} /> 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 4c906bb93154d..432c93b6a7d2b 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 @@ -67,10 +67,10 @@ export const SendToTimelineButton: FC { const pageTitle = useMemo(() => , []); const { sourcererDataView: oldSourcererDataView } = useSourcererDataView(); - - const newDataViewPickerEnabled = useIsExperimentalFeatureEnabled('newDataViewPickerEnabled'); - const { dataViewSpec } = useDataViewSpec(); - - const sourcererDataView = newDataViewPickerEnabled ? dataViewSpec : oldSourcererDataView; + const { dataView: experimentalDataView } = useDataView(); // filterQuery is the combined search bar query and filters in ES format: const [filterQuery, kqlError] = useMemo( () => convertToBuildEsQuery({ config: getEsQueryConfig(uiSettings), - dataViewSpec: sourcererDataView, + dataViewSpec: oldSourcererDataView, + dataView: experimentalDataView, queries: [query ?? getDefaultQuery()], // <-- search bar query filters: filters ?? [], // <-- search bar filters }), - [filters, sourcererDataView, query, uiSettings] + [experimentalDataView, filters, oldSourcererDataView, query, uiSettings] ); // renders a toast if the filter query is invalid: diff --git a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/settings_flyout/schedule/create_flyout/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/settings_flyout/schedule/create_flyout/index.tsx index 1fe95ff8f04dc..be00e1a3caed7 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/settings_flyout/schedule/create_flyout/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/settings_flyout/schedule/create_flyout/index.tsx @@ -17,6 +17,8 @@ import { } from '@elastic/eui'; import { useAssistantContext, useLoadConnectors } from '@kbn/elastic-assistant'; +import { DataViewManagerScopeName } from '../../../../../data_view_manager/constants'; +import { useDataView } from '../../../../../data_view_manager/hooks/use_data_view'; import { useKibana } from '../../../../../common/lib/kibana'; import { useSourcererDataView } from '../../../../../sourcerer/containers'; import { Footer } from '../../footer'; @@ -46,6 +48,7 @@ export const CreateFlyout: React.FC = React.memo(({ onClose }) => { }); const { sourcererDataView } = useSourcererDataView(); + const { dataView: experimentalDataView } = useDataView(DataViewManagerScopeName.detections); const { mutateAsync: createAttackDiscoverySchedule, isLoading: isLoadingQuery } = useCreateAttackDiscoverySchedule(); @@ -63,7 +66,8 @@ export const CreateFlyout: React.FC = React.memo(({ onClose }) => { alertsIndexPattern ?? '', connector, sourcererDataView, - uiSettings + uiSettings, + experimentalDataView ); await createAttackDiscoverySchedule({ scheduleToCreate }); onClose(); @@ -75,6 +79,7 @@ export const CreateFlyout: React.FC = React.memo(({ onClose }) => { aiConnectors, alertsIndexPattern, createAttackDiscoverySchedule, + experimentalDataView, onClose, sourcererDataView, uiSettings, diff --git a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/settings_flyout/schedule/details_flyout/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/settings_flyout/schedule/details_flyout/index.tsx index f97d5df36f1c3..d16e56c1fda9c 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/settings_flyout/schedule/details_flyout/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/settings_flyout/schedule/details_flyout/index.tsx @@ -24,6 +24,7 @@ import { useAssistantContext, useLoadConnectors } from '@kbn/elastic-assistant'; import { DEFAULT_END, DEFAULT_START } from '@kbn/elastic-assistant-common'; import type { Filter } from '@kbn/es-query'; +import { useDataView } from '../../../../../data_view_manager/hooks/use_data_view'; import * as i18n from './translations'; import { useKibana } from '../../../../../common/lib/kibana'; @@ -39,6 +40,7 @@ import { ScheduleDefinition } from './definition'; import { Header } from './header'; import { ScheduleExecutionLogs } from './execution_logs'; import { convertFormDataInBaseSchedule } from '../utils/convert_form_data'; +import { DataViewManagerScopeName } from '../../../../../data_view_manager/constants'; interface Props { scheduleId: string; @@ -65,6 +67,7 @@ export const DetailsFlyout: React.FC = React.memo(({ scheduleId, onClose }); const { sourcererDataView } = useSourcererDataView(); + const { dataView: experimentalDataView } = useDataView(DataViewManagerScopeName.detections); const [isEditing, setIsEditing] = useState(false); @@ -84,7 +87,8 @@ export const DetailsFlyout: React.FC = React.memo(({ scheduleId, onClose alertsIndexPattern ?? '', connector, sourcererDataView, - uiSettings + uiSettings, + experimentalDataView ); await updateAttackDiscoverySchedule({ id: scheduleId, scheduleToUpdate }); setIsEditing(false); @@ -94,11 +98,12 @@ export const DetailsFlyout: React.FC = React.memo(({ scheduleId, onClose }, [ aiConnectors, - uiSettings, - sourcererDataView, - scheduleId, alertsIndexPattern, + sourcererDataView, + uiSettings, + experimentalDataView, updateAttackDiscoverySchedule, + scheduleId, ] ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/settings_flyout/schedule/utils/convert_form_data.test.ts b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/settings_flyout/schedule/utils/convert_form_data.test.ts index 7b3e62fca8fc4..6f15fe55b695f 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/settings_flyout/schedule/utils/convert_form_data.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/settings_flyout/schedule/utils/convert_form_data.test.ts @@ -13,6 +13,7 @@ import { convertFormDataInBaseSchedule } from './convert_form_data'; import { convertToBuildEsQuery } from '../../../../../common/lib/kuery'; import { getGenAiConfig } from '../../../use_attack_discovery/helpers'; import { parseFilterQuery } from '../../parse_filter_query'; +import { createStubDataView } from '@kbn/data-views-plugin/common/data_views/data_view.stub'; jest.mock('../../../../../common/lib/kuery'); jest.mock('../../../use_attack_discovery/helpers'); @@ -50,7 +51,8 @@ describe('convertFormDataInBaseSchedule', () => { {} as DataViewSpec, { get: jest.fn(), - } as unknown as IUiSettingsClient + } as unknown as IUiSettingsClient, + createStubDataView({ spec: {} }) ); expect(baseSchedule).toEqual({ actions: [], diff --git a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/settings_flyout/schedule/utils/convert_form_data.ts b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/settings_flyout/schedule/utils/convert_form_data.ts index 7d54801b6478b..7ba7b547920ae 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/settings_flyout/schedule/utils/convert_form_data.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/attack_discovery/pages/settings_flyout/schedule/utils/convert_form_data.ts @@ -6,7 +6,7 @@ */ import type { IUiSettingsClient } from '@kbn/core/public'; -import type { DataViewSpec } from '@kbn/data-plugin/common'; +import type { DataView, DataViewSpec } from '@kbn/data-plugin/common'; import { getEsQueryConfig } from '@kbn/data-plugin/common'; import type { AIConnector } from '@kbn/elastic-assistant'; @@ -20,13 +20,15 @@ export const convertFormDataInBaseSchedule = ( alertsIndexPattern: string, connector: AIConnector, dataViewSpec: DataViewSpec, - uiSettings: IUiSettingsClient + uiSettings: IUiSettingsClient, + dataView: DataView ) => { const alertsSelectionSettings = scheduleData.alertsSelectionSettings; const [filterQuery, kqlError] = convertToBuildEsQuery({ config: getEsQueryConfig(uiSettings), dataViewSpec, + dataView, queries: [alertsSelectionSettings.query], filters: alertsSelectionSettings.filters, }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/cell_actions/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/cell_actions/index.tsx index 51ee44c081886..878fab09ebab5 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/cell_actions/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/cell_actions/index.tsx @@ -71,7 +71,7 @@ export const SecurityCellActions: React.FC = ({ const newDataViewPickerEnabled = useIsExperimentalFeatureEnabled('newDataViewPickerEnabled'); const { dataView: experimentalDataView } = useDataView(sourcererScopeId); - const dataViewId = newDataViewPickerEnabled ? experimentalDataView?.id : oldDataViewId; + const dataViewId = newDataViewPickerEnabled ? experimentalDataView.id : oldDataViewId; // Make a dependency key to prevent unnecessary re-renders when data object is defined inline // It is necessary because the data object is an array or an object and useMemo would always re-render @@ -82,13 +82,13 @@ export const SecurityCellActions: React.FC = ({ (Array.isArray(data) ? data : [data]) .map(({ field, value }) => ({ field: newDataViewPickerEnabled - ? experimentalDataView?.fields?.getByName(field)?.toSpec() + ? experimentalDataView.fields?.getByName(field)?.toSpec() : oldGetFieldSpec(field), value, })) .filter((item): item is CellActionsData => !!item.field), // eslint-disable-next-line react-hooks/exhaustive-deps -- Use the dependencyKey to prevent unnecessary re-renders - [dependencyKey, oldGetFieldSpec, newDataViewPickerEnabled, experimentalDataView?.fields] + [dependencyKey, oldGetFieldSpec, newDataViewPickerEnabled, experimentalDataView.fields] ); const metadataWithDataView = useMemo(() => ({ ...metadata, dataViewId }), [dataViewId, metadata]); diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/events_viewer/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/events_viewer/index.tsx index 339354f7c2d35..e9f2afee4ed14 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/events_viewer/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/events_viewer/index.tsx @@ -35,7 +35,6 @@ import { getEsQueryConfig } from '@kbn/data-plugin/common'; import type { EuiTheme } from '@kbn/kibana-react-plugin/common'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import type { RunTimeMappings } from '@kbn/timelines-plugin/common/search_strategy'; -import { useDataViewSpec } from '../../../data_view_manager/hooks/use_data_view_spec'; import { useDataView } from '../../../data_view_manager/hooks/use_data_view'; import { InspectButton } from '../inspect'; import type { @@ -160,27 +159,31 @@ const StatefulEventsViewerComponent: React.FC { + return newDataViewPickerEnabled + ? (experimentalDataView.getRuntimeMappings() as RunTimeMappings) ?? {} + : (oldSourcererDataView?.runtimeFieldMap as RunTimeMappings) ?? {}; + }, [newDataViewPickerEnabled, experimentalDataView, oldSourcererDataView]); + const experimentalGetFieldSpec = useCallback( (fieldName: string) => { - return experimentalDataView?.fields?.getByName(fieldName)?.toSpec(); + return experimentalDataView.fields?.getByName(fieldName)?.toSpec(); }, - [experimentalDataView?.fields] + [experimentalDataView.fields] ); const getFieldSpec = newDataViewPickerEnabled ? experimentalGetFieldSpec : oldGetFieldSpec; @@ -264,12 +267,22 @@ const StatefulEventsViewerComponent: React.FC([[]]); @@ -416,7 +415,7 @@ const InsightEditorComponent = ({ ); }, [labelController.field.value, providers, dataView]); const filtersStub = useMemo(() => { - const index = sourcererDataView.name ?? '*'; + const index = dataViewName ?? '*'; return [ { $state: { @@ -430,7 +429,7 @@ const InsightEditorComponent = ({ }, }, ]; - }, [sourcererDataView]); + }, [dataViewName]); const isPlatinum = useLicense().isAtLeast('platinum'); return ( @@ -496,11 +495,11 @@ const InsightEditorComponent = ({ /> - {oldDataView ? ( + {dataView ? ( ) : ( diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/markdown_editor/plugins/insight/use_insight_query.ts b/x-pack/solutions/security/plugins/security_solution/public/common/components/markdown_editor/plugins/insight/use_insight_query.ts index aa2a64729f93e..6c4bb236794b1 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/markdown_editor/plugins/insight/use_insight_query.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/markdown_editor/plugins/insight/use_insight_query.ts @@ -18,7 +18,7 @@ import { useTimelineEvents } from '../../../../../timelines/containers'; import { useSourcererDataView } from '../../../../../sourcerer/containers'; import { SourcererScopeName } from '../../../../../sourcerer/store/model'; import type { TimeRange } from '../../../../store/inputs/model'; -import { useDataViewSpec } from '../../../../../data_view_manager/hooks/use_data_view_spec'; +import { useDataView } from '../../../../../data_view_manager/hooks/use_data_view'; import { useSelectedPatterns } from '../../../../../data_view_manager/hooks/use_selected_patterns'; import { useBrowserFields } from '../../../../../data_view_manager/hooks/use_browser_fields'; @@ -54,16 +54,15 @@ export const useInsightQuery = ({ const newDataViewPickerEnabled = useIsExperimentalFeatureEnabled('newDataViewPickerEnabled'); - const { dataViewSpec } = useDataViewSpec(SourcererScopeName.timeline); + const { dataView: experimentalDataView } = useDataView(SourcererScopeName.timeline); const experimentalSelectedPatterns = useSelectedPatterns(SourcererScopeName.timeline); const experimentalBrowserFields = useBrowserFields(SourcererScopeName.timeline); - const sourcererDataView = newDataViewPickerEnabled ? dataViewSpec : oldSourcererDataView; const selectedPatterns = newDataViewPickerEnabled ? experimentalSelectedPatterns : oldSelectedPatterns; const browserFields = newDataViewPickerEnabled ? experimentalBrowserFields : oldBrowserFields; - const dataViewId = newDataViewPickerEnabled ? dataViewSpec?.id ?? '' : oldDataViewId; + const dataViewId = newDataViewPickerEnabled ? experimentalDataView.id ?? '' : oldDataViewId; const [hasError, setHasError] = useState(false); const combinedQueries = useMemo(() => { @@ -72,7 +71,8 @@ export const useInsightQuery = ({ const parsedCombinedQueries = combineQueries({ config: esQueryConfig, dataProviders, - dataViewSpec: sourcererDataView, + dataViewSpec: oldSourcererDataView, + dataView: experimentalDataView, browserFields, filters, kqlQuery: { @@ -87,7 +87,15 @@ export const useInsightQuery = ({ setHasError(true); return null; } - }, [browserFields, dataProviders, esQueryConfig, hasError, sourcererDataView, filters]); + }, [ + hasError, + esQueryConfig, + dataProviders, + oldSourcererDataView, + experimentalDataView, + browserFields, + filters, + ]); const [dataLoadingState, { events, totalCount }] = useTimelineEvents({ dataViewId, diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/top_n/index.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/top_n/index.test.tsx index c680ae5a87dfe..5b60f954693df 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/top_n/index.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/top_n/index.test.tsx @@ -11,11 +11,12 @@ import { TableId } from '@kbn/securitysolution-data-table'; import { TimelineId } from '../../../../common/types/timeline'; import { mockBrowserFields } from '../../containers/source/mock'; -import { mockGlobalState, TestProviders, createMockStore, mockDataViewSpec } from '../../mock'; +import { createMockStore, mockDataViewSpec, mockGlobalState, TestProviders } from '../../mock'; import type { State } from '../../store'; import { TopN } from './top_n'; import { detectionAlertsTables } from './helpers'; import { StatefulTopN } from '.'; +import { createStubDataView } from '@kbn/data-views-plugin/common/data_views/data_view.stub'; jest.mock('react-router-dom', () => { const original = jest.requireActual('react-router-dom'); @@ -152,6 +153,7 @@ const store = createMockStore(state); const testProps = { browserFields: mockBrowserFields, + dataView: createStubDataView({ spec: {} }), field, indexPattern: mockDataViewSpec, scopeId: TableId.hostsPageEvents, diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/top_n/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/top_n/index.tsx index 7cf729e3bc457..371bcdc83b807 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/top_n/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/top_n/index.tsx @@ -10,7 +10,7 @@ import type { ConnectedProps } from 'react-redux'; import { connect } from 'react-redux'; import type { Filter, Query } from '@kbn/es-query'; -import { type DataViewSpec, getEsQueryConfig } from '@kbn/data-plugin/common'; +import { type DataView, type DataViewSpec, getEsQueryConfig } from '@kbn/data-plugin/common'; import { isActiveTimeline } from '../../../helpers'; import { InputsModelId } from '../../store/inputs/constants'; import { useGlobalTime } from '../../containers/use_global_time'; @@ -78,12 +78,14 @@ export interface OwnProps { browserFields: BrowserFields; field: string; dataViewSpec?: DataViewSpec; + dataView: DataView; scopeId?: string; toggleTopN: () => void; onFilterAdded?: () => void; paddingSize?: 's' | 'm' | 'l' | 'none'; globalFilters?: Filter[]; } + type PropsFromRedux = ConnectedProps; type Props = OwnProps & PropsFromRedux; @@ -97,6 +99,7 @@ const StatefulTopNComponent: React.FC = ({ dataProviders, field, dataViewSpec, + dataView, globalFilters = EMPTY_FILTERS, globalQuery = EMPTY_QUERY, kqlMode, @@ -120,6 +123,7 @@ const StatefulTopNComponent: React.FC = ({ dataProviders, filters: activeTimelineFilters, dataViewSpec, + dataView, kqlMode, kqlQuery: { language: 'kuery', @@ -134,6 +138,7 @@ const StatefulTopNComponent: React.FC = ({ dataProviders, activeTimelineFilters, dataViewSpec, + dataView, kqlMode, activeTimelineKqlQueryExpression, ] @@ -152,6 +157,7 @@ const StatefulTopNComponent: React.FC = ({ field={field as AlertsStackByField} filters={isActiveTimeline(scopeId ?? '') ? EMPTY_FILTERS : globalFilters} from={isActiveTimeline(scopeId ?? '') ? activeTimelineFrom : from} + dataView={dataView} dataViewSpec={dataViewSpec} options={options} paddingSize={paddingSize} diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/top_n/top_n.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/top_n/top_n.test.tsx index 949786a08da0a..08864ebd19fa1 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/top_n/top_n.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/top_n/top_n.test.tsx @@ -6,14 +6,15 @@ */ import React from 'react'; -import { screen, render, waitFor, fireEvent } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; -import { TestProviders, mockDataViewSpec } from '../../mock'; +import { mockDataViewSpec, TestProviders } from '../../mock'; import { allEvents, defaultOptions } from './helpers'; import type { Props as TopNProps } from './top_n'; import { TopN } from './top_n'; import { InputsModelId } from '../../store/inputs/constants'; +import { createStubDataView } from '@kbn/data-views-plugin/common/data_views/data_view.stub'; jest.mock('../visualization_actions/visualization_embeddable'); @@ -105,6 +106,7 @@ describe('TopN', () => { field, filters: [], from: '2020-04-14T00:31:47.695Z', + dataView: createStubDataView({ spec: {} }), dataViewSpec: mockDataViewSpec, options: defaultOptions, query, diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/top_n/top_n.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/top_n/top_n.tsx index 861d1f4a408b3..4f82fbd0a1d93 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/top_n/top_n.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/top_n/top_n.tsx @@ -10,7 +10,7 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { css } from '@emotion/react'; import type { Filter, Query } from '@kbn/es-query'; -import type { DataViewSpec } from '@kbn/data-plugin/common'; +import type { DataView, DataViewSpec } from '@kbn/data-plugin/common'; import type { GlobalTimeArgs } from '../../containers/use_global_time'; import { EventsByDataset } from '../../../overview/components/events_by_dataset'; import { SignalsByCategory } from '../../../overview/components/signals_by_category'; @@ -52,6 +52,7 @@ export interface Props extends Pick = ({ filters, field, from, + dataView, dataViewSpec, options, paddingSize, @@ -123,6 +125,7 @@ const TopNComponent: React.FC = ({ filters={applicableFilters} from={from} headerChildren={headerChildren} + dataView={dataView} dataViewSpec={dataViewSpec} onlyField={field} paddingSize={paddingSize} diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/use_lens_attributes.tsx b/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/use_lens_attributes.tsx index 21beea2c1cfda..41f5b974ce6d5 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/use_lens_attributes.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/common/components/visualization_actions/use_lens_attributes.tsx @@ -45,12 +45,12 @@ export const useLensAttributes = ({ const newDataViewPickerEnabled = useIsExperimentalFeatureEnabled('newDataViewPickerEnabled'); - const { dataView } = useDataView(scopeId); + const { dataView: experimentalDataView } = useDataView(scopeId); const experimentalSelectedPatterns = useSelectedPatterns(scopeId); - const dataViewId = newDataViewPickerEnabled ? dataView?.id ?? '' : oldDataViewId; + const dataViewId = newDataViewPickerEnabled ? experimentalDataView.id ?? '' : oldDataViewId; const indicesExist = newDataViewPickerEnabled - ? !!dataView?.matchedIndices?.length + ? !!experimentalDataView.matchedIndices?.length : oldIndicesExist; const selectedPatterns = newDataViewPickerEnabled ? experimentalSelectedPatterns diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/lib/kuery/index.test.ts b/x-pack/solutions/security/plugins/security_solution/public/common/lib/kuery/index.test.ts index 98c59d415d447..22f32fc1e10a1 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/lib/kuery/index.test.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/common/lib/kuery/index.test.ts @@ -7,8 +7,9 @@ import expect from '@kbn/expect'; import type { DataProvider } from '../../../../common/types/timeline'; -import { convertToBuildEsQuery, buildGlobalQuery } from '.'; +import { buildGlobalQuery, convertToBuildEsQuery } from '.'; import { mockDataViewSpec } from '../../mock'; +import { createStubDataView } from '@kbn/data-views-plugin/common/data_views/data_view.stub'; describe('convertToBuildEsQuery', () => { /** @@ -60,6 +61,7 @@ describe('convertToBuildEsQuery', () => { it('should, by default, build a query where the `nested` fields syntax includes the `"ignore_unmapped":true` option', () => { const [converted, _] = convertToBuildEsQuery({ config, + dataView: createStubDataView({ spec: {} }), queries: queryWithNestedFields, dataViewSpec: mockDataViewSpec, filters, @@ -175,6 +177,7 @@ describe('convertToBuildEsQuery', () => { const [converted, _] = convertToBuildEsQuery({ config: configWithOverride, + dataView: createStubDataView({ spec: {} }), queries: queryWithNestedFields, dataViewSpec: mockDataViewSpec, filters, diff --git a/x-pack/solutions/security/plugins/security_solution/public/common/lib/kuery/index.ts b/x-pack/solutions/security/plugins/security_solution/public/common/lib/kuery/index.ts index ac66e8f051b2e..ecc90b7f13985 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/common/lib/kuery/index.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/common/lib/kuery/index.ts @@ -5,16 +5,16 @@ * 2.0. */ -import type { Filter, EsQueryConfig, Query, DataViewBase } from '@kbn/es-query'; +import type { DataViewBase, EsQueryConfig, Filter, Query } from '@kbn/es-query'; import { + buildEsQuery, + FilterStateStore, fromKueryExpression, toElasticsearchQuery, - FilterStateStore, - buildEsQuery, } from '@kbn/es-query'; import { get, isEmpty } from 'lodash/fp'; import memoizeOne from 'memoize-one'; -import type { DataViewSpec } from '@kbn/data-plugin/common'; +import type { DataView, DataViewSpec } from '@kbn/data-plugin/common'; import { prepareKQLParam } from '../../../../common/utils/kql'; import type { BrowserFields } from '../../../../common/search_strategy'; import type { DataProvider, DataProvidersAnd } from '../../../../common/types'; @@ -30,7 +30,11 @@ export type PrimitiveOrArrayOfPrimitives = export interface CombineQueries { config: EsQueryConfig; dataProviders: DataProvider[]; + /** + * @deprecated Use `dataView` instead. Which accepts a DataView instance instead of a DataViewSpec. + */ dataViewSpec?: DataViewSpec; + dataView: DataView; browserFields: BrowserFields; filters: Filter[]; kqlQuery: Query; @@ -206,12 +210,17 @@ export const dataViewSpecToViewBase = (dataViewSpec?: DataViewSpec): DataViewBas export const convertToBuildEsQuery = ({ config, - dataViewSpec, + dataView, // New dataview prepended with feature flag to enable easy cleanup + dataViewSpec, // Account for the case where sourcerer is active, but this can just use dataView queries, filters, }: { config: EsQueryConfig; - dataViewSpec: DataViewSpec | undefined; + dataView: DataView; + /** + * @deprecated Use `dataView` instead. Which accepts a DataView instance instead of a DataViewSpec. + */ + dataViewSpec?: DataViewSpec; // Ignored but kept for type compatibility queries: Query[]; filters: Filter[]; }): [string, undefined] | [undefined, Error] => { @@ -219,7 +228,7 @@ export const convertToBuildEsQuery = ({ return [ JSON.stringify( buildEsQuery( - dataViewSpecToViewBase(dataViewSpec), + dataView ?? (dataViewSpecToViewBase(dataViewSpec) as DataView), queries, filters.filter((f) => f.meta.disabled === false), { @@ -246,6 +255,7 @@ export const combineQueries = ({ config, dataProviders = [], dataViewSpec, + dataView, browserFields, filters = [], kqlQuery, @@ -259,6 +269,7 @@ export const combineQueries = ({ config, queries: [kuery], dataViewSpec, + dataView, filters, }); @@ -287,6 +298,7 @@ export const combineQueries = ({ config, queries: [kuery], dataViewSpec, + dataView, filters, }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/dashboards/pages/details/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/dashboards/pages/details/index.tsx index c8df8c2b08e20..391c9bd93c847 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/dashboards/pages/details/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/dashboards/pages/details/index.tsx @@ -13,7 +13,6 @@ import { useParams } from 'react-router-dom'; import { pick } from 'lodash/fp'; import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import type { ViewMode } from '@kbn/presentation-publishing'; -import { useIsExperimentalFeatureEnabled } from '../../../common/hooks/use_experimental_features'; import { SecurityPageName } from '../../../../common/constants'; import { SpyRoute } from '../../../common/utils/route/spy_routes'; import { useCapabilities } from '../../../common/lib/kibana'; @@ -32,7 +31,6 @@ import { DashboardToolBar } from '../../components/dashboard_tool_bar'; import { useDashboardRenderer } from '../../hooks/use_dashboard_renderer'; import { DashboardTitle } from '../../components/dashboard_title'; -import { useDataViewSpec } from '../../../data_view_manager/hooks/use_data_view_spec'; const dashboardViewFlexGroupStyle = { minHeight: `calc(100vh - 140px)` }; @@ -56,11 +54,6 @@ const DashboardViewComponent: React.FC = ({ const filters = useDeepEqualSelector(getGlobalFiltersQuerySelector); const { sourcererDataView: oldSourcererDataView } = useSourcererDataView(); - const newDataViewPickerEnabled = useIsExperimentalFeatureEnabled('newDataViewPickerEnabled'); - const { dataViewSpec } = useDataViewSpec(); - - const sourcererDataView = newDataViewPickerEnabled ? dataViewSpec : oldSourcererDataView; - const { show: canReadDashboard } = useCapabilities(LEGACY_DASHBOARD_APP_ID); const errorState = useMemo( @@ -79,7 +72,10 @@ const DashboardViewComponent: React.FC = ({ return ( <> - + = ({ ); const newDataViewPickerEnabled = useIsExperimentalFeatureEnabled('newDataViewPickerEnabled'); - const { dataViewSpec } = useDataViewSpec(SourcererScopeName.detections); - const sourcererDataView = newDataViewPickerEnabled ? dataViewSpec : oldSourcererDataView; + const { dataView: experimentalDataView } = useDataView(SourcererScopeName.detections); const { addError, addSuccess, remove } = useAppToasts(); @@ -244,8 +243,11 @@ const ExecutionLogTableComponent: React.FC = ({ // Cache UUID field from data view as it can be expensive to iterate all data view fields const uuidDataViewField = useMemo( - () => sourcererDataView.fields?.[EXECUTION_UUID_FIELD_NAME], - [sourcererDataView] + () => + newDataViewPickerEnabled + ? experimentalDataView.fields?.getByName(EXECUTION_UUID_FIELD_NAME) + : oldSourcererDataView.fields?.[EXECUTION_UUID_FIELD_NAME], + [experimentalDataView.fields, newDataViewPickerEnabled, oldSourcererDataView.fields] ); // Callbacks @@ -311,7 +313,9 @@ const ExecutionLogTableComponent: React.FC = ({ const onFilterByExecutionIdCallback = useCallback( (executionId: string, executionStart: string) => { - const dataViewAsViewBase = dataViewSpecToViewBase(sourcererDataView); + const dataViewAsViewBase = newDataViewPickerEnabled + ? experimentalDataView + : dataViewSpecToViewBase(oldSourcererDataView); if ( uuidDataViewField != null && @@ -368,11 +372,13 @@ const ExecutionLogTableComponent: React.FC = ({ } }, [ + newDataViewPickerEnabled, + experimentalDataView, + oldSourcererDataView, uuidDataViewField, filters, query, timerange, - sourcererDataView, dispatch, filterManager, selectAlertsTab, diff --git a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx index 95954745ccecc..87963165b7cb1 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx @@ -43,7 +43,7 @@ import { usePrebuiltRuleBaseVersionContext, } from '../../../rule_management/components/rule_details/base_version_diff/base_version_context'; import { useGroupTakeActionsItems } from '../../../../detections/hooks/alerts_table/use_group_take_action_items'; -import { useDataViewSpec } from '../../../../data_view_manager/hooks/use_data_view_spec'; +import { useDataView } from '../../../../data_view_manager/hooks/use_data_view'; import { defaultGroupStatsAggregations, defaultGroupStatsRenderer, @@ -265,14 +265,11 @@ const RuleDetailsPageComponent: React.FC = ({ const { loading: listsConfigLoading, needsConfiguration: needsListsConfiguration } = useListsConfig(); - const { sourcererDataView: oldSourcererDataView, loading: oldIsLoadingIndexPattern } = + const { sourcererDataView: oldSourcererDataViewSpec, loading: oldIsLoadingIndexPattern } = useSourcererDataView(SourcererScopeName.detections); const newDataViewPickerEnabled = useIsExperimentalFeatureEnabled('newDataViewPickerEnabled'); - - const { dataViewSpec, status } = useDataViewSpec(SourcererScopeName.detections); - - const sourcererDataViewSpec = newDataViewPickerEnabled ? dataViewSpec : oldSourcererDataView; + const { dataView: experimentalDataView, status } = useDataView(SourcererScopeName.detections); const isLoadingIndexPattern = newDataViewPickerEnabled ? status !== 'ready' : oldIsLoadingIndexPattern; @@ -648,7 +645,7 @@ const RuleDetailsPageComponent: React.FC = ({ @@ -819,7 +816,8 @@ const RuleDetailsPageComponent: React.FC = ({ , diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/table/table_section.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/table/table_section.tsx index da99131576e78..f19c6856553a1 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/table/table_section.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alert_summary/table/table_section.tsx @@ -88,7 +88,8 @@ export const TableSection = memo(({ dataView, packages, ruleResponse }: TableSec groupIdSelector(), []); const { options } = useDeepEqualSelector((state) => groupId(state, tableType)) ?? { @@ -80,9 +77,13 @@ const AdditionalToolbarControlsComponent = ({ [dispatch, tableType, trackGroupChange] ); - const fields = useMemo(() => { - return Object.values(sourcererDataView?.fields || {}); - }, [sourcererDataView?.fields]); + const fields = useMemo( + () => + experimentalDataView + ? experimentalDataView.fields.map((field) => field.spec) + : Object.values(oldSourcererDataView.fields || {}), + [experimentalDataView, oldSourcererDataView.fields] + ); const groupSelector = useGetGroupSelectorStateless({ groupingId: tableType, diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/alerts_grouping.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/alerts_grouping.tsx index 527c0e7de2a09..52ec16492c5b4 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/alerts_grouping.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/alerts_grouping.tsx @@ -8,7 +8,7 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { useDispatch } from 'react-redux'; import type { Filter, Query } from '@kbn/es-query'; -import type { DataViewSpec } from '@kbn/data-views-plugin/common'; +import type { DataViewSpec, DataView } from '@kbn/data-views-plugin/common'; import { type GroupOption, type GroupStatsItem, @@ -21,6 +21,7 @@ import { isEmpty, isEqual } from 'lodash/fp'; import type { Storage } from '@kbn/kibana-utils-plugin/public'; import type { TableIdLiteral } from '@kbn/securitysolution-data-table'; import type { GetGroupStats, GroupingArgs, GroupPanelRenderer } from '@kbn/grouping/src'; +import { useIsExperimentalFeatureEnabled } from '../../../common/hooks/use_experimental_features'; import type { GroupTakeActionItems } from './types'; import type { AlertsGroupingAggregation } from './grouping_settings/types'; import { groupIdSelector } from '../../../common/store/grouping/selectors'; @@ -59,6 +60,10 @@ export interface AlertsTableComponentProps { * DataViewSpec object to use internally to fetch the data */ dataViewSpec: DataViewSpec; + /** + * DataView object to use internally to fetch the data. + */ + dataView?: DataView; defaultFilters?: Filter[]; /** * Default values to display in the group selection dropdown. @@ -135,7 +140,7 @@ const useStorage = (storage: Storage, tableId: string) => const GroupedAlertsTableComponent: React.FC = (props) => { const dispatch = useDispatch(); - + const newDataViewPickerEnabled = useIsExperimentalFeatureEnabled('newDataViewPickerEnabled'); const { services: { storage, telemetry }, } = useKibana(); @@ -174,8 +179,24 @@ const GroupedAlertsTableComponent: React.FC = (props) ); const fields = useMemo( - () => Object.values(props.dataViewSpec.fields || {}), - [props.dataViewSpec] + () => + newDataViewPickerEnabled + ? props.dataView?.fields.map((field) => field.spec) || [] + : Object.values(props.dataViewSpec.fields || {}), + [newDataViewPickerEnabled, props.dataView?.fields, props.dataViewSpec.fields] + ); + + const runtimeMappings = useMemo( + () => + newDataViewPickerEnabled + ? (props.dataView?.getRuntimeMappings() as RunTimeMappings) + : (props.dataViewSpec?.runtimeFieldMap as RunTimeMappings), + [newDataViewPickerEnabled, props.dataView, props.dataViewSpec?.runtimeFieldMap] + ); + + const dataViewTitle = useMemo( + () => (newDataViewPickerEnabled ? props.dataView?.title : props.dataViewSpec.title), + [newDataViewPickerEnabled, props.dataView?.title, props.dataViewSpec.title] ); const groupingOptions = useMemo( @@ -336,18 +357,28 @@ const GroupedAlertsTableComponent: React.FC = (props) pageSize={pageSize[level] ?? DEFAULT_PAGE_SIZE} parentGroupingFilter={parentGroupingFilter} renderChildComponent={rcc} - runtimeMappings={props.dataViewSpec.runtimeFieldMap as RunTimeMappings} + runtimeMappings={runtimeMappings} selectedGroup={selectedGroup} setPageIndex={(newIndex: number) => setPageVar(newIndex, level, 'index')} setPageSize={(newSize: number) => setPageVar(newSize, level, 'size')} - signalIndexName={props.dataViewSpec.title} + signalIndexName={dataViewTitle} /> ); }, - [getGrouping, groupStatusAggregations, pageIndex, pageSize, props, selectedGroups, setPageVar] + [ + dataViewTitle, + getGrouping, + groupStatusAggregations, + pageIndex, + pageSize, + props, + runtimeMappings, + selectedGroups, + setPageVar, + ] ); - if (isEmpty(props.dataViewSpec.title)) { + if (isEmpty(dataViewTitle)) { return null; } diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/alerts_sub_grouping.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/alerts_sub_grouping.tsx index 92b813621acbf..cd4a674605172 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/alerts_sub_grouping.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/alerts_sub_grouping.tsx @@ -15,6 +15,7 @@ import { getEsQueryConfig } from '@kbn/data-plugin/common'; import type { DynamicGroupingProps } from '@kbn/grouping/src'; import { parseGroupingQuery } from '@kbn/grouping/src'; import type { TableIdLiteral } from '@kbn/securitysolution-data-table'; +import { useDataView } from '../../../data_view_manager/hooks/use_data_view'; import type { GroupTakeActionItems } from './types'; import { useIsExperimentalFeatureEnabled } from '../../../common/hooks/use_experimental_features'; import type { RunTimeMappings } from '../../../sourcerer/store/model'; @@ -33,7 +34,6 @@ import * as i18n from './translations'; import { useQueryAlerts } from '../../containers/detection_engine/alerts/use_query'; import { ALERTS_QUERY_NAMES } from '../../containers/detection_engine/alerts/constants'; import { getAlertsGroupingQuery } from './grouping_settings'; -import { useDataViewSpec } from '../../../data_view_manager/hooks/use_data_view_spec'; import { useBrowserFields } from '../../../data_view_manager/hooks/use_browser_fields'; const ALERTS_GROUPING_ID = 'alerts-grouping'; @@ -106,10 +106,10 @@ export const GroupedSubLevelComponent: React.FC = ({ const newDataViewPickerEnabled = useIsExperimentalFeatureEnabled('newDataViewPickerEnabled'); - const { dataViewSpec } = useDataViewSpec(SourcererScopeName.detections); + const { dataView: experimentalDataView } = useDataView(SourcererScopeName.detections); const experimentalBrowserFields = useBrowserFields(SourcererScopeName.detections); - const sourcererDataView = newDataViewPickerEnabled ? dataViewSpec : oldSourcererDataView; + const sourcererDataView = oldSourcererDataView; const browserFields = newDataViewPickerEnabled ? experimentalBrowserFields : oldBrowserFields; const getGlobalQuery = useCallback( @@ -119,6 +119,7 @@ export const GroupedSubLevelComponent: React.FC = ({ config: getEsQueryConfig(uiSettings), dataProviders: [], dataViewSpec: sourcererDataView, + dataView: experimentalDataView, browserFields, filters: [ ...defaultFilters, @@ -135,14 +136,15 @@ export const GroupedSubLevelComponent: React.FC = ({ }, [ browserFields, + sourcererDataView, + uiSettings, + experimentalDataView, defaultFilters, - from, globalFilters, - globalQuery, parentGroupingFilter, + from, to, - uiSettings, - sourcererDataView, + globalQuery, ] ); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/index.tsx index 1df2a4cb5fcd8..32d89a6c3a8ea 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/alerts_table/index.tsx @@ -20,7 +20,7 @@ import type { SetOptional } from 'type-fest'; import { noop } from 'lodash'; import type { Alert } from '@kbn/alerting-types'; import { AlertsTable } from '@kbn/response-ops-alerts-table'; -import { useDataViewSpec } from '../../../data_view_manager/hooks/use_data_view_spec'; +import { useDataView } from '../../../data_view_manager/hooks/use_data_view'; import { useAlertsContext } from './alerts_context'; import { useBulkActionsByTableType } from '../../hooks/trigger_actions_alert_table/use_bulk_actions'; import { useIsExperimentalFeatureEnabled } from '../../../common/hooks/use_experimental_features'; @@ -191,12 +191,16 @@ const DetectionEngineAlertsTableComponent: FC + newDataViewPickerEnabled + ? experimentalDataView.getRuntimeMappings() + : (oldSourcererDataView.runtimeFieldMap as RunTimeMappings), + [newDataViewPickerEnabled, experimentalDataView, oldSourcererDataView] + ); - const sourcererDataView = newDataViewPickerEnabled - ? experimentalDataViewSpec - : oldSourcererDataView; const browserFields = newDataViewPickerEnabled ? experimentalBrowserFields : oldBrowserFields; const license = useLicense(); @@ -228,11 +232,12 @@ const DetectionEngineAlertsTableComponent: FC { - if (browserFields != null && sourcererDataView) { + if (browserFields != null && (oldSourcererDataView || experimentalDataView)) { return combineQueries({ config: getEsQueryConfig(uiSettings), dataProviders: [], - dataViewSpec: sourcererDataView, + dataViewSpec: oldSourcererDataView, + dataView: experimentalDataView, browserFields, filters: [...allFilters], kqlQuery: globalQuery, @@ -240,7 +245,14 @@ const DetectionEngineAlertsTableComponent: FC { + return newDataViewPickerEnabled + ? (experimentalDataView.getRuntimeMappings() as RunTimeMappings) + : (oldSourcererDataViewSpec.runtimeFieldMap as RunTimeMappings); + }, [newDataViewPickerEnabled, experimentalDataView, oldSourcererDataViewSpec.runtimeFieldMap]); + const dataViewId = useMemo( - () => (newDataViewPickerEnabled ? experimentalDataViewSpec.id ?? '' : oldDataViewId), - [experimentalDataViewSpec.id, newDataViewPickerEnabled, oldDataViewId] + () => (newDataViewPickerEnabled ? experimentalDataView.id ?? '' : oldDataViewId), + [experimentalDataView.id, newDataViewPickerEnabled, oldDataViewId] ); const browserFields = useMemo( () => (newDataViewPickerEnabled ? experimentalBrowserFields : oldBrowserFields), [experimentalBrowserFields, newDataViewPickerEnabled, oldBrowserFields] ); - const dataViewSpec: DataViewSpec = useMemo( - () => (newDataViewPickerEnabled ? experimentalDataViewSpec : oldSourcererDataViewSpec), - [experimentalDataViewSpec, newDataViewPickerEnabled, oldSourcererDataViewSpec] - ); const selectedPatterns = useMemo( () => (newDataViewPickerEnabled ? experimentalSelectedPatterns : oldSelectedPatterns), [experimentalSelectedPatterns, newDataViewPickerEnabled, oldSelectedPatterns] @@ -132,13 +133,20 @@ export const useAddBulkToTimelineAction = ({ return combineQueries({ config: esQueryConfig, dataProviders: [], - dataViewSpec, + dataViewSpec: oldSourcererDataViewSpec, + dataView: experimentalDataView, filters: combinedFilters, kqlQuery: { query: '', language: 'kuery' }, browserFields, kqlMode: 'filter', }); - }, [esQueryConfig, dataViewSpec, combinedFilters, browserFields]); + }, [ + esQueryConfig, + oldSourcererDataViewSpec, + experimentalDataView, + combinedFilters, + browserFields, + ]); const filterQuery = useMemo(() => { if (!combinedQuery) return ''; @@ -156,7 +164,7 @@ export const useAddBulkToTimelineAction = ({ sort: timelineQuerySortField, indexNames: selectedPatterns, filterQuery, - runtimeMappings: dataViewSpec.runtimeFieldMap as RunTimeMappings, + runtimeMappings, limit: Math.min(BULK_ADD_TO_TIMELINE_LIMIT, totalCount), timerangeKind: 'absolute', }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/detection_engine_filters/detection_engine_filters.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/components/detection_engine_filters/detection_engine_filters.test.tsx index 427551700bf5d..3edfd3823a931 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/detection_engine_filters/detection_engine_filters.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/detection_engine_filters/detection_engine_filters.test.tsx @@ -73,7 +73,7 @@ describe('DetectionEngineFilters', () => { }, timeRange: { from: 'now-15m', to: 'now' }, onInit: jest.fn(), - dataViewSpec: { + dataView: { title: 'mock-title', fields: {}, }, @@ -99,7 +99,7 @@ describe('DetectionEngineFilters', () => { expect(container).toBeEmptyDOMElement(); }); - it('renders correctly when spaceId and dataViewSpec are defined', () => { + it('renders correctly when spaceId and dataView are defined', () => { const { container } = render(); expect(container).toBeInTheDocument(); }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/components/detection_engine_filters/detection_engine_filters.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/components/detection_engine_filters/detection_engine_filters.tsx index 57837db80eced..f8b12669986d7 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/components/detection_engine_filters/detection_engine_filters.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/components/detection_engine_filters/detection_engine_filters.tsx @@ -13,7 +13,7 @@ import type { AlertFilterControlsProps } from '@kbn/alerts-ui-shared/src/alert_f import { AlertFilterControls } from '@kbn/alerts-ui-shared/src/alert_filter_controls'; import { useHistory } from 'react-router-dom'; import { SECURITY_SOLUTION_RULE_TYPE_IDS } from '@kbn/securitysolution-rules'; -import type { DataViewSpec } from '@kbn/data-plugin/common'; +import type { DataView, DataViewSpec } from '@kbn/data-plugin/common'; import { useIsExperimentalFeatureEnabled } from '../../../common/hooks/use_experimental_features'; import { useKibana } from '../../../common/lib/kibana'; import { DEFAULT_DETECTION_PAGE_FILTERS } from '../../../../common/constants'; @@ -25,11 +25,11 @@ export type DetectionEngineFiltersProps = Pick< AlertFilterControlsProps, 'filters' | 'onFiltersChange' | 'query' | 'timeRange' | 'onInit' > & { - dataViewSpec?: DataViewSpec; + dataView?: DataView | DataViewSpec; }; export const DetectionEngineFilters = ({ - dataViewSpec: indexPattern, + dataView: indexPattern, ...props }: DetectionEngineFiltersProps) => { const newDataViewPickerEnabled = useIsExperimentalFeatureEnabled('newDataViewPickerEnabled'); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.tsx index 4e71532089cf3..5046b5cd9d9a3 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/containers/detection_engine/rules/use_rule_from_timeline.tsx @@ -57,13 +57,13 @@ export const useRuleFromTimeline = (setRuleQuery: SetRuleQuery): RuleFromTimelin const experimentalSelectedPatterns = useSelectedPatterns(SourcererScopeName.timeline); const experimentalBrowserFields = useBrowserFields(SourcererScopeName.timeline); - const { dataView } = useDataView(SourcererScopeName.timeline); + const { dataView: experimentalDataView } = useDataView(SourcererScopeName.timeline); const selectedPatterns = newDataViewPickerEnabled ? experimentalSelectedPatterns : oldSelectedPatterns; const browserFields = newDataViewPickerEnabled ? experimentalBrowserFields : oldBrowserFields; - const dataViewId = newDataViewPickerEnabled ? dataView?.id ?? '' : oldDataViewId; + const dataViewId = newDataViewPickerEnabled ? experimentalDataView?.id ?? '' : oldDataViewId; const isEql = useRef(false); diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_cell_actions.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_cell_actions.tsx index 33f4665e673be..44ad35b4b7077 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_cell_actions.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_cell_actions.tsx @@ -41,7 +41,7 @@ export const useCellActionsOptions = ( } = context ?? {}; const oldGetFieldSpec = useGetFieldSpec(SourcererScopeName.detections); const oldDataViewId = useDataViewId(SourcererScopeName.detections); - const dataViewId = newDataViewPickerEnabled ? experimentalDataView?.id : oldDataViewId; + const dataViewId = newDataViewPickerEnabled ? experimentalDataView.id : oldDataViewId; const cellActionsMetadata = useMemo( () => ({ scopeId: tableId, dataViewId }), @@ -52,7 +52,7 @@ export const useCellActionsOptions = ( columns.map( (column) => (newDataViewPickerEnabled - ? experimentalDataView?.fields?.getByName(column.id)?.toSpec() + ? experimentalDataView.fields?.getByName(column.id)?.toSpec() : oldGetFieldSpec(column.id)) ?? { name: '', type: '', // When type is an empty string all cell actions are incompatible @@ -60,7 +60,7 @@ export const useCellActionsOptions = ( searchable: false, } ), - [columns, experimentalDataView?.fields, oldGetFieldSpec, newDataViewPickerEnabled] + [columns, experimentalDataView.fields, oldGetFieldSpec, newDataViewPickerEnabled] ); /** diff --git a/x-pack/solutions/security/plugins/security_solution/public/detections/pages/alerts/detection_engine.tsx b/x-pack/solutions/security/plugins/security_solution/public/detections/pages/alerts/detection_engine.tsx index 1e57e22303a9f..153477ee0a6ae 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/detections/pages/alerts/detection_engine.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/detections/pages/alerts/detection_engine.tsx @@ -34,6 +34,7 @@ import { import { isEqual } from 'lodash'; import type { FilterGroupHandler } from '@kbn/alerts-ui-shared'; import type { RunTimeMappings } from '@kbn/timelines-plugin/common/search_strategy'; +import { useDataView } from '../../../data_view_manager/hooks/use_data_view'; import { useGroupTakeActionsItems } from '../../hooks/alerts_table/use_group_take_action_items'; import { defaultGroupingOptions, @@ -93,7 +94,6 @@ import type { Status } from '../../../../common/api/detection_engine'; import { GroupedAlertsTable } from '../../components/alerts_table/alerts_grouping'; import { DetectionEngineAlertsTable } from '../../components/alerts_table'; import type { AddFilterProps } from '../../components/alerts_kpis/common/types'; -import { useDataViewSpec } from '../../../data_view_manager/hooks/use_data_view_spec'; /** * Need a 100% height here to account for the graph/analyze tool, which sets no explicit height parameters, but fills the available space. @@ -159,19 +159,21 @@ const DetectionEnginePageComponent: React.FC = () FilterGroupHandler | undefined >(); - const { sourcererDataView: oldSourcererDataView, loading: oldIsLoadingIndexPattern } = + const { sourcererDataView: oldSourcererDataViewSpec, loading: oldIsLoadingIndexPattern } = useSourcererDataView(SourcererScopeName.detections); const newDataViewPickerEnabled = useIsExperimentalFeatureEnabled('newDataViewPickerEnabled'); - const { dataViewSpec: experimentalDataViewSpec, status: dataViewSpecStatus } = useDataViewSpec( + const { dataView: experimentalDataView, status: experimentalDataViewStatus } = useDataView( SourcererScopeName.detections ); + const runtimeMappings = useMemo(() => { + return newDataViewPickerEnabled + ? (experimentalDataView.getRuntimeMappings() as RunTimeMappings) ?? {} + : (oldSourcererDataViewSpec.runtimeFieldMap as RunTimeMappings) ?? {}; + }, [newDataViewPickerEnabled, experimentalDataView, oldSourcererDataViewSpec.runtimeFieldMap]); - const sourcererDataViewSpec = newDataViewPickerEnabled - ? experimentalDataViewSpec - : oldSourcererDataView; const isLoadingIndexPattern = newDataViewPickerEnabled - ? dataViewSpecStatus !== 'ready' + ? experimentalDataViewStatus !== 'ready' : oldIsLoadingIndexPattern; const { formatUrl } = useFormatUrl(SecurityPageName.rules); @@ -402,7 +404,7 @@ const DetectionEnginePageComponent: React.FC = () = () query={query} timeRange={pageFiltersTimerange} onInit={setDetectionPageFilterHandler} - dataViewSpec={sourcererDataViewSpec} + dataView={ + newDataViewPickerEnabled ? experimentalDataView : oldSourcererDataViewSpec + } /> = () alertsDefaultFilters={alertsDefaultFilters} isLoadingIndexPattern={isChartPanelLoading} query={query} - runtimeMappings={sourcererDataViewSpec.runtimeFieldMap as RunTimeMappings} + runtimeMappings={runtimeMappings} signalIndexName={signalIndexName} updateDateRangeCallback={updateDateRangeCallback} /> @@ -455,7 +459,8 @@ const DetectionEnginePageComponent: React.FC = () { toggleStatus: boolean; @@ -54,14 +53,11 @@ export const TopRiskScoreContributorsAlerts = ({ }: TopRiskScoreContributorsAlertsProps) => { const { to, from } = useGlobalTime(); const [{ loading: userInfoLoading, hasIndexWrite, hasIndexMaintenance }] = useUserData(); - const { sourcererDataView: oldSourcererDataView } = useSourcererDataView( + const { sourcererDataView: oldSourcererDataViewSpec } = useSourcererDataView( SourcererScopeName.detections ); - const newDataViewPickerEnabled = useIsExperimentalFeatureEnabled('newDataViewPickerEnabled'); - const { dataViewSpec } = useDataViewSpec(SourcererScopeName.detections); - - const sourcererDataViewSpec = newDataViewPickerEnabled ? dataViewSpec : oldSourcererDataView; + const { dataView: experimentalDataView } = useDataView(SourcererScopeName.detections); const getGlobalFiltersQuerySelector = useMemo( () => inputsSelectors.globalFiltersQuerySelector(), @@ -146,7 +142,8 @@ export const TopRiskScoreContributorsAlerts = ({ { const newDataViewPickerEnabled = useIsExperimentalFeatureEnabled('newDataViewPickerEnabled'); const { dataView, status } = useDataView(); - const { dataViewSpec: experimentalDataViewSpec } = useDataViewSpec(); - const dataViewSpec: DataViewSpec = useMemo( - () => (newDataViewPickerEnabled ? experimentalDataViewSpec : oldSourcererDataViewSpec), - [experimentalDataViewSpec, newDataViewPickerEnabled, oldSourcererDataViewSpec] - ); const indicesExist = useMemo( () => (newDataViewPickerEnabled ? !!dataView?.matchedIndices?.length : oldIndicesExist), [dataView?.matchedIndices?.length, newDataViewPickerEnabled, oldIndicesExist] @@ -70,7 +63,10 @@ const EntityAnalyticsComponent = () => { {indicesExist ? ( <> - + diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/hosts/pages/details/details_tabs.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/explore/hosts/pages/details/details_tabs.test.tsx index 327db18136542..9414b0ca9ebe5 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/hosts/pages/details/details_tabs.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/hosts/pages/details/details_tabs.test.tsx @@ -12,7 +12,6 @@ import useResizeObserver from 'use-resize-observer/polyfilled'; import { createMockStore, - mockDataViewSpec, mockGlobalState, mockIndexPattern, TestProviders, @@ -163,7 +162,6 @@ describe('body', () => { setQuery={jest.fn()} hostDetailsPagePath={hostDetailsPagePath} indexNames={[]} - dataViewSpec={mockDataViewSpec} type={HostsType.details} hostDetailsFilter={mockHostDetailsPageFilters} filterQuery={filterQuery} @@ -181,35 +179,6 @@ describe('body', () => { skip: false, startDate: '2020-07-07T08:20:18.966Z', type: 'details', - indexPattern: { - fields: { - '@timestamp': { searchable: true, type: 'date', aggregatable: true }, - '@version': { searchable: true, type: 'string', aggregatable: true }, - 'agent.ephemeral_id': { searchable: true, type: 'string', aggregatable: true }, - 'agent.hostname': { searchable: true, type: 'string', aggregatable: true }, - 'agent.id': { searchable: true, type: 'string', aggregatable: true }, - 'agent.test1': { searchable: true, type: 'string', aggregatable: true }, - 'agent.test2': { searchable: true, type: 'string', aggregatable: true }, - 'agent.test3': { searchable: true, type: 'string', aggregatable: true }, - 'agent.test4': { searchable: true, type: 'string', aggregatable: true }, - 'agent.test5': { searchable: true, type: 'string', aggregatable: true }, - 'agent.test6': { searchable: true, type: 'string', aggregatable: true }, - 'agent.test7': { searchable: true, type: 'string', aggregatable: true }, - 'agent.test8': { searchable: true, type: 'string', aggregatable: true }, - 'host.name': { searchable: true, type: 'string', aggregatable: true }, - 'nestedField.firstAttributes': { - aggregatable: false, - searchable: true, - type: 'string', - }, - 'nestedField.secondAttributes': { - aggregatable: false, - searchable: true, - type: 'string', - }, - }, - title: 'filebeat-*,auditbeat-*,packetbeat-*', - }, hostName: 'host-1', ...(path === 'events' && { additionalFilters: mockHostDetailsPageFilters }), }); diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/hosts/pages/details/details_tabs.tsx b/x-pack/solutions/security/plugins/security_solution/public/explore/hosts/pages/details/details_tabs.tsx index 228e1a9663e27..1edb02de0b0af 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/hosts/pages/details/details_tabs.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/hosts/pages/details/details_tabs.tsx @@ -25,14 +25,7 @@ import { } from '../navigation'; export const HostDetailsTabs = React.memo( - ({ - detailName, - filterQuery, - indexNames, - dataViewSpec: indexPattern, - hostDetailsPagePath, - hostDetailsFilter, - }) => { + ({ detailName, filterQuery, indexNames, hostDetailsPagePath, hostDetailsFilter }) => { const { from, to, isInitializing, deleteQuery, setQuery } = useGlobalTime(); const tabProps = { @@ -43,7 +36,6 @@ export const HostDetailsTabs = React.memo( setQuery, startDate: from, type: HostsType.details, - indexPattern, indexNames, hostName: detailName, }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/hosts/pages/details/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/explore/hosts/pages/details/index.tsx index 35e52aa0e9506..0bb44e57e05e6 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/hosts/pages/details/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/hosts/pages/details/index.tsx @@ -85,7 +85,6 @@ import { ResponderActionButton } from '../../../../common/components/endpoint/re import { useRefetchOverviewPageRiskScore } from '../../../../entity_analytics/api/hooks/use_refetch_overview_page_risk_score'; import { SourcererScopeName } from '../../../../sourcerer/store/model'; import { useDataView } from '../../../../data_view_manager/hooks/use_data_view'; -import { useDataViewSpec } from '../../../../data_view_manager/hooks/use_data_view_spec'; import { useSelectedPatterns } from '../../../../data_view_manager/hooks/use_selected_patterns'; import { PageLoader } from '../../../../common/components/page_loader'; @@ -144,13 +143,11 @@ const HostDetailsComponent: React.FC = ({ detailName, hostDeta const newDataViewPickerEnabled = useIsExperimentalFeatureEnabled('newDataViewPickerEnabled'); - const { dataView, status } = useDataView(DataViewManagerScopeName.explore); - const { dataViewSpec } = useDataViewSpec(DataViewManagerScopeName.explore); + const { dataView: experimentalDataView, status } = useDataView(DataViewManagerScopeName.explore); const experimentalSelectedPatterns = useSelectedPatterns(DataViewManagerScopeName.explore); - const sourcererDataView = newDataViewPickerEnabled ? dataViewSpec : oldSourcererDataView; const indicesExist = newDataViewPickerEnabled - ? !!dataView?.matchedIndices?.length + ? !!experimentalDataView.matchedIndices?.length : oldIndicesExist; const selectedPatterns = newDataViewPickerEnabled ? experimentalSelectedPatterns @@ -168,7 +165,9 @@ const HostDetailsComponent: React.FC = ({ detailName, hostDeta try { return [ buildEsQuery( - dataViewSpecToViewBase(sourcererDataView), + newDataViewPickerEnabled + ? experimentalDataView + : dataViewSpecToViewBase(oldSourcererDataView), [query], [...hostDetailsPageFilters, ...globalFilters], getEsQueryConfig(uiSettings) @@ -177,7 +176,15 @@ const HostDetailsComponent: React.FC = ({ detailName, hostDeta } catch (e) { return [undefined, e]; } - }, [sourcererDataView, query, hostDetailsPageFilters, globalFilters, uiSettings]); + }, [ + newDataViewPickerEnabled, + experimentalDataView, + oldSourcererDataView, + query, + hostDetailsPageFilters, + globalFilters, + uiSettings, + ]); const stringifiedAdditionalFilters = JSON.stringify(rawFilteredQuery); useInvalidFilterQuery({ @@ -237,7 +244,7 @@ const HostDetailsComponent: React.FC = ({ detailName, hostDeta <> - + = ({ detailName, hostDeta setQuery={setQuery} filterQuery={stringifiedAdditionalFilters} hostDetailsPagePath={hostDetailsPagePath} - dataViewSpec={sourcererDataView} /> diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/hosts/pages/hosts.tsx b/x-pack/solutions/security/plugins/security_solution/public/explore/hosts/pages/hosts.tsx index c705c491bd136..c32b1fb4fc781 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/hosts/pages/hosts.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/hosts/pages/hosts.tsx @@ -57,7 +57,6 @@ import { EmptyPrompt } from '../../../common/components/empty_prompt'; import { fieldNameExistsFilter } from '../../../common/components/visualization_actions/utils'; import { useLicense } from '../../../common/hooks/use_license'; import { useDataView } from '../../../data_view_manager/hooks/use_data_view'; -import { useDataViewSpec } from '../../../data_view_manager/hooks/use_data_view_spec'; import { useSelectedPatterns } from '../../../data_view_manager/hooks/use_selected_patterns'; import { PageLoader } from '../../../common/components/page_loader'; @@ -119,12 +118,12 @@ const HostsComponent = () => { const newDataViewPickerEnabled = useIsExperimentalFeatureEnabled('newDataViewPickerEnabled'); - const { dataView, status } = useDataView(DataViewManagerScopeName.explore); - const { dataViewSpec } = useDataViewSpec(DataViewManagerScopeName.explore); + const { dataView: experimentalDataView, status } = useDataView(DataViewManagerScopeName.explore); const experimentalSelectedPatterns = useSelectedPatterns(DataViewManagerScopeName.explore); - const sourcererDataView = newDataViewPickerEnabled ? dataViewSpec : oldSourcererDataView; - const indicesExist = newDataViewPickerEnabled ? dataView.hasMatchedIndices() : oldIndicesExist; + const indicesExist = newDataViewPickerEnabled + ? experimentalDataView.hasMatchedIndices() + : oldIndicesExist; const selectedPatterns = newDataViewPickerEnabled ? experimentalSelectedPatterns : oldSelectedPatterns; @@ -133,21 +132,23 @@ const HostsComponent = () => { () => convertToBuildEsQuery({ config: getEsQueryConfig(uiSettings), - dataViewSpec: sourcererDataView, + dataViewSpec: oldSourcererDataView, + dataView: experimentalDataView, queries: [query], filters: globalFilters, }), - [globalFilters, sourcererDataView, uiSettings, query] + [uiSettings, oldSourcererDataView, experimentalDataView, query, globalFilters] ); const [tabsFilterQuery] = useMemo( () => convertToBuildEsQuery({ config: getEsQueryConfig(uiSettings), - dataViewSpec: sourcererDataView, + dataViewSpec: oldSourcererDataView, + dataView: experimentalDataView, queries: [query], filters: tabsFilters, }), - [sourcererDataView, query, tabsFilters, uiSettings] + [uiSettings, oldSourcererDataView, experimentalDataView, query, tabsFilters] ); useInvalidFilterQuery({ @@ -195,7 +196,10 @@ const HostsComponent = () => { - + diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/network/pages/details/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/explore/network/pages/details/index.tsx index 8b83c68dcbff1..310ff3c22fcd0 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/network/pages/details/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/network/pages/details/index.tsx @@ -64,7 +64,6 @@ import { } from '../../../../common/components/cell_actions'; import { SourcererScopeName } from '../../../../sourcerer/store/model'; import { useDataView } from '../../../../data_view_manager/hooks/use_data_view'; -import { useDataViewSpec } from '../../../../data_view_manager/hooks/use_data_view_spec'; import { useSelectedPatterns } from '../../../../data_view_manager/hooks/use_selected_patterns'; const NetworkDetailsManage = manageQuery(IpOverview); @@ -120,12 +119,12 @@ const NetworkDetailsComponent: React.FC = () => { const newDataViewPickerEnabled = useIsExperimentalFeatureEnabled('newDataViewPickerEnabled'); - const { dataView, status } = useDataView(DataViewManagerScopeName.explore); - const { dataViewSpec } = useDataViewSpec(DataViewManagerScopeName.explore); + const { dataView: experimentalDataView, status } = useDataView(DataViewManagerScopeName.explore); const experimentalSelectedPatterns = useSelectedPatterns(DataViewManagerScopeName.explore); - const sourcererDataView = newDataViewPickerEnabled ? dataViewSpec : oldSourcererDataView; - const indicesExist = newDataViewPickerEnabled ? dataView.hasMatchedIndices() : oldIndicesExist; + const indicesExist = newDataViewPickerEnabled + ? experimentalDataView.hasMatchedIndices() + : oldIndicesExist; const selectedPatterns = newDataViewPickerEnabled ? experimentalSelectedPatterns : oldSelectedPatterns; @@ -137,7 +136,9 @@ const NetworkDetailsComponent: React.FC = () => { try { return [ buildEsQuery( - dataViewSpecToViewBase(sourcererDataView), + newDataViewPickerEnabled + ? experimentalDataView + : dataViewSpecToViewBase(oldSourcererDataView), [query], [...networkDetailsFilter, ...globalFilters], getEsQueryConfig(uiSettings) @@ -146,7 +147,15 @@ const NetworkDetailsComponent: React.FC = () => { } catch (e) { return [undefined, e]; } - }, [globalFilters, networkDetailsFilter, query, sourcererDataView, uiSettings]); + }, [ + experimentalDataView, + globalFilters, + networkDetailsFilter, + newDataViewPickerEnabled, + oldSourcererDataView, + query, + uiSettings, + ]); const additionalFilters = useMemo( () => (rawFilteredQuery ? [rawFilteredQuery] : []), @@ -190,8 +199,10 @@ const NetworkDetailsComponent: React.FC = () => { ); const indexPattern = useMemo(() => { - return dataViewSpecToViewBase(sourcererDataView); - }, [sourcererDataView]); + return newDataViewPickerEnabled + ? experimentalDataView || { title: '', fields: [] } + : dataViewSpecToViewBase(oldSourcererDataView); + }, [experimentalDataView, newDataViewPickerEnabled, oldSourcererDataView]); if (newDataViewPickerEnabled && status === 'pristine') { return ; @@ -202,7 +213,10 @@ const NetworkDetailsComponent: React.FC = () => { {indicesExist ? ( <> - + diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/network/pages/navigation/countries_query_tab_body.tsx b/x-pack/solutions/security/plugins/security_solution/public/explore/network/pages/navigation/countries_query_tab_body.tsx index cd19ab18956c5..4badd8e7dca24 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/network/pages/navigation/countries_query_tab_body.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/network/pages/navigation/countries_query_tab_body.tsx @@ -22,7 +22,6 @@ export const CountriesQueryTabBody = ({ filterQuery, flowTarget, indexNames, - indexPattern, ip, setQuery, skip, diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/network/pages/navigation/network_routes.tsx b/x-pack/solutions/security/plugins/security_solution/public/explore/network/pages/navigation/network_routes.tsx index 6e49c65454239..fa8210bbe65f2 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/network/pages/navigation/network_routes.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/network/pages/navigation/network_routes.tsx @@ -5,13 +5,12 @@ * 2.0. */ -import React, { useMemo } from 'react'; +import React from 'react'; import { Routes, Route } from '@kbn/shared-ux-router'; import { EuiFlexItem, EuiSpacer } from '@elastic/eui'; import { TableId } from '@kbn/securitysolution-data-table'; -import { dataViewSpecToViewBase } from '../../../../common/lib/kuery'; import { FlowTargetSourceDest } from '../../../../../common/search_strategy/security_solution/network'; import { @@ -31,9 +30,7 @@ import { NetworkRouteType } from './types'; import { NETWORK_PATH } from '../../../../../common/constants'; export const NetworkRoutes = React.memo( - ({ type, to, filterQuery, isInitializing, from, dataViewSpec, indexNames, setQuery }) => { - const index = useMemo(() => dataViewSpecToViewBase(dataViewSpec), [dataViewSpec]); - + ({ type, to, filterQuery, isInitializing, from, indexNames, setQuery }) => { const networkAnomaliesFilterQuery = { bool: { should: [ @@ -64,7 +61,6 @@ export const NetworkRoutes = React.memo( const tabProps = { ...commonProps, - indexPattern: index, }; const anomaliesProps = { diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/network/pages/navigation/types.ts b/x-pack/solutions/security/plugins/security_solution/public/explore/network/pages/navigation/types.ts index 339ad2fc71acc..242de09af8646 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/network/pages/navigation/types.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/network/pages/navigation/types.ts @@ -7,8 +7,6 @@ import type { Optional } from 'utility-types'; -import type { DataViewBase } from '@kbn/es-query'; -import type { DataViewSpec } from '@kbn/data-plugin/common'; import type { ESTermQuery } from '../../../../../common/typed_json'; import type { NavTab } from '../../../../common/components/navigation/types'; @@ -30,7 +28,6 @@ export type NetworkComponentQueryProps = QueryTabBodyProps; export type IPsQueryTabBodyProps = QueryTabBodyProps & { flowTarget: FlowTargetSourceDest; - indexPattern: DataViewBase; }; export type FTQueryTabBodyProps = QueryTabBodyProps & { @@ -46,7 +43,6 @@ export type HttpQueryTabBodyProps = QueryTabBodyProps; export type NetworkRoutesProps = GlobalTimeArgs & { type: networkModel.NetworkType; filterQuery?: string | ESTermQuery; - dataViewSpec: DataViewSpec; indexNames: string[]; }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/network/pages/network.tsx b/x-pack/solutions/security/plugins/security_solution/public/explore/network/pages/network.tsx index 44822fcd24890..457ac7401439a 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/network/pages/network.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/network/pages/network.tsx @@ -51,7 +51,6 @@ import { useInvalidFilterQuery } from '../../../common/hooks/use_invalid_filter_ import { sourceOrDestinationIpExistsFilter } from '../../../common/components/visualization_actions/utils'; import { EmptyPrompt } from '../../../common/components/empty_prompt'; import { useDataView } from '../../../data_view_manager/hooks/use_data_view'; -import { useDataViewSpec } from '../../../data_view_manager/hooks/use_data_view_spec'; import { useSelectedPatterns } from '../../../data_view_manager/hooks/use_selected_patterns'; import { PageLoader } from '../../../common/components/page_loader'; @@ -104,10 +103,8 @@ const NetworkComponent = React.memo( const newDataViewPickerEnabled = useIsExperimentalFeatureEnabled('newDataViewPickerEnabled'); const { dataView, status } = useDataView(DataViewManagerScopeName.explore); - const { dataViewSpec } = useDataViewSpec(DataViewManagerScopeName.explore); const experimentalSelectedPatterns = useSelectedPatterns(DataViewManagerScopeName.explore); - const sourcererDataView = newDataViewPickerEnabled ? dataViewSpec : oldSourcererDataView; const indicesExist = newDataViewPickerEnabled ? dataView.hasMatchedIndices() : oldIndicesExist; const selectedPatterns = newDataViewPickerEnabled ? experimentalSelectedPatterns @@ -137,19 +134,29 @@ const NetworkComponent = React.memo( [containerElement, onSkipFocusBeforeEventsTable, onSkipFocusAfterEventsTable] ); - const [filterQuery, kqlError] = convertToBuildEsQuery({ - config: getEsQueryConfig(kibana.services.uiSettings), - dataViewSpec: sourcererDataView, - queries: [query], - filters: globalFilters, - }); + const [filterQuery, kqlError] = useMemo( + () => + convertToBuildEsQuery({ + config: getEsQueryConfig(kibana.services.uiSettings), + dataViewSpec: oldSourcererDataView, + dataView, + queries: [query], + filters: globalFilters, + }), + [kibana.services.uiSettings, oldSourcererDataView, dataView, query, globalFilters] + ); - const [tabsFilterQuery] = convertToBuildEsQuery({ - config: getEsQueryConfig(kibana.services.uiSettings), - dataViewSpec: sourcererDataView, - queries: [query], - filters: tabsFilters, - }); + const [tabsFilterQuery] = useMemo( + () => + convertToBuildEsQuery({ + config: getEsQueryConfig(kibana.services.uiSettings), + dataViewSpec: oldSourcererDataView, + dataView, + queries: [query], + filters: tabsFilters, + }), + [kibana.services.uiSettings, oldSourcererDataView, dataView, query, tabsFilters] + ); useInvalidFilterQuery({ id: ID, filterQuery, kqlError, query, startDate: from, endDate: to }); @@ -163,7 +170,7 @@ const NetworkComponent = React.memo( - + @@ -201,7 +208,7 @@ const NetworkComponent = React.memo( - {capabilitiesFetched && !isInitializing && sourcererDataView ? ( + {capabilitiesFetched && !isInitializing && oldSourcererDataView ? ( <> @@ -213,7 +220,6 @@ const NetworkComponent = React.memo( filterQuery={tabsFilterQuery} from={from} isInitializing={isInitializing} - dataViewSpec={sourcererDataView} indexNames={selectedPatterns} setQuery={setQuery} type={networkModel.NetworkType.page} diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/users/pages/details/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/explore/users/pages/details/index.tsx index 39ba8750924fd..4fd345fa1bac6 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/users/pages/details/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/users/pages/details/index.tsx @@ -84,7 +84,6 @@ import { useMlCapabilities } from '../../../../common/components/ml/hooks/use_ml import { EmptyPrompt } from '../../../../common/components/empty_prompt'; import { useRefetchOverviewPageRiskScore } from '../../../../entity_analytics/api/hooks/use_refetch_overview_page_risk_score'; import { useDataView } from '../../../../data_view_manager/hooks/use_data_view'; -import { useDataViewSpec } from '../../../../data_view_manager/hooks/use_data_view_spec'; import { useSelectedPatterns } from '../../../../data_view_manager/hooks/use_selected_patterns'; import { PageLoader } from '../../../../common/components/page_loader'; @@ -132,12 +131,12 @@ const UsersDetailsComponent: React.FC = ({ const newDataViewPickerEnabled = useIsExperimentalFeatureEnabled('newDataViewPickerEnabled'); - const { dataView, status } = useDataView(DataViewManagerScopeName.explore); - const { dataViewSpec } = useDataViewSpec(DataViewManagerScopeName.explore); + const { dataView: experimentalDataView, status } = useDataView(DataViewManagerScopeName.explore); const experimentalSelectedPatterns = useSelectedPatterns(DataViewManagerScopeName.explore); - const sourcererDataView = newDataViewPickerEnabled ? dataViewSpec : oldSourcererDataView; - const indicesExist = newDataViewPickerEnabled ? dataView.hasMatchedIndices() : oldIndicesExist; + const indicesExist = newDataViewPickerEnabled + ? experimentalDataView.hasMatchedIndices() + : oldIndicesExist; const selectedPatterns = newDataViewPickerEnabled ? experimentalSelectedPatterns : oldSelectedPatterns; @@ -146,7 +145,9 @@ const UsersDetailsComponent: React.FC = ({ try { return [ buildEsQuery( - dataViewSpecToViewBase(sourcererDataView), + newDataViewPickerEnabled + ? experimentalDataView + : dataViewSpecToViewBase(oldSourcererDataView), [query], [...usersDetailsPageFilters, ...globalFilters], getEsQueryConfig(uiSettings) @@ -155,7 +156,15 @@ const UsersDetailsComponent: React.FC = ({ } catch (e) { return [undefined, e]; } - }, [globalFilters, sourcererDataView, query, uiSettings, usersDetailsPageFilters]); + }, [ + experimentalDataView, + globalFilters, + newDataViewPickerEnabled, + oldSourcererDataView, + query, + uiSettings, + usersDetailsPageFilters, + ]); const stringifiedAdditionalFilters = JSON.stringify(rawFilteredQuery); useInvalidFilterQuery({ @@ -235,8 +244,11 @@ const UsersDetailsComponent: React.FC = ({ {indicesExist ? ( <> - - + + @@ -324,7 +336,6 @@ const UsersDetailsComponent: React.FC = ({ filterQuery={stringifiedAdditionalFilters} from={from} indexNames={selectedPatterns} - dataViewSpec={sourcererDataView} isInitializing={isInitializing} userDetailFilter={usersDetailsPageFilters} setQuery={setQuery} diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/users/pages/details/types.ts b/x-pack/solutions/security/plugins/security_solution/public/explore/users/pages/details/types.ts index 8b531af663990..65ee492c584c6 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/users/pages/details/types.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/users/pages/details/types.ts @@ -7,7 +7,6 @@ import type { ActionCreator } from 'typescript-fsa'; -import { type DataViewSpec } from '@kbn/data-plugin/common'; import type { Filter, Query } from '@kbn/es-query'; import type { UsersQueryProps } from '../types'; @@ -48,6 +47,5 @@ export type UsersDetailsTabsProps = UserBodyComponentDispatchProps & indexNames: string[]; userDetailFilter: Filter[]; filterQuery?: string; - dataViewSpec?: DataViewSpec; type: usersModel.UsersType; }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/users/pages/users.tsx b/x-pack/solutions/security/plugins/security_solution/public/explore/users/pages/users.tsx index df6d4e4ab7a95..76d2017de127d 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/users/pages/users.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/users/pages/users.tsx @@ -53,7 +53,6 @@ import { useMlCapabilities } from '../../../common/components/ml/hooks/use_ml_ca import { EmptyPrompt } from '../../../common/components/empty_prompt'; import { userNameExistsFilter } from './details/helpers'; import { useDataView } from '../../../data_view_manager/hooks/use_data_view'; -import { useDataViewSpec } from '../../../data_view_manager/hooks/use_data_view_spec'; import { useSelectedPatterns } from '../../../data_view_manager/hooks/use_selected_patterns'; import { PageLoader } from '../../../common/components/page_loader'; @@ -113,12 +112,12 @@ const UsersComponent = () => { const newDataViewPickerEnabled = useIsExperimentalFeatureEnabled('newDataViewPickerEnabled'); - const { dataView, status } = useDataView(DataViewManagerScopeName.explore); - const { dataViewSpec } = useDataViewSpec(DataViewManagerScopeName.explore); + const { dataView: experimentalDataView, status } = useDataView(DataViewManagerScopeName.explore); const experimentalSelectedPatterns = useSelectedPatterns(DataViewManagerScopeName.explore); - const sourcererDataView = newDataViewPickerEnabled ? dataViewSpec : oldSourcererDataView; - const indicesExist = newDataViewPickerEnabled ? dataView.hasMatchedIndices() : oldIndicesExist; + const indicesExist = newDataViewPickerEnabled + ? experimentalDataView.hasMatchedIndices() + : oldIndicesExist; const selectedPatterns = newDataViewPickerEnabled ? experimentalSelectedPatterns : oldSelectedPatterns; @@ -127,21 +126,23 @@ const UsersComponent = () => { () => convertToBuildEsQuery({ config: getEsQueryConfig(uiSettings), - dataViewSpec: sourcererDataView, + dataViewSpec: oldSourcererDataView, + dataView: experimentalDataView, queries: [query], filters: globalFilters, }), - [globalFilters, sourcererDataView, uiSettings, query] + [uiSettings, oldSourcererDataView, experimentalDataView, query, globalFilters] ); const [tabsFilterQuery] = useMemo( () => convertToBuildEsQuery({ config: getEsQueryConfig(uiSettings), - dataViewSpec: sourcererDataView, + dataViewSpec: oldSourcererDataView, + dataView: experimentalDataView, queries: [query], filters: tabsFilters, }), - [sourcererDataView, query, tabsFilters, uiSettings] + [experimentalDataView, oldSourcererDataView, query, tabsFilters, uiSettings] ); useInvalidFilterQuery({ @@ -190,7 +191,10 @@ const UsersComponent = () => { - + diff --git a/x-pack/solutions/security/plugins/security_solution/public/flyout/network_details/components/network_details.tsx b/x-pack/solutions/security/plugins/security_solution/public/flyout/network_details/components/network_details.tsx index 78fb04370a911..fd196c323796b 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/flyout/network_details/components/network_details.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/flyout/network_details/components/network_details.tsx @@ -31,7 +31,6 @@ import { EmptyPrompt } from '../../../common/components/empty_prompt'; import type { NarrowDateRange } from '../../../common/components/ml/types'; import { SourcererScopeName } from '../../../sourcerer/store/model'; import { useDataView } from '../../../data_view_manager/hooks/use_data_view'; -import { useDataViewSpec } from '../../../data_view_manager/hooks/use_data_view_spec'; import { useSelectedPatterns } from '../../../data_view_manager/hooks/use_selected_patterns'; export interface NetworkDetailsProps { @@ -86,24 +85,27 @@ export const NetworkDetails = ({ ip, flowTarget }: NetworkDetailsProps) => { const newDataViewPickerEnabled = useIsExperimentalFeatureEnabled('newDataViewPickerEnabled'); - const { dataView, status } = useDataView(); - const { dataViewSpec } = useDataViewSpec(); + const { dataView: experimentalDataView, status } = useDataView(); const experimentalSelectedPatterns = useSelectedPatterns(); - const sourcererDataView = newDataViewPickerEnabled ? dataViewSpec : oldSourcererDataView; const indicesExist = newDataViewPickerEnabled - ? !!dataView?.matchedIndices?.length + ? !!experimentalDataView.matchedIndices?.length : oldIndicesExist; const selectedPatterns = newDataViewPickerEnabled ? experimentalSelectedPatterns : oldSelectedPatterns; - const [filterQuery, kqlError] = convertToBuildEsQuery({ - config: getEsQueryConfig(uiSettings), - dataViewSpec: sourcererDataView, - queries: [query], - filters, - }); + const [filterQuery, kqlError] = useMemo( + () => + convertToBuildEsQuery({ + config: getEsQueryConfig(uiSettings), + dataViewSpec: oldSourcererDataView, + dataView: experimentalDataView, + queries: [query], + filters, + }), + [uiSettings, oldSourcererDataView, experimentalDataView, query, filters] + ); const [loading, { id, networkDetails }] = useNetworkDetails({ skip: isInitializing || filterQuery === undefined, diff --git a/x-pack/solutions/security/plugins/security_solution/public/overview/components/event_counts/index.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/overview/components/event_counts/index.test.tsx index f061ead1073ae..86012ea4bd03f 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/overview/components/event_counts/index.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/overview/components/event_counts/index.test.tsx @@ -13,6 +13,7 @@ import { OverviewHost } from '../overview_host'; import { OverviewNetwork } from '../overview_network'; import { EventCounts } from '.'; +import { createStubDataView } from '@kbn/data-views-plugin/common/data_views/data_view.stub'; jest.mock('../../../common/components/link_to'); jest.mock('../overview_host', () => ({ @@ -36,6 +37,7 @@ describe('EventCounts', () => { from, indexNames: [], dataViewSpec: mockDataViewSpec, + dataView: createStubDataView({ spec: {} }), setQuery: jest.fn(), to, query: { diff --git a/x-pack/solutions/security/plugins/security_solution/public/overview/components/event_counts/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/overview/components/event_counts/index.tsx index 3f20d3365537f..a6e8ae70f1b1e 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/overview/components/event_counts/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/overview/components/event_counts/index.tsx @@ -9,6 +9,7 @@ import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import React, { useMemo } from 'react'; import type { Filter, Query } from '@kbn/es-query'; +import type { DataView } from '@kbn/data-plugin/common'; import { type DataViewSpec, getEsQueryConfig } from '@kbn/data-plugin/common'; import { ID as OverviewHostQueryId } from '../../containers/overview_host'; import { OverviewHost } from '../overview_host'; @@ -27,6 +28,7 @@ interface Props extends Pick { filters: Filter[]; indexNames: string[]; dataViewSpec?: DataViewSpec; + dataView: DataView; query: Query; } @@ -35,6 +37,7 @@ const EventCountsComponent: React.FC = ({ from, indexNames, dataViewSpec, + dataView, query, setQuery, to, @@ -46,10 +49,11 @@ const EventCountsComponent: React.FC = ({ convertToBuildEsQuery({ config: getEsQueryConfig(uiSettings), dataViewSpec, + dataView, queries: [query], filters: [...filters, ...fieldNameExistsFilter(SecurityPageName.hosts)], }), - [dataViewSpec, filters, query, uiSettings] + [dataViewSpec, filters, dataView, query, uiSettings] ); const [networkFilterQuery] = useMemo( @@ -57,10 +61,11 @@ const EventCountsComponent: React.FC = ({ convertToBuildEsQuery({ config: getEsQueryConfig(uiSettings), dataViewSpec, + dataView, queries: [query], filters: [...filters, ...sourceOrDestinationIpExistsFilter], }), - [uiSettings, dataViewSpec, query, filters] + [uiSettings, dataViewSpec, dataView, query, filters] ); useInvalidFilterQuery({ diff --git a/x-pack/solutions/security/plugins/security_solution/public/overview/components/events_by_dataset/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/overview/components/events_by_dataset/index.tsx index a37e6adda8ad5..2c871649d9bbd 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/overview/components/events_by_dataset/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/overview/components/events_by_dataset/index.tsx @@ -7,14 +7,14 @@ import { Position } from '@elastic/charts'; import numeral from '@elastic/numeral'; -import React, { useEffect, useMemo, useCallback } from 'react'; +import React, { useCallback, useEffect, useMemo } from 'react'; import type { Filter, Query } from '@kbn/es-query'; import styled from '@emotion/styled'; import { EuiButton } from '@elastic/eui'; -import type { DataViewSpec } from '@kbn/data-plugin/common'; +import type { DataView, DataViewSpec } from '@kbn/data-plugin/common'; import { getEsQueryConfig } from '@kbn/data-plugin/common'; -import { DEFAULT_NUMBER_FORMAT, APP_UI_ID } from '../../../../common/constants'; +import { APP_UI_ID, DEFAULT_NUMBER_FORMAT } from '../../../../common/constants'; import { SHOWING, UNIT } from '../../../common/components/events_viewer/translations'; import { getTabsOnHostsUrl } from '../../../common/components/link_to/redirect_to_hosts'; import { MatrixHistogram } from '../../../common/components/matrix_histogram'; @@ -25,8 +25,8 @@ import type { import { convertToBuildEsQuery } from '../../../common/lib/kuery'; import { useKibana, useUiSetting$ } from '../../../common/lib/kibana'; import { - eventsStackByOptions, eventsHistogramConfig, + eventsStackByOptions, NO_BREAKDOWN_STACK_BY_VALUE, } from '../../../common/components/events_tab/histogram_configurations'; import { HostsTableType } from '../../../explore/hosts/store/model'; @@ -48,6 +48,7 @@ interface Props extends Pick { filters: Filter[]; headerChildren?: React.ReactNode; dataViewSpec?: DataViewSpec; + dataView: DataView; onlyField?: string; paddingSize?: 's' | 'm' | 'l' | 'none'; query: Query; @@ -78,6 +79,7 @@ const EventsByDatasetComponent: React.FC = ({ from, headerChildren, dataViewSpec, + dataView, onlyField, paddingSize, query, @@ -131,12 +133,13 @@ const EventsByDatasetComponent: React.FC = ({ return convertToBuildEsQuery({ config: getEsQueryConfig(kibana.services.uiSettings), dataViewSpec, + dataView, queries: [query], filters, }); } return [filterQueryFromProps]; - }, [filterQueryFromProps, kibana.services.uiSettings, dataViewSpec, query, filters]); + }, [filterQueryFromProps, kibana.services.uiSettings, dataViewSpec, dataView, query, filters]); useInvalidFilterQuery({ id: uniqueQueryId, diff --git a/x-pack/solutions/security/plugins/security_solution/public/overview/pages/detection_response.tsx b/x-pack/solutions/security/plugins/security_solution/public/overview/pages/detection_response.tsx index b7c256b57fe4a..c38d5ceff32cf 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/overview/pages/detection_response.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/overview/pages/detection_response.tsx @@ -33,7 +33,6 @@ import { FiltersGlobal } from '../../common/components/filters_global'; import { useGlobalFilterQuery } from '../../common/hooks/use_global_filter_query'; import { useKibana } from '../../common/lib/kibana'; import { useDataView } from '../../data_view_manager/hooks/use_data_view'; -import { useDataViewSpec } from '../../data_view_manager/hooks/use_data_view_spec'; import { PageLoader } from '../../common/components/page_loader'; const DetectionResponseComponent = () => { @@ -47,12 +46,10 @@ const DetectionResponseComponent = () => { } = useSourcererDataView(); const newDataViewPickerEnabled = useIsExperimentalFeatureEnabled('newDataViewPickerEnabled'); - const { dataView, status } = useDataView(); - const { dataViewSpec } = useDataViewSpec(); + const { dataView: experimentalDataView, status } = useDataView(); - const sourcererDataView = newDataViewPickerEnabled ? dataViewSpec : oldSourcererDataView; const indicesExist = newDataViewPickerEnabled - ? !!dataView?.matchedIndices?.length + ? !!experimentalDataView.matchedIndices?.length : oldIndicesExist; const isSourcererLoading = newDataViewPickerEnabled ? status !== 'ready' : oldIsSourcererLoading; @@ -77,7 +74,10 @@ const DetectionResponseComponent = () => { {indicesExist ? ( <> - + diff --git a/x-pack/solutions/security/plugins/security_solution/public/overview/pages/overview.tsx b/x-pack/solutions/security/plugins/security_solution/public/overview/pages/overview.tsx index fa9e88efe27fd..d5dcfea83625e 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/overview/pages/overview.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/overview/pages/overview.tsx @@ -40,7 +40,6 @@ import { useUserPrivileges } from '../../common/components/user_privileges'; import { useAlertsPrivileges } from '../../detections/containers/detection_engine/alerts/use_alerts_privileges'; import { EmptyPrompt } from '../../common/components/empty_prompt'; import { useSelectedPatterns } from '../../data_view_manager/hooks/use_selected_patterns'; -import { useDataViewSpec } from '../../data_view_manager/hooks/use_data_view_spec'; import { useDataView } from '../../data_view_manager/hooks/use_data_view'; import { useIsExperimentalFeatureEnabled } from '../../common/hooks/use_experimental_features'; import { PageLoader } from '../../common/components/page_loader'; @@ -63,13 +62,11 @@ const OverviewComponent = () => { const newDataViewPickerEnabled = useIsExperimentalFeatureEnabled('newDataViewPickerEnabled'); - const { dataView, status } = useDataView(); - const { dataViewSpec } = useDataViewSpec(); + const { dataView: experimentalDataView, status } = useDataView(); const experimentalSelectedPatterns = useSelectedPatterns(); - const sourcererDataView = newDataViewPickerEnabled ? dataViewSpec : oldSourcererDataView; const indicesExist = newDataViewPickerEnabled - ? !!dataView?.matchedIndices?.length + ? !!experimentalDataView.matchedIndices?.length : oldIndicesExist; const selectedPatterns = newDataViewPickerEnabled ? experimentalSelectedPatterns @@ -109,7 +106,10 @@ const OverviewComponent = () => { {indicesExist ? ( <> - + @@ -140,7 +140,8 @@ const OverviewComponent = () => { deleteQuery={deleteQuery} filters={filters} from={from} - dataViewSpec={sourcererDataView} + dataViewSpec={oldSourcererDataView} + dataView={experimentalDataView} query={query} queryType="overview" to={to} @@ -152,7 +153,8 @@ const OverviewComponent = () => { filters={filters} from={from} indexNames={selectedPatterns} - dataViewSpec={sourcererDataView} + dataViewSpec={oldSourcererDataView} + dataView={experimentalDataView} query={query} setQuery={setQuery} to={to} diff --git a/x-pack/solutions/security/plugins/security_solution/public/resolver/view/controls/sourcerer_selection.test.tsx b/x-pack/solutions/security/plugins/security_solution/public/resolver/view/controls/sourcerer_selection.test.tsx index 55140a8e53d3f..909c5c65bf025 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/resolver/view/controls/sourcerer_selection.test.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/resolver/view/controls/sourcerer_selection.test.tsx @@ -11,12 +11,13 @@ import { useLocation } from 'react-router-dom'; import { SourcererButton } from './sourcerer_selection'; 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'; import { createMockStore, mockGlobalState } from '../../../common/mock'; import { TestProviders } from '../../../common/mock/test_providers'; import { DATA_VIEW_PICKER_TEST_ID } from '../../../data_view_manager/components/data_view_picker/constants'; import { ALERTS_PATH } from '../../../../common/constants'; import { DEFAULT_SECURITY_SOLUTION_DATA_VIEW_ID } from '../../../data_view_manager/constants'; +import type { DataView } from '@kbn/data-views-plugin/common'; jest.mock('react-router-dom', () => { const actual = jest.requireActual('react-router-dom'); @@ -32,8 +33,8 @@ jest.mock('react-redux', () => { jest.mock('../../../common/lib/kibana'); jest.mock('../../../common/hooks/use_experimental_features'); -jest.mock('../../../data_view_manager/hooks/use_data_view_spec', () => ({ - useDataViewSpec: jest.fn(), +jest.mock('../../../data_view_manager/hooks/use_data_view', () => ({ + useDataView: jest.fn(), })); jest.mock('../../../data_view_manager/hooks/use_select_data_view', () => ({ useSelectDataView: jest.fn().mockReturnValue(jest.fn()), @@ -45,11 +46,11 @@ describe('SourcererButton', () => { beforeEach(() => { jest.clearAllMocks(); (useLocation as jest.Mock).mockReturnValue({ pathname: ALERTS_PATH }); - jest.mocked(useDataViewSpec).mockReturnValue({ - dataViewSpec: { + jest.mocked(useDataView).mockReturnValue({ + dataView: { id: DEFAULT_SECURITY_SOLUTION_DATA_VIEW_ID, name: 'Default Security Data View', - }, + } as DataView, status: 'ready', }); jest.mocked(useKibana).mockReturnValue({ diff --git a/x-pack/solutions/security/plugins/security_solution/public/sourcerer/components/use_get_sourcerer_data_view.tsx b/x-pack/solutions/security/plugins/security_solution/public/sourcerer/components/use_get_sourcerer_data_view.tsx index 52b5ca9717e8d..2471aa620db4b 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/sourcerer/components/use_get_sourcerer_data_view.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/sourcerer/components/use_get_sourcerer_data_view.tsx @@ -10,6 +10,7 @@ import { DataView } from '@kbn/data-views-plugin/public'; import { useSourcererDataView } from '../containers'; import { useKibana } from '../../common/lib/kibana'; import type { SourcererScopeName } from '../store/model'; +import { useIsExperimentalFeatureEnabled } from '../../common/hooks/use_experimental_features'; export interface UseGetScopedSourcererDataViewArgs { sourcererScope: SourcererScopeName; @@ -27,15 +28,16 @@ export const useGetScopedSourcererDataView = ({ const { services: { fieldFormats }, } = useKibana(); + const newDataViewPickerEnabled = useIsExperimentalFeatureEnabled('newDataViewPickerEnabled'); const { sourcererDataView } = useSourcererDataView(sourcererScope); const dataView = useMemo(() => { - if (Object.keys(sourcererDataView).length) { + if (!newDataViewPickerEnabled && Object.keys(sourcererDataView).length) { return new DataView({ spec: sourcererDataView, fieldFormats }); } else { return undefined; } - }, [sourcererDataView, fieldFormats]); + }, [newDataViewPickerEnabled, sourcererDataView, fieldFormats]); return dataView; }; diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/modal/header/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/modal/header/index.tsx index da204ce3a5cbf..ba4ed94918c2d 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/modal/header/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/modal/header/index.tsx @@ -15,14 +15,13 @@ import { } from '@elastic/eui'; import React, { useCallback, useMemo } from 'react'; import { useDispatch, useSelector } from 'react-redux'; -import { type DataViewSpec, getEsQueryConfig } from '@kbn/data-plugin/common'; +import { getEsQueryConfig } from '@kbn/data-plugin/common'; import { euiStyled } from '@kbn/kibana-react-plugin/common'; import styled from 'styled-components'; +import { useDataView } from '../../../../data_view_manager/hooks/use_data_view'; import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; import { useSourcererDataView } from '../../../../sourcerer/containers'; import { SourcererScopeName } from '../../../../sourcerer/store/model'; - -import { useDataViewSpec } from '../../../../data_view_manager/hooks/use_data_view_spec'; import { NewTimelineButton } from '../actions/new_timeline_button'; import { OpenTimelineButton } from '../actions/open_timeline_button'; import { APP_ID } from '../../../../../common'; @@ -79,18 +78,12 @@ export const TimelineModalHeader = React.memo( const { browserFields: sourcererBrowserFields, sourcererDataView: oldSourcererDataViewSpec } = useSourcererDataView(SourcererScopeName.timeline); - const { dataViewSpec: experimentalDataViewSpec } = useDataViewSpec( - DataViewManagerScopeName.timeline - ); + const { dataView: experimentalDataView } = useDataView(DataViewManagerScopeName.timeline); const experimentalBrowserFields = useBrowserFields(DataViewManagerScopeName.timeline); const browserFields = useMemo( () => (newDataViewPickerEnabled ? experimentalBrowserFields : sourcererBrowserFields), [experimentalBrowserFields, newDataViewPickerEnabled, sourcererBrowserFields] ); - const dataViewSpec: DataViewSpec = useMemo( - () => (newDataViewPickerEnabled ? experimentalDataViewSpec : oldSourcererDataViewSpec), - [experimentalDataViewSpec, newDataViewPickerEnabled, oldSourcererDataViewSpec] - ); const { cases, uiSettings } = useKibana().services; const esQueryConfig = useMemo(() => getEsQueryConfig(uiSettings), [uiSettings]); @@ -109,13 +102,23 @@ export const TimelineModalHeader = React.memo( combineQueries({ config: esQueryConfig, dataProviders, - dataViewSpec, + dataViewSpec: oldSourcererDataViewSpec, + dataView: experimentalDataView, browserFields, filters: filters ? filters : [], kqlQuery: kqlQueryObj, kqlMode, }), - [browserFields, dataProviders, esQueryConfig, filters, kqlMode, kqlQueryObj, dataViewSpec] + [ + browserFields, + dataProviders, + esQueryConfig, + experimentalDataView, + filters, + kqlMode, + kqlQueryObj, + oldSourcererDataViewSpec, + ] ); const isInspectDisabled = !isDataInTimeline || combinedQueries?.filterQuery === undefined; diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/index.tsx index 0fdbb03484b54..3a2be081fede7 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/open_timeline/index.tsx @@ -58,7 +58,7 @@ import { useStartTransaction } from '../../../common/lib/apm/use_start_transacti import { TIMELINE_ACTIONS } from '../../../common/lib/apm/user_actions'; import { defaultUdtHeaders } from '../timeline/body/column_headers/default_headers'; import { timelineDefaults } from '../../store/defaults'; -import { useDataViewSpec } from '../../../data_view_manager/hooks/use_data_view_spec'; +import { useDataView } from '../../../data_view_manager/hooks/use_data_view'; interface OwnProps { /** Displays open timeline in modal */ @@ -164,12 +164,12 @@ export const StatefulOpenTimelineComponent = React.memo( useSourcererDataView(SourcererScopeName.timeline); const { newDataViewPickerEnabled } = useEnableExperimental(); - const { dataViewSpec: experimentalDataViewSpec } = useDataViewSpec(SourcererScopeName.timeline); + const { dataView: experimentalDataView } = useDataView(SourcererScopeName.timeline); const experimentalSelectedPatterns = useSelectedPatterns(SourcererScopeName.timeline); 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), diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/index.tsx index a535eba0d318a..2c012437bc017 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/index.tsx @@ -32,7 +32,7 @@ import { useResolveConflict } from '../../../common/hooks/use_resolve_conflict'; import { sourcererSelectors } from '../../../common/store'; import { defaultUdtHeaders } from './body/column_headers/default_headers'; import { useSelectedPatterns } from '../../../data_view_manager/hooks/use_selected_patterns'; -import { useDataViewSpec } from '../../../data_view_manager/hooks/use_data_view_spec'; +import { useDataView } from '../../../data_view_manager/hooks/use_data_view'; import { TimelineContext } from './context'; const TimelineBody = styled.div` @@ -106,12 +106,11 @@ const StatefulTimelineComponent: React.FC = ({ const newDataViewPickerEnabled = useIsExperimentalFeatureEnabled('newDataViewPickerEnabled'); const experimentalSelectedPatterns = useSelectedPatterns(SourcererScopeName.timeline); - const { dataViewSpec: experimentalDataViewSpec } = useDataViewSpec(SourcererScopeName.timeline); + const { dataView: experimentalDataView } = useDataView(SourcererScopeName.timeline); const selectedDataViewId = useMemo( - () => - newDataViewPickerEnabled ? experimentalDataViewSpec?.id ?? '' : selectedDataViewIdSourcerer, - [experimentalDataViewSpec?.id, newDataViewPickerEnabled, selectedDataViewIdSourcerer] + () => (newDataViewPickerEnabled ? experimentalDataView.id ?? '' : selectedDataViewIdSourcerer), + [experimentalDataView.id, newDataViewPickerEnabled, selectedDataViewIdSourcerer] ); const selectedPatterns = useMemo( diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/kpi/kpi_container.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/kpi/kpi_container.tsx index d6b49f94d32ae..50633afb5316e 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/kpi/kpi_container.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/kpi/kpi_container.tsx @@ -8,7 +8,7 @@ import React, { useMemo } from 'react'; import { isEmpty, pick } from 'lodash/fp'; import { useSelector } from 'react-redux'; -import { type DataViewSpec, getEsQueryConfig } from '@kbn/data-plugin/common'; +import { getEsQueryConfig } from '@kbn/data-plugin/common'; import type { TimerangeInput } from '@kbn/timelines-plugin/common'; import { EuiPanel } from '@elastic/eui'; import { useEnableExperimental } from '../../../../common/hooks/use_experimental_features'; @@ -29,7 +29,7 @@ import { startSelector, } from '../../../../common/components/super_date_picker/selectors'; import { useSelectedPatterns } from '../../../../data_view_manager/hooks/use_selected_patterns'; -import { useDataViewSpec } from '../../../../data_view_manager/hooks/use_data_view_spec'; +import { useDataView } from '../../../../data_view_manager/hooks/use_data_view'; interface KpiExpandedProps { timelineId: string; @@ -38,7 +38,7 @@ interface KpiExpandedProps { export const TimelineKpisContainer = ({ timelineId }: KpiExpandedProps) => { const { newDataViewPickerEnabled } = useEnableExperimental(); const experimentalBrowserFields = useBrowserFields(SourcererScopeName.timeline); - const { dataViewSpec: experimentalDataViewSpec } = useDataViewSpec(SourcererScopeName.timeline); + const { dataView: experimentalDataView } = useDataView(SourcererScopeName.timeline); const experimentalSelectedPatterns = useSelectedPatterns(SourcererScopeName.timeline); const { @@ -51,10 +51,6 @@ export const TimelineKpisContainer = ({ timelineId }: KpiExpandedProps) => { () => (newDataViewPickerEnabled ? experimentalBrowserFields : oldBrowserFields), [experimentalBrowserFields, newDataViewPickerEnabled, oldBrowserFields] ); - const dataViewSpec: DataViewSpec = useMemo( - () => (newDataViewPickerEnabled ? experimentalDataViewSpec : oldSourcererDataViewSpec), - [experimentalDataViewSpec, newDataViewPickerEnabled, oldSourcererDataViewSpec] - ); const selectedPatterns = useMemo( () => (newDataViewPickerEnabled ? experimentalSelectedPatterns : oldSelectedPatterns), [experimentalSelectedPatterns, newDataViewPickerEnabled, oldSelectedPatterns] @@ -106,13 +102,23 @@ export const TimelineKpisContainer = ({ timelineId }: KpiExpandedProps) => { combineQueries({ config: esQueryConfig, dataProviders, - dataViewSpec, + dataViewSpec: oldSourcererDataViewSpec, + dataView: experimentalDataView, browserFields, filters: filters ? filters : [], kqlQuery, kqlMode, }), - [browserFields, dataProviders, esQueryConfig, filters, dataViewSpec, kqlMode, kqlQuery] + [ + esQueryConfig, + dataProviders, + oldSourcererDataViewSpec, + experimentalDataView, + browserFields, + filters, + kqlQuery, + kqlMode, + ] ); const isBlankTimeline: boolean = useMemo( diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/query_bar/eql/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/query_bar/eql/index.tsx index 6345568d21a41..f64073fc1b558 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/query_bar/eql/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/query_bar/eql/index.tsx @@ -11,9 +11,8 @@ import { EuiOutsideClickDetector } from '@elastic/eui'; import { useDispatch } from 'react-redux'; import { css } from '@emotion/css'; -import type { DataViewSpec } from '@kbn/data-views-plugin/common'; import { useEnableExperimental } 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'; import type { EqlOptions } from '../../../../../../common/search_strategy'; import { useDeepEqualSelector } from '../../../../../common/hooks/use_selector'; import { SourcererScopeName } from '../../../../../sourcerer/store/model'; @@ -71,19 +70,13 @@ export const EqlQueryBarTimeline = memo(({ timelineId }: { timelineId: string }) const { newDataViewPickerEnabled } = useEnableExperimental(); - const { dataViewSpec: experimentalDataViewSpec, status } = useDataViewSpec( - SourcererScopeName.timeline - ); + const { dataView: experimentalDataView, status } = useDataView(SourcererScopeName.timeline); const experimentalSelectedPatterns = useSelectedPatterns(SourcererScopeName.timeline); const indexPatternsLoading = useMemo( () => (newDataViewPickerEnabled ? status !== 'ready' : oldIndexPatternsLoading), [newDataViewPickerEnabled, oldIndexPatternsLoading, status] ); - const dataViewSpec: DataViewSpec = useMemo( - () => (newDataViewPickerEnabled ? experimentalDataViewSpec : oldSourcererDataViewSpec), - [experimentalDataViewSpec, newDataViewPickerEnabled, oldSourcererDataViewSpec] - ); const selectedPatterns = useMemo( () => (newDataViewPickerEnabled ? experimentalSelectedPatterns : oldSelectedPatterns), [experimentalSelectedPatterns, newDataViewPickerEnabled, oldSelectedPatterns] @@ -178,17 +171,19 @@ export const EqlQueryBarTimeline = memo(({ timelineId }: { timelineId: string }) } }, [getFields, selectedPatterns]); - const dataView = useMemo( - () => ({ - ...dataViewSpec, - title: dataViewSpec.title ?? '', - fields: Object.values(dataViewSpec.fields || {}), - }), - [dataViewSpec] - ); + const dataView = useMemo(() => { + return newDataViewPickerEnabled + ? experimentalDataView || { title: '', fields: [] } + : { + title: oldSourcererDataViewSpec.title ?? '', + fields: Object.values(oldSourcererDataViewSpec.fields || {}), + }; + }, [experimentalDataView, newDataViewPickerEnabled, oldSourcererDataViewSpec]); /* Force casting `dataViewSpec` to `DataViewBase` is required since EqlQueryEdit - accepts DataViewBase but `useSourcererDataView()` returns `DataViewSpec`. + accepts DataViewBase but `useSourcererDataView()` returns `DataViewSpec`. Since + the DataView class inherits from DataViewBase, it is safe to use directly and the prioir statement is only valid + while sourcerer is not migrated to the new data view picker. When using `UseField` with `EqlQueryBar` such casting isn't required by TS since `UseField` component props are types as `Record`. */ diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/query_bar/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/query_bar/index.tsx index 58cdd9c444145..98a679fda16e3 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/query_bar/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/query_bar/index.tsx @@ -13,10 +13,8 @@ import type { Filter, Query } from '@kbn/es-query'; import { FilterStateStore } from '@kbn/es-query'; import type { FilterManager, SavedQuery, SavedQueryTimeFilter } from '@kbn/data-plugin/public'; import styled from '@emotion/styled'; -import type { DataViewSpec } from '@kbn/data-views-plugin/common'; import { useEnableExperimental } from '../../../../common/hooks/use_experimental_features'; import { useDataView } from '../../../../data_view_manager/hooks/use_data_view'; -import { useDataViewSpec } from '../../../../data_view_manager/hooks/use_data_view_spec'; import { InputsModelId } from '../../../../common/store/inputs/constants'; import { SourcererScopeName } from '../../../../sourcerer/store/model'; @@ -121,17 +119,16 @@ export const QueryBarTimeline = memo( const { newDataViewPickerEnabled } = useEnableExperimental(); const { dataView: experimentalDataView } = useDataView(SourcererScopeName.timeline); - const { dataViewSpec: experimentalDataViewSpec } = useDataViewSpec(SourcererScopeName.timeline); + const experimentalBrowserFields = useBrowserFields(SourcererScopeName.timeline); - const dataViewSpec: DataViewSpec = useMemo( - () => (newDataViewPickerEnabled ? experimentalDataViewSpec : oldSourcererDataViewSpec), - [experimentalDataViewSpec, newDataViewPickerEnabled, oldSourcererDataViewSpec] + const dataViewBase = useMemo( + () => dataViewSpecToViewBase(oldSourcererDataViewSpec), + [oldSourcererDataViewSpec] ); - const dataViewBase = useMemo(() => dataViewSpecToViewBase(dataViewSpec), [dataViewSpec]); + const dataView = useMemo( - () => - newDataViewPickerEnabled && experimentalDataView ? experimentalDataView : dataViewBase, + () => (newDataViewPickerEnabled ? experimentalDataView : dataViewBase), [newDataViewPickerEnabled, experimentalDataView, dataViewBase] ); @@ -148,7 +145,7 @@ export const QueryBarTimeline = memo( const queryBarFilters = useMemo(() => getNonDropAreaFilters(filters), [filters]); const [dataProvidersDsl, setDataProvidersDsl] = useState( - convertKueryToElasticSearchQuery(buildGlobalQuery(dataProviders, browserFields), dataViewBase) + convertKueryToElasticSearchQuery(buildGlobalQuery(dataProviders, browserFields), dataView) ); const savedQueryServices = useSavedQueryServices(); @@ -162,11 +159,11 @@ export const QueryBarTimeline = memo( kind, expression, }, - serializedQuery: convertKueryToElasticSearchQuery(expression, dataViewBase), + serializedQuery: convertKueryToElasticSearchQuery(expression, dataView), }, }) ), - [dispatch, dataViewBase, timelineId] + [dispatch, dataView, timelineId] ); useEffect(() => { @@ -178,12 +175,9 @@ export const QueryBarTimeline = memo( useEffect(() => { setDataProvidersDsl( - convertKueryToElasticSearchQuery( - buildGlobalQuery(dataProviders, browserFields), - dataViewBase - ) + convertKueryToElasticSearchQuery(buildGlobalQuery(dataProviders, browserFields), dataView) ); - }, [dataProviders, browserFields, dataViewBase]); + }, [dataProviders, browserFields, dataView]); useEffect(() => { if (fromStr != null && toStr != null) { diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/eql/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/eql/index.tsx index 1fc2bb64a1cb6..0814b486e4fa7 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/eql/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/eql/index.tsx @@ -16,7 +16,6 @@ import { InPortal } from 'react-reverse-portal'; import { DataLoadingState } from '@kbn/unified-data-table'; import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; import type { RunTimeMappings } from '@kbn/timelines-plugin/common/search_strategy'; -import type { DataViewSpec } from '@kbn/data-views-plugin/common'; import { useFetchNotes } from '../../../../../notes/hooks/use_fetch_notes'; import { InputsModelId } from '../../../../../common/store/inputs/constants'; import { useKibana } from '../../../../../common/lib/kibana'; @@ -49,7 +48,7 @@ import { useNotesInFlyout } from '../../properties/use_notes_in_flyout'; import { NotesFlyout } from '../../properties/notes_flyout'; import { DocumentEventTypes, NotesEventTypes } from '../../../../../common/lib/telemetry'; import { TimelineRefetch } from '../../refetch_timeline'; -import { useDataViewSpec } from '../../../../../data_view_manager/hooks/use_data_view_spec'; +import { useDataView } from '../../../../../data_view_manager/hooks/use_data_view'; import { useSelectedPatterns } from '../../../../../data_view_manager/hooks/use_selected_patterns'; export type Props = TimelineTabCommonProps & PropsFromRedux; @@ -88,11 +87,9 @@ export const EqlTabContentComponent: React.FC = ({ sourcererDataView: oldSourcererDataViewSpec, } = useSourcererDataView(SourcererScopeName.timeline); - const { dataViewSpec: experimentalDataViewSpec, status } = useDataViewSpec( - SourcererScopeName.timeline - ); + const { dataView: experimentalDataView, status } = useDataView(SourcererScopeName.timeline); const experimentalSelectedPatterns = useSelectedPatterns(SourcererScopeName.timeline); - const experimentalDataViewId = experimentalDataViewSpec.id ?? null; + const experimentalDataViewId = experimentalDataView.id ?? null; const dataViewId = useMemo( () => (newDataViewPickerEnabled ? experimentalDataViewId : oldDataViewId), @@ -102,10 +99,13 @@ export const EqlTabContentComponent: React.FC = ({ () => (newDataViewPickerEnabled ? status !== 'ready' : oldSourcererLoading), [newDataViewPickerEnabled, oldSourcererLoading, status] ); - const dataViewSpec: DataViewSpec = useMemo( - () => (newDataViewPickerEnabled ? experimentalDataViewSpec : oldSourcererDataViewSpec), - [experimentalDataViewSpec, newDataViewPickerEnabled, oldSourcererDataViewSpec] - ); + + const runtimeMappings = useMemo(() => { + return newDataViewPickerEnabled + ? (experimentalDataView.getRuntimeMappings() as RunTimeMappings) + : (oldSourcererDataViewSpec.runtimeFieldMap as RunTimeMappings); + }, [newDataViewPickerEnabled, experimentalDataView, oldSourcererDataViewSpec.runtimeFieldMap]); + const selectedPatterns = useMemo( () => (newDataViewPickerEnabled ? experimentalSelectedPatterns : oldSelectedPatterns), [experimentalSelectedPatterns, newDataViewPickerEnabled, oldSelectedPatterns] @@ -144,7 +144,7 @@ export const EqlTabContentComponent: React.FC = ({ indexNames: selectedPatterns, language: 'eql', limit: sampleSize, - runtimeMappings: dataViewSpec.runtimeFieldMap as RunTimeMappings, + runtimeMappings, skip: !canQueryTimeline(), startDate: start, timerangeKind, diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/esql/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/esql/index.tsx index c41a2155b50c6..07257a4ebc66e 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/esql/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/esql/index.tsx @@ -19,7 +19,7 @@ import type { TimeRange } from '@kbn/es-query'; import { useDispatch } from 'react-redux'; import type { DataViewSpec } from '@kbn/data-views-plugin/common'; 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'; import { updateSavedSearchId } from '../../../../store/actions'; import { useDiscoverInTimelineContext } from '../../../../../common/components/discover_in_timeline/use_discover_in_timeline_context'; import { useKibana } from '../../../../../common/lib/kibana'; @@ -62,17 +62,12 @@ export const DiscoverTabContent: FC = ({ timelineId }) const dispatch = useDispatch(); const newDataViewPickerEnabled = useIsExperimentalFeatureEnabled('newDataViewPickerEnabled'); - const { dataViewSpec: experimentalDataViewSpec } = useDataViewSpec(SourcererScopeName.detections); + const { status: dataViewStatus } = useDataView(SourcererScopeName.detections); const { dataViewId } = useSourcererDataView(SourcererScopeName.detections); const [oldDataViewSpec, setDataViewSpec] = useState(); - const dataViewSpec: DataViewSpec | undefined = useMemo( - () => (newDataViewPickerEnabled ? experimentalDataViewSpec : oldDataViewSpec), - [experimentalDataViewSpec, newDataViewPickerEnabled, oldDataViewSpec] - ); - const [discoverTimerange, setDiscoverTimerange] = useState(); const discoverAppStateSubscription = useRef(); @@ -82,9 +77,9 @@ export const DiscoverTabContent: FC = ({ timelineId }) // TODO: (DV_PICKER) should not be here, used to make discover container work I suppose useEffect(() => { - if (!dataViewId) return; + if (!dataViewId || newDataViewPickerEnabled) return; dataViewService.get(dataViewId).then((dv) => setDataViewSpec(dv?.toSpec?.())); - }, [dataViewId, dataViewService]); + }, [dataViewId, dataViewService, newDataViewPickerEnabled]); const { discoverStateContainer, @@ -289,8 +284,9 @@ export const DiscoverTabContent: FC = ({ timelineId }) const DiscoverContainer = discover.DiscoverContainer; - // TODO: (DV_PICKER) this should not work like that - const isLoading = !dataViewSpec; + const isLoading = newDataViewPickerEnabled + ? dataViewStatus === 'loading' || dataViewStatus === 'pristine' + : !oldDataViewSpec; // TODO: (DV_PICKER) this should not work like that return ( diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/pinned/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/pinned/index.tsx index efee515b081a5..f34e6c099ca57 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/pinned/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/pinned/index.tsx @@ -13,9 +13,8 @@ import deepEqual from 'fast-deep-equal'; import type { EuiDataGridControlColumn } from '@elastic/eui'; import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; import type { RunTimeMappings } from '@kbn/timelines-plugin/common/search_strategy'; -import type { DataViewSpec } from '@kbn/data-views-plugin/common'; import { useSourcererDataView } from '../../../../../sourcerer/containers'; -import { useDataViewSpec } from '../../../../../data_view_manager/hooks/use_data_view_spec'; +import { useDataView } from '../../../../../data_view_manager/hooks/use_data_view'; import { useSelectedPatterns } from '../../../../../data_view_manager/hooks/use_selected_patterns'; import { useFetchNotes } from '../../../../../notes/hooks/use_fetch_notes'; import { @@ -94,19 +93,24 @@ export const PinnedTabContentComponent: React.FC = ({ } = useSourcererDataView(SourcererScopeName.timeline); const experimentalSelectedPatterns = useSelectedPatterns(SourcererScopeName.timeline); - const { dataViewSpec: experimentalDataViewSpec } = useDataViewSpec(SourcererScopeName.timeline); + const { dataView: experimentalDataView } = useDataView(SourcererScopeName.timeline); const selectedPatterns = useMemo( () => (newDataViewPickerEnabled ? experimentalSelectedPatterns : oldSelectedPatterns), [experimentalSelectedPatterns, newDataViewPickerEnabled, oldSelectedPatterns] ); - const dataViewSpec: DataViewSpec = useMemo( - () => (newDataViewPickerEnabled ? experimentalDataViewSpec : oldSourcererDataViewSpec), - [experimentalDataViewSpec, newDataViewPickerEnabled, oldSourcererDataViewSpec] - ); + const dataViewId = useMemo( - () => (newDataViewPickerEnabled ? experimentalDataViewSpec.id ?? '' : oldDataViewId), - [experimentalDataViewSpec.id, newDataViewPickerEnabled, oldDataViewId] + () => (newDataViewPickerEnabled ? experimentalDataView.id ?? '' : oldDataViewId), + [experimentalDataView.id, newDataViewPickerEnabled, oldDataViewId] + ); + + const runtimeMappings = useMemo( + () => + newDataViewPickerEnabled + ? (experimentalDataView.getRuntimeMappings() as RunTimeMappings) + : (oldSourcererDataViewSpec?.runtimeFieldMap as RunTimeMappings), + [experimentalDataView, newDataViewPickerEnabled, oldSourcererDataViewSpec] ); const filterQuery = useMemo(() => { @@ -175,7 +179,7 @@ export const PinnedTabContentComponent: React.FC = ({ fields: timelineQueryFields, limit: itemsPerPage, filterQuery, - runtimeMappings: dataViewSpec.runtimeFieldMap as RunTimeMappings, + runtimeMappings, skip: filterQuery === '', startDate: '', sort: timelineQuerySortField, diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/query/events_count.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/query/events_count.tsx index 1734e38f5828d..c3f47d0d4c19b 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/query/events_count.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/query/events_count.tsx @@ -12,6 +12,7 @@ import { getEsQueryConfig } from '@kbn/data-plugin/common'; import type { RunTimeMappings } from '@kbn/timelines-plugin/common/search_strategy'; import { EuiLoadingSpinner } from '@elastic/eui'; import { DataLoadingState } from '@kbn/unified-data-table'; +import { useDataView } from '../../../../../data_view_manager/hooks/use_data_view'; import { useDeepEqualSelector } from '../../../../../common/hooks/use_selector'; import { useTimelineDataFilters } from '../../../../containers/use_timeline_data_filters'; import { useInvalidFilterQuery } from '../../../../../common/hooks/use_invalid_filter_query'; @@ -95,6 +96,7 @@ export const TimelineQueryTabEventsCountComponent: React.FC<{ timelineId: string selectedPatterns, sourcererDataView, } = useSourcererDataView(SourcererScopeName.timeline); + const { dataView: experimentalDataView } = useDataView(SourcererScopeName.timeline); /* * `pageIndex` needs to be maintained for each table in each tab independently * and consequently it cannot be the part of common redux state @@ -117,12 +119,22 @@ export const TimelineQueryTabEventsCountComponent: React.FC<{ timelineId: string config: esQueryConfig, dataProviders, dataViewSpec: sourcererDataView, + dataView: experimentalDataView, browserFields, filters, kqlQuery, kqlMode, }); - }, [esQueryConfig, dataProviders, sourcererDataView, browserFields, filters, kqlQuery, kqlMode]); + }, [ + esQueryConfig, + dataProviders, + sourcererDataView, + experimentalDataView, + browserFields, + filters, + kqlQuery, + kqlMode, + ]); useInvalidFilterQuery({ id: timelineId, diff --git a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/query/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/query/index.tsx index 8990af034bbac..c6c3829790c93 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/query/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/timelines/components/timeline/tabs/query/index.tsx @@ -11,13 +11,13 @@ import type { ConnectedProps } from 'react-redux'; import { connect, useDispatch } from 'react-redux'; import deepEqual from 'fast-deep-equal'; import type { EuiDataGridControlColumn } from '@elastic/eui'; -import { type DataViewSpec, getEsQueryConfig } from '@kbn/data-plugin/common'; +import { getEsQueryConfig } from '@kbn/data-plugin/common'; import { DataLoadingState } from '@kbn/unified-data-table'; import { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; import type { RunTimeMappings } from '@kbn/timelines-plugin/common/search_strategy'; +import { useDataView } from '../../../../../data_view_manager/hooks/use_data_view'; import { useSelectedPatterns } from '../../../../../data_view_manager/hooks/use_selected_patterns'; import { useBrowserFields } from '../../../../../data_view_manager/hooks/use_browser_fields'; -import { useDataViewSpec } from '../../../../../data_view_manager/hooks/use_data_view_spec'; import { useFetchNotes } from '../../../../../notes/hooks/use_fetch_notes'; import { DocumentDetailsLeftPanelKey, @@ -71,13 +71,11 @@ export const QueryTabContentComponent: React.FC = ({ end, filters, timelineId, - isLive, itemsPerPage, itemsPerPageOptions, kqlMode, kqlQueryExpression, kqlQueryLanguage, - renderCellValue, rowRenderers, show, showCallOutUnauthorizedMsg, @@ -91,7 +89,7 @@ export const QueryTabContentComponent: React.FC = ({ const dispatch = useDispatch(); const { newDataViewPickerEnabled } = useEnableExperimental(); - const { dataViewSpec: experimentalDataViewSpec, status: sourcererStatus } = useDataViewSpec( + const { dataView: experimentalDataView, status: sourcererStatus } = useDataView( SourcererScopeName.timeline ); const experimentalBrowserFields = useBrowserFields(SourcererScopeName.timeline); @@ -111,10 +109,6 @@ export const QueryTabContentComponent: React.FC = ({ () => (newDataViewPickerEnabled ? sourcererStatus !== 'ready' : oldLoadingSourcerer), [newDataViewPickerEnabled, oldLoadingSourcerer, sourcererStatus] ); - const dataViewSpec: DataViewSpec = useMemo( - () => (newDataViewPickerEnabled ? experimentalDataViewSpec : oldSourcererDataViewSpec), - [experimentalDataViewSpec, newDataViewPickerEnabled, oldSourcererDataViewSpec] - ); const browserFields = useMemo( () => (newDataViewPickerEnabled ? experimentalBrowserFields : oldBrowserFields), [experimentalBrowserFields, newDataViewPickerEnabled, oldBrowserFields] @@ -124,8 +118,8 @@ export const QueryTabContentComponent: React.FC = ({ [experimentalSelectedPatterns, newDataViewPickerEnabled, oldSelectedPatterns] ); const dataViewId = useMemo( - () => (newDataViewPickerEnabled ? experimentalDataViewSpec.id ?? '' : oldDataViewId), - [experimentalDataViewSpec.id, newDataViewPickerEnabled, oldDataViewId] + () => (newDataViewPickerEnabled ? experimentalDataView.id ?? '' : oldDataViewId), + [experimentalDataView.id, newDataViewPickerEnabled, oldDataViewId] ); /* @@ -158,17 +152,33 @@ export const QueryTabContentComponent: React.FC = ({ [kqlQueryExpression, kqlQueryLanguage] ); + const runtimeMappings = useMemo(() => { + return newDataViewPickerEnabled + ? (experimentalDataView.getRuntimeMappings() as RunTimeMappings) + : (oldSourcererDataViewSpec.runtimeFieldMap as RunTimeMappings); + }, [newDataViewPickerEnabled, experimentalDataView, oldSourcererDataViewSpec.runtimeFieldMap]); + const combinedQueries = useMemo(() => { return combineQueries({ config: esQueryConfig, dataProviders, - dataViewSpec, + dataViewSpec: oldSourcererDataViewSpec, + dataView: experimentalDataView, browserFields, filters, kqlQuery, kqlMode, }); - }, [esQueryConfig, dataProviders, dataViewSpec, browserFields, filters, kqlQuery, kqlMode]); + }, [ + esQueryConfig, + dataProviders, + oldSourcererDataViewSpec, + experimentalDataView, + browserFields, + filters, + kqlQuery, + kqlMode, + ]); useInvalidFilterQuery({ id: timelineId, @@ -218,7 +228,7 @@ export const QueryTabContentComponent: React.FC = ({ indexNames: selectedPatterns, language: kqlQuery.language, limit: sampleSize, - runtimeMappings: dataViewSpec.runtimeFieldMap as RunTimeMappings, + runtimeMappings, skip: !canQueryTimeline, sort: timelineQuerySortField, startDate: start, @@ -473,7 +483,6 @@ const makeMapStateToProps = () => { timelineId, pinnedEventIds, eventIdToNoteIds, - isLive: input.policy.kind === 'interval', itemsPerPage, itemsPerPageOptions, kqlMode, @@ -501,7 +510,6 @@ const QueryTabContent = connector( compareQueryProps(prevProps, nextProps) && prevProps.activeTab === nextProps.activeTab && isTimerangeSame(prevProps, nextProps) && - prevProps.isLive === nextProps.isLive && prevProps.itemsPerPage === nextProps.itemsPerPage && prevProps.show === nextProps.show && prevProps.showCallOutUnauthorizedMsg === nextProps.showCallOutUnauthorizedMsg && From bc968510d3ccc83dff14b0ece576cdfc645704b5 Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 16 Jul 2025 23:18:45 +0000 Subject: [PATCH 2/4] [CI] Auto-commit changed files from 'node scripts/eslint_all_files --no-cache --fix' --- .../public/explore/users/pages/details/index.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/users/pages/details/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/explore/users/pages/details/index.tsx index 4fd345fa1bac6..2713b26ba59dd 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/users/pages/details/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/users/pages/details/index.tsx @@ -56,7 +56,6 @@ import { UsersDetailsTabs } from './details_tabs'; import { navTabsUsersDetails } from './nav_tabs'; import type { UsersDetailsProps } from './types'; import { getUsersDetailsPageFilters } from './helpers'; -import { showGlobalFilters } from '../../../../timelines/components/timeline/helpers'; import { useGlobalFullScreen } from '../../../../common/containers/use_full_screen'; import { timelineDefaults } from '../../../../timelines/store/defaults'; import { useSourcererDataView } from '../../../../sourcerer/containers'; From a55b839619ed7725c3d02528b576fec6de6c0835 Mon Sep 17 00:00:00 2001 From: Davis Plumlee Date: Wed, 16 Jul 2025 20:23:33 -0400 Subject: [PATCH 3/4] fix type errors --- .../public/explore/users/pages/details/index.tsx | 11 +---------- .../public/kubernetes/pages/index.tsx | 13 ++++++++----- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/x-pack/solutions/security/plugins/security_solution/public/explore/users/pages/details/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/explore/users/pages/details/index.tsx index 2713b26ba59dd..cc10d1bfad456 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/explore/users/pages/details/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/explore/users/pages/details/index.tsx @@ -19,7 +19,6 @@ import { useDispatch } from 'react-redux'; import { getEsQueryConfig } from '@kbn/data-plugin/common'; import type { Filter } from '@kbn/es-query'; import { buildEsQuery } from '@kbn/es-query'; -import { dataTableSelectors, TableId } from '@kbn/securitysolution-data-table'; import { LastEventIndexKey } from '@kbn/timelines-plugin/common'; import { DataViewManagerScopeName } from '../../../../data_view_manager/constants'; import { SourcererScopeName } from '../../../../sourcerer/store/model'; @@ -57,12 +56,8 @@ import { navTabsUsersDetails } from './nav_tabs'; import type { UsersDetailsProps } from './types'; import { getUsersDetailsPageFilters } from './helpers'; import { useGlobalFullScreen } from '../../../../common/containers/use_full_screen'; -import { timelineDefaults } from '../../../../timelines/store/defaults'; import { useSourcererDataView } from '../../../../sourcerer/containers'; -import { - useDeepEqualSelector, - useShallowEqualSelector, -} from '../../../../common/hooks/use_selector'; +import { useDeepEqualSelector } from '../../../../common/hooks/use_selector'; import { useInvalidFilterQuery } from '../../../../common/hooks/use_invalid_filter_query'; import { LastEventTime } from '../../../../common/components/last_event_time'; import { EntityType } from '../../../../../common/entity_analytics/types'; @@ -94,10 +89,6 @@ const UsersDetailsComponent: React.FC = ({ usersDetailsPagePath, }) => { const dispatch = useDispatch(); - const getTable = useMemo(() => dataTableSelectors.getTableByIdSelector(), []); - const graphEventId = useShallowEqualSelector( - (state) => (getTable(state, TableId.hostsPageEvents) ?? timelineDefaults).graphEventId - ); const getGlobalFiltersQuerySelector = useMemo( () => inputsSelectors.globalFiltersQuerySelector(), [] diff --git a/x-pack/solutions/security/plugins/security_solution/public/kubernetes/pages/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/kubernetes/pages/index.tsx index 55c8a4472379b..db1469d765283 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/kubernetes/pages/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/kubernetes/pages/index.tsx @@ -26,12 +26,14 @@ import { useInvalidFilterQuery } from '../../common/hooks/use_invalid_filter_que import { SessionsView } from '../../common/components/sessions_viewer'; import { kubernetesSessionsHeaders } from './constants'; import { dataViewSpecToIndexPattern } from './utils/data_view_spec_to_index_pattern'; +import { useDataView } from '../../data_view_manager/hooks/use_data_view'; export const KubernetesContainer = React.memo(() => { const { kubernetesSecurity, uiSettings } = useKibana().services; const { globalFullScreen } = useGlobalFullScreen(); - const { sourcererDataView, dataViewId } = useSourcererDataView(); + const { sourcererDataView: oldSourcererDataView, dataViewId } = useSourcererDataView(); + const { dataView: experimentalDataView } = useDataView(); const { from, to } = useGlobalTime(); const getGlobalFiltersQuerySelector = useMemo( @@ -46,11 +48,12 @@ export const KubernetesContainer = React.memo(() => { () => convertToBuildEsQuery({ config: getEsQueryConfig(uiSettings), - dataViewSpec: sourcererDataView, + dataViewSpec: oldSourcererDataView, + dataView: experimentalDataView, queries: [query], filters, }), - [filters, sourcererDataView, uiSettings, query] + [filters, oldSourcererDataView, uiSettings, query] ); useInvalidFilterQuery({ @@ -82,10 +85,10 @@ export const KubernetesContainer = React.memo(() => { {kubernetesSecurity.getKubernetesPage({ filter: ( - + ), - indexPattern: dataViewSpecToIndexPattern(sourcererDataView), + indexPattern: dataViewSpecToIndexPattern(oldSourcererDataView), globalFilter: { filterQuery, startDate: from, From 3796300150b3389327fb443b2805f2e4cc862449 Mon Sep 17 00:00:00 2001 From: Michael Olorunnisola Date: Wed, 16 Jul 2025 21:08:05 -0400 Subject: [PATCH 4/4] fix deps list --- .../plugins/security_solution/public/kubernetes/pages/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/solutions/security/plugins/security_solution/public/kubernetes/pages/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/kubernetes/pages/index.tsx index db1469d765283..9004db61ae6df 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/kubernetes/pages/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/kubernetes/pages/index.tsx @@ -53,7 +53,7 @@ export const KubernetesContainer = React.memo(() => { queries: [query], filters, }), - [filters, oldSourcererDataView, uiSettings, query] + [uiSettings, oldSourcererDataView, experimentalDataView, query, filters] ); useInvalidFilterQuery({