From 00e77ef6d9992eef9cf8b0968a9ec75b93c2710e Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Wed, 12 Oct 2022 14:22:12 +0100 Subject: [PATCH 01/25] Use Unified Search Bar for query input --- .../public/search_bar/search_bar.tsx | 4 +- .../logs/log_filter/log_filter_state.ts | 65 ++++++------------- .../log_filter/with_log_filter_url_state.tsx | 13 ++-- .../public/pages/logs/stream/page_toolbar.tsx | 45 ++++++------- 4 files changed, 52 insertions(+), 75 deletions(-) diff --git a/src/plugins/unified_search/public/search_bar/search_bar.tsx b/src/plugins/unified_search/public/search_bar/search_bar.tsx index 76746d8a86979..6824c136d881f 100644 --- a/src/plugins/unified_search/public/search_bar/search_bar.tsx +++ b/src/plugins/unified_search/public/search_bar/search_bar.tsx @@ -450,7 +450,7 @@ class SearchBarUI extends C /> ); - const queryBarMenu = ( + const queryBarMenu = this.props.showQueryBar ? ( extends C : undefined } /> - ); + ) : undefined; let filterBar; if (this.shouldRenderFilterBar()) { diff --git a/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts b/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts index 70d72c25158da..fd7097acf740f 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts +++ b/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts @@ -5,12 +5,14 @@ * 2.0. */ +import { useMemo } from 'react'; import { buildEsQuery, DataViewBase, Query } from '@kbn/es-query'; import createContainer from 'constate'; import { useCallback, useState } from 'react'; -import useDebounce from 'react-use/lib/useDebounce'; import { useKibanaQuerySettings } from '../../../utils/use_kibana_query_settings'; import { BuiltEsQuery } from '../log_stream'; +import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; +import { useSubscription } from '../../../utils/use_observable'; interface ILogFilterState { filterQuery: { @@ -19,7 +21,6 @@ interface ILogFilterState { originalQuery: Query; } | null; filterQueryDraft: Query; - validationErrors: string[]; } const initialLogFilterState: ILogFilterState = { @@ -28,12 +29,14 @@ const initialLogFilterState: ILogFilterState = { language: 'kuery', query: '', }, - validationErrors: [], }; -const validationDebounceTimeout = 1000; // milliseconds - export const useLogFilterState = ({ indexPattern }: { indexPattern: DataViewBase }) => { + const { + data: { + query: { queryString }, + }, + } = useKibanaContextForPlugin().services; const [logFilterState, setLogFilterState] = useState(initialLogFilterState); const kibanaQuerySettings = useKibanaQuerySettings(); @@ -42,38 +45,8 @@ export const useLogFilterState = ({ indexPattern }: { indexPattern: DataViewBase [indexPattern, kibanaQuerySettings] ); - const setLogFilterQueryDraft = useCallback((filterQueryDraft: Query) => { - setLogFilterState((previousLogFilterState) => ({ - ...previousLogFilterState, - filterQueryDraft, - validationErrors: [], - })); - }, []); - - const [, cancelPendingValidation] = useDebounce( - () => { - setLogFilterState((previousLogFilterState) => { - try { - parseQuery(logFilterState.filterQueryDraft); - return { - ...previousLogFilterState, - validationErrors: [], - }; - } catch (error) { - return { - ...previousLogFilterState, - validationErrors: [`${error}`], - }; - } - }); - }, - validationDebounceTimeout, - [logFilterState.filterQueryDraft, parseQuery] - ); - const applyLogFilterQuery = useCallback( (filterQuery: Query) => { - cancelPendingValidation(); try { const parsedQuery = parseQuery(filterQuery); setLogFilterState((previousLogFilterState) => ({ @@ -83,24 +56,26 @@ export const useLogFilterState = ({ indexPattern }: { indexPattern: DataViewBase serializedQuery: JSON.stringify(parsedQuery), originalQuery: filterQuery, }, - filterQueryDraft: filterQuery, - validationErrors: [], })); } catch (error) { - setLogFilterState((previousLogFilterState) => ({ - ...previousLogFilterState, - validationErrors: [`${error}`], - })); + // This shouldn't really happen as the Unified Search Bar handles passing through the query. } }, - [cancelPendingValidation, parseQuery] + [parseQuery] + ); + + useSubscription( + useMemo(() => queryString.getUpdates$(), [queryString]), + { + next: useCallback(() => { + const esQuery = queryString.getQuery(); + applyLogFilterQuery(esQuery as Query); + }, [applyLogFilterQuery, queryString]), + } ); return { filterQuery: logFilterState.filterQuery, - filterQueryDraft: logFilterState.filterQueryDraft, - isFilterQueryDraftValid: logFilterState.validationErrors.length === 0, - setLogFilterQueryDraft, applyLogFilterQuery, }; }; diff --git a/x-pack/plugins/infra/public/containers/logs/log_filter/with_log_filter_url_state.tsx b/x-pack/plugins/infra/public/containers/logs/log_filter/with_log_filter_url_state.tsx index 2a5970721f5e5..578c7052e0b85 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_filter/with_log_filter_url_state.tsx +++ b/x-pack/plugins/infra/public/containers/logs/log_filter/with_log_filter_url_state.tsx @@ -10,10 +10,15 @@ import React from 'react'; import { Query } from '@kbn/es-query'; import { replaceStateKeyInQueryString, UrlStateContainer } from '../../../utils/url_state'; import { useLogFilterStateContext } from './log_filter_state'; +import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; export const WithLogFilterUrlState: React.FC = () => { - const { filterQuery, applyLogFilterQuery } = useLogFilterStateContext(); - + const { filterQuery } = useLogFilterStateContext(); + const { + data: { + query: { queryString }, + }, + } = useKibanaContextForPlugin().services; return ( { mapToUrlState={mapToFilterQuery} onChange={(urlState) => { if (urlState) { - applyLogFilterQuery(urlState); + queryString.setQuery(urlState); } }} onInitialize={(urlState) => { if (urlState) { - applyLogFilterQuery(urlState); + queryString.setQuery(urlState); } }} /> diff --git a/x-pack/plugins/infra/public/pages/logs/stream/page_toolbar.tsx b/x-pack/plugins/infra/public/pages/logs/stream/page_toolbar.tsx index 440edcbdd6c0e..5938f60b1ef32 100644 --- a/x-pack/plugins/infra/public/pages/logs/stream/page_toolbar.tsx +++ b/x-pack/plugins/infra/public/pages/logs/stream/page_toolbar.tsx @@ -6,10 +6,8 @@ */ import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { Query } from '@kbn/es-query'; import { i18n } from '@kbn/i18n'; import React from 'react'; -import { QueryStringInput } from '@kbn/unified-search-plugin/public'; import { DataView } from '@kbn/data-views-plugin/public'; import { euiStyled } from '@kbn/kibana-react-plugin/common'; import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; @@ -18,7 +16,6 @@ import { LogDatepicker } from '../../../components/logging/log_datepicker'; import { LogHighlightsMenu } from '../../../components/logging/log_highlights_menu'; import { LogTextScaleControls } from '../../../components/logging/log_text_scale_controls'; import { LogTextWrapControls } from '../../../components/logging/log_text_wrap_controls'; -import { useLogFilterStateContext } from '../../../containers/logs/log_filter'; import { useLogEntryFlyoutContext } from '../../../containers/logs/log_flyout'; import { useLogHighlightsStateContext } from '../../../containers/logs/log_highlights/log_highlights'; import { useLogPositionStateContext } from '../../../containers/logs/log_position'; @@ -29,11 +26,18 @@ export const LogsToolbar = () => { const { derivedDataView } = useLogViewContext(); const { availableTextScales, setTextScale, setTextWrap, textScale, textWrap } = useLogViewConfigurationContext(); - const { filterQueryDraft, isFilterQueryDraftValid, applyLogFilterQuery, setLogFilterQueryDraft } = - useLogFilterStateContext(); const { setSurroundingLogsId } = useLogEntryFlyoutContext(); - const { http, notifications, docLinks, uiSettings, data, storage, unifiedSearch } = - useKibanaContextForPlugin().services; + const { + http, + notifications, + docLinks, + uiSettings, + data, + storage, + unifiedSearch: { + ui: { SearchBar }, + }, + } = useKibanaContextForPlugin().services; const { setHighlightTerms, @@ -57,27 +61,20 @@ export const LogsToolbar = () => {
- { - setSurroundingLogsId(null); - setLogFilterQueryDraft(query); - }} - onSubmit={(query: Query) => { - setSurroundingLogsId(null); - applyLogFilterQuery(query); - }} placeholder={i18n.translate('xpack.infra.logsPage.toolbar.kqlSearchFieldPlaceholder', { defaultMessage: 'Search for log entries… (e.g. host.name:host-1)', })} - query={filterQueryDraft} - appName={i18n.translate('xpack.infra.appName', { - defaultMessage: 'Infra logs', - })} - deps={{ unifiedSearch, notifications, http, docLinks, uiSettings, data, storage }} + useDefaultBehaviors={true} + indexPatterns={[derivedDataView as DataView]} + showQueryInput={true} + showQueryBar={false} + showFilterBar={false} + showDatePicker={false} /> From d116eb771a9a23d206fcd281155b2a7f550fe368 Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Wed, 12 Oct 2022 17:12:32 +0100 Subject: [PATCH 02/25] Fix initial state quirks --- .../logs/log_filter/log_filter_state.ts | 46 +++++++++++-------- .../log_filter/with_log_filter_url_state.tsx | 2 + .../plugins/infra/public/utils/url_state.tsx | 2 +- 3 files changed, 30 insertions(+), 20 deletions(-) diff --git a/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts b/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts index fd7097acf740f..608fb6ae3e844 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts +++ b/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts @@ -20,24 +20,14 @@ interface ILogFilterState { serializedQuery: string; originalQuery: Query; } | null; - filterQueryDraft: Query; } -const initialLogFilterState: ILogFilterState = { - filterQuery: null, - filterQueryDraft: { - language: 'kuery', - query: '', - }, -}; - export const useLogFilterState = ({ indexPattern }: { indexPattern: DataViewBase }) => { const { data: { query: { queryString }, }, } = useKibanaContextForPlugin().services; - const [logFilterState, setLogFilterState] = useState(initialLogFilterState); const kibanaQuerySettings = useKibanaQuerySettings(); const parseQuery = useCallback( @@ -45,23 +35,41 @@ export const useLogFilterState = ({ indexPattern }: { indexPattern: DataViewBase [indexPattern, kibanaQuerySettings] ); - const applyLogFilterQuery = useCallback( + const getLogFilterQuery = useCallback( (filterQuery: Query) => { try { const parsedQuery = parseQuery(filterQuery); + return { + parsedQuery, + serializedQuery: JSON.stringify(parsedQuery), + originalQuery: filterQuery, + }; + } catch (error) { + // If for some reason parsing the query fails we should revert back to a safe default. This would most likely happen due to a bad URL parameter. + queryString.setQuery({ + language: 'kuery', + query: '', + }); + } + }, + [parseQuery, queryString] + ); + + const [logFilterState, setLogFilterState] = useState({ + filterQuery: getLogFilterQuery(queryString.getQuery()) || null, + }); + + const applyLogFilterQuery = useCallback( + (filterQuery: Query) => { + const logFilterQuery = getLogFilterQuery(filterQuery); + if (logFilterQuery) { setLogFilterState((previousLogFilterState) => ({ ...previousLogFilterState, - filterQuery: { - parsedQuery, - serializedQuery: JSON.stringify(parsedQuery), - originalQuery: filterQuery, - }, + filterQuery: logFilterQuery, })); - } catch (error) { - // This shouldn't really happen as the Unified Search Bar handles passing through the query. } }, - [parseQuery] + [getLogFilterQuery] ); useSubscription( diff --git a/x-pack/plugins/infra/public/containers/logs/log_filter/with_log_filter_url_state.tsx b/x-pack/plugins/infra/public/containers/logs/log_filter/with_log_filter_url_state.tsx index 578c7052e0b85..0bf2edb26863c 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_filter/with_log_filter_url_state.tsx +++ b/x-pack/plugins/infra/public/containers/logs/log_filter/with_log_filter_url_state.tsx @@ -19,8 +19,10 @@ export const WithLogFilterUrlState: React.FC = () => { query: { queryString }, }, } = useKibanaContextForPlugin().services; + return ( { urlState: UrlState | undefined; From 8c1506a2663eec498b3bb3cdff4df684ecc44bbc Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Wed, 12 Oct 2022 17:42:22 +0100 Subject: [PATCH 03/25] Improve type checking --- .../logs/log_filter/log_filter_state.ts | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts b/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts index 608fb6ae3e844..f7f964d67fecb 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts +++ b/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts @@ -6,7 +6,7 @@ */ import { useMemo } from 'react'; -import { buildEsQuery, DataViewBase, Query } from '@kbn/es-query'; +import { buildEsQuery, DataViewBase, Query, AggregateQuery } from '@kbn/es-query'; import createContainer from 'constate'; import { useCallback, useState } from 'react'; import { useKibanaQuerySettings } from '../../../utils/use_kibana_query_settings'; @@ -35,9 +35,17 @@ export const useLogFilterState = ({ indexPattern }: { indexPattern: DataViewBase [indexPattern, kibanaQuerySettings] ); + function isQuery(value: Query | AggregateQuery): value is Query { + return value.hasOwnProperty('query'); + } + const getLogFilterQuery = useCallback( - (filterQuery: Query) => { + (filterQuery: Query | AggregateQuery) => { try { + // NOTE: We sync with the QueryString manager - and therefore other solutions - but we don't support SQL syntax. + if (!isQuery(filterQuery)) { + throw new Error('Only Query types are supported'); + } const parsedQuery = parseQuery(filterQuery); return { parsedQuery, @@ -45,7 +53,7 @@ export const useLogFilterState = ({ indexPattern }: { indexPattern: DataViewBase originalQuery: filterQuery, }; } catch (error) { - // If for some reason parsing the query fails we should revert back to a safe default. This would most likely happen due to a bad URL parameter. + // NOTE: If parsing fails or an AggregateQuery is in use queryString.setQuery({ language: 'kuery', query: '', @@ -60,7 +68,7 @@ export const useLogFilterState = ({ indexPattern }: { indexPattern: DataViewBase }); const applyLogFilterQuery = useCallback( - (filterQuery: Query) => { + (filterQuery: Query | AggregateQuery) => { const logFilterQuery = getLogFilterQuery(filterQuery); if (logFilterQuery) { setLogFilterState((previousLogFilterState) => ({ @@ -77,7 +85,7 @@ export const useLogFilterState = ({ indexPattern }: { indexPattern: DataViewBase { next: useCallback(() => { const esQuery = queryString.getQuery(); - applyLogFilterQuery(esQuery as Query); + applyLogFilterQuery(esQuery); }, [applyLogFilterQuery, queryString]), } ); From ac3c90cac39d4c5f715d4b216b33a3f9c5df55e0 Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Thu, 13 Oct 2022 12:48:44 +0100 Subject: [PATCH 04/25] Add new showQueryMenu prop with tests / story --- .../public/__stories__/search_bar.stories.tsx | 9 +++++++++ .../public/search_bar/search_bar.test.tsx | 15 +++++++++++++++ .../public/search_bar/search_bar.tsx | 4 +++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/plugins/unified_search/public/__stories__/search_bar.stories.tsx b/src/plugins/unified_search/public/__stories__/search_bar.stories.tsx index 40d3abfb7fae0..30b7cb7eaef44 100644 --- a/src/plugins/unified_search/public/__stories__/search_bar.stories.tsx +++ b/src/plugins/unified_search/public/__stories__/search_bar.stories.tsx @@ -292,6 +292,15 @@ storiesOf('SearchBar', module) query: { query: 'Test: miaou', language: 'kuery' }, } as unknown as SearchBarProps) ) + .add('with query menu off', () => + wrapSearchBarInContext({ + showDatePicker: false, + showFilterBar: false, + showQueryInput: true, + showQueryMenu: false, + query: { query: 'Test: miaou', language: 'kuery' }, + } as unknown as SearchBarProps) + ) .add('with only the filter bar and the date picker on', () => wrapSearchBarInContext({ showDatePicker: true, diff --git a/src/plugins/unified_search/public/search_bar/search_bar.test.tsx b/src/plugins/unified_search/public/search_bar/search_bar.test.tsx index 518f9d1f16e16..407550cf77a3e 100644 --- a/src/plugins/unified_search/public/search_bar/search_bar.test.tsx +++ b/src/plugins/unified_search/public/search_bar/search_bar.test.tsx @@ -138,6 +138,7 @@ describe('SearchBar', () => { const FILTER_BAR = '[data-test-subj="unifiedFilterBar"]'; const QUERY_BAR = '.kbnQueryBar'; const QUERY_INPUT = '[data-test-subj="unifiedQueryInput"]'; + const QUERY_MENU_BUTTON = '[data-test-subj="showQueryBarMenu"]'; const EDITOR = '[data-test-subj="unifiedTextLangEditor"]'; beforeEach(() => { @@ -221,6 +222,20 @@ describe('SearchBar', () => { expect(component.find(QUERY_INPUT).length).toBeFalsy(); }); + it('Should NOT render the query menu button, if disabled', () => { + const component = mount( + wrapSearchBarInContext({ + indexPatterns: [mockIndexPattern], + screenTitle: 'test screen', + onQuerySubmit: noop, + query: kqlQuery, + showQueryMenu: false, + }) + ); + + expect(component.find(QUERY_MENU_BUTTON).length).toBeFalsy(); + }); + it('Should render query bar and filter bar', () => { const component = mount( wrapSearchBarInContext({ diff --git a/src/plugins/unified_search/public/search_bar/search_bar.tsx b/src/plugins/unified_search/public/search_bar/search_bar.tsx index 6824c136d881f..0279188cd7814 100644 --- a/src/plugins/unified_search/public/search_bar/search_bar.tsx +++ b/src/plugins/unified_search/public/search_bar/search_bar.tsx @@ -49,6 +49,7 @@ export interface SearchBarOwnProps { dataTestSubj?: string; // Togglers showQueryBar?: boolean; + showQueryMenu?: boolean; showQueryInput?: boolean; showFilterBar?: boolean; showDatePicker?: boolean; @@ -123,6 +124,7 @@ class SearchBarUI extends C > { public static defaultProps = { showQueryBar: true, + showQueryMenu: true, showFilterBar: true, showDatePicker: true, showSubmitButton: true, @@ -450,7 +452,7 @@ class SearchBarUI extends C /> ); - const queryBarMenu = this.props.showQueryBar ? ( + const queryBarMenu = this.props.showQueryMenu ? ( Date: Thu, 13 Oct 2022 12:52:00 +0100 Subject: [PATCH 05/25] Add showQueryMenu option to Logs and the create_search_bar wrapper --- .../unified_search/public/search_bar/create_search_bar.tsx | 1 + x-pack/plugins/infra/public/pages/logs/stream/page_toolbar.tsx | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/unified_search/public/search_bar/create_search_bar.tsx b/src/plugins/unified_search/public/search_bar/create_search_bar.tsx index 5c0dfda5d9b2c..a5f1a233dd313 100644 --- a/src/plugins/unified_search/public/search_bar/create_search_bar.tsx +++ b/src/plugins/unified_search/public/search_bar/create_search_bar.tsx @@ -191,6 +191,7 @@ export function createSearchBar({ showDatePicker={props.showDatePicker} showFilterBar={props.showFilterBar} showQueryBar={props.showQueryBar} + showQueryMenu={props.showQueryMenu} showQueryInput={props.showQueryInput} showSaveQuery={props.showSaveQuery} showSubmitButton={props.showSubmitButton} diff --git a/x-pack/plugins/infra/public/pages/logs/stream/page_toolbar.tsx b/x-pack/plugins/infra/public/pages/logs/stream/page_toolbar.tsx index 5938f60b1ef32..f8f4db13d8602 100644 --- a/x-pack/plugins/infra/public/pages/logs/stream/page_toolbar.tsx +++ b/x-pack/plugins/infra/public/pages/logs/stream/page_toolbar.tsx @@ -72,7 +72,7 @@ export const LogsToolbar = () => { useDefaultBehaviors={true} indexPatterns={[derivedDataView as DataView]} showQueryInput={true} - showQueryBar={false} + showQueryMenu={false} showFilterBar={false} showDatePicker={false} /> From fe33caa8817730c51007af3f0330fc2285dca46b Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Thu, 13 Oct 2022 14:36:52 +0100 Subject: [PATCH 06/25] Remove unused variables --- .../infra/public/pages/logs/stream/page_toolbar.tsx | 8 -------- 1 file changed, 8 deletions(-) diff --git a/x-pack/plugins/infra/public/pages/logs/stream/page_toolbar.tsx b/x-pack/plugins/infra/public/pages/logs/stream/page_toolbar.tsx index f8f4db13d8602..2929151a1902e 100644 --- a/x-pack/plugins/infra/public/pages/logs/stream/page_toolbar.tsx +++ b/x-pack/plugins/infra/public/pages/logs/stream/page_toolbar.tsx @@ -16,7 +16,6 @@ import { LogDatepicker } from '../../../components/logging/log_datepicker'; import { LogHighlightsMenu } from '../../../components/logging/log_highlights_menu'; import { LogTextScaleControls } from '../../../components/logging/log_text_scale_controls'; import { LogTextWrapControls } from '../../../components/logging/log_text_wrap_controls'; -import { useLogEntryFlyoutContext } from '../../../containers/logs/log_flyout'; import { useLogHighlightsStateContext } from '../../../containers/logs/log_highlights/log_highlights'; import { useLogPositionStateContext } from '../../../containers/logs/log_position'; import { useLogViewConfigurationContext } from '../../../containers/logs/log_view_configuration'; @@ -26,14 +25,7 @@ export const LogsToolbar = () => { const { derivedDataView } = useLogViewContext(); const { availableTextScales, setTextScale, setTextWrap, textScale, textWrap } = useLogViewConfigurationContext(); - const { setSurroundingLogsId } = useLogEntryFlyoutContext(); const { - http, - notifications, - docLinks, - uiSettings, - data, - storage, unifiedSearch: { ui: { SearchBar }, }, From 33e494bc893ef35a95194918185d23d20f8b9fbb Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Fri, 14 Oct 2022 14:38:26 +0100 Subject: [PATCH 07/25] Update x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Felix Stürmer --- .../public/containers/logs/log_filter/log_filter_state.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts b/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts index f7f964d67fecb..84cccf62fb224 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts +++ b/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts @@ -63,9 +63,9 @@ export const useLogFilterState = ({ indexPattern }: { indexPattern: DataViewBase [parseQuery, queryString] ); - const [logFilterState, setLogFilterState] = useState({ + const [logFilterState, setLogFilterState] = useState(() => ({ filterQuery: getLogFilterQuery(queryString.getQuery()) || null, - }); + })); const applyLogFilterQuery = useCallback( (filterQuery: Query | AggregateQuery) => { From 09f8330a2ba7357de346307d909fb899a7fb1d47 Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Fri, 14 Oct 2022 15:42:58 +0100 Subject: [PATCH 08/25] PR tweaks --- .../logs/log_filter/log_filter_state.ts | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts b/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts index f7f964d67fecb..f779d84e5650a 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts +++ b/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts @@ -6,7 +6,7 @@ */ import { useMemo } from 'react'; -import { buildEsQuery, DataViewBase, Query, AggregateQuery } from '@kbn/es-query'; +import { buildEsQuery, DataViewBase, Query, AggregateQuery, isOfQueryType } from '@kbn/es-query'; import createContainer from 'constate'; import { useCallback, useState } from 'react'; import { useKibanaQuerySettings } from '../../../utils/use_kibana_query_settings'; @@ -35,15 +35,11 @@ export const useLogFilterState = ({ indexPattern }: { indexPattern: DataViewBase [indexPattern, kibanaQuerySettings] ); - function isQuery(value: Query | AggregateQuery): value is Query { - return value.hasOwnProperty('query'); - } - const getLogFilterQuery = useCallback( (filterQuery: Query | AggregateQuery) => { try { // NOTE: We sync with the QueryString manager - and therefore other solutions - but we don't support SQL syntax. - if (!isQuery(filterQuery)) { + if (!isOfQueryType(filterQuery)) { throw new Error('Only Query types are supported'); } const parsedQuery = parseQuery(filterQuery); @@ -82,12 +78,14 @@ export const useLogFilterState = ({ indexPattern }: { indexPattern: DataViewBase useSubscription( useMemo(() => queryString.getUpdates$(), [queryString]), - { - next: useCallback(() => { - const esQuery = queryString.getQuery(); - applyLogFilterQuery(esQuery); - }, [applyLogFilterQuery, queryString]), - } + useMemo(() => { + return { + next: () => { + const esQuery = queryString.getQuery(); + applyLogFilterQuery(esQuery); + }, + }; + }, [applyLogFilterQuery, queryString]) ); return { From e0e70e8b76cb2c1d6be515f51a088cce15d830fc Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Fri, 14 Oct 2022 16:55:10 +0100 Subject: [PATCH 09/25] Fix loading from URL --- .../containers/logs/log_filter/log_filter_state.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts b/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts index 4246822bfe9d4..d576835cb14cd 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts +++ b/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts @@ -6,6 +6,7 @@ */ import { useMemo } from 'react'; +import { of, merge } from 'rxjs'; import { buildEsQuery, DataViewBase, Query, AggregateQuery, isOfQueryType } from '@kbn/es-query'; import createContainer from 'constate'; import { useCallback, useState } from 'react'; @@ -59,9 +60,11 @@ export const useLogFilterState = ({ indexPattern }: { indexPattern: DataViewBase [parseQuery, queryString] ); - const [logFilterState, setLogFilterState] = useState(() => ({ - filterQuery: getLogFilterQuery(queryString.getQuery()) || null, - })); + const [logFilterState, setLogFilterState] = useState(() => { + return { + filterQuery: getLogFilterQuery(queryString.getQuery()) || null, + }; + }); const applyLogFilterQuery = useCallback( (filterQuery: Query | AggregateQuery) => { @@ -77,7 +80,9 @@ export const useLogFilterState = ({ indexPattern }: { indexPattern: DataViewBase ); useSubscription( - useMemo(() => queryString.getUpdates$(), [queryString]), + useMemo(() => { + return merge(of(undefined), queryString.getUpdates$()); // The internal useEffect will subscribe afer the initial emit from the Observable, and there is no replay. + }, [queryString]), useMemo(() => { return { next: () => { From a7abf8f65e7c2b91cdd3b6556d784a19c66defb8 Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Tue, 18 Oct 2022 09:48:35 +0100 Subject: [PATCH 10/25] Adjust state handling to account for invalid manager queries --- .../containers/logs/log_filter/errors.ts | 21 ++++ .../logs/log_filter/log_filter_state.ts | 111 +++++++++++++----- .../log_filter/with_log_filter_url_state.tsx | 7 +- .../pages/logs/stream/page_logs_content.tsx | 10 +- 4 files changed, 117 insertions(+), 32 deletions(-) create mode 100644 x-pack/plugins/infra/public/containers/logs/log_filter/errors.ts diff --git a/x-pack/plugins/infra/public/containers/logs/log_filter/errors.ts b/x-pack/plugins/infra/public/containers/logs/log_filter/errors.ts new file mode 100644 index 0000000000000..09e3af3e241a4 --- /dev/null +++ b/x-pack/plugins/infra/public/containers/logs/log_filter/errors.ts @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +/* eslint-disable max-classes-per-file */ +export class UnsupportedLanguageError extends Error { + constructor(message?: string) { + super(message); + Object.setPrototypeOf(this, new.target.prototype); + } +} + +export class QueryParsingError extends Error { + constructor(message?: string) { + super(message); + Object.setPrototypeOf(this, new.target.prototype); + } +} diff --git a/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts b/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts index d576835cb14cd..e9c05a1522fb1 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts +++ b/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts @@ -6,6 +6,7 @@ */ import { useMemo } from 'react'; +import { i18n } from '@kbn/i18n'; import { of, merge } from 'rxjs'; import { buildEsQuery, DataViewBase, Query, AggregateQuery, isOfQueryType } from '@kbn/es-query'; import createContainer from 'constate'; @@ -14,6 +15,7 @@ import { useKibanaQuerySettings } from '../../../utils/use_kibana_query_settings import { BuiltEsQuery } from '../log_stream'; import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; import { useSubscription } from '../../../utils/use_observable'; +import { UnsupportedLanguageError, QueryParsingError } from './errors'; interface ILogFilterState { filterQuery: { @@ -21,10 +23,29 @@ interface ILogFilterState { serializedQuery: string; originalQuery: Query; } | null; + queryStringQuery: Query | AggregateQuery; } +const DEFAULT_QUERY = { + language: 'kuery', + query: '', +}; + +// Error toasts +const errorToastTitle = i18n.translate('xpack.infra.logsPage.toolbar.logFilterErrorToastTitle', { + defaultMessage: 'Log filter error', +}); + +const unsupportedLanguageError = i18n.translate( + 'xpack.infra.logsPage.toolbar.logFilterUnsupportedLanguageError', + { + defaultMessage: 'SQL is not supported', + } +); + export const useLogFilterState = ({ indexPattern }: { indexPattern: DataViewBase }) => { const { + notifications: { toasts }, data: { query: { queryString }, }, @@ -37,38 +58,64 @@ export const useLogFilterState = ({ indexPattern }: { indexPattern: DataViewBase ); const getLogFilterQuery = useCallback( - (filterQuery: Query | AggregateQuery) => { + (filterQuery: Query) => { + const parsedQuery = parseQuery(filterQuery); + return { + parsedQuery, + serializedQuery: JSON.stringify(parsedQuery), + originalQuery: filterQuery, + }; + }, + [parseQuery] + ); + + const validateQuery = useCallback( + (query: Query | AggregateQuery) => { + if (!isOfQueryType(query)) { + throw new UnsupportedLanguageError(unsupportedLanguageError); + } + try { - // NOTE: We sync with the QueryString manager - and therefore other solutions - but we don't support SQL syntax. - if (!isOfQueryType(filterQuery)) { - throw new Error('Only Query types are supported'); - } - const parsedQuery = parseQuery(filterQuery); - return { - parsedQuery, - serializedQuery: JSON.stringify(parsedQuery), - originalQuery: filterQuery, - }; + parseQuery(query); } catch (error) { - // NOTE: If parsing fails or an AggregateQuery is in use - queryString.setQuery({ - language: 'kuery', - query: '', - }); + throw new QueryParsingError(error); + } + }, + [parseQuery] + ); + + const handleValidationError = useCallback( + (error: Error) => { + if (error instanceof UnsupportedLanguageError) { + toasts.addError(error, { title: errorToastTitle }); + queryString.setQuery(DEFAULT_QUERY); + } else if (error instanceof QueryParsingError) { + toasts.addError(error, { title: errorToastTitle }); } }, - [parseQuery, queryString] + [queryString, toasts] ); const [logFilterState, setLogFilterState] = useState(() => { - return { - filterQuery: getLogFilterQuery(queryString.getQuery()) || null, - }; + const query = queryString.getQuery(); + try { + validateQuery(query); + return { + filterQuery: getLogFilterQuery(query as Query), + queryStringQuery: query, + }; + } catch (error) { + handleValidationError(error); + return { + filterQuery: getLogFilterQuery(DEFAULT_QUERY), + queryStringQuery: query, + }; + } }); const applyLogFilterQuery = useCallback( - (filterQuery: Query | AggregateQuery) => { - const logFilterQuery = getLogFilterQuery(filterQuery); + (validFilterQuery: Query) => { + const logFilterQuery = getLogFilterQuery(validFilterQuery); if (logFilterQuery) { setLogFilterState((previousLogFilterState) => ({ ...previousLogFilterState, @@ -81,20 +128,30 @@ export const useLogFilterState = ({ indexPattern }: { indexPattern: DataViewBase useSubscription( useMemo(() => { - return merge(of(undefined), queryString.getUpdates$()); // The internal useEffect will subscribe afer the initial emit from the Observable, and there is no replay. + return merge(of(undefined), queryString.getUpdates$()); }, [queryString]), useMemo(() => { return { next: () => { - const esQuery = queryString.getQuery(); - applyLogFilterQuery(esQuery); + try { + const query = queryString.getQuery(); + setLogFilterState((previousLogFilterState) => ({ + ...previousLogFilterState, + queryStringQuery: query, + })); + validateQuery(query); + applyLogFilterQuery(query as Query); + } catch (error) { + handleValidationError(error); + } }, }; - }, [applyLogFilterQuery, queryString]) + }, [applyLogFilterQuery, handleValidationError, queryString, validateQuery]) ); return { - filterQuery: logFilterState.filterQuery, + queryStringQuery: logFilterState.queryStringQuery, // NOTE: Query String Manager query. + filterQuery: logFilterState.filterQuery, // NOTE: Valid and syntactically correct query applied to requests etc. applyLogFilterQuery, }; }; diff --git a/x-pack/plugins/infra/public/containers/logs/log_filter/with_log_filter_url_state.tsx b/x-pack/plugins/infra/public/containers/logs/log_filter/with_log_filter_url_state.tsx index 0bf2edb26863c..430084e938b68 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_filter/with_log_filter_url_state.tsx +++ b/x-pack/plugins/infra/public/containers/logs/log_filter/with_log_filter_url_state.tsx @@ -13,17 +13,18 @@ import { useLogFilterStateContext } from './log_filter_state'; import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; export const WithLogFilterUrlState: React.FC = () => { - const { filterQuery } = useLogFilterStateContext(); const { data: { query: { queryString }, }, } = useKibanaContextForPlugin().services; + const { queryStringQuery } = useLogFilterStateContext(); + return ( { diff --git a/x-pack/plugins/infra/public/pages/logs/stream/page_logs_content.tsx b/x-pack/plugins/infra/public/pages/logs/stream/page_logs_content.tsx index 18ac30bb35e14..17385242008e0 100644 --- a/x-pack/plugins/infra/public/pages/logs/stream/page_logs_content.tsx +++ b/x-pack/plugins/infra/public/pages/logs/stream/page_logs_content.tsx @@ -34,10 +34,16 @@ import { useLogViewContext } from '../../../hooks/use_log_view'; import { datemathToEpochMillis, isValidDatemath } from '../../../utils/datemath'; import { LogsToolbar } from './page_toolbar'; import { PageViewLogInContext } from './page_view_log_in_context'; +import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; const PAGE_THRESHOLD = 2; export const LogsPageLogsContent: React.FunctionComponent = () => { + const { + data: { + query: { queryString }, + }, + } = useKibanaContextForPlugin().services; const { resolvedLogView, logView, logViewId } = useLogViewContext(); const { textScale, textWrap } = useLogViewConfigurationContext(); const { @@ -193,14 +199,14 @@ export const LogsPageLogsContent: React.FunctionComponent = () => { const setFilter = useCallback( (filter: Query, flyoutItemId: string, timeKey: TimeKey | undefined | null) => { - applyLogFilterQuery(filter); + queryString.setQuery(filter); if (timeKey) { jumpToTargetPosition(timeKey); } setSurroundingLogsId(flyoutItemId); stopLiveStreaming(); }, - [applyLogFilterQuery, jumpToTargetPosition, setSurroundingLogsId, stopLiveStreaming] + [jumpToTargetPosition, queryString, setSurroundingLogsId, stopLiveStreaming] ); return ( From 3147810476ee97d2dbdfec06337e0304c05e3dab Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Tue, 18 Oct 2022 15:38:19 +0100 Subject: [PATCH 11/25] Show filter error within UI and block requests --- .../logs/log_filter/log_filter_state.ts | 40 +++++--- .../pages/logs/stream/page_logs_content.tsx | 92 ++++++++++++++----- 2 files changed, 99 insertions(+), 33 deletions(-) diff --git a/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts b/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts index e9c05a1522fb1..0400847aa8eab 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts +++ b/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { useMemo } from 'react'; +import { useMemo, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; import { of, merge } from 'rxjs'; import { buildEsQuery, DataViewBase, Query, AggregateQuery, isOfQueryType } from '@kbn/es-query'; @@ -24,6 +24,7 @@ interface ILogFilterState { originalQuery: Query; } | null; queryStringQuery: Query | AggregateQuery; + validationError: Error | null; } const DEFAULT_QUERY = { @@ -32,9 +33,12 @@ const DEFAULT_QUERY = { }; // Error toasts -const errorToastTitle = i18n.translate('xpack.infra.logsPage.toolbar.logFilterErrorToastTitle', { - defaultMessage: 'Log filter error', -}); +export const errorToastTitle = i18n.translate( + 'xpack.infra.logsPage.toolbar.logFilterErrorToastTitle', + { + defaultMessage: 'Log filter error', + } +); const unsupportedLanguageError = i18n.translate( 'xpack.infra.logsPage.toolbar.logFilterUnsupportedLanguageError', @@ -103,16 +107,23 @@ export const useLogFilterState = ({ indexPattern }: { indexPattern: DataViewBase return { filterQuery: getLogFilterQuery(query as Query), queryStringQuery: query, + validationError: null, }; } catch (error) { - handleValidationError(error); return { - filterQuery: getLogFilterQuery(DEFAULT_QUERY), + filterQuery: null, queryStringQuery: query, + validationError: error, }; } }); + useEffect(() => { + if (logFilterState.validationError) { + handleValidationError(logFilterState.validationError); + } + }, [handleValidationError, logFilterState.validationError]); + const applyLogFilterQuery = useCallback( (validFilterQuery: Query) => { const logFilterQuery = getLogFilterQuery(validFilterQuery); @@ -128,31 +139,38 @@ export const useLogFilterState = ({ indexPattern }: { indexPattern: DataViewBase useSubscription( useMemo(() => { - return merge(of(undefined), queryString.getUpdates$()); + return merge(of(undefined), queryString.getUpdates$()); // NOTE: getUpdates$ uses skip(1) so we do this to ensure an initial emit of a value. }, [queryString]), useMemo(() => { return { next: () => { + const query = queryString.getQuery(); try { - const query = queryString.getQuery(); + validateQuery(query); setLogFilterState((previousLogFilterState) => ({ ...previousLogFilterState, queryStringQuery: query, + validationError: null, })); - validateQuery(query); applyLogFilterQuery(query as Query); } catch (error) { - handleValidationError(error); + setLogFilterState((previousLogFilterState) => ({ + ...previousLogFilterState, + queryStringQuery: query, + validationError: error, + filterQuery: null, + })); } }, }; - }, [applyLogFilterQuery, handleValidationError, queryString, validateQuery]) + }, [applyLogFilterQuery, queryString, validateQuery]) ); return { queryStringQuery: logFilterState.queryStringQuery, // NOTE: Query String Manager query. filterQuery: logFilterState.filterQuery, // NOTE: Valid and syntactically correct query applied to requests etc. applyLogFilterQuery, + validationError: logFilterState.validationError, }; }; diff --git a/x-pack/plugins/infra/public/pages/logs/stream/page_logs_content.tsx b/x-pack/plugins/infra/public/pages/logs/stream/page_logs_content.tsx index 17385242008e0..fcbe107749cae 100644 --- a/x-pack/plugins/infra/public/pages/logs/stream/page_logs_content.tsx +++ b/x-pack/plugins/infra/public/pages/logs/stream/page_logs_content.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { EuiSpacer } from '@elastic/eui'; +import { EuiSpacer, EuiCallOut } from '@elastic/eui'; import type { Query } from '@kbn/es-query'; import React, { useCallback, useEffect, useMemo } from 'react'; import usePrevious from 'react-use/lib/usePrevious'; @@ -18,7 +18,10 @@ import { LogMinimap } from '../../../components/logging/log_minimap'; import { ScrollableLogTextStreamView } from '../../../components/logging/log_text_stream'; import { LogEntryStreamItem } from '../../../components/logging/log_text_stream/item'; import { PageContent } from '../../../components/page'; -import { useLogFilterStateContext } from '../../../containers/logs/log_filter'; +import { + useLogFilterStateContext, + errorToastTitle as logFilterErrorToastTitle, +} from '../../../containers/logs/log_filter'; import { useLogEntryFlyoutContext, WithFlyoutOptionsUrlState, @@ -71,7 +74,7 @@ export const LogsPageLogsContent: React.FunctionComponent = () => { updateDateRange, lastCompleteDateRangeExpressionUpdate, } = useLogPositionStateContext(); - const { filterQuery, applyLogFilterQuery } = useLogFilterStateContext(); + const { filterQuery, validationError: queryValidationError } = useLogFilterStateContext(); const { isReloading, @@ -110,10 +113,11 @@ export const LogsPageLogsContent: React.FunctionComponent = () => { const hasQueryChanged = filterQuery !== prevFilterQuery; if ( - isFirstLoad || - completeDateRangeExpressionHasChanged || - isCenterPointOutsideLoadedRange || - hasQueryChanged + (isFirstLoad || + completeDateRangeExpressionHasChanged || + isCenterPointOutsideLoadedRange || + hasQueryChanged) && + !queryValidationError ) { if (isStreaming) { fetchNewestEntries(); @@ -136,6 +140,7 @@ export const LogsPageLogsContent: React.FunctionComponent = () => { prevFilterQuery, lastCompleteDateRangeExpressionUpdate, prevLastCompleteDateRangeExpressionUpdate, + queryValidationError, ]); const { logSummaryHighlights, currentHighlightKey, logEntryHighlightsById } = @@ -209,21 +214,16 @@ export const LogsPageLogsContent: React.FunctionComponent = () => { [jumpToTargetPosition, queryString, setSurroundingLogsId, stopLiveStreaming] ); - return ( - <> - - - - - - {isFlyoutOpen ? ( - - ) : null} + const pageContent = useMemo(() => { + if (queryValidationError) { + return ( + +

{queryValidationError.toString()}

+
+ ); + } + + return ( { }} + ); + }, [ + currentHighlightKey, + endDateExpression, + fetchEntries, + handleDateRangeExtension, + handlePagination, + hasMoreAfterEnd, + hasMoreBeforeStart, + isLoadingMore, + isReloading, + isStreaming, + items, + jumpToTargetPosition, + lastLoadedTime, + logSummaryHighlights, + logView?.version, + logViewId, + openLogEntryFlyout, + queryValidationError, + resolvedLogView, + setContextEntry, + startDateExpression, + startLiveStreaming, + surroundingLogsId, + targetPosition, + textScale, + textWrap, + visibleMidpointTime, + visibleTimeInterval, + ]); + + return ( + <> + + + + + + {isFlyoutOpen ? ( + + ) : null} + {pageContent} ); }; From e322bbc83593e9810ed399cbbef56c93ac6f17c1 Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Wed, 19 Oct 2022 13:21:37 +0100 Subject: [PATCH 12/25] PR amendments - Use a single getNewLogFilterState function - Remove callout --- .../logs/log_filter/log_filter_state.ts | 148 +++++++----------- .../log_filter/with_log_filter_url_state.tsx | 1 - .../pages/logs/stream/page_logs_content.tsx | 92 +++-------- 3 files changed, 81 insertions(+), 160 deletions(-) diff --git a/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts b/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts index 0400847aa8eab..65a75bcb5ce01 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts +++ b/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts @@ -6,8 +6,8 @@ */ import { useMemo, useEffect } from 'react'; +import { merge, of } from 'rxjs'; import { i18n } from '@kbn/i18n'; -import { of, merge } from 'rxjs'; import { buildEsQuery, DataViewBase, Query, AggregateQuery, isOfQueryType } from '@kbn/es-query'; import createContainer from 'constate'; import { useCallback, useState } from 'react'; @@ -23,7 +23,7 @@ interface ILogFilterState { serializedQuery: string; originalQuery: Query; } | null; - queryStringQuery: Query | AggregateQuery; + queryStringQuery: Query | AggregateQuery | null; validationError: Error | null; } @@ -32,6 +32,12 @@ const DEFAULT_QUERY = { query: '', }; +const INITIAL_LOG_FILTER_STATE = { + filterQuery: null, + queryStringQuery: null, + validationError: null, +}; + // Error toasts export const errorToastTitle = i18n.translate( 'xpack.infra.logsPage.toolbar.logFilterErrorToastTitle', @@ -54,87 +60,68 @@ export const useLogFilterState = ({ indexPattern }: { indexPattern: DataViewBase query: { queryString }, }, } = useKibanaContextForPlugin().services; - const kibanaQuerySettings = useKibanaQuerySettings(); - - const parseQuery = useCallback( - (filterQuery: Query) => buildEsQuery(indexPattern, filterQuery, [], kibanaQuerySettings), - [indexPattern, kibanaQuerySettings] - ); - - const getLogFilterQuery = useCallback( - (filterQuery: Query) => { - const parsedQuery = parseQuery(filterQuery); - return { - parsedQuery, - serializedQuery: JSON.stringify(parsedQuery), - originalQuery: filterQuery, - }; - }, - [parseQuery] - ); - const validateQuery = useCallback( - (query: Query | AggregateQuery) => { - if (!isOfQueryType(query)) { - throw new UnsupportedLanguageError(unsupportedLanguageError); - } + const kibanaQuerySettings = useKibanaQuerySettings(); - try { - parseQuery(query); - } catch (error) { - throw new QueryParsingError(error); - } - }, - [parseQuery] - ); + const [logFilterState, setLogFilterState] = useState(() => { + // NOTE: Set a default on the queryString manager so we don't pull in values from other solutions. + queryString.setQuery({ + language: 'kuery', + query: '', + }); + return INITIAL_LOG_FILTER_STATE; + }); - const handleValidationError = useCallback( - (error: Error) => { + useEffect(() => { + const handleValidationError = (error: Error) => { if (error instanceof UnsupportedLanguageError) { toasts.addError(error, { title: errorToastTitle }); queryString.setQuery(DEFAULT_QUERY); } else if (error instanceof QueryParsingError) { toasts.addError(error, { title: errorToastTitle }); } - }, - [queryString, toasts] - ); - - const [logFilterState, setLogFilterState] = useState(() => { - const query = queryString.getQuery(); - try { - validateQuery(query); - return { - filterQuery: getLogFilterQuery(query as Query), - queryStringQuery: query, - validationError: null, - }; - } catch (error) { - return { - filterQuery: null, - queryStringQuery: query, - validationError: error, - }; - } - }); + }; - useEffect(() => { if (logFilterState.validationError) { handleValidationError(logFilterState.validationError); } - }, [handleValidationError, logFilterState.validationError]); - - const applyLogFilterQuery = useCallback( - (validFilterQuery: Query) => { - const logFilterQuery = getLogFilterQuery(validFilterQuery); - if (logFilterQuery) { - setLogFilterState((previousLogFilterState) => ({ - ...previousLogFilterState, - filterQuery: logFilterQuery, - })); - } - }, - [getLogFilterQuery] + }, [logFilterState.validationError, queryString, toasts]); + + const parseQuery = useCallback( + (filterQuery: Query) => buildEsQuery(indexPattern, filterQuery, [], kibanaQuerySettings), + [indexPattern, kibanaQuerySettings] + ); + + const getNewLogFilterState = useCallback( + (newQuery: Query | AggregateQuery) => + (previousLogFilterState: ILogFilterState): ILogFilterState => { + try { + if (!isOfQueryType(newQuery)) { + throw new UnsupportedLanguageError(unsupportedLanguageError); + } + try { + const parsedQuery = parseQuery(newQuery); + return { + filterQuery: { + parsedQuery, + serializedQuery: JSON.stringify(parsedQuery), + originalQuery: newQuery, + }, + queryStringQuery: newQuery, + validationError: null, + }; + } catch (error) { + throw new QueryParsingError(error); + } + } catch (error) { + return { + ...previousLogFilterState, + queryStringQuery: newQuery, + validationError: error, + }; + } + }, + [parseQuery] ); useSubscription( @@ -144,32 +131,15 @@ export const useLogFilterState = ({ indexPattern }: { indexPattern: DataViewBase useMemo(() => { return { next: () => { - const query = queryString.getQuery(); - try { - validateQuery(query); - setLogFilterState((previousLogFilterState) => ({ - ...previousLogFilterState, - queryStringQuery: query, - validationError: null, - })); - applyLogFilterQuery(query as Query); - } catch (error) { - setLogFilterState((previousLogFilterState) => ({ - ...previousLogFilterState, - queryStringQuery: query, - validationError: error, - filterQuery: null, - })); - } + setLogFilterState(getNewLogFilterState(queryString.getQuery())); }, }; - }, [applyLogFilterQuery, queryString, validateQuery]) + }, [getNewLogFilterState, queryString]) ); return { queryStringQuery: logFilterState.queryStringQuery, // NOTE: Query String Manager query. filterQuery: logFilterState.filterQuery, // NOTE: Valid and syntactically correct query applied to requests etc. - applyLogFilterQuery, validationError: logFilterState.validationError, }; }; diff --git a/x-pack/plugins/infra/public/containers/logs/log_filter/with_log_filter_url_state.tsx b/x-pack/plugins/infra/public/containers/logs/log_filter/with_log_filter_url_state.tsx index 430084e938b68..9226cbe3972d3 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_filter/with_log_filter_url_state.tsx +++ b/x-pack/plugins/infra/public/containers/logs/log_filter/with_log_filter_url_state.tsx @@ -23,7 +23,6 @@ export const WithLogFilterUrlState: React.FC = () => { return ( { updateDateRange, lastCompleteDateRangeExpressionUpdate, } = useLogPositionStateContext(); - const { filterQuery, validationError: queryValidationError } = useLogFilterStateContext(); + const { filterQuery } = useLogFilterStateContext(); const { isReloading, @@ -113,11 +110,10 @@ export const LogsPageLogsContent: React.FunctionComponent = () => { const hasQueryChanged = filterQuery !== prevFilterQuery; if ( - (isFirstLoad || - completeDateRangeExpressionHasChanged || - isCenterPointOutsideLoadedRange || - hasQueryChanged) && - !queryValidationError + isFirstLoad || + completeDateRangeExpressionHasChanged || + isCenterPointOutsideLoadedRange || + hasQueryChanged ) { if (isStreaming) { fetchNewestEntries(); @@ -140,7 +136,6 @@ export const LogsPageLogsContent: React.FunctionComponent = () => { prevFilterQuery, lastCompleteDateRangeExpressionUpdate, prevLastCompleteDateRangeExpressionUpdate, - queryValidationError, ]); const { logSummaryHighlights, currentHighlightKey, logEntryHighlightsById } = @@ -214,16 +209,21 @@ export const LogsPageLogsContent: React.FunctionComponent = () => { [jumpToTargetPosition, queryString, setSurroundingLogsId, stopLiveStreaming] ); - const pageContent = useMemo(() => { - if (queryValidationError) { - return ( - -

{queryValidationError.toString()}

-
- ); - } - - return ( + return ( + <> + + + + + + {isFlyoutOpen ? ( + + ) : null} { }} - ); - }, [ - currentHighlightKey, - endDateExpression, - fetchEntries, - handleDateRangeExtension, - handlePagination, - hasMoreAfterEnd, - hasMoreBeforeStart, - isLoadingMore, - isReloading, - isStreaming, - items, - jumpToTargetPosition, - lastLoadedTime, - logSummaryHighlights, - logView?.version, - logViewId, - openLogEntryFlyout, - queryValidationError, - resolvedLogView, - setContextEntry, - startDateExpression, - startLiveStreaming, - surroundingLogsId, - targetPosition, - textScale, - textWrap, - visibleMidpointTime, - visibleTimeInterval, - ]); - - return ( - <> - - - - - - {isFlyoutOpen ? ( - - ) : null} - {pageContent} ); }; From a395d27e6b1d0de1dfe4f1de778529f508714d9d Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Thu, 20 Oct 2022 15:05:38 +0100 Subject: [PATCH 13/25] Use a real DataView reference with derivedDataView --- .../infra/common/log_views/resolved_log_view.mock.ts | 8 ++++++++ .../infra/common/log_views/resolved_log_view.ts | 9 +++++++++ .../infra/public/components/log_stream/log_stream.tsx | 2 +- .../containers/logs/log_filter/log_filter_state.ts | 2 +- x-pack/plugins/infra/public/hooks/use_log_view.mock.ts | 5 +---- x-pack/plugins/infra/public/hooks/use_log_view.ts | 10 +++------- .../infra/public/pages/logs/stream/page_toolbar.tsx | 3 +-- 7 files changed, 24 insertions(+), 15 deletions(-) diff --git a/x-pack/plugins/infra/common/log_views/resolved_log_view.mock.ts b/x-pack/plugins/infra/common/log_views/resolved_log_view.mock.ts index 268b2f692f62a..a910205fc8366 100644 --- a/x-pack/plugins/infra/common/log_views/resolved_log_view.mock.ts +++ b/x-pack/plugins/infra/common/log_views/resolved_log_view.mock.ts @@ -10,6 +10,13 @@ import { createStubDataView } from '@kbn/data-views-plugin/common/stubs'; import { defaultLogViewsStaticConfig } from './defaults'; import { ResolvedLogView, resolveLogView } from './resolved_log_view'; import { LogViewAttributes } from './types'; +import { DataView } from '@kbn/data-views-plugin/common'; + +const dataViewMock = { + id: 'log-view-data-view-mock', + title: 'log-view-data-view-mock-title', + fields: [], +} as unknown as DataView; export const createResolvedLogViewMock = ( resolvedLogViewOverrides: Partial = {} @@ -41,6 +48,7 @@ export const createResolvedLogViewMock = ( messageColumn: { id: 'MESSAGE_COLUMN_ID' }, }, ], + dataViewReference: dataViewMock, ...resolvedLogViewOverrides, }); diff --git a/x-pack/plugins/infra/common/log_views/resolved_log_view.ts b/x-pack/plugins/infra/common/log_views/resolved_log_view.ts index d7e155172a57e..329dc948a2da0 100644 --- a/x-pack/plugins/infra/common/log_views/resolved_log_view.ts +++ b/x-pack/plugins/infra/common/log_views/resolved_log_view.ts @@ -23,6 +23,7 @@ export interface ResolvedLogView { fields: ResolvedLogViewField[]; runtimeMappings: estypes.MappingRuntimeFields; columns: LogViewColumnConfiguration[]; + dataViewReference: DataView; } export const resolveLogView = async ( @@ -60,6 +61,12 @@ const resolveLegacyReference = async ( ); }); + const dataViewReference = await dataViewsService.create({ + id: '___InfraLogsLegacyLogViewReference___', + title: logViewAttributes.logIndices.indexName, + timeFieldName: TIMESTAMP_FIELD, + }); + return { indices: logViewAttributes.logIndices.indexName, timestampField: TIMESTAMP_FIELD, @@ -70,6 +77,7 @@ const resolveLegacyReference = async ( columns: logViewAttributes.logColumns, name: logViewAttributes.name, description: logViewAttributes.description, + dataViewReference, }; }; @@ -97,6 +105,7 @@ const resolveDataViewReference = async ( columns: logViewAttributes.logColumns, name: logViewAttributes.name, description: logViewAttributes.description, + dataViewReference: dataView, }; }; diff --git a/x-pack/plugins/infra/public/components/log_stream/log_stream.tsx b/x-pack/plugins/infra/public/components/log_stream/log_stream.tsx index 2913b2cbb5ecf..e5aeefba983f1 100644 --- a/x-pack/plugins/infra/public/components/log_stream/log_stream.tsx +++ b/x-pack/plugins/infra/public/components/log_stream/log_stream.tsx @@ -7,11 +7,11 @@ import { buildEsQuery, Filter, Query } from '@kbn/es-query'; import { JsonValue } from '@kbn/utility-types'; -import { noop } from 'lodash'; import React, { useCallback, useEffect, useMemo } from 'react'; import { DataPublicPluginStart } from '@kbn/data-plugin/public'; import { euiStyled } from '@kbn/kibana-react-plugin/common'; import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { noop } from 'lodash'; import { LogEntryCursor } from '../../../common/log_entry'; import { defaultLogViewsStaticConfig } from '../../../common/log_views'; import { BuiltEsQuery, useLogStream } from '../../containers/logs/log_stream'; diff --git a/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts b/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts index 65a75bcb5ce01..521e00331dd97 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts +++ b/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts @@ -53,7 +53,7 @@ const unsupportedLanguageError = i18n.translate( } ); -export const useLogFilterState = ({ indexPattern }: { indexPattern: DataViewBase }) => { +export const useLogFilterState = ({ indexPattern }: { indexPattern?: DataViewBase }) => { const { notifications: { toasts }, data: { diff --git a/x-pack/plugins/infra/public/hooks/use_log_view.mock.ts b/x-pack/plugins/infra/public/hooks/use_log_view.mock.ts index daebfb82b4564..8bef101abe666 100644 --- a/x-pack/plugins/infra/public/hooks/use_log_view.mock.ts +++ b/x-pack/plugins/infra/public/hooks/use_log_view.mock.ts @@ -17,10 +17,7 @@ const defaultLogViewId = 'default'; export const createUninitializedUseLogViewMock = (logViewId: string = defaultLogViewId) => (): IUseLogView => ({ - derivedDataView: { - fields: [], - title: 'unknown', - }, + derivedDataView: undefined, hasFailedLoading: false, hasFailedLoadingLogView: false, hasFailedLoadingLogViewStatus: false, diff --git a/x-pack/plugins/infra/public/hooks/use_log_view.ts b/x-pack/plugins/infra/public/hooks/use_log_view.ts index b1b8bb6e33cc9..9dd0468d60b40 100644 --- a/x-pack/plugins/infra/public/hooks/use_log_view.ts +++ b/x-pack/plugins/infra/public/hooks/use_log_view.ts @@ -63,13 +63,9 @@ export const useLogView = ({ [logViews] ); - const derivedDataView = useMemo( - () => ({ - fields: resolvedLogView?.fields ?? [], - title: resolvedLogView?.indices ?? 'unknown', - }), - [resolvedLogView] - ); + const derivedDataView = useMemo(() => { + return resolvedLogView?.dataViewReference; + }, [resolvedLogView]); const isLoadingLogView = loadLogViewRequest.state === 'pending'; const isResolvingLogView = resolveLogViewRequest.state === 'pending'; diff --git a/x-pack/plugins/infra/public/pages/logs/stream/page_toolbar.tsx b/x-pack/plugins/infra/public/pages/logs/stream/page_toolbar.tsx index 2929151a1902e..cf30518f78ede 100644 --- a/x-pack/plugins/infra/public/pages/logs/stream/page_toolbar.tsx +++ b/x-pack/plugins/infra/public/pages/logs/stream/page_toolbar.tsx @@ -8,7 +8,6 @@ import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; -import { DataView } from '@kbn/data-views-plugin/public'; import { euiStyled } from '@kbn/kibana-react-plugin/common'; import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; import { LogCustomizationMenu } from '../../../components/logging/log_customization_menu'; @@ -62,7 +61,7 @@ export const LogsToolbar = () => { defaultMessage: 'Search for log entries… (e.g. host.name:host-1)', })} useDefaultBehaviors={true} - indexPatterns={[derivedDataView as DataView]} + indexPatterns={derivedDataView ? [derivedDataView] : undefined} showQueryInput={true} showQueryMenu={false} showFilterBar={false} From 929e9dfa1b581ca03330784e3de8831daa662528 Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Thu, 20 Oct 2022 15:08:56 +0100 Subject: [PATCH 14/25] Update x-pack/plugins/infra/public/containers/logs/log_filter/with_log_filter_url_state.tsx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Felix Stürmer --- .../containers/logs/log_filter/with_log_filter_url_state.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x-pack/plugins/infra/public/containers/logs/log_filter/with_log_filter_url_state.tsx b/x-pack/plugins/infra/public/containers/logs/log_filter/with_log_filter_url_state.tsx index 9226cbe3972d3..9530177002939 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_filter/with_log_filter_url_state.tsx +++ b/x-pack/plugins/infra/public/containers/logs/log_filter/with_log_filter_url_state.tsx @@ -34,6 +34,8 @@ export const WithLogFilterUrlState: React.FC = () => { onInitialize={(urlState) => { if (urlState) { queryString.setQuery(urlState); + } else { + queryString.setQuery(DEFAULT_QUERY); } }} /> From fd193dd95fd38478ba8637f0a49db926c792615f Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Thu, 20 Oct 2022 15:13:10 +0100 Subject: [PATCH 15/25] Move location of default query setting --- .../public/containers/logs/log_filter/log_filter_state.ts | 7 +------ .../logs/log_filter/with_log_filter_url_state.tsx | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts b/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts index 521e00331dd97..d55062214d27b 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts +++ b/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts @@ -27,7 +27,7 @@ interface ILogFilterState { validationError: Error | null; } -const DEFAULT_QUERY = { +export const DEFAULT_QUERY = { language: 'kuery', query: '', }; @@ -64,11 +64,6 @@ export const useLogFilterState = ({ indexPattern }: { indexPattern?: DataViewBas const kibanaQuerySettings = useKibanaQuerySettings(); const [logFilterState, setLogFilterState] = useState(() => { - // NOTE: Set a default on the queryString manager so we don't pull in values from other solutions. - queryString.setQuery({ - language: 'kuery', - query: '', - }); return INITIAL_LOG_FILTER_STATE; }); diff --git a/x-pack/plugins/infra/public/containers/logs/log_filter/with_log_filter_url_state.tsx b/x-pack/plugins/infra/public/containers/logs/log_filter/with_log_filter_url_state.tsx index 9530177002939..a6f6166b7cf06 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_filter/with_log_filter_url_state.tsx +++ b/x-pack/plugins/infra/public/containers/logs/log_filter/with_log_filter_url_state.tsx @@ -9,7 +9,7 @@ import * as rt from 'io-ts'; import React from 'react'; import { Query } from '@kbn/es-query'; import { replaceStateKeyInQueryString, UrlStateContainer } from '../../../utils/url_state'; -import { useLogFilterStateContext } from './log_filter_state'; +import { useLogFilterStateContext, DEFAULT_QUERY } from './log_filter_state'; import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; export const WithLogFilterUrlState: React.FC = () => { From 6cdbe6b7bb60f92961ece120b36b8dd07b32f2b8 Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Thu, 20 Oct 2022 17:42:24 +0100 Subject: [PATCH 16/25] Respond to dataView changes --- .../logs/log_filter/log_filter_state.ts | 15 ++++++++++++--- .../public/pages/logs/stream/page_providers.tsx | 2 +- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts b/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts index d55062214d27b..d5c6a86d8ce75 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts +++ b/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts @@ -53,7 +53,7 @@ const unsupportedLanguageError = i18n.translate( } ); -export const useLogFilterState = ({ indexPattern }: { indexPattern?: DataViewBase }) => { +export const useLogFilterState = ({ dataView }: { dataView?: DataViewBase }) => { const { notifications: { toasts }, data: { @@ -83,8 +83,10 @@ export const useLogFilterState = ({ indexPattern }: { indexPattern?: DataViewBas }, [logFilterState.validationError, queryString, toasts]); const parseQuery = useCallback( - (filterQuery: Query) => buildEsQuery(indexPattern, filterQuery, [], kibanaQuerySettings), - [indexPattern, kibanaQuerySettings] + (filterQuery: Query) => { + return buildEsQuery(dataView, filterQuery, [], kibanaQuerySettings); + }, + [dataView, kibanaQuerySettings] ); const getNewLogFilterState = useCallback( @@ -132,6 +134,13 @@ export const useLogFilterState = ({ indexPattern }: { indexPattern?: DataViewBas }, [getNewLogFilterState, queryString]) ); + // NOTE: If the dataView changes the query will need to be reparsed and the filter regenerated. + useEffect(() => { + if (dataView) { + setLogFilterState(getNewLogFilterState(queryString.getQuery())); + } + }, [dataView, getNewLogFilterState, queryString]); + return { queryStringQuery: logFilterState.queryStringQuery, // NOTE: Query String Manager query. filterQuery: logFilterState.filterQuery, // NOTE: Valid and syntactically correct query applied to requests etc. diff --git a/x-pack/plugins/infra/public/pages/logs/stream/page_providers.tsx b/x-pack/plugins/infra/public/pages/logs/stream/page_providers.tsx index ea2af542586a2..026119ff5c74c 100644 --- a/x-pack/plugins/infra/public/pages/logs/stream/page_providers.tsx +++ b/x-pack/plugins/infra/public/pages/logs/stream/page_providers.tsx @@ -27,7 +27,7 @@ const LogFilterState: React.FC = ({ children }) => { const { derivedDataView } = useLogViewContext(); return ( - + {children} From f2ccde90a371022077a9221dad77632ddb4d69f6 Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Mon, 24 Oct 2022 11:29:05 +0100 Subject: [PATCH 17/25] Revert "Use a real DataView reference with derivedDataView" This reverts commit a395d27e6b1d0de1dfe4f1de778529f508714d9d. --- .../infra/common/log_views/resolved_log_view.mock.ts | 8 -------- .../infra/common/log_views/resolved_log_view.ts | 9 --------- .../infra/public/components/log_stream/log_stream.tsx | 2 +- .../containers/logs/log_filter/log_filter_state.ts | 2 +- x-pack/plugins/infra/public/hooks/use_log_view.mock.ts | 5 ++++- x-pack/plugins/infra/public/hooks/use_log_view.ts | 10 +++++++--- .../infra/public/pages/logs/stream/page_toolbar.tsx | 3 ++- 7 files changed, 15 insertions(+), 24 deletions(-) diff --git a/x-pack/plugins/infra/common/log_views/resolved_log_view.mock.ts b/x-pack/plugins/infra/common/log_views/resolved_log_view.mock.ts index a910205fc8366..268b2f692f62a 100644 --- a/x-pack/plugins/infra/common/log_views/resolved_log_view.mock.ts +++ b/x-pack/plugins/infra/common/log_views/resolved_log_view.mock.ts @@ -10,13 +10,6 @@ import { createStubDataView } from '@kbn/data-views-plugin/common/stubs'; import { defaultLogViewsStaticConfig } from './defaults'; import { ResolvedLogView, resolveLogView } from './resolved_log_view'; import { LogViewAttributes } from './types'; -import { DataView } from '@kbn/data-views-plugin/common'; - -const dataViewMock = { - id: 'log-view-data-view-mock', - title: 'log-view-data-view-mock-title', - fields: [], -} as unknown as DataView; export const createResolvedLogViewMock = ( resolvedLogViewOverrides: Partial = {} @@ -48,7 +41,6 @@ export const createResolvedLogViewMock = ( messageColumn: { id: 'MESSAGE_COLUMN_ID' }, }, ], - dataViewReference: dataViewMock, ...resolvedLogViewOverrides, }); diff --git a/x-pack/plugins/infra/common/log_views/resolved_log_view.ts b/x-pack/plugins/infra/common/log_views/resolved_log_view.ts index 329dc948a2da0..d7e155172a57e 100644 --- a/x-pack/plugins/infra/common/log_views/resolved_log_view.ts +++ b/x-pack/plugins/infra/common/log_views/resolved_log_view.ts @@ -23,7 +23,6 @@ export interface ResolvedLogView { fields: ResolvedLogViewField[]; runtimeMappings: estypes.MappingRuntimeFields; columns: LogViewColumnConfiguration[]; - dataViewReference: DataView; } export const resolveLogView = async ( @@ -61,12 +60,6 @@ const resolveLegacyReference = async ( ); }); - const dataViewReference = await dataViewsService.create({ - id: '___InfraLogsLegacyLogViewReference___', - title: logViewAttributes.logIndices.indexName, - timeFieldName: TIMESTAMP_FIELD, - }); - return { indices: logViewAttributes.logIndices.indexName, timestampField: TIMESTAMP_FIELD, @@ -77,7 +70,6 @@ const resolveLegacyReference = async ( columns: logViewAttributes.logColumns, name: logViewAttributes.name, description: logViewAttributes.description, - dataViewReference, }; }; @@ -105,7 +97,6 @@ const resolveDataViewReference = async ( columns: logViewAttributes.logColumns, name: logViewAttributes.name, description: logViewAttributes.description, - dataViewReference: dataView, }; }; diff --git a/x-pack/plugins/infra/public/components/log_stream/log_stream.tsx b/x-pack/plugins/infra/public/components/log_stream/log_stream.tsx index e5aeefba983f1..2913b2cbb5ecf 100644 --- a/x-pack/plugins/infra/public/components/log_stream/log_stream.tsx +++ b/x-pack/plugins/infra/public/components/log_stream/log_stream.tsx @@ -7,11 +7,11 @@ import { buildEsQuery, Filter, Query } from '@kbn/es-query'; import { JsonValue } from '@kbn/utility-types'; +import { noop } from 'lodash'; import React, { useCallback, useEffect, useMemo } from 'react'; import { DataPublicPluginStart } from '@kbn/data-plugin/public'; import { euiStyled } from '@kbn/kibana-react-plugin/common'; import { useKibana } from '@kbn/kibana-react-plugin/public'; -import { noop } from 'lodash'; import { LogEntryCursor } from '../../../common/log_entry'; import { defaultLogViewsStaticConfig } from '../../../common/log_views'; import { BuiltEsQuery, useLogStream } from '../../containers/logs/log_stream'; diff --git a/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts b/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts index d5c6a86d8ce75..f836c642aa0b3 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts +++ b/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts @@ -53,7 +53,7 @@ const unsupportedLanguageError = i18n.translate( } ); -export const useLogFilterState = ({ dataView }: { dataView?: DataViewBase }) => { +export const useLogFilterState = ({ dataView }: { dataView: DataViewBase }) => { const { notifications: { toasts }, data: { diff --git a/x-pack/plugins/infra/public/hooks/use_log_view.mock.ts b/x-pack/plugins/infra/public/hooks/use_log_view.mock.ts index 8bef101abe666..daebfb82b4564 100644 --- a/x-pack/plugins/infra/public/hooks/use_log_view.mock.ts +++ b/x-pack/plugins/infra/public/hooks/use_log_view.mock.ts @@ -17,7 +17,10 @@ const defaultLogViewId = 'default'; export const createUninitializedUseLogViewMock = (logViewId: string = defaultLogViewId) => (): IUseLogView => ({ - derivedDataView: undefined, + derivedDataView: { + fields: [], + title: 'unknown', + }, hasFailedLoading: false, hasFailedLoadingLogView: false, hasFailedLoadingLogViewStatus: false, diff --git a/x-pack/plugins/infra/public/hooks/use_log_view.ts b/x-pack/plugins/infra/public/hooks/use_log_view.ts index 9dd0468d60b40..b1b8bb6e33cc9 100644 --- a/x-pack/plugins/infra/public/hooks/use_log_view.ts +++ b/x-pack/plugins/infra/public/hooks/use_log_view.ts @@ -63,9 +63,13 @@ export const useLogView = ({ [logViews] ); - const derivedDataView = useMemo(() => { - return resolvedLogView?.dataViewReference; - }, [resolvedLogView]); + const derivedDataView = useMemo( + () => ({ + fields: resolvedLogView?.fields ?? [], + title: resolvedLogView?.indices ?? 'unknown', + }), + [resolvedLogView] + ); const isLoadingLogView = loadLogViewRequest.state === 'pending'; const isResolvingLogView = resolveLogViewRequest.state === 'pending'; diff --git a/x-pack/plugins/infra/public/pages/logs/stream/page_toolbar.tsx b/x-pack/plugins/infra/public/pages/logs/stream/page_toolbar.tsx index cf30518f78ede..2929151a1902e 100644 --- a/x-pack/plugins/infra/public/pages/logs/stream/page_toolbar.tsx +++ b/x-pack/plugins/infra/public/pages/logs/stream/page_toolbar.tsx @@ -8,6 +8,7 @@ import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; +import { DataView } from '@kbn/data-views-plugin/public'; import { euiStyled } from '@kbn/kibana-react-plugin/common'; import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; import { LogCustomizationMenu } from '../../../components/logging/log_customization_menu'; @@ -61,7 +62,7 @@ export const LogsToolbar = () => { defaultMessage: 'Search for log entries… (e.g. host.name:host-1)', })} useDefaultBehaviors={true} - indexPatterns={derivedDataView ? [derivedDataView] : undefined} + indexPatterns={[derivedDataView as DataView]} showQueryInput={true} showQueryMenu={false} showFilterBar={false} From b484f3ef477f50d3c702d61ea0d999d2299ce11d Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Mon, 24 Oct 2022 12:12:17 +0100 Subject: [PATCH 18/25] Add "type" property rather than use a "real" data view --- x-pack/plugins/infra/public/hooks/use_log_view.mock.ts | 1 + x-pack/plugins/infra/public/hooks/use_log_view.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/x-pack/plugins/infra/public/hooks/use_log_view.mock.ts b/x-pack/plugins/infra/public/hooks/use_log_view.mock.ts index daebfb82b4564..f9f3007e814fd 100644 --- a/x-pack/plugins/infra/public/hooks/use_log_view.mock.ts +++ b/x-pack/plugins/infra/public/hooks/use_log_view.mock.ts @@ -20,6 +20,7 @@ export const createUninitializedUseLogViewMock = derivedDataView: { fields: [], title: 'unknown', + type: 'title', }, hasFailedLoading: false, hasFailedLoadingLogView: false, diff --git a/x-pack/plugins/infra/public/hooks/use_log_view.ts b/x-pack/plugins/infra/public/hooks/use_log_view.ts index b1b8bb6e33cc9..1a031b31f7dff 100644 --- a/x-pack/plugins/infra/public/hooks/use_log_view.ts +++ b/x-pack/plugins/infra/public/hooks/use_log_view.ts @@ -67,6 +67,7 @@ export const useLogView = ({ () => ({ fields: resolvedLogView?.fields ?? [], title: resolvedLogView?.indices ?? 'unknown', + type: 'title', }), [resolvedLogView] ); From 809238b86c2bb098c7f567839fcb1686e9859a9f Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Tue, 25 Oct 2022 10:58:23 +0100 Subject: [PATCH 19/25] Update x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Felix Stürmer --- .../public/containers/logs/log_filter/log_filter_state.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts b/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts index f836c642aa0b3..359e6121a069f 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts +++ b/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts @@ -63,9 +63,7 @@ export const useLogFilterState = ({ dataView }: { dataView: DataViewBase }) => { const kibanaQuerySettings = useKibanaQuerySettings(); - const [logFilterState, setLogFilterState] = useState(() => { - return INITIAL_LOG_FILTER_STATE; - }); + const [logFilterState, setLogFilterState] = useState(INITIAL_LOG_FILTER_STATE); useEffect(() => { const handleValidationError = (error: Error) => { From 6256bc828092d8487cc13be2663e705e64819684 Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Tue, 25 Oct 2022 14:29:52 +0100 Subject: [PATCH 20/25] Revert "Revert "Use a real DataView reference with derivedDataView"" This reverts commit f2ccde90a371022077a9221dad77632ddb4d69f6. --- .../infra/common/log_views/resolved_log_view.mock.ts | 8 ++++++++ .../infra/common/log_views/resolved_log_view.ts | 9 +++++++++ .../infra/public/components/log_stream/log_stream.tsx | 2 +- .../containers/logs/log_filter/log_filter_state.ts | 2 +- .../plugins/infra/public/hooks/use_log_view.mock.ts | 6 +----- x-pack/plugins/infra/public/hooks/use_log_view.ts | 11 +++-------- .../infra/public/pages/logs/stream/page_toolbar.tsx | 3 +-- 7 files changed, 24 insertions(+), 17 deletions(-) diff --git a/x-pack/plugins/infra/common/log_views/resolved_log_view.mock.ts b/x-pack/plugins/infra/common/log_views/resolved_log_view.mock.ts index 268b2f692f62a..a910205fc8366 100644 --- a/x-pack/plugins/infra/common/log_views/resolved_log_view.mock.ts +++ b/x-pack/plugins/infra/common/log_views/resolved_log_view.mock.ts @@ -10,6 +10,13 @@ import { createStubDataView } from '@kbn/data-views-plugin/common/stubs'; import { defaultLogViewsStaticConfig } from './defaults'; import { ResolvedLogView, resolveLogView } from './resolved_log_view'; import { LogViewAttributes } from './types'; +import { DataView } from '@kbn/data-views-plugin/common'; + +const dataViewMock = { + id: 'log-view-data-view-mock', + title: 'log-view-data-view-mock-title', + fields: [], +} as unknown as DataView; export const createResolvedLogViewMock = ( resolvedLogViewOverrides: Partial = {} @@ -41,6 +48,7 @@ export const createResolvedLogViewMock = ( messageColumn: { id: 'MESSAGE_COLUMN_ID' }, }, ], + dataViewReference: dataViewMock, ...resolvedLogViewOverrides, }); diff --git a/x-pack/plugins/infra/common/log_views/resolved_log_view.ts b/x-pack/plugins/infra/common/log_views/resolved_log_view.ts index d7e155172a57e..329dc948a2da0 100644 --- a/x-pack/plugins/infra/common/log_views/resolved_log_view.ts +++ b/x-pack/plugins/infra/common/log_views/resolved_log_view.ts @@ -23,6 +23,7 @@ export interface ResolvedLogView { fields: ResolvedLogViewField[]; runtimeMappings: estypes.MappingRuntimeFields; columns: LogViewColumnConfiguration[]; + dataViewReference: DataView; } export const resolveLogView = async ( @@ -60,6 +61,12 @@ const resolveLegacyReference = async ( ); }); + const dataViewReference = await dataViewsService.create({ + id: '___InfraLogsLegacyLogViewReference___', + title: logViewAttributes.logIndices.indexName, + timeFieldName: TIMESTAMP_FIELD, + }); + return { indices: logViewAttributes.logIndices.indexName, timestampField: TIMESTAMP_FIELD, @@ -70,6 +77,7 @@ const resolveLegacyReference = async ( columns: logViewAttributes.logColumns, name: logViewAttributes.name, description: logViewAttributes.description, + dataViewReference, }; }; @@ -97,6 +105,7 @@ const resolveDataViewReference = async ( columns: logViewAttributes.logColumns, name: logViewAttributes.name, description: logViewAttributes.description, + dataViewReference: dataView, }; }; diff --git a/x-pack/plugins/infra/public/components/log_stream/log_stream.tsx b/x-pack/plugins/infra/public/components/log_stream/log_stream.tsx index 2913b2cbb5ecf..e5aeefba983f1 100644 --- a/x-pack/plugins/infra/public/components/log_stream/log_stream.tsx +++ b/x-pack/plugins/infra/public/components/log_stream/log_stream.tsx @@ -7,11 +7,11 @@ import { buildEsQuery, Filter, Query } from '@kbn/es-query'; import { JsonValue } from '@kbn/utility-types'; -import { noop } from 'lodash'; import React, { useCallback, useEffect, useMemo } from 'react'; import { DataPublicPluginStart } from '@kbn/data-plugin/public'; import { euiStyled } from '@kbn/kibana-react-plugin/common'; import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { noop } from 'lodash'; import { LogEntryCursor } from '../../../common/log_entry'; import { defaultLogViewsStaticConfig } from '../../../common/log_views'; import { BuiltEsQuery, useLogStream } from '../../containers/logs/log_stream'; diff --git a/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts b/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts index f836c642aa0b3..d5c6a86d8ce75 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts +++ b/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts @@ -53,7 +53,7 @@ const unsupportedLanguageError = i18n.translate( } ); -export const useLogFilterState = ({ dataView }: { dataView: DataViewBase }) => { +export const useLogFilterState = ({ dataView }: { dataView?: DataViewBase }) => { const { notifications: { toasts }, data: { diff --git a/x-pack/plugins/infra/public/hooks/use_log_view.mock.ts b/x-pack/plugins/infra/public/hooks/use_log_view.mock.ts index f9f3007e814fd..8bef101abe666 100644 --- a/x-pack/plugins/infra/public/hooks/use_log_view.mock.ts +++ b/x-pack/plugins/infra/public/hooks/use_log_view.mock.ts @@ -17,11 +17,7 @@ const defaultLogViewId = 'default'; export const createUninitializedUseLogViewMock = (logViewId: string = defaultLogViewId) => (): IUseLogView => ({ - derivedDataView: { - fields: [], - title: 'unknown', - type: 'title', - }, + derivedDataView: undefined, hasFailedLoading: false, hasFailedLoadingLogView: false, hasFailedLoadingLogViewStatus: false, diff --git a/x-pack/plugins/infra/public/hooks/use_log_view.ts b/x-pack/plugins/infra/public/hooks/use_log_view.ts index 1a031b31f7dff..9dd0468d60b40 100644 --- a/x-pack/plugins/infra/public/hooks/use_log_view.ts +++ b/x-pack/plugins/infra/public/hooks/use_log_view.ts @@ -63,14 +63,9 @@ export const useLogView = ({ [logViews] ); - const derivedDataView = useMemo( - () => ({ - fields: resolvedLogView?.fields ?? [], - title: resolvedLogView?.indices ?? 'unknown', - type: 'title', - }), - [resolvedLogView] - ); + const derivedDataView = useMemo(() => { + return resolvedLogView?.dataViewReference; + }, [resolvedLogView]); const isLoadingLogView = loadLogViewRequest.state === 'pending'; const isResolvingLogView = resolveLogViewRequest.state === 'pending'; diff --git a/x-pack/plugins/infra/public/pages/logs/stream/page_toolbar.tsx b/x-pack/plugins/infra/public/pages/logs/stream/page_toolbar.tsx index 2929151a1902e..cf30518f78ede 100644 --- a/x-pack/plugins/infra/public/pages/logs/stream/page_toolbar.tsx +++ b/x-pack/plugins/infra/public/pages/logs/stream/page_toolbar.tsx @@ -8,7 +8,6 @@ import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; -import { DataView } from '@kbn/data-views-plugin/public'; import { euiStyled } from '@kbn/kibana-react-plugin/common'; import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; import { LogCustomizationMenu } from '../../../components/logging/log_customization_menu'; @@ -62,7 +61,7 @@ export const LogsToolbar = () => { defaultMessage: 'Search for log entries… (e.g. host.name:host-1)', })} useDefaultBehaviors={true} - indexPatterns={[derivedDataView as DataView]} + indexPatterns={derivedDataView ? [derivedDataView] : undefined} showQueryInput={true} showQueryMenu={false} showFilterBar={false} From 3595f0fbb3c358e72a05eecb494efaf6d1af8196 Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Tue, 25 Oct 2022 16:53:17 +0100 Subject: [PATCH 21/25] Use real dataView in resolved logView --- .../log_views/resolved_log_view.mock.ts | 1 + .../common/log_views/resolved_log_view.ts | 35 +++++++++---------- .../infra/public/hooks/use_log_view.ts | 7 ++-- .../services/log_views/log_views_client.ts | 9 +++-- .../infra/public/services/log_views/types.ts | 2 +- .../log_views/log_views_client.test.ts | 2 +- .../services/log_views/log_views_client.ts | 9 +++-- .../infra/server/services/log_views/types.ts | 2 +- 8 files changed, 38 insertions(+), 29 deletions(-) diff --git a/x-pack/plugins/infra/common/log_views/resolved_log_view.mock.ts b/x-pack/plugins/infra/common/log_views/resolved_log_view.mock.ts index a910205fc8366..dd7b4b4430370 100644 --- a/x-pack/plugins/infra/common/log_views/resolved_log_view.mock.ts +++ b/x-pack/plugins/infra/common/log_views/resolved_log_view.mock.ts @@ -54,6 +54,7 @@ export const createResolvedLogViewMock = ( export const createResolvedLogViewMockFromAttributes = (logViewAttributes: LogViewAttributes) => resolveLogView( + 'log-view-id', logViewAttributes, { get: async () => createStubDataView({ spec: {} }), diff --git a/x-pack/plugins/infra/common/log_views/resolved_log_view.ts b/x-pack/plugins/infra/common/log_views/resolved_log_view.ts index 329dc948a2da0..2fc2fd7aa2374 100644 --- a/x-pack/plugins/infra/common/log_views/resolved_log_view.ts +++ b/x-pack/plugins/infra/common/log_views/resolved_log_view.ts @@ -27,18 +27,20 @@ export interface ResolvedLogView { } export const resolveLogView = async ( + logViewId: string, logViewAttributes: LogViewAttributes, dataViewsService: DataViewsContract, config: LogViewsStaticConfig ): Promise => { if (logViewAttributes.logIndices.type === 'index_name') { - return await resolveLegacyReference(logViewAttributes, dataViewsService, config); + return await resolveLegacyReference(logViewId, logViewAttributes, dataViewsService, config); } else { return await resolveDataViewReference(logViewAttributes, dataViewsService); } }; const resolveLegacyReference = async ( + logViewId: string, logViewAttributes: LogViewAttributes, dataViewsService: DataViewsContract, config: LogViewsStaticConfig @@ -49,30 +51,27 @@ const resolveLegacyReference = async ( const indices = logViewAttributes.logIndices.indexName; - const fields = await dataViewsService - .getFieldsForWildcard({ - pattern: indices, - allowNoIndex: true, - }) + const dataViewReference = await dataViewsService + .create( + { + id: `log-view-${logViewId}`, + title: indices, + timeFieldName: TIMESTAMP_FIELD, + allowNoIndex: true, + }, + false, + false + ) .catch((error) => { - throw new ResolveLogViewError( - `Failed to fetch fields for indices "${indices}": ${error}`, - error - ); + throw new ResolveLogViewError(`Failed to create Data View reference: ${error}`, error); }); - const dataViewReference = await dataViewsService.create({ - id: '___InfraLogsLegacyLogViewReference___', - title: logViewAttributes.logIndices.indexName, - timeFieldName: TIMESTAMP_FIELD, - }); - return { - indices: logViewAttributes.logIndices.indexName, + indices, timestampField: TIMESTAMP_FIELD, tiebreakerField: TIEBREAKER_FIELD, messageField: config.messageFields, - fields, + fields: dataViewReference.fields, runtimeMappings: {}, columns: logViewAttributes.logColumns, name: logViewAttributes.name, diff --git a/x-pack/plugins/infra/public/hooks/use_log_view.ts b/x-pack/plugins/infra/public/hooks/use_log_view.ts index 9dd0468d60b40..eef3d5dd13422 100644 --- a/x-pack/plugins/infra/public/hooks/use_log_view.ts +++ b/x-pack/plugins/infra/public/hooks/use_log_view.ts @@ -93,7 +93,7 @@ export const useLogView = ({ const load = useCallback(async () => { const loadedLogView = await loadLogView(logViewId); - const resolvedLoadedLogView = await resolveLogView(loadedLogView.attributes); + const resolvedLoadedLogView = await resolveLogView(loadedLogView.id, loadedLogView.attributes); const resolvedLogViewStatus = await loadLogViewStatus(resolvedLoadedLogView); return [loadedLogView, resolvedLoadedLogView, resolvedLogViewStatus]; @@ -102,7 +102,10 @@ export const useLogView = ({ const update = useCallback( async (logViewAttributes: Partial) => { const updatedLogView = await updateLogView(logViewId, logViewAttributes); - const resolvedUpdatedLogView = await resolveLogView(updatedLogView.attributes); + const resolvedUpdatedLogView = await resolveLogView( + updatedLogView.id, + updatedLogView.attributes + ); const resolvedLogViewStatus = await loadLogViewStatus(resolvedUpdatedLogView); return [updatedLogView, resolvedUpdatedLogView, resolvedLogViewStatus]; diff --git a/x-pack/plugins/infra/public/services/log_views/log_views_client.ts b/x-pack/plugins/infra/public/services/log_views/log_views_client.ts index 0de44f87d719e..65bb031d3407b 100644 --- a/x-pack/plugins/infra/public/services/log_views/log_views_client.ts +++ b/x-pack/plugins/infra/public/services/log_views/log_views_client.ts @@ -53,7 +53,7 @@ export class LogViewsClient implements ILogViewsClient { public async getResolvedLogView(logViewId: string): Promise { const logView = await this.getLogView(logViewId); - const resolvedLogView = await this.resolveLogView(logView.attributes); + const resolvedLogView = await this.resolveLogView(logView.id, logView.attributes); return resolvedLogView; } @@ -118,8 +118,11 @@ export class LogViewsClient implements ILogViewsClient { return data; } - public async resolveLogView(logViewAttributes: LogViewAttributes): Promise { - return await resolveLogView(logViewAttributes, this.dataViews, this.config); + public async resolveLogView( + logViewId: string, + logViewAttributes: LogViewAttributes + ): Promise { + return await resolveLogView(logViewId, logViewAttributes, this.dataViews, this.config); } } diff --git a/x-pack/plugins/infra/public/services/log_views/types.ts b/x-pack/plugins/infra/public/services/log_views/types.ts index 20e176db4cab4..9054ef79b4a4c 100644 --- a/x-pack/plugins/infra/public/services/log_views/types.ts +++ b/x-pack/plugins/infra/public/services/log_views/types.ts @@ -32,5 +32,5 @@ export interface ILogViewsClient { getResolvedLogViewStatus(resolvedLogView: ResolvedLogView): Promise; getResolvedLogView(logViewId: string): Promise; putLogView(logViewId: string, logViewAttributes: Partial): Promise; - resolveLogView(logViewAttributes: LogViewAttributes): Promise; + resolveLogView(logViewId: string, logViewAttributes: LogViewAttributes): Promise; } diff --git a/x-pack/plugins/infra/server/services/log_views/log_views_client.test.ts b/x-pack/plugins/infra/server/services/log_views/log_views_client.test.ts index 7b1debf981f8c..cf0d1ea155bb9 100644 --- a/x-pack/plugins/infra/server/services/log_views/log_views_client.test.ts +++ b/x-pack/plugins/infra/server/services/log_views/log_views_client.test.ts @@ -239,7 +239,7 @@ describe('LogViewsClient class', () => { }) ); - const resolvedLogView = await logViewsClient.resolveLogView({ + const resolvedLogView = await logViewsClient.resolveLogView('log-view-id', { name: 'LOG VIEW', description: 'LOG VIEW DESCRIPTION', logIndices: { diff --git a/x-pack/plugins/infra/server/services/log_views/log_views_client.ts b/x-pack/plugins/infra/server/services/log_views/log_views_client.ts index 57c90235452ba..9f43cee871f73 100644 --- a/x-pack/plugins/infra/server/services/log_views/log_views_client.ts +++ b/x-pack/plugins/infra/server/services/log_views/log_views_client.ts @@ -67,7 +67,7 @@ export class LogViewsClient implements ILogViewsClient { public async getResolvedLogView(logViewId: string): Promise { const logView = await this.getLogView(logViewId); - const resolvedLogView = await this.resolveLogView(logView.attributes); + const resolvedLogView = await this.resolveLogView(logView.id, logView.attributes); return resolvedLogView; } @@ -98,8 +98,11 @@ export class LogViewsClient implements ILogViewsClient { return getLogViewFromSavedObject(savedObject); } - public async resolveLogView(logViewAttributes: LogViewAttributes): Promise { - return await resolveLogView(logViewAttributes, await this.dataViews, this.config); + public async resolveLogView( + logViewId: string, + logViewAttributes: LogViewAttributes + ): Promise { + return await resolveLogView(logViewId, logViewAttributes, await this.dataViews, this.config); } private async getSavedLogView(logViewId: string): Promise { diff --git a/x-pack/plugins/infra/server/services/log_views/types.ts b/x-pack/plugins/infra/server/services/log_views/types.ts index 4146b6e2fd7e3..c10bd2002163d 100644 --- a/x-pack/plugins/infra/server/services/log_views/types.ts +++ b/x-pack/plugins/infra/server/services/log_views/types.ts @@ -46,5 +46,5 @@ export interface ILogViewsClient { getLogView(logViewId: string): Promise; getResolvedLogView(logViewId: string): Promise; putLogView(logViewId: string, logViewAttributes: Partial): Promise; - resolveLogView(logViewAttributes: LogViewAttributes): Promise; + resolveLogView(logViewId: string, logViewAttributes: LogViewAttributes): Promise; } From f948012f33a7284e4ee31baf3378c79726b5b954 Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Mon, 31 Oct 2022 11:05:10 +0000 Subject: [PATCH 22/25] Small tweaks - Remove duplicate import - Remove unnecessary memoization --- .../public/containers/logs/log_filter/log_filter_state.ts | 3 +-- x-pack/plugins/infra/public/hooks/use_log_view.ts | 8 ++------ 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts b/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts index c28d5cd21706b..4a2f6e280ebe6 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts +++ b/x-pack/plugins/infra/public/containers/logs/log_filter/log_filter_state.ts @@ -5,12 +5,11 @@ * 2.0. */ -import { useMemo, useEffect } from 'react'; +import { useMemo, useEffect, useCallback, useState } from 'react'; import { merge, of } from 'rxjs'; import { i18n } from '@kbn/i18n'; import { buildEsQuery, DataViewBase, Query, AggregateQuery, isOfQueryType } from '@kbn/es-query'; import createContainer from 'constate'; -import { useCallback, useState } from 'react'; import { useKibanaQuerySettings } from '../../../utils/use_kibana_query_settings'; import { BuiltEsQuery } from '../log_stream'; import { useKibanaContextForPlugin } from '../../../hooks/use_kibana'; diff --git a/x-pack/plugins/infra/public/hooks/use_log_view.ts b/x-pack/plugins/infra/public/hooks/use_log_view.ts index eef3d5dd13422..1781bc7346a2f 100644 --- a/x-pack/plugins/infra/public/hooks/use_log_view.ts +++ b/x-pack/plugins/infra/public/hooks/use_log_view.ts @@ -6,7 +6,7 @@ */ import createContainer from 'constate'; -import { useCallback, useEffect, useMemo, useState } from 'react'; +import { useCallback, useEffect, useState } from 'react'; import type { HttpHandler } from '@kbn/core/public'; import { LogView, LogViewAttributes, LogViewStatus, ResolvedLogView } from '../../common/log_views'; import type { ILogViewsClient } from '../services/log_views'; @@ -63,10 +63,6 @@ export const useLogView = ({ [logViews] ); - const derivedDataView = useMemo(() => { - return resolvedLogView?.dataViewReference; - }, [resolvedLogView]); - const isLoadingLogView = loadLogViewRequest.state === 'pending'; const isResolvingLogView = resolveLogViewRequest.state === 'pending'; const isLoadingLogViewStatus = loadLogViewStatusRequest.state === 'pending'; @@ -120,7 +116,7 @@ export const useLogView = ({ return { logViewId, isUninitialized, - derivedDataView, + derivedDataView: resolvedLogView?.dataViewReference, // Failure states hasFailedLoading, From 8867aefb2b85b091188f7db20f79c93c615b2a0c Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Mon, 31 Oct 2022 11:29:38 +0000 Subject: [PATCH 23/25] Fix tests in link_to_logs.test.tsx --- .../infra/common/log_views/resolved_log_view.mock.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/infra/common/log_views/resolved_log_view.mock.ts b/x-pack/plugins/infra/common/log_views/resolved_log_view.mock.ts index dd7b4b4430370..88544b02a24c6 100644 --- a/x-pack/plugins/infra/common/log_views/resolved_log_view.mock.ts +++ b/x-pack/plugins/infra/common/log_views/resolved_log_view.mock.ts @@ -10,7 +10,7 @@ import { createStubDataView } from '@kbn/data-views-plugin/common/stubs'; import { defaultLogViewsStaticConfig } from './defaults'; import { ResolvedLogView, resolveLogView } from './resolved_log_view'; import { LogViewAttributes } from './types'; -import { DataView } from '@kbn/data-views-plugin/common'; +import { DataView, DataViewSpec } from '@kbn/data-views-plugin/common'; const dataViewMock = { id: 'log-view-data-view-mock', @@ -59,6 +59,10 @@ export const createResolvedLogViewMockFromAttributes = (logViewAttributes: LogVi { get: async () => createStubDataView({ spec: {} }), getFieldsForWildcard: async () => [], + create: async (spec: DataViewSpec) => + createStubDataView({ + spec, + }), } as unknown as DataViewsContract, defaultLogViewsStaticConfig ); From 3f5f8d87c4b0630f540189bfd8792ba017c57b18 Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Mon, 31 Oct 2022 11:38:23 +0000 Subject: [PATCH 24/25] Update snapshot for log_views_client.test.ts --- .../log_views/log_views_client.test.ts | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/x-pack/plugins/infra/server/services/log_views/log_views_client.test.ts b/x-pack/plugins/infra/server/services/log_views/log_views_client.test.ts index cf0d1ea155bb9..e517ae8aef7f0 100644 --- a/x-pack/plugins/infra/server/services/log_views/log_views_client.test.ts +++ b/x-pack/plugins/infra/server/services/log_views/log_views_client.test.ts @@ -280,6 +280,64 @@ describe('LogViewsClient class', () => { }, }, ], + "dataViewReference": DataView { + "allowNoIndex": false, + "deleteFieldFormat": [Function], + "fieldAttrs": Object {}, + "fieldFormatMap": Object {}, + "fieldFormats": Object { + "deserialize": [MockFunction], + "getByFieldType": [MockFunction], + "getDefaultConfig": [MockFunction], + "getDefaultInstance": [MockFunction], + "getDefaultInstanceCacheResolver": [MockFunction], + "getDefaultInstancePlain": [MockFunction], + "getDefaultType": [MockFunction], + "getDefaultTypeName": [MockFunction], + "getInstance": [MockFunction], + "getType": [MockFunction], + "getTypeNameByEsTypes": [MockFunction], + "getTypeWithoutMetaParams": [MockFunction], + "has": [MockFunction], + "init": [MockFunction], + "parseDefaultTypeMap": [MockFunction], + "register": [MockFunction], + }, + "fields": FldList [], + "flattenHit": [Function], + "getFieldAttrs": [Function], + "getIndexPattern": [Function], + "getName": [Function], + "getOriginalSavedObjectBody": [Function], + "id": "LOG_DATA_VIEW", + "matchedIndices": Array [], + "metaFields": Array [ + "_id", + "_type", + "_source", + ], + "name": "", + "namespaces": Array [], + "originalSavedObjectBody": Object {}, + "resetOriginalSavedObjectBody": [Function], + "runtimeFieldMap": Object { + "runtime_field": Object { + "script": Object { + "source": "emit(\\"runtime value\\")", + }, + "type": "keyword", + }, + }, + "setFieldFormat": [Function], + "setIndexPattern": [Function], + "shortDotsEnable": false, + "sourceFilters": Array [], + "timeFieldName": "@timestamp", + "title": "log-indices-*", + "type": undefined, + "typeMeta": undefined, + "version": "1", + }, "description": "LOG VIEW DESCRIPTION", "fields": FldList [], "indices": "log-indices-*", From 7c99c5e604b0a8bfdb45440d3278240dfdad361d Mon Sep 17 00:00:00 2001 From: Kerry Gallagher Date: Tue, 1 Nov 2022 15:52:28 +0000 Subject: [PATCH 25/25] Use createStubDataView over custom object --- .../common/log_views/resolved_log_view.mock.ts | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/infra/common/log_views/resolved_log_view.mock.ts b/x-pack/plugins/infra/common/log_views/resolved_log_view.mock.ts index 88544b02a24c6..8c09f16e3b53e 100644 --- a/x-pack/plugins/infra/common/log_views/resolved_log_view.mock.ts +++ b/x-pack/plugins/infra/common/log_views/resolved_log_view.mock.ts @@ -10,13 +10,7 @@ import { createStubDataView } from '@kbn/data-views-plugin/common/stubs'; import { defaultLogViewsStaticConfig } from './defaults'; import { ResolvedLogView, resolveLogView } from './resolved_log_view'; import { LogViewAttributes } from './types'; -import { DataView, DataViewSpec } from '@kbn/data-views-plugin/common'; - -const dataViewMock = { - id: 'log-view-data-view-mock', - title: 'log-view-data-view-mock-title', - fields: [], -} as unknown as DataView; +import { DataViewSpec } from '@kbn/data-views-plugin/common'; export const createResolvedLogViewMock = ( resolvedLogViewOverrides: Partial = {} @@ -48,7 +42,12 @@ export const createResolvedLogViewMock = ( messageColumn: { id: 'MESSAGE_COLUMN_ID' }, }, ], - dataViewReference: dataViewMock, + dataViewReference: createStubDataView({ + spec: { + id: 'log-view-data-view-mock', + title: 'log-indices-*', + }, + }), ...resolvedLogViewOverrides, });