diff --git a/public/components/common/search/__tests__/search.test.tsx b/public/components/common/search/__tests__/search.test.tsx
index dafa7567a..821e264e9 100644
--- a/public/components/common/search/__tests__/search.test.tsx
+++ b/public/components/common/search/__tests__/search.test.tsx
@@ -3,15 +3,18 @@
* SPDX-License-Identifier: Apache-2.0
*/
+import { applyMiddleware, createStore } from '@reduxjs/toolkit';
+import { render } from '@testing-library/react';
import { configure, mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import React from 'react';
-import { applyMiddleware, createStore } from '@reduxjs/toolkit';
-import { rootReducer } from '../../../../framework/redux/reducers';
import { Provider } from 'react-redux';
-import { Search } from '../search';
import thunk from 'redux-thunk';
+import { coreRefs } from '../../../../framework/core_refs';
+import { rootReducer } from '../../../../framework/redux/reducers';
import { initialTabId } from '../../../../framework/redux/store/shared_state';
+import * as hookExports from '../../../event_analytics/explorer/query_assist/hooks';
+import { Search } from '../search';
describe('Explorer Search component', () => {
configure({ adapter: new Adapter() });
@@ -27,3 +30,63 @@ describe('Explorer Search component', () => {
expect(wrapper).toMatchSnapshot();
});
});
+
+describe('Search state', () => {
+ const catIndicesSpy = jest.spyOn(hookExports, 'useCatIndices');
+ const getIndexPatternsSpy = jest.spyOn(hookExports, 'useGetIndexPatterns');
+ const store = createStore(rootReducer, applyMiddleware(thunk));
+
+ beforeEach(() => {
+ coreRefs.queryAssistEnabled = true;
+ });
+
+ afterEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it('selects logs sample data over others', async () => {
+ catIndicesSpy.mockReturnValue({
+ data: [{ label: 'opensearch_dashboards_sample_data_flights' }],
+ loading: false,
+ refresh: jest.fn(),
+ });
+ getIndexPatternsSpy.mockReturnValue({
+ data: [{ label: 'test-index' }, { label: 'opensearch_dashboards_sample_data_logs' }],
+ loading: false,
+ refresh: jest.fn(),
+ });
+ const component = render(
+
+ Promise.resolve() }}
+ />
+
+ );
+ expect(component.getByText('opensearch_dashboards_sample_data_logs')).toBeInTheDocument();
+ });
+
+ it('selects other sample data', async () => {
+ catIndicesSpy.mockReturnValue({
+ data: [{ label: 'test-index' }, { label: 'opensearch_dashboards_sample_data_flights' }],
+ loading: false,
+ refresh: jest.fn(),
+ });
+ getIndexPatternsSpy.mockReturnValue({
+ data: [],
+ loading: false,
+ refresh: jest.fn(),
+ });
+ const component = render(
+
+ Promise.resolve() }}
+ />
+
+ );
+ expect(component.getByText('opensearch_dashboards_sample_data_flights')).toBeInTheDocument();
+ });
+});
diff --git a/public/components/common/search/query_area.tsx b/public/components/common/search/query_area.tsx
index 2345f0b2c..b176f4559 100644
--- a/public/components/common/search/query_area.tsx
+++ b/public/components/common/search/query_area.tsx
@@ -37,7 +37,7 @@ export function QueryArea({
const memoizedGetAvailableFields = useMemo(() => getAvailableFields, []);
const memoizedHandleQueryChange = useMemo(() => handleQueryChange, []);
useEffect(() => {
- const indexQuery = `source = ${selectedIndex[0].label}`;
+ const indexQuery = `source = ${selectedIndex[0]?.label || ''}`;
memoizedHandleQueryChange(indexQuery);
memoizedGetAvailableFields(indexQuery);
}, [selectedIndex, memoizedGetAvailableFields, memoizedHandleQueryChange]);
diff --git a/public/components/common/search/search.tsx b/public/components/common/search/search.tsx
index a99e02763..f101079fb 100644
--- a/public/components/common/search/search.tsx
+++ b/public/components/common/search/search.tsx
@@ -30,7 +30,11 @@ import {
OLLY_QUERY_ASSISTANT,
RAW_QUERY,
} from '../../../../common/constants/explorer';
-import { PPL_SPAN_REGEX } from '../../../../common/constants/shared';
+import {
+ PPL_SPAN_REGEX,
+ QUERY_ASSIST_END_TIME,
+ QUERY_ASSIST_START_TIME,
+} from '../../../../common/constants/shared';
import { uiSettingsService } from '../../../../common/utils';
import { useFetchEvents } from '../../../components/event_analytics/hooks';
import { usePolling } from '../../../components/hooks/use_polling';
@@ -277,14 +281,16 @@ export const Search = (props: any) => {
dispatch(changeQuery({ tabId, query: { [RAW_QUERY]: tempQuery } }));
});
onQuerySearch(queryLang);
- handleTimePickerChange([startTime, endTime]);
+ if (coreRefs.queryAssistEnabled) {
+ handleTimePickerChange([QUERY_ASSIST_START_TIME, QUERY_ASSIST_END_TIME]);
+ } else {
+ handleTimePickerChange([startTime, endTime]);
+ }
setNeedsUpdate(false);
};
// STATE FOR LANG PICKER AND INDEX PICKER
- const [selectedIndex, setSelectedIndex] = useState([
- { label: 'opensearch_dashboards_sample_data_logs' },
- ]);
+ const [selectedIndex, setSelectedIndex] = useState([]);
const { data: indices, loading: indicesLoading } = useCatIndices();
const { data: indexPatterns, loading: indexPatternsLoading } = useGetIndexPatterns();
const indicesAndIndexPatterns =
@@ -292,9 +298,25 @@ export const Search = (props: any) => {
? [...indexPatterns, ...indices].filter(
(v1, index, array) => array.findIndex((v2) => v1.label === v2.label) === index
)
- : undefined;
+ : [];
const loading = indicesLoading || indexPatternsLoading;
+ useEffect(() => {
+ if (selectedIndex.length || !indicesAndIndexPatterns.length) return;
+ // pre-fill selected index with sample logs or other sample data index
+ const sampleLogOption = indicesAndIndexPatterns.find(
+ (option) => option.label === 'opensearch_dashboards_sample_data_logs'
+ );
+ if (sampleLogOption) {
+ setSelectedIndex([sampleLogOption]);
+ return;
+ }
+ const sampleDataOption = indicesAndIndexPatterns.find((option) =>
+ option.label.startsWith('opensearch_dashboards_sample_data_')
+ );
+ if (sampleDataOption) setSelectedIndex([sampleDataOption]);
+ }, [indicesAndIndexPatterns]);
+
const onLanguagePopoverClick = () => {
setLanguagePopoverOpen(!_isLanguagePopoverOpen);
};
@@ -352,7 +374,7 @@ export const Search = (props: any) => {
Index}
singleSelection={{ asPlainText: true }}
isLoading={loading}
diff --git a/public/components/event_analytics/explorer/events_views/data_grid.tsx b/public/components/event_analytics/explorer/events_views/data_grid.tsx
index 2aede681f..2e5543713 100644
--- a/public/components/event_analytics/explorer/events_views/data_grid.tsx
+++ b/public/components/event_analytics/explorer/events_views/data_grid.tsx
@@ -29,7 +29,7 @@ import PPLService from '../../../../services/requests/ppl';
import { useFetchEvents } from '../../hooks';
import { redoQuery } from '../../utils/utils';
import { FlyoutButton } from './docViewRow';
-import { HitsCounter } from '../hits_counter/hits_counter';
+import { HitsCounter } from '../timechart/hits_counter';
export interface DataGridProps {
http: HttpSetup;
diff --git a/public/components/event_analytics/explorer/explorer.tsx b/public/components/event_analytics/explorer/explorer.tsx
index 0dd15575a..bccd7740b 100644
--- a/public/components/event_analytics/explorer/explorer.tsx
+++ b/public/components/event_analytics/explorer/explorer.tsx
@@ -21,7 +21,11 @@ import {
EuiText,
} from '@elastic/eui';
import { FormattedMessage } from '@osd/i18n/react';
-import _, { isEmpty, isEqual, reduce } from 'lodash';
+import { createBrowserHistory } from 'history';
+import isEmpty from 'lodash/isEmpty';
+import isEqual from 'lodash/isEqual';
+import reduce from 'lodash/reduce';
+import sum from 'lodash/sum';
import React, {
ReactElement,
useCallback,
@@ -32,7 +36,6 @@ import React, {
useState,
} from 'react';
import { batch, useDispatch, useSelector } from 'react-redux';
-import { createBrowserHistory } from 'history';
import { LogExplorerRouterContext } from '..';
import {
DEFAULT_DATA_SOURCE_TYPE,
@@ -127,13 +130,11 @@ import { formatError, getContentTabTitle } from '../utils/utils';
import { DataSourceSelection } from './datasources/datasources_selection';
import { DirectQueryRunning } from './direct_query_running';
import { DataGrid } from './events_views/data_grid';
-import { HitsCounter } from './hits_counter/hits_counter';
import { LogPatterns } from './log_patterns/log_patterns';
import { NoResults } from './no_results';
import { ObservabilitySideBar } from './sidebar/observability_sidebar';
-import { TimechartHeader } from './timechart_header';
+import { getTimeRangeFromCountDistribution, HitsCounter, Timechart } from './timechart';
import { ExplorerVisualizations } from './visualizations';
-import { CountDistribution } from './visualizations/count_distribution';
import { DirectQueryVisualization } from './visualizations/direct_query_vis';
export const Explorer = ({
@@ -527,12 +528,25 @@ export const Explorer = ({
handleQuerySearch();
};
+ /**
+ * If query assist is enabled, the time range is fixed to
+ * QUERY_ASSIST_START_TIME and QUERY_ASSIST_END_TIME and not useful. Return
+ * the time range based on aggregation buckets instead.
+ *
+ * @returns startTime and endTime
+ */
+ const getTimeChartRange = (): { startTime?: string; endTime?: string } => {
+ if (!coreRefs.queryAssistEnabled) return { startTime, endTime };
+ const { startTime: start, endTime: end } = getTimeRangeFromCountDistribution(countDistribution);
+ return { startTime: start ?? startTime, endTime: end ?? endTime };
+ };
+
const totalHits: number = useMemo(() => {
if (isLiveTailOn && countDistribution?.data) {
const hits = reduce(
countDistribution.data['count()'],
- (sum, n) => {
- return sum + n;
+ (total, n) => {
+ return total + n;
},
liveHits
);
@@ -558,13 +572,9 @@ export const Explorer = ({
{countDistribution?.data && !isLiveTailOnRef.current && (
- {}}
- />
- {
const intervalOptionsIndex = timeIntervalOptions.findIndex(
(item) => item.value === selectedIntrv
@@ -580,20 +590,10 @@ export const Explorer = ({
selectedIntervalRef.current = timeIntervalOptions[intervalOptionsIndex];
getPatterns(intrv, getErrorHandler('Error fetching patterns'));
}}
- stateInterval={
- countDistribution.selectedInterval || selectedIntervalRef.current?.value
- }
- startTime={startTime}
- endTime={endTime}
- />
-
-
)}
diff --git a/public/components/event_analytics/explorer/log_explorer.tsx b/public/components/event_analytics/explorer/log_explorer.tsx
index 8d7ea7b80..f49565161 100644
--- a/public/components/event_analytics/explorer/log_explorer.tsx
+++ b/public/components/event_analytics/explorer/log_explorer.tsx
@@ -18,13 +18,8 @@ import { EmptyTabParams, ILogExplorerProps } from '../../../../common/types/expl
import { selectQueryResult } from '../redux/slices/query_result_slice';
import { selectQueries } from '../redux/slices/query_slice';
import { selectQueryTabs } from '../redux/slices/query_tab_slice';
-import { Explorer } from './explorer';
import { getDateRange } from '../utils/utils';
-import {
- QUERY_ASSIST_END_TIME,
- QUERY_ASSIST_START_TIME,
-} from '../../../../common/constants/shared';
-import { coreRefs } from '../../../../public/framework/core_refs';
+import { Explorer } from './explorer';
const searchBarConfigs = {
[TAB_EVENT_ID]: {
diff --git a/public/components/event_analytics/explorer/query_assist/__tests__/__snapshots__/callouts.test.tsx.snap b/public/components/event_analytics/explorer/query_assist/__tests__/__snapshots__/callouts.test.tsx.snap
index 4bd92a425..6989a255d 100644
--- a/public/components/event_analytics/explorer/query_assist/__tests__/__snapshots__/callouts.test.tsx.snap
+++ b/public/components/event_analytics/explorer/query_assist/__tests__/__snapshots__/callouts.test.tsx.snap
@@ -4,7 +4,7 @@ exports[`Callouts spec EmptyQueryCallOut should match snapshot 1`] = `