Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Discover][Main] Split single query into 2 queries for faster results #104818

Merged
Merged
Show file tree
Hide file tree
Changes from 65 commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
bc93e88
Improve code
kertal Jun 14, 2021
e1ad9da
Fix hideChart issue
kertal Jun 14, 2021
1c35e4d
Merge branch 'master' into kertal-pr-2021-06-14-discover-improve-state
kibanamachine Jun 14, 2021
47f204b
Fix types
kertal Jun 14, 2021
d04c3e9
Merge branch 'kertal-pr-2021-06-14-discover-improve-state' of github.…
kertal Jun 14, 2021
ac0531a
Adding docs
kertal Jun 15, 2021
948068c
Initial draft version
kertal Jun 16, 2021
f41aead
Split data subjects
kertal Jun 17, 2021
d0ba9a2
Fix timechart_header.tsx
kertal Jun 17, 2021
504f9d6
Improve code
kertal Jun 18, 2021
4311045
Fix fetch counter
kertal Jun 18, 2021
ecd9fdc
Merge branch 'master' into kertal-pr-2021-06-16-discover-split-queries
kibanamachine Jun 18, 2021
0d28f79
Merge remote-tracking branch 'upstream/master' into kertal-pr-2021-06…
kertal Jun 18, 2021
aa8b517
Fix inspector functional test
kertal Jun 18, 2021
014bb5e
Adapt code for csv export
kertal Jun 18, 2021
bd28b0e
Improve code
kertal Jun 21, 2021
461e9f7
Improve code
kertal Jun 21, 2021
3f8fb25
Merge upstream / fix conflicts
kertal Jun 23, 2021
7eedebf
Fix double fetches
kertal Jun 28, 2021
1ca104c
Merge remote-tracking branch 'upstream/master' into kertal-pr-2021-06…
kertal Jun 29, 2021
84dd9b6
Refactor
kertal Jun 29, 2021
7c3ff5b
Fix another functional test
kertal Jun 30, 2021
abc9f64
Merge remote-tracking branch 'upstream/master' into kertal-pr-2021-06…
kertal Jun 30, 2021
19d8a70
Fix lots of jest tests
kertal Jul 1, 2021
2aec2c0
Fix sidebar test
kertal Jul 1, 2021
17932c7
Fix another functional
kertal Jul 1, 2021
3e0c5aa
Fix types
kertal Jul 1, 2021
27dbcc5
Merge remote-tracking branch 'upstream/master' into kertal-pr-2021-06…
kertal Jul 1, 2021
d3ce85c
Fix inspect functional test
kertal Jul 1, 2021
747bcad
Fix inspector test
kertal Jul 4, 2021
b5bd65a
Fix inspector test, part 2
kertal Jul 4, 2021
8ded1f3
Fix inspector test, part 2
kertal Jul 4, 2021
bc8bf95
Fix types
kertal Jul 5, 2021
dd0ab44
Merge remote-tracking branch 'upstream/master' into kertal-pr-2021-06…
kertal Jul 5, 2021
e25f5ac
fix runtime field tests
kertal Jul 5, 2021
7b3e14d
Cleanup code, fix functional tests
kertal Jul 5, 2021
fc0eb05
Refactor and add tests
kertal Jul 6, 2021
3db98eb
Add jest test for fetchChart
kertal Jul 7, 2021
4b2c450
Add basic fetchAll unit test
kertal Jul 7, 2021
06f3e67
Move function to utils
kertal Jul 7, 2021
fe54fa1
Improve queries of chart and total hits
kertal Jul 7, 2021
22a566b
Switch 2 to queries instead of 3
kertal Jul 8, 2021
c9d47be
Merge branch 'master' into kertal-pr-2020-06-08-discover-split-queries-2
kibanamachine Jul 12, 2021
7b37dab
Remove aggregation from total hits query
Jul 16, 2021
07b7d7e
Replace chart loading spinner
Jul 16, 2021
e8fbc3f
Show partial hit count while loading
Jul 16, 2021
e56c941
Minor design adjustments
Jul 16, 2021
b3f8a5b
Improve hit counter accessibility
Jul 16, 2021
31eb12a
Merge master, fix conflicts
kertal Jul 26, 2021
4826983
Remove unused translations
kertal Jul 26, 2021
6361297
Fix type
kertal Jul 26, 2021
62b48b2
Add test
kertal Jul 26, 2021
21bcc85
Improve tests
kertal Jul 27, 2021
ae3597c
Add tests
kertal Jul 29, 2021
c76a198
Merge branch 'master' into kertal-pr-2020-06-08-discover-split-queries-2
kibanamachine Jul 29, 2021
dbd38da
Update src/plugins/discover/public/application/apps/main/services/use…
kertal Jul 30, 2021
337abae
Update src/plugins/data/common/search/search_source/mocks.ts
kertal Jul 30, 2021
f4cd431
Address review comments
kertal Jul 30, 2021
f55d736
Merge branch 'kertal-pr-2020-06-08-discover-split-queries-2' of githu…
kertal Jul 30, 2021
cf88173
Add version to es doc search
kertal Jul 30, 2021
974063f
Add version to doc request
kertal Jul 30, 2021
a9f26fa
fix formatting
kertal Jul 30, 2021
4156dcc
Improve rendering in theme hooks
Jul 30, 2021
f778f68
Fix jest test failure
kertal Jul 30, 2021
af4f0c3
Merge branch 'kertal-pr-2020-06-08-discover-split-queries-2' of githu…
kertal Jul 30, 2021
4117df8
Merge branch 'master' into kertal-pr-2020-06-08-discover-split-queries-2
kibanamachine Aug 2, 2021
2da3b4e
Add tests for theme hook
Aug 2, 2021
62d2a38
Merge branch 'master' into kertal-pr-2020-06-08-discover-split-queries-2
kibanamachine Aug 2, 2021
5af3a8e
Merge branch 'master' into kertal-pr-2020-06-08-discover-split-queries-2
kibanamachine Aug 2, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 19 additions & 5 deletions src/plugins/charts/public/services/theme/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* Side Public License, v 1.
*/

import { useEffect, useState } from 'react';
import { useEffect, useRef, useState } from 'react';
import { Observable, BehaviorSubject } from 'rxjs';

import { CoreSetup } from 'kibana/public';
Expand Down Expand Up @@ -54,11 +54,18 @@ export class ThemeService {
/** A React hook for consuming the charts theme */
public useChartsTheme = (): PartialTheme => {
// eslint-disable-next-line react-hooks/rules-of-hooks
const [value, update] = useState(this.chartsDefaultTheme);
const [value, update] = useState(this._chartsTheme$.getValue());
// eslint-disable-next-line react-hooks/rules-of-hooks
const ref = useRef(value);

// eslint-disable-next-line react-hooks/rules-of-hooks
useEffect(() => {
const s = this.chartsTheme$.subscribe(update);
const s = this.chartsTheme$.subscribe((val) => {
if (val !== ref.current) {
ref.current = val;
update(val);
}
});
return () => s.unsubscribe();
}, []);

Expand All @@ -68,11 +75,18 @@ export class ThemeService {
/** A React hook for consuming the charts theme */
public useChartsBaseTheme = (): Theme => {
// eslint-disable-next-line react-hooks/rules-of-hooks
const [value, update] = useState(this.chartsDefaultBaseTheme);
const [value, update] = useState(this._chartsBaseTheme$.getValue());
// eslint-disable-next-line react-hooks/rules-of-hooks
const ref = useRef(value);

// eslint-disable-next-line react-hooks/rules-of-hooks
useEffect(() => {
const s = this.chartsBaseTheme$.subscribe(update);
const s = this.chartsBaseTheme$.subscribe((val) => {
if (val !== ref.current) {
ref.current = val;
update(val);
}
});
return () => s.unsubscribe();
}, []);

Expand Down
16 changes: 10 additions & 6 deletions src/plugins/data/common/search/search_source/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,17 @@ export const searchSourceCommonMock: jest.Mocked<ISearchStartSearchSource> = {
createEmpty: jest.fn().mockReturnValue(searchSourceInstanceMock),
};

export const createSearchSourceMock = (fields?: SearchSourceFields) =>
export const createSearchSourceMock = (fields?: SearchSourceFields, response?: any) =>
new SearchSource(fields, {
getConfig: uiSettingsServiceMock.createStartContract().get,
search: jest
.fn()
.mockReturnValue(
of({ rawResponse: { hits: { hits: [], total: 0 } }, isPartial: false, isRunning: false })
),
search: jest.fn().mockReturnValue(
of(
response ?? {
rawResponse: { hits: { hits: [], total: 0 } },
isPartial: false,
isRunning: false,
}
)
),
onResponse: jest.fn().mockImplementation((req, res) => res),
});
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ const indexPattern = ({
getSourceFiltering: () => ({}),
getFieldByName: (name: string) => fields.getByName(name),
timeFieldName: 'timestamp',
getFormatterForField: () => ({ convert: () => 'formatted' }),
} as unknown) as IndexPattern;

indexPattern.flattenHit = indexPatterns.flattenHitWrapper(indexPattern, indexPattern.metaFields);
Expand Down
23 changes: 23 additions & 0 deletions src/plugins/discover/public/__mocks__/saved_search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import { SavedSearch } from '../saved_searches';
import { createSearchSourceMock } from '../../../data/public/mocks';
import { indexPatternMock } from './index_pattern';
import { indexPatternWithTimefieldMock } from './index_pattern_with_timefield';

export const savedSearchMock = ({
id: 'the-saved-search-id',
Expand All @@ -31,3 +32,25 @@ export const savedSearchMock = ({
error: undefined,
searchSource: createSearchSourceMock({ index: indexPatternMock }),
} as unknown) as SavedSearch;

export const savedSearchMockWithTimeField = ({
id: 'the-saved-search-id-with-timefield',
type: 'search',
attributes: {
title: 'the-saved-search-title',
kibanaSavedObjectMeta: {
searchSourceJSON:
'{"highlightAll":true,"version":true,"query":{"query":"foo : \\"bar\\" ","language":"kuery"},"filter":[],"indexRefName":"kibanaSavedObjectMeta.searchSourceJSON.index"}',
},
},
references: [
{
name: 'kibanaSavedObjectMeta.searchSourceJSON.index',
type: 'index-pattern',
id: 'the-index-pattern-id',
},
],
migrationVersion: { search: '7.5.0' },
error: undefined,
searchSource: createSearchSourceMock({ index: indexPatternWithTimefieldMock }),
} as unknown) as SavedSearch;
18 changes: 17 additions & 1 deletion src/plugins/discover/public/__mocks__/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,15 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { EUI_CHARTS_THEME_LIGHT } from '@elastic/eui/dist/eui_charts_theme';
import { DiscoverServices } from '../build_services';
import { dataPluginMock } from '../../../data/public/mocks';
import { chromeServiceMock, coreMock, docLinksServiceMock } from '../../../../core/public/mocks';
import { DEFAULT_COLUMNS_SETTING } from '../../common';
import {
DEFAULT_COLUMNS_SETTING,
SAMPLE_SIZE_SETTING,
SORT_DEFAULT_ORDER_SETTING,
} from '../../common';
import { savedSearchMock } from './saved_search';
import { UI_SETTINGS } from '../../../data/common';
import { TopNavMenu } from '../../../navigation/public';
Expand Down Expand Up @@ -44,8 +49,15 @@ export const discoverServiceMock = ({
return [];
} else if (key === UI_SETTINGS.META_FIELDS) {
return [];
} else if (key === SAMPLE_SIZE_SETTING) {
return 250;
} else if (key === SORT_DEFAULT_ORDER_SETTING) {
return 'desc';
}
},
isDefault: (key: string) => {
return true;
},
},
indexPatternFieldEditor: {
openEditor: jest.fn(),
Expand All @@ -60,4 +72,8 @@ export const discoverServiceMock = ({
metadata: {
branch: 'test',
},
theme: {
useChartsTheme: jest.fn(() => EUI_CHARTS_THEME_LIGHT.theme),
useChartsBaseTheme: jest.fn(() => EUI_CHARTS_THEME_LIGHT.theme),
},
} as unknown) as DiscoverServices;
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import React from 'react';
import { Subject, BehaviorSubject } from 'rxjs';
import { mountWithIntl } from '@kbn/test/jest';
import { setHeaderActionMenuMounter } from '../../../../../kibana_services';
import { esHits } from '../../../../../__mocks__/es_hits';
import { savedSearchMock } from '../../../../../__mocks__/saved_search';
import { createSearchSourceMock } from '../../../../../../../data/common/search/search_source/mocks';
import { GetStateReturn } from '../../services/discover_state';
import { DataCharts$, DataTotalHits$ } from '../../services/use_saved_search';
import { discoverServiceMock } from '../../../../../__mocks__/services';
import { FetchStatus } from '../../../../types';
import { Chart } from './point_series';
import { DiscoverChart } from './discover_chart';

setHeaderActionMenuMounter(jest.fn());

function getProps(timefield?: string) {
const searchSourceMock = createSearchSourceMock({});
const services = discoverServiceMock;
services.data.query.timefilter.timefilter.getTime = () => {
return { from: '2020-05-14T11:05:13.590', to: '2020-05-14T11:20:13.590' };
};

const totalHits$ = new BehaviorSubject({
fetchStatus: FetchStatus.COMPLETE,
result: Number(esHits.length),
}) as DataTotalHits$;

const chartData = ({
xAxisOrderedValues: [
1623880800000,
1623967200000,
1624053600000,
1624140000000,
1624226400000,
1624312800000,
1624399200000,
1624485600000,
1624572000000,
1624658400000,
1624744800000,
1624831200000,
1624917600000,
1625004000000,
1625090400000,
],
xAxisFormat: { id: 'date', params: { pattern: 'YYYY-MM-DD' } },
xAxisLabel: 'order_date per day',
yAxisFormat: { id: 'number' },
ordered: {
date: true,
interval: {
asMilliseconds: jest.fn(),
},
intervalESUnit: 'd',
intervalESValue: 1,
min: '2021-03-18T08:28:56.411Z',
max: '2021-07-01T07:28:56.411Z',
},
yAxisLabel: 'Count',
values: [
{ x: 1623880800000, y: 134 },
{ x: 1623967200000, y: 152 },
{ x: 1624053600000, y: 141 },
{ x: 1624140000000, y: 138 },
{ x: 1624226400000, y: 142 },
{ x: 1624312800000, y: 157 },
{ x: 1624399200000, y: 149 },
{ x: 1624485600000, y: 146 },
{ x: 1624572000000, y: 170 },
{ x: 1624658400000, y: 137 },
{ x: 1624744800000, y: 150 },
{ x: 1624831200000, y: 144 },
{ x: 1624917600000, y: 147 },
{ x: 1625004000000, y: 137 },
{ x: 1625090400000, y: 66 },
],
} as unknown) as Chart;

const charts$ = new BehaviorSubject({
fetchStatus: FetchStatus.COMPLETE,
chartData,
bucketInterval: {
scaled: true,
description: 'test',
scale: 2,
},
}) as DataCharts$;

return {
isLegacy: false,
resetQuery: jest.fn(),
savedSearch: savedSearchMock,
savedSearchDataChart$: charts$,
savedSearchDataTotalHits$: totalHits$,
savedSearchRefetch$: new Subject(),
searchSource: searchSourceMock,
services,
state: { columns: [] },
stateContainer: {} as GetStateReturn,
timefield,
};
}

describe('Discover chart', () => {
test('render without timefield', () => {
const component = mountWithIntl(<DiscoverChart {...getProps()} />);
expect(component.find('[data-test-subj="discoverChartToggle"]').exists()).toBeFalsy();
});
test('render with filefield', () => {
const component = mountWithIntl(<DiscoverChart {...getProps('timefield')} />);
expect(component.find('[data-test-subj="discoverChartToggle"]').exists()).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,48 +5,43 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import React, { useCallback, useEffect, useRef } from 'react';
import React, { useCallback, useEffect, useRef, memo } from 'react';
import moment from 'moment';
import { EuiFlexGroup, EuiFlexItem, EuiButtonEmpty, EuiSpacer } from '@elastic/eui';
import { IUiSettingsClient } from 'kibana/public';
import { i18n } from '@kbn/i18n';
import { HitsCounter } from '../hits_counter';
import { DataPublicPluginStart, IndexPattern, search } from '../../../../../../../data/public';
import { search } from '../../../../../../../data/public';
import { TimechartHeader } from '../timechart_header';
import { SavedSearch } from '../../../../../saved_searches';
import { AppState, GetStateReturn } from '../../services/discover_state';
import { TimechartBucketInterval } from '../timechart_header/timechart_header';
import { Chart as IChart } from './point_series';
import { DiscoverHistogram } from './histogram';
import { DataCharts$, DataTotalHits$ } from '../../services/use_saved_search';
import { DiscoverServices } from '../../../../../build_services';

const TimechartHeaderMemoized = React.memo(TimechartHeader);
const DiscoverHistogramMemoized = React.memo(DiscoverHistogram);
const TimechartHeaderMemoized = memo(TimechartHeader);
const DiscoverHistogramMemoized = memo(DiscoverHistogram);
export function DiscoverChart({
config,
data,
bucketInterval,
chartData,
hits,
isLegacy,
resetQuery,
savedSearch,
savedSearchDataChart$,
savedSearchDataTotalHits$,
services,
state,
stateContainer,
timefield,
}: {
config: IUiSettingsClient;
data: DataPublicPluginStart;
bucketInterval?: TimechartBucketInterval;
chartData?: IChart;
hits?: number;
indexPattern: IndexPattern;
isLegacy: boolean;
resetQuery: () => void;
savedSearch: SavedSearch;
savedSearchDataChart$: DataCharts$;
savedSearchDataTotalHits$: DataTotalHits$;
services: DiscoverServices;
state: AppState;
stateContainer: GetStateReturn;
timefield?: string;
}) {
const { data, uiSettings: config } = services;
const chartRef = useRef<{ element: HTMLElement | null; moveFocus: boolean }>({
element: null,
moveFocus: false,
Expand Down Expand Up @@ -93,7 +88,7 @@ export function DiscoverChart({
className="dscResuntCount__title eui-textTruncate eui-textNoWrap"
>
<HitsCounter
hits={hits}
savedSearchData$={savedSearchDataTotalHits$}
showResetButton={!!(savedSearch && savedSearch.id)}
onResetQuery={resetQuery}
/>
Expand All @@ -106,7 +101,7 @@ export function DiscoverChart({
options={search.aggs.intervalOptions}
onChangeInterval={onChangeInterval}
stateInterval={state.interval || ''}
bucketInterval={bucketInterval}
savedSearchData$={savedSearchDataChart$}
/>
</EuiFlexItem>
)}
Expand All @@ -130,7 +125,7 @@ export function DiscoverChart({
)}
</EuiFlexGroup>
</EuiFlexItem>
{!state.hideChart && chartData && (
{timefield && !state.hideChart && (
<EuiFlexItem grow={false}>
<section
ref={(element) => (chartRef.current.element = element)}
Expand All @@ -145,8 +140,9 @@ export function DiscoverChart({
data-test-subj="discoverChart"
>
<DiscoverHistogramMemoized
chartData={chartData}
savedSearchData$={savedSearchDataChart$}
timefilterUpdateHandler={timefilterUpdateHandler}
services={services}
/>
</div>
</section>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.dscChart__loading {
display: flex;
flex-direction: column;
justify-content: center;
flex: 1 0 100%;
text-align: center;
height: 100%;
width: 100%;
}
Loading