From 9ce22752544fb0ab1d7c68038f3dcad35e514b4c Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Tue, 18 Aug 2020 19:06:12 -0700 Subject: [PATCH 01/77] [Search] Remove long-running query pop-up --- .../collectors/create_usage_collector.test.ts | 27 ------ .../collectors/create_usage_collector.ts | 24 ----- .../data/public/search/collectors/types.ts | 6 -- .../public/search/long_query_notification.tsx | 59 ------------- .../public/search/search_interceptor.test.ts | 43 +-------- .../data/public/search/search_interceptor.ts | 63 +------------ .../data/public/search/search_service.ts | 1 - x-pack/plugins/data_enhanced/public/plugin.ts | 1 - .../public/search/long_query_notification.tsx | 47 ---------- .../public/search/search_interceptor.test.ts | 88 ------------------- .../public/search/search_interceptor.ts | 28 ------ 11 files changed, 3 insertions(+), 384 deletions(-) delete mode 100644 src/plugins/data/public/search/long_query_notification.tsx delete mode 100644 x-pack/plugins/data_enhanced/public/search/long_query_notification.tsx diff --git a/src/plugins/data/public/search/collectors/create_usage_collector.test.ts b/src/plugins/data/public/search/collectors/create_usage_collector.test.ts index aaaac5ae6ff7c..7ad14237a47ea 100644 --- a/src/plugins/data/public/search/collectors/create_usage_collector.test.ts +++ b/src/plugins/data/public/search/collectors/create_usage_collector.test.ts @@ -63,31 +63,4 @@ describe('Search Usage Collector', () => { SEARCH_EVENT_TYPE.QUERIES_CANCELLED ); }); - - test('tracks long popups', async () => { - await usageCollector.trackLongQueryPopupShown(); - expect(mockUsageCollectionSetup.reportUiStats).toHaveBeenCalled(); - expect(mockUsageCollectionSetup.reportUiStats.mock.calls[0][1]).toBe(METRIC_TYPE.LOADED); - expect(mockUsageCollectionSetup.reportUiStats.mock.calls[0][2]).toBe( - SEARCH_EVENT_TYPE.LONG_QUERY_POPUP_SHOWN - ); - }); - - test('tracks long popups dismissed', async () => { - await usageCollector.trackLongQueryDialogDismissed(); - expect(mockUsageCollectionSetup.reportUiStats).toHaveBeenCalled(); - expect(mockUsageCollectionSetup.reportUiStats.mock.calls[0][1]).toBe(METRIC_TYPE.CLICK); - expect(mockUsageCollectionSetup.reportUiStats.mock.calls[0][2]).toBe( - SEARCH_EVENT_TYPE.LONG_QUERY_DIALOG_DISMISSED - ); - }); - - test('tracks run query beyond timeout', async () => { - await usageCollector.trackLongQueryRunBeyondTimeout(); - expect(mockUsageCollectionSetup.reportUiStats).toHaveBeenCalled(); - expect(mockUsageCollectionSetup.reportUiStats.mock.calls[0][1]).toBe(METRIC_TYPE.CLICK); - expect(mockUsageCollectionSetup.reportUiStats.mock.calls[0][2]).toBe( - SEARCH_EVENT_TYPE.LONG_QUERY_RUN_BEYOND_TIMEOUT - ); - }); }); diff --git a/src/plugins/data/public/search/collectors/create_usage_collector.ts b/src/plugins/data/public/search/collectors/create_usage_collector.ts index 7adb0c3caa675..cf32dbc03b3b1 100644 --- a/src/plugins/data/public/search/collectors/create_usage_collector.ts +++ b/src/plugins/data/public/search/collectors/create_usage_collector.ts @@ -48,29 +48,5 @@ export const createUsageCollector = ( SEARCH_EVENT_TYPE.QUERIES_CANCELLED ); }, - trackLongQueryPopupShown: async () => { - const currentApp = await getCurrentApp(); - return usageCollection?.reportUiStats( - currentApp!, - METRIC_TYPE.LOADED, - SEARCH_EVENT_TYPE.LONG_QUERY_POPUP_SHOWN - ); - }, - trackLongQueryDialogDismissed: async () => { - const currentApp = await getCurrentApp(); - return usageCollection?.reportUiStats( - currentApp!, - METRIC_TYPE.CLICK, - SEARCH_EVENT_TYPE.LONG_QUERY_DIALOG_DISMISSED - ); - }, - trackLongQueryRunBeyondTimeout: async () => { - const currentApp = await getCurrentApp(); - return usageCollection?.reportUiStats( - currentApp!, - METRIC_TYPE.CLICK, - SEARCH_EVENT_TYPE.LONG_QUERY_RUN_BEYOND_TIMEOUT - ); - }, }; }; diff --git a/src/plugins/data/public/search/collectors/types.ts b/src/plugins/data/public/search/collectors/types.ts index 3e98f901eb0c3..bb7fa1e6ae4a2 100644 --- a/src/plugins/data/public/search/collectors/types.ts +++ b/src/plugins/data/public/search/collectors/types.ts @@ -20,15 +20,9 @@ export enum SEARCH_EVENT_TYPE { QUERY_TIMED_OUT = 'queryTimedOut', QUERIES_CANCELLED = 'queriesCancelled', - LONG_QUERY_POPUP_SHOWN = 'longQueryPopupShown', - LONG_QUERY_DIALOG_DISMISSED = 'longQueryDialogDismissed', - LONG_QUERY_RUN_BEYOND_TIMEOUT = 'longQueryRunBeyondTimeout', } export interface SearchUsageCollector { trackQueryTimedOut: () => Promise; trackQueriesCancelled: () => Promise; - trackLongQueryPopupShown: () => Promise; - trackLongQueryDialogDismissed: () => Promise; - trackLongQueryRunBeyondTimeout: () => Promise; } diff --git a/src/plugins/data/public/search/long_query_notification.tsx b/src/plugins/data/public/search/long_query_notification.tsx deleted file mode 100644 index 1db298618fae8..0000000000000 --- a/src/plugins/data/public/search/long_query_notification.tsx +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; -import React from 'react'; -import { ApplicationStart } from 'kibana/public'; -import { toMountPoint } from '../../../kibana_react/public'; - -interface Props { - application: ApplicationStart; -} - -export function getLongQueryNotification(props: Props) { - return toMountPoint(); -} - -export function LongQueryNotification(props: Props) { - return ( -
- - - - - { - await props.application.navigateToApp('management/stack/license_management'); - }} - > - - - - -
- ); -} diff --git a/src/plugins/data/public/search/search_interceptor.test.ts b/src/plugins/data/public/search/search_interceptor.test.ts index 2eded17bda88c..70224306efe39 100644 --- a/src/plugins/data/public/search/search_interceptor.test.ts +++ b/src/plugins/data/public/search/search_interceptor.test.ts @@ -34,7 +34,6 @@ describe('SearchInterceptor', () => { mockCoreSetup = coreMock.createSetup(); searchInterceptor = new SearchInterceptor( { - toasts: mockCoreSetup.notifications.toasts, startServices: mockCoreSetup.getStartServices(), uiSettings: mockCoreSetup.uiSettings, http: mockCoreSetup.http, @@ -126,7 +125,7 @@ describe('SearchInterceptor', () => { await flushPromises(); }); - test('Immediatelly aborts if passed an aborted abort signal', async (done) => { + test('Immediately aborts if passed an aborted abort signal', async (done) => { const abort = new AbortController(); const mockRequest: IEsSearchRequest = { params: {}, @@ -142,44 +141,4 @@ describe('SearchInterceptor', () => { response.subscribe({ error }); }); }); - - describe('getPendingCount$', () => { - test('should observe the number of pending requests', () => { - const pendingCount$ = searchInterceptor.getPendingCount$(); - const pendingNext = jest.fn(); - pendingCount$.subscribe(pendingNext); - - const mockResponse: any = { result: 200 }; - mockCoreSetup.http.fetch.mockResolvedValue(mockResponse); - const mockRequest: IEsSearchRequest = { - params: {}, - }; - const response = searchInterceptor.search(mockRequest); - - response.subscribe({ - complete: () => { - expect(pendingNext.mock.calls).toEqual([[0], [1], [0]]); - }, - }); - }); - - test('should observe the number of pending requests on error', () => { - const pendingCount$ = searchInterceptor.getPendingCount$(); - const pendingNext = jest.fn(); - pendingCount$.subscribe(pendingNext); - - const mockResponse: any = { result: 500 }; - mockCoreSetup.http.fetch.mockRejectedValue(mockResponse); - const mockRequest: IEsSearchRequest = { - params: {}, - }; - const response = searchInterceptor.search(mockRequest); - - response.subscribe({ - complete: () => { - expect(pendingNext.mock.calls).toEqual([[0], [1], [0]]); - }, - }); - }); - }); }); diff --git a/src/plugins/data/public/search/search_interceptor.ts b/src/plugins/data/public/search/search_interceptor.ts index 99fccda7fddf3..de73a77bca8cc 100644 --- a/src/plugins/data/public/search/search_interceptor.ts +++ b/src/plugins/data/public/search/search_interceptor.ts @@ -19,18 +19,15 @@ import { trimEnd } from 'lodash'; import { BehaviorSubject, throwError, timer, Subscription, defer, from, Observable } from 'rxjs'; -import { finalize, filter } from 'rxjs/operators'; -import { Toast, CoreStart, ToastsSetup, CoreSetup } from 'kibana/public'; +import { finalize } from 'rxjs/operators'; +import { CoreStart, CoreSetup } from 'kibana/public'; import { getCombinedSignal, AbortError } from '../../common/utils'; import { IEsSearchRequest, IEsSearchResponse, ES_SEARCH_STRATEGY } from '../../common/search'; import { ISearchOptions } from './types'; -import { getLongQueryNotification } from './long_query_notification'; import { SearchUsageCollector } from './collectors'; -const LONG_QUERY_NOTIFICATION_DELAY = 10000; export interface SearchInterceptorDeps { - toasts: ToastsSetup; http: CoreSetup['http']; uiSettings: CoreSetup['uiSettings']; startServices: Promise<[CoreStart, any, unknown]>; @@ -56,12 +53,6 @@ export class SearchInterceptor { */ protected timeoutSubscriptions: Subscription = new Subscription(); - /** - * The current long-running toast (if there is one). - * @internal - */ - protected longRunningToast?: Toast; - /** * @internal */ @@ -70,7 +61,6 @@ export class SearchInterceptor { /** * This class should be instantiated with a `requestTimeout` corresponding with how many ms after * requests are initiated that they should automatically cancel. - * @param toasts The `core.notifications.toasts` service * @param application The `core.application` service * @param requestTimeout Usually config value `elasticsearch.requestTimeout` */ @@ -83,20 +73,6 @@ export class SearchInterceptor { this.deps.startServices.then(([coreStart]) => { this.application = coreStart.application; }); - - // When search requests go out, a notification is scheduled allowing users to continue the - // request past the timeout. When all search requests complete, we remove the notification. - this.getPendingCount$() - .pipe(filter((count) => count === 0)) - .subscribe(this.hideToast); - } - - /** - * Returns an `Observable` over the current number of pending searches. This could mean that one - * of the search requests is still in flight, or that it has only received partial responses. - */ - public getPendingCount$() { - return this.pendingCount$.asObservable(); } protected runSearch( @@ -154,9 +130,6 @@ export class SearchInterceptor { }); this.timeoutSubscriptions.add(subscription); - // Schedule the notification to allow users to cancel or wait beyond the timeout - const notificationSubscription = timer(LONG_QUERY_NOTIFICATION_DELAY).subscribe(this.showToast); - // Get a combined `AbortSignal` that will be aborted whenever the first of the following occurs: // 1. The user manually aborts (via `cancelPending`) // 2. The request times out @@ -170,7 +143,6 @@ export class SearchInterceptor { const combinedSignal = getCombinedSignal(signals); const cleanup = () => { this.timeoutSubscriptions.remove(subscription); - notificationSubscription.unsubscribe(); }; combinedSignal.addEventListener('abort', cleanup); @@ -180,37 +152,6 @@ export class SearchInterceptor { cleanup, }; } - - /** - * @internal - */ - protected showToast = () => { - if (this.longRunningToast) return; - this.longRunningToast = this.deps.toasts.addInfo( - { - title: 'Your query is taking a while', - text: getLongQueryNotification({ - application: this.application, - }), - }, - { - toastLifeTimeMs: 1000000, - } - ); - }; - - /** - * @internal - */ - protected hideToast = () => { - if (this.longRunningToast) { - this.deps.toasts.remove(this.longRunningToast); - delete this.longRunningToast; - if (this.deps.usageCollector) { - this.deps.usageCollector.trackLongQueryDialogDismissed(); - } - } - }; } export type ISearchInterceptor = PublicMethodsOf; diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts index 04e1a46c84652..e8c5c89398b89 100644 --- a/src/plugins/data/public/search/search_service.ts +++ b/src/plugins/data/public/search/search_service.ts @@ -64,7 +64,6 @@ export class SearchService implements Plugin { */ this.searchInterceptor = new SearchInterceptor( { - toasts: core.notifications.toasts, http: core.http, uiSettings: core.uiSettings, startServices: core.getStartServices(), diff --git a/x-pack/plugins/data_enhanced/public/plugin.ts b/x-pack/plugins/data_enhanced/public/plugin.ts index 7f6e3feac0671..e50ea298e1234 100644 --- a/x-pack/plugins/data_enhanced/public/plugin.ts +++ b/x-pack/plugins/data_enhanced/public/plugin.ts @@ -34,7 +34,6 @@ export class DataEnhancedPlugin const enhancedSearchInterceptor = new EnhancedSearchInterceptor( { - toasts: core.notifications.toasts, http: core.http, uiSettings: core.uiSettings, startServices: core.getStartServices(), diff --git a/x-pack/plugins/data_enhanced/public/search/long_query_notification.tsx b/x-pack/plugins/data_enhanced/public/search/long_query_notification.tsx deleted file mode 100644 index 325cf1145fa5f..0000000000000 --- a/x-pack/plugins/data_enhanced/public/search/long_query_notification.tsx +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { EuiButton, EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; -import React from 'react'; -import { toMountPoint } from '../../../../../src/plugins/kibana_react/public'; - -interface Props { - cancel: () => void; - runBeyondTimeout: () => void; -} - -export function getLongQueryNotification(props: Props) { - return toMountPoint( - - ); -} - -export function LongQueryNotification(props: Props) { - return ( -
- - - - - - - - - - - - - -
- ); -} diff --git a/x-pack/plugins/data_enhanced/public/search/search_interceptor.test.ts b/x-pack/plugins/data_enhanced/public/search/search_interceptor.test.ts index fe954f1602cd3..9b1b41ef1e3bf 100644 --- a/x-pack/plugins/data_enhanced/public/search/search_interceptor.test.ts +++ b/x-pack/plugins/data_enhanced/public/search/search_interceptor.test.ts @@ -51,9 +51,6 @@ describe('EnhancedSearchInterceptor', () => { mockUsageCollector = { trackQueryTimedOut: jest.fn(), trackQueriesCancelled: jest.fn(), - trackLongQueryPopupShown: jest.fn(), - trackLongQueryDialogDismissed: jest.fn(), - trackLongQueryRunBeyondTimeout: jest.fn(), }; const mockPromise = new Promise((resolve) => { @@ -66,7 +63,6 @@ describe('EnhancedSearchInterceptor', () => { searchInterceptor = new EnhancedSearchInterceptor( { - toasts: mockCoreSetup.notifications.toasts, startServices: mockPromise as any, http: mockCoreSetup.http, uiSettings: mockCoreSetup.uiSettings, @@ -384,88 +380,4 @@ describe('EnhancedSearchInterceptor', () => { expect(mockUsageCollector.trackQueriesCancelled).toBeCalledTimes(1); }); }); - - describe('runBeyondTimeout', () => { - const timedResponses = [ - { - time: 250, - value: { - isPartial: true, - isRunning: true, - id: 1, - rawResponse: { - took: 1, - }, - }, - }, - { - time: 2000, - value: { - isPartial: false, - isRunning: false, - id: 1, - rawResponse: { - took: 1, - }, - }, - }, - ]; - - test('times out if runBeyondTimeout is not called', async () => { - mockFetchImplementation(timedResponses); - - const response = searchInterceptor.search({}); - response.subscribe({ next, error }); - - await timeTravel(250); - - expect(next).toHaveBeenCalled(); - expect(next.mock.calls[0][0]).toStrictEqual(timedResponses[0].value); - - await timeTravel(750); - - expect(error).toHaveBeenCalled(); - expect(error.mock.calls[0][0]).toBeInstanceOf(AbortError); - }); - - test('times out if runBeyondTimeout is called too late', async () => { - mockFetchImplementation(timedResponses); - - const response = searchInterceptor.search({}); - response.subscribe({ next, error }); - setTimeout(() => searchInterceptor.runBeyondTimeout(), 1100); - - await timeTravel(250); - - expect(next).toHaveBeenCalled(); - expect(next.mock.calls[0][0]).toStrictEqual(timedResponses[0].value); - - await timeTravel(750); - - expect(error).toHaveBeenCalled(); - expect(error.mock.calls[0][0]).toBeInstanceOf(AbortError); - }); - - test('should prevent the request from timing out', async () => { - mockFetchImplementation(timedResponses); - - const response = searchInterceptor.search({}, { pollInterval: 0 }); - response.subscribe({ next, error, complete }); - setTimeout(() => searchInterceptor.runBeyondTimeout(), 500); - - await timeTravel(250); - - expect(next).toHaveBeenCalled(); - expect(next.mock.calls[0][0]).toStrictEqual(timedResponses[0].value); - - await timeTravel(250); // Run beyond timeout - await timeTravel(1750); // Final response - - expect(next).toHaveBeenCalledTimes(2); - expect(next.mock.calls[0][0]).toStrictEqual(timedResponses[0].value); - expect(next.mock.calls[1][0]).toStrictEqual(timedResponses[1].value); - expect(error).not.toHaveBeenCalled(); - expect(mockUsageCollector.trackLongQueryRunBeyondTimeout).toBeCalledTimes(1); - }); - }); }); diff --git a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts index ae6dddf33536f..e33f773256b14 100644 --- a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts +++ b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts @@ -6,7 +6,6 @@ import { throwError, EMPTY, timer, from } from 'rxjs'; import { mergeMap, expand, takeUntil, finalize, tap } from 'rxjs/operators'; -import { getLongQueryNotification } from './long_query_notification'; import { SearchInterceptor, SearchInterceptorDeps, @@ -31,38 +30,11 @@ export class EnhancedSearchInterceptor extends SearchInterceptor { * Abort our `AbortController`, which in turn aborts any intercepted searches. */ public cancelPending = () => { - this.hideToast(); this.abortController.abort(); this.abortController = new AbortController(); if (this.deps.usageCollector) this.deps.usageCollector.trackQueriesCancelled(); }; - /** - * Un-schedule timing out all of the searches intercepted. - */ - public runBeyondTimeout = () => { - this.hideToast(); - this.timeoutSubscriptions.unsubscribe(); - if (this.deps.usageCollector) this.deps.usageCollector.trackLongQueryRunBeyondTimeout(); - }; - - protected showToast = () => { - if (this.longRunningToast) return; - this.longRunningToast = this.deps.toasts.addInfo( - { - title: 'Your query is taking a while', - text: getLongQueryNotification({ - cancel: this.cancelPending, - runBeyondTimeout: this.runBeyondTimeout, - }), - }, - { - toastLifeTimeMs: 1000000, - } - ); - if (this.deps.usageCollector) this.deps.usageCollector.trackLongQueryPopupShown(); - }; - public search( request: IAsyncSearchRequest, { pollInterval = 1000, ...options }: IAsyncSearchOptions = {} From c1217b001972a3ed1a4d2d7ae7e84ba71d5a524a Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Thu, 20 Aug 2020 11:26:36 -0700 Subject: [PATCH 02/77] Don't timeout if requestTimeout isn't configured --- .../public/search/search_interceptor.test.ts | 32 +++++++++++++++++++ .../data/public/search/search_interceptor.ts | 15 +++++++-- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/src/plugins/data/public/search/search_interceptor.test.ts b/src/plugins/data/public/search/search_interceptor.test.ts index 70224306efe39..0737de28a2e87 100644 --- a/src/plugins/data/public/search/search_interceptor.test.ts +++ b/src/plugins/data/public/search/search_interceptor.test.ts @@ -97,6 +97,38 @@ describe('SearchInterceptor', () => { await flushPromises(); }); + test('Should not timeout if requestTimeout is undefined', async () => { + searchInterceptor = new SearchInterceptor({ + startServices: mockCoreSetup.getStartServices(), + uiSettings: mockCoreSetup.uiSettings, + http: mockCoreSetup.http, + }); + mockCoreSetup.http.fetch.mockImplementationOnce((options: any) => { + return new Promise((resolve, reject) => { + options.signal.addEventListener('abort', () => { + reject(new AbortError()); + }); + + setTimeout(resolve, 5000); + }); + }); + const mockRequest: IEsSearchRequest = { + params: {}, + }; + const response = searchInterceptor.search(mockRequest); + + expect.assertions(1); + const next = jest.fn(); + const complete = () => { + expect(next).toBeCalled(); + }; + response.subscribe({ next, complete }); + + jest.advanceTimersByTime(5000); + + await flushPromises(); + }); + test('Observable should fail if user aborts (test merged signal)', async () => { const abortController = new AbortController(); mockCoreSetup.http.fetch.mockImplementationOnce((options: any) => { diff --git a/src/plugins/data/public/search/search_interceptor.ts b/src/plugins/data/public/search/search_interceptor.ts index de73a77bca8cc..c639cdbbaeda0 100644 --- a/src/plugins/data/public/search/search_interceptor.ts +++ b/src/plugins/data/public/search/search_interceptor.ts @@ -18,7 +18,16 @@ */ import { trimEnd } from 'lodash'; -import { BehaviorSubject, throwError, timer, Subscription, defer, from, Observable } from 'rxjs'; +import { + BehaviorSubject, + throwError, + timer, + Subscription, + defer, + from, + Observable, + NEVER, +} from 'rxjs'; import { finalize } from 'rxjs/operators'; import { CoreStart, CoreSetup } from 'kibana/public'; import { getCombinedSignal, AbortError } from '../../common/utils'; @@ -26,7 +35,6 @@ import { IEsSearchRequest, IEsSearchResponse, ES_SEARCH_STRATEGY } from '../../c import { ISearchOptions } from './types'; import { SearchUsageCollector } from './collectors'; - export interface SearchInterceptorDeps { http: CoreSetup['http']; uiSettings: CoreSetup['uiSettings']; @@ -124,7 +132,8 @@ export class SearchInterceptor { // Schedule this request to automatically timeout after some interval const timeoutController = new AbortController(); const { signal: timeoutSignal } = timeoutController; - const timeout$ = timer(this.requestTimeout); + const timeout$ = + this.requestTimeout != null && this.requestTimeout > 0 ? timer(this.requestTimeout) : NEVER; const subscription = timeout$.subscribe(() => { timeoutController.abort(); }); From b9aa07d2ab3cd79389ed87b333fe032058055ba2 Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Thu, 20 Aug 2020 16:29:24 -0700 Subject: [PATCH 03/77] Remove unused kibanaUtils --- x-pack/plugins/data_enhanced/kibana.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/data_enhanced/kibana.json b/x-pack/plugins/data_enhanced/kibana.json index 637af39339e27..15898e32d42cd 100644 --- a/x-pack/plugins/data_enhanced/kibana.json +++ b/x-pack/plugins/data_enhanced/kibana.json @@ -8,8 +8,8 @@ "requiredPlugins": [ "data" ], - "optionalPlugins": ["kibanaReact", "kibanaUtils", "usageCollection"], + "optionalPlugins": ["kibanaReact", "usageCollection"], "server": true, "ui": true, - "requiredBundles": ["kibanaReact", "kibanaUtils"] + "requiredBundles": ["kibanaReact"] } From c2c0237fefbb9f67b5354540dc3b149e8c506986 Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Fri, 21 Aug 2020 10:25:20 -0700 Subject: [PATCH 04/77] Remove unused kibanaReact --- x-pack/plugins/data_enhanced/kibana.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/data_enhanced/kibana.json b/x-pack/plugins/data_enhanced/kibana.json index 15898e32d42cd..4d73c524ab0f6 100644 --- a/x-pack/plugins/data_enhanced/kibana.json +++ b/x-pack/plugins/data_enhanced/kibana.json @@ -8,8 +8,8 @@ "requiredPlugins": [ "data" ], - "optionalPlugins": ["kibanaReact", "usageCollection"], + "optionalPlugins": ["usageCollection"], "server": true, "ui": true, - "requiredBundles": ["kibanaReact"] + "requiredBundles": [] } From 7927af648e6083e3f98d7ef58a45858e30cdcdc3 Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Fri, 21 Aug 2020 11:47:48 -0700 Subject: [PATCH 05/77] Re-add reference to kibanaUtils --- x-pack/plugins/data_enhanced/kibana.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/data_enhanced/kibana.json b/x-pack/plugins/data_enhanced/kibana.json index 4d73c524ab0f6..b3e438e2a356e 100644 --- a/x-pack/plugins/data_enhanced/kibana.json +++ b/x-pack/plugins/data_enhanced/kibana.json @@ -8,8 +8,8 @@ "requiredPlugins": [ "data" ], - "optionalPlugins": ["usageCollection"], + "optionalPlugins": ["kibanaUtils", "usageCollection"], "server": true, "ui": true, - "requiredBundles": [] + "requiredBundles": ["kibanaUtils"] } From 0f69bac84016565e1a02f9cacafe9fc2a94773c8 Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Fri, 21 Aug 2020 13:31:17 -0700 Subject: [PATCH 06/77] Remove unused translations and update documentation --- ...public.searchinterceptor.getpendingcount_.md | 17 ----------------- ...gin-plugins-data-public.searchinterceptor.md | 1 - ...plugins-data-public.searchinterceptordeps.md | 1 - ...-data-public.searchinterceptordeps.toasts.md | 11 ----------- src/plugins/data/public/public.api.md | 11 ----------- .../translations/translations/ja-JP.json | 4 ---- .../translations/translations/zh-CN.json | 4 ---- 7 files changed, 49 deletions(-) delete mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.getpendingcount_.md delete mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.toasts.md diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.getpendingcount_.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.getpendingcount_.md deleted file mode 100644 index ef36b3f37b0c7..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.getpendingcount_.md +++ /dev/null @@ -1,17 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchInterceptor](./kibana-plugin-plugins-data-public.searchinterceptor.md) > [getPendingCount$](./kibana-plugin-plugins-data-public.searchinterceptor.getpendingcount_.md) - -## SearchInterceptor.getPendingCount$() method - -Returns an `Observable` over the current number of pending searches. This could mean that one of the search requests is still in flight, or that it has only received partial responses. - -Signature: - -```typescript -getPendingCount$(): Observable; -``` -Returns: - -`Observable` - diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md index 32954927504ae..2cf4d17fa5162 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md @@ -27,7 +27,6 @@ export declare class SearchInterceptor | Method | Modifiers | Description | | --- | --- | --- | -| [getPendingCount$()](./kibana-plugin-plugins-data-public.searchinterceptor.getpendingcount_.md) | | Returns an Observable over the current number of pending searches. This could mean that one of the search requests is still in flight, or that it has only received partial responses. | | [runSearch(request, signal, strategy)](./kibana-plugin-plugins-data-public.searchinterceptor.runsearch.md) | | | | [search(request, options)](./kibana-plugin-plugins-data-public.searchinterceptor.search.md) | | Searches using the given search method. Overrides the AbortSignal with one that will abort either when cancelPending is called, when the request times out, or when the original AbortSignal is aborted. Updates pendingCount$ when the request is started/finalized. | | [setupTimers(options)](./kibana-plugin-plugins-data-public.searchinterceptor.setuptimers.md) | | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.md index 63eb67ce48246..e4f262ed47961 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.md @@ -16,7 +16,6 @@ export interface SearchInterceptorDeps | --- | --- | --- | | [http](./kibana-plugin-plugins-data-public.searchinterceptordeps.http.md) | CoreSetup['http'] | | | [startServices](./kibana-plugin-plugins-data-public.searchinterceptordeps.startservices.md) | Promise<[CoreStart, any, unknown]> | | -| [toasts](./kibana-plugin-plugins-data-public.searchinterceptordeps.toasts.md) | ToastsSetup | | | [uiSettings](./kibana-plugin-plugins-data-public.searchinterceptordeps.uisettings.md) | CoreSetup['uiSettings'] | | | [usageCollector](./kibana-plugin-plugins-data-public.searchinterceptordeps.usagecollector.md) | SearchUsageCollector | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.toasts.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.toasts.md deleted file mode 100644 index 1f560dfa5cf7c..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.toasts.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchInterceptorDeps](./kibana-plugin-plugins-data-public.searchinterceptordeps.md) > [toasts](./kibana-plugin-plugins-data-public.searchinterceptordeps.toasts.md) - -## SearchInterceptorDeps.toasts property - -Signature: - -```typescript -toasts: ToastsSetup; -``` diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index 7defddb8f570a..40818b0a4efa1 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -64,9 +64,7 @@ import { Search } from '@elastic/elasticsearch/api/requestParams'; import { SearchResponse as SearchResponse_2 } from 'elasticsearch'; import { SerializedFieldFormat as SerializedFieldFormat_2 } from 'src/plugins/expressions/common'; import { Subscription } from 'rxjs'; -import { Toast } from 'kibana/public'; import { ToastInputFields } from 'src/core/public/notifications'; -import { ToastsSetup } from 'kibana/public'; import { TransportRequestOptions } from '@elastic/elasticsearch/lib/Transport'; import { TransportRequestParams } from '@elastic/elasticsearch/lib/Transport'; import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; @@ -1742,11 +1740,6 @@ export class SearchInterceptor { protected application: CoreStart['application']; // (undocumented) protected readonly deps: SearchInterceptorDeps; - getPendingCount$(): Observable; - // @internal (undocumented) - protected hideToast: () => void; - // @internal - protected longRunningToast?: Toast; // @internal protected pendingCount$: BehaviorSubject; // (undocumented) @@ -1759,8 +1752,6 @@ export class SearchInterceptor { combinedSignal: AbortSignal; cleanup: () => void; }; - // @internal (undocumented) - protected showToast: () => void; // @internal protected timeoutSubscriptions: Subscription; } @@ -1774,8 +1765,6 @@ export interface SearchInterceptorDeps { // (undocumented) startServices: Promise<[CoreStart, any, unknown]>; // (undocumented) - toasts: ToastsSetup; - // (undocumented) uiSettings: CoreSetup_2['uiSettings']; // Warning: (ae-forgotten-export) The symbol "SearchUsageCollector" needs to be exported by the entry point index.d.ts // diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 6a7737d367005..8654182edd255 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -843,8 +843,6 @@ "data.query.queryBar.KQLNestedQuerySyntaxInfoTitle": "KQL ネストされたクエリ構文", "data.query.queryBar.kqlOffLabel": "オフ", "data.query.queryBar.kqlOnLabel": "オン", - "data.query.queryBar.licenseOptions": "ライセンスオプションに進む", - "data.query.queryBar.longQueryMessage": "ライセンスをアップグレードすれば、リクエストの完了までに十分な時間を確保できます。", "data.query.queryBar.luceneLanguageName": "Lucene", "data.query.queryBar.luceneSyntaxWarningMessage": "Lucene クエリ構文を使用しているようですが、Kibana クエリ言語 (KQL) が選択されています。KQL ドキュメント {link} を確認してください。", "data.query.queryBar.luceneSyntaxWarningOptOutText": "今後表示しない", @@ -6794,8 +6792,6 @@ "xpack.data.kueryAutocomplete.lessThanOrEqualOperatorDescription.lessThanOrEqualToText": "より小さいまたは等しい", "xpack.data.kueryAutocomplete.orOperatorDescription": "{oneOrMoreArguments} が true であることを条件とする", "xpack.data.kueryAutocomplete.orOperatorDescription.oneOrMoreArgumentsText": "1つ以上の引数", - "xpack.data.query.queryBar.cancelLongQuery": "キャンセル", - "xpack.data.query.queryBar.runBeyond": "タイムアウトを越えて実行", "xpack.discover.FlyoutCreateDrilldownAction.displayName": "基本データを調査", "xpack.embeddableEnhanced.actions.panelNotifications.manyDrilldowns": "パネルには{count}個のドリルダウンがあります", "xpack.embeddableEnhanced.actions.panelNotifications.oneDrilldown": "パネルには1個のドリルダウンがあります", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 4d0186141f38d..edeb640da3f29 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -844,8 +844,6 @@ "data.query.queryBar.KQLNestedQuerySyntaxInfoTitle": "KQL 嵌套查询语法", "data.query.queryBar.kqlOffLabel": "关闭", "data.query.queryBar.kqlOnLabel": "开启", - "data.query.queryBar.licenseOptions": "前往许可证选项", - "data.query.queryBar.longQueryMessage": "使用升级的许可证,您可以确保有足够的时间来完成请求。", "data.query.queryBar.luceneLanguageName": "Lucene", "data.query.queryBar.luceneSyntaxWarningMessage": "尽管您选择了 Kibana 查询语言 (KQL),但似乎您正在尝试使用 Lucene 查询语法。请查看 KQL 文档 {link}。", "data.query.queryBar.luceneSyntaxWarningOptOutText": "不再显示", @@ -6796,8 +6794,6 @@ "xpack.data.kueryAutocomplete.lessThanOrEqualOperatorDescription.lessThanOrEqualToText": "小于或等于", "xpack.data.kueryAutocomplete.orOperatorDescription": "需要{oneOrMoreArguments}为 true", "xpack.data.kueryAutocomplete.orOperatorDescription.oneOrMoreArgumentsText": "一个或多个参数", - "xpack.data.query.queryBar.cancelLongQuery": "取消", - "xpack.data.query.queryBar.runBeyond": "运行超时", "xpack.discover.FlyoutCreateDrilldownAction.displayName": "浏览底层数据", "xpack.embeddableEnhanced.actions.panelNotifications.manyDrilldowns": "面板有 {count} 个向下钻取", "xpack.embeddableEnhanced.actions.panelNotifications.oneDrilldown": "面板有 1 个向下钻取", From c29ab1b59f7f01d430e6888292da4d8c7cefa16f Mon Sep 17 00:00:00 2001 From: Liza K Date: Sun, 23 Aug 2020 18:38:02 +0300 Subject: [PATCH 07/77] Add new x-pack advanced setting searchTimeout and use it in the EnhancedSearchInterceptor --- src/plugins/data/common/constants.ts | 1 + .../data/public/search/search_interceptor.ts | 15 +++++----- x-pack/plugins/data_enhanced/public/plugin.ts | 25 +++++++++-------- .../public/search/search_interceptor.ts | 21 ++++++++++---- x-pack/plugins/data_enhanced/server/plugin.ts | 3 ++ .../data_enhanced/server/ui_settings.ts | 28 +++++++++++++++++++ 6 files changed, 69 insertions(+), 24 deletions(-) create mode 100644 x-pack/plugins/data_enhanced/server/ui_settings.ts diff --git a/src/plugins/data/common/constants.ts b/src/plugins/data/common/constants.ts index 22db1552e4303..43120583bd3a4 100644 --- a/src/plugins/data/common/constants.ts +++ b/src/plugins/data/common/constants.ts @@ -32,6 +32,7 @@ export const UI_SETTINGS = { COURIER_MAX_CONCURRENT_SHARD_REQUESTS: 'courier:maxConcurrentShardRequests', COURIER_BATCH_SEARCHES: 'courier:batchSearches', SEARCH_INCLUDE_FROZEN: 'search:includeFrozen', + SEARCH_TIMEOUT: 'search:timeout', HISTOGRAM_BAR_TARGET: 'histogram:barTarget', HISTOGRAM_MAX_BARS: 'histogram:maxBars', HISTORY_LIMIT: 'history:limit', diff --git a/src/plugins/data/public/search/search_interceptor.ts b/src/plugins/data/public/search/search_interceptor.ts index 30e509edd4987..7b5f02e384202 100644 --- a/src/plugins/data/public/search/search_interceptor.ts +++ b/src/plugins/data/public/search/search_interceptor.ts @@ -68,16 +68,13 @@ export class SearchInterceptor { protected application!: CoreStart['application']; /** - * This class should be instantiated with a `requestTimeout` corresponding with how many ms after + * This class should be instantiated with a `searchTimeout` corresponding with how many ms after * requests are initiated that they should automatically cancel. * @param toasts The `core.notifications.toasts` service * @param application The `core.application` service - * @param requestTimeout Usually config value `elasticsearch.requestTimeout` + * @param searchTimeout Timeout for running search requests */ - constructor( - protected readonly deps: SearchInterceptorDeps, - protected readonly requestTimeout?: number - ) { + constructor(protected readonly deps: SearchInterceptorDeps, protected searchTimeout?: number) { this.deps.http.addLoadingCountSource(this.pendingCount$); this.deps.startServices.then(([coreStart]) => { @@ -91,6 +88,10 @@ export class SearchInterceptor { .subscribe(this.hideToast); } + protected setSearchTimeout(timeout?: number) { + this.searchTimeout = timeout; + } + /** * Returns an `Observable` over the current number of pending searches. This could mean that one * of the search requests is still in flight, or that it has only received partial responses. @@ -148,7 +149,7 @@ export class SearchInterceptor { // Schedule this request to automatically timeout after some interval const timeoutController = new AbortController(); const { signal: timeoutSignal } = timeoutController; - const timeout$ = timer(this.requestTimeout); + const timeout$ = timer(this.searchTimeout); const subscription = timeout$.subscribe(() => { timeoutController.abort(); }); diff --git a/x-pack/plugins/data_enhanced/public/plugin.ts b/x-pack/plugins/data_enhanced/public/plugin.ts index 7f6e3feac0671..ccc93316482c2 100644 --- a/x-pack/plugins/data_enhanced/public/plugin.ts +++ b/x-pack/plugins/data_enhanced/public/plugin.ts @@ -23,6 +23,8 @@ export type DataEnhancedStart = ReturnType; export class DataEnhancedPlugin implements Plugin { + private enhancedSearchInterceptor!: EnhancedSearchInterceptor; + public setup( core: CoreSetup, { data }: DataEnhancedSetupDependencies @@ -32,20 +34,17 @@ export class DataEnhancedPlugin setupKqlQuerySuggestionProvider(core) ); - const enhancedSearchInterceptor = new EnhancedSearchInterceptor( - { - toasts: core.notifications.toasts, - http: core.http, - uiSettings: core.uiSettings, - startServices: core.getStartServices(), - usageCollector: data.search.usageCollector, - }, - core.injectedMetadata.getInjectedVar('esRequestTimeout') as number - ); + this.enhancedSearchInterceptor = new EnhancedSearchInterceptor({ + toasts: core.notifications.toasts, + http: core.http, + uiSettings: core.uiSettings, + startServices: core.getStartServices(), + usageCollector: data.search.usageCollector, + }); data.__enhance({ search: { - searchInterceptor: enhancedSearchInterceptor, + searchInterceptor: this.enhancedSearchInterceptor, }, }); } @@ -53,4 +52,8 @@ export class DataEnhancedPlugin public start(core: CoreStart, plugins: DataEnhancedStartDependencies) { setAutocompleteService(plugins.data.autocomplete); } + + public stop() { + this.enhancedSearchInterceptor.stop(); + } } diff --git a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts index 47099e32fcc72..dd980abb2ed89 100644 --- a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts +++ b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { throwError, EMPTY, timer, from } from 'rxjs'; +import { throwError, EMPTY, timer, from, Subscription } from 'rxjs'; import { mergeMap, expand, takeUntil, finalize, tap } from 'rxjs/operators'; import { getLongQueryNotification } from './long_query_notification'; import { @@ -17,14 +17,23 @@ import { IAsyncSearchOptions } from '.'; import { IAsyncSearchRequest } from '../../common'; export class EnhancedSearchInterceptor extends SearchInterceptor { + private uiSettingsSub: Subscription; + /** - * This class should be instantiated with a `requestTimeout` corresponding with how many ms after - * requests are initiated that they should automatically cancel. * @param deps `SearchInterceptorDeps` - * @param requestTimeout Usually config value `elasticsearch.requestTimeout` */ - constructor(deps: SearchInterceptorDeps, requestTimeout?: number) { - super(deps, requestTimeout); + constructor(deps: SearchInterceptorDeps) { + super(deps, deps.uiSettings.get(UI_SETTINGS.SEARCH_TIMEOUT)); + + this.uiSettingsSub = deps.uiSettings + .get$(UI_SETTINGS.SEARCH_TIMEOUT) + .subscribe((timeout: number) => { + this.setSearchTimeout(timeout); + }); + } + + public stop() { + this.uiSettingsSub.unsubscribe(); } /** diff --git a/x-pack/plugins/data_enhanced/server/plugin.ts b/x-pack/plugins/data_enhanced/server/plugin.ts index 0e9731a414119..76d94a07dd57b 100644 --- a/x-pack/plugins/data_enhanced/server/plugin.ts +++ b/x-pack/plugins/data_enhanced/server/plugin.ts @@ -19,6 +19,7 @@ import { } from '../../../../src/plugins/data/server'; import { enhancedEsSearchStrategyProvider } from './search'; import { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/server'; +import { getUiSettings } from './ui_settings'; interface SetupDependencies { data: DataPluginSetup; @@ -35,6 +36,8 @@ export class EnhancedDataServerPlugin implements Plugin, deps: SetupDependencies) { const usage = deps.usageCollection ? usageProvider(core) : undefined; + core.uiSettings.register(getUiSettings()); + deps.data.search.registerSearchStrategy( ES_SEARCH_STRATEGY, enhancedEsSearchStrategyProvider( diff --git a/x-pack/plugins/data_enhanced/server/ui_settings.ts b/x-pack/plugins/data_enhanced/server/ui_settings.ts new file mode 100644 index 0000000000000..76b84a7d09fee --- /dev/null +++ b/x-pack/plugins/data_enhanced/server/ui_settings.ts @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { i18n } from '@kbn/i18n'; +import { schema } from '@kbn/config-schema'; +import { UiSettingsParams } from 'kibana/server'; +import { UI_SETTINGS } from '../../../../src/plugins/data/server'; + +export function getUiSettings(): Record> { + return { + [UI_SETTINGS.SEARCH_TIMEOUT]: { + name: i18n.translate('kbn.advancedSettings.searchTimeout', { + defaultMessage: 'Search Timeout', + }), + value: 600000, + description: i18n.translate('kbn.advancedSettings.searchTimeoutDesc', { + defaultMessage: + 'Change the maximum timeout for a search session or set to 0 to disable the timeout and allow queries to run to completion.', + }), + type: 'number', + category: ['search'], + schema: schema.number(), + }, + }; +} From 4f603ce082330af16d1b5da07c98f52c31db0730 Mon Sep 17 00:00:00 2001 From: Liza K Date: Sun, 23 Aug 2020 18:58:10 +0300 Subject: [PATCH 08/77] docs --- ...-public.searchinterceptor._constructor_.md | 6 ++-- ...n-plugins-data-public.searchinterceptor.md | 5 +--- ...public.searchinterceptor.requesttimeout.md | 11 -------- ...data-public.searchinterceptor.runsearch.md | 24 ---------------- ...ta-public.searchinterceptor.setuptimers.md | 28 ------------------- ...-plugin-plugins-data-public.ui_settings.md | 1 + ...-plugin-plugins-data-server.ui_settings.md | 1 + src/plugins/data/public/public.api.md | 13 +++++---- .../data/public/search/search_interceptor.ts | 23 +++++++++++---- src/plugins/data/server/server.api.md | 1 + .../public/search/search_interceptor.ts | 2 +- 11 files changed, 33 insertions(+), 82 deletions(-) delete mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.requesttimeout.md delete mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.runsearch.md delete mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.setuptimers.md diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor._constructor_.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor._constructor_.md index 6f5dd1076fb40..dd613725470db 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor._constructor_.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor._constructor_.md @@ -4,12 +4,12 @@ ## SearchInterceptor.(constructor) -This class should be instantiated with a `requestTimeout` corresponding with how many ms after requests are initiated that they should automatically cancel. +Constructs a new instance of the `SearchInterceptor` class Signature: ```typescript -constructor(deps: SearchInterceptorDeps, requestTimeout?: number | undefined); +constructor(deps: SearchInterceptorDeps, searchTimeout?: number); ``` ## Parameters @@ -17,5 +17,5 @@ constructor(deps: SearchInterceptorDeps, requestTimeout?: number | undefined); | Parameter | Type | Description | | --- | --- | --- | | deps | SearchInterceptorDeps | | -| requestTimeout | number | undefined | | +| searchTimeout | number | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md index 32954927504ae..f2e30a0c04cfc 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md @@ -14,21 +14,18 @@ export declare class SearchInterceptor | Constructor | Modifiers | Description | | --- | --- | --- | -| [(constructor)(deps, requestTimeout)](./kibana-plugin-plugins-data-public.searchinterceptor._constructor_.md) | | This class should be instantiated with a requestTimeout corresponding with how many ms after requests are initiated that they should automatically cancel. | +| [(constructor)(deps, searchTimeout)](./kibana-plugin-plugins-data-public.searchinterceptor._constructor_.md) | | Constructs a new instance of the SearchInterceptor class | ## Properties | Property | Modifiers | Type | Description | | --- | --- | --- | --- | | [deps](./kibana-plugin-plugins-data-public.searchinterceptor.deps.md) | | SearchInterceptorDeps | | -| [requestTimeout](./kibana-plugin-plugins-data-public.searchinterceptor.requesttimeout.md) | | number | undefined | | ## Methods | Method | Modifiers | Description | | --- | --- | --- | | [getPendingCount$()](./kibana-plugin-plugins-data-public.searchinterceptor.getpendingcount_.md) | | Returns an Observable over the current number of pending searches. This could mean that one of the search requests is still in flight, or that it has only received partial responses. | -| [runSearch(request, signal, strategy)](./kibana-plugin-plugins-data-public.searchinterceptor.runsearch.md) | | | | [search(request, options)](./kibana-plugin-plugins-data-public.searchinterceptor.search.md) | | Searches using the given search method. Overrides the AbortSignal with one that will abort either when cancelPending is called, when the request times out, or when the original AbortSignal is aborted. Updates pendingCount$ when the request is started/finalized. | -| [setupTimers(options)](./kibana-plugin-plugins-data-public.searchinterceptor.setuptimers.md) | | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.requesttimeout.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.requesttimeout.md deleted file mode 100644 index 3123433762991..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.requesttimeout.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchInterceptor](./kibana-plugin-plugins-data-public.searchinterceptor.md) > [requestTimeout](./kibana-plugin-plugins-data-public.searchinterceptor.requesttimeout.md) - -## SearchInterceptor.requestTimeout property - -Signature: - -```typescript -protected readonly requestTimeout?: number | undefined; -``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.runsearch.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.runsearch.md deleted file mode 100644 index ad1d1dcb59d7b..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.runsearch.md +++ /dev/null @@ -1,24 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchInterceptor](./kibana-plugin-plugins-data-public.searchinterceptor.md) > [runSearch](./kibana-plugin-plugins-data-public.searchinterceptor.runsearch.md) - -## SearchInterceptor.runSearch() method - -Signature: - -```typescript -protected runSearch(request: IEsSearchRequest, signal: AbortSignal, strategy?: string): Observable; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| request | IEsSearchRequest | | -| signal | AbortSignal | | -| strategy | string | | - -Returns: - -`Observable` - diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.setuptimers.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.setuptimers.md deleted file mode 100644 index fe35655258b4c..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.setuptimers.md +++ /dev/null @@ -1,28 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchInterceptor](./kibana-plugin-plugins-data-public.searchinterceptor.md) > [setupTimers](./kibana-plugin-plugins-data-public.searchinterceptor.setuptimers.md) - -## SearchInterceptor.setupTimers() method - -Signature: - -```typescript -protected setupTimers(options?: ISearchOptions): { - combinedSignal: AbortSignal; - cleanup: () => void; - }; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| options | ISearchOptions | | - -Returns: - -`{ - combinedSignal: AbortSignal; - cleanup: () => void; - }` - diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ui_settings.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ui_settings.md index e515c3513df6c..6ed20beb396f1 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ui_settings.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ui_settings.md @@ -20,6 +20,7 @@ UI_SETTINGS: { readonly COURIER_MAX_CONCURRENT_SHARD_REQUESTS: "courier:maxConcurrentShardRequests"; readonly COURIER_BATCH_SEARCHES: "courier:batchSearches"; readonly SEARCH_INCLUDE_FROZEN: "search:includeFrozen"; + readonly SEARCH_TIMEOUT: "search:timeout"; readonly HISTOGRAM_BAR_TARGET: "histogram:barTarget"; readonly HISTOGRAM_MAX_BARS: "histogram:maxBars"; readonly HISTORY_LIMIT: "history:limit"; diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.ui_settings.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.ui_settings.md index e419b64cd43aa..2d4ce75b956df 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.ui_settings.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.ui_settings.md @@ -20,6 +20,7 @@ UI_SETTINGS: { readonly COURIER_MAX_CONCURRENT_SHARD_REQUESTS: "courier:maxConcurrentShardRequests"; readonly COURIER_BATCH_SEARCHES: "courier:batchSearches"; readonly SEARCH_INCLUDE_FROZEN: "search:includeFrozen"; + readonly SEARCH_TIMEOUT: "search:timeout"; readonly HISTOGRAM_BAR_TARGET: "histogram:barTarget"; readonly HISTOGRAM_MAX_BARS: "histogram:maxBars"; readonly HISTORY_LIMIT: "history:limit"; diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index f8a108a5a4c58..69e75243d4752 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -1736,7 +1736,7 @@ export interface SearchError { // // @public (undocumented) export class SearchInterceptor { - constructor(deps: SearchInterceptorDeps, requestTimeout?: number | undefined); + constructor(deps: SearchInterceptorDeps, searchTimeout?: number); // @internal protected abortController: AbortController; // @internal (undocumented) @@ -1750,12 +1750,14 @@ export class SearchInterceptor { protected longRunningToast?: Toast; // @internal protected pendingCount$: BehaviorSubject; - // (undocumented) - protected readonly requestTimeout?: number | undefined; - // (undocumented) + // @internal (undocumented) protected runSearch(request: IEsSearchRequest, signal: AbortSignal, strategy?: string): Observable; search(request: IEsSearchRequest, options?: ISearchOptions): Observable; - // (undocumented) + // @internal (undocumented) + protected searchTimeout?: number; + // @internal (undocumented) + protected setSearchTimeout(timeout?: number): void; + // @internal (undocumented) protected setupTimers(options?: ISearchOptions): { combinedSignal: AbortSignal; cleanup: () => void; @@ -1927,6 +1929,7 @@ export const UI_SETTINGS: { readonly COURIER_MAX_CONCURRENT_SHARD_REQUESTS: "courier:maxConcurrentShardRequests"; readonly COURIER_BATCH_SEARCHES: "courier:batchSearches"; readonly SEARCH_INCLUDE_FROZEN: "search:includeFrozen"; + readonly SEARCH_TIMEOUT: "search:timeout"; readonly HISTOGRAM_BAR_TARGET: "histogram:barTarget"; readonly HISTOGRAM_MAX_BARS: "histogram:maxBars"; readonly HISTORY_LIMIT: "history:limit"; diff --git a/src/plugins/data/public/search/search_interceptor.ts b/src/plugins/data/public/search/search_interceptor.ts index 7b5f02e384202..b43e067ee84ae 100644 --- a/src/plugins/data/public/search/search_interceptor.ts +++ b/src/plugins/data/public/search/search_interceptor.ts @@ -68,14 +68,16 @@ export class SearchInterceptor { protected application!: CoreStart['application']; /** - * This class should be instantiated with a `searchTimeout` corresponding with how many ms after - * requests are initiated that they should automatically cancel. - * @param toasts The `core.notifications.toasts` service - * @param application The `core.application` service - * @param searchTimeout Timeout for running search requests + * @internal + */ + protected searchTimeout?: number; + + /* + * @internal */ - constructor(protected readonly deps: SearchInterceptorDeps, protected searchTimeout?: number) { + constructor(protected readonly deps: SearchInterceptorDeps, searchTimeout?: number) { this.deps.http.addLoadingCountSource(this.pendingCount$); + this.searchTimeout = searchTimeout; this.deps.startServices.then(([coreStart]) => { this.application = coreStart.application; @@ -88,6 +90,9 @@ export class SearchInterceptor { .subscribe(this.hideToast); } + /** + * @internal + */ protected setSearchTimeout(timeout?: number) { this.searchTimeout = timeout; } @@ -100,6 +105,9 @@ export class SearchInterceptor { return this.pendingCount$.asObservable(); } + /** + * @internal + */ protected runSearch( request: IEsSearchRequest, signal: AbortSignal, @@ -145,6 +153,9 @@ export class SearchInterceptor { }); } + /** + * @internal + */ protected setupTimers(options?: ISearchOptions) { // Schedule this request to automatically timeout after some interval const timeoutController = new AbortController(); diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md index f870030ae9562..fbac4f7574d1a 100644 --- a/src/plugins/data/server/server.api.md +++ b/src/plugins/data/server/server.api.md @@ -1030,6 +1030,7 @@ export const UI_SETTINGS: { readonly COURIER_MAX_CONCURRENT_SHARD_REQUESTS: "courier:maxConcurrentShardRequests"; readonly COURIER_BATCH_SEARCHES: "courier:batchSearches"; readonly SEARCH_INCLUDE_FROZEN: "search:includeFrozen"; + readonly SEARCH_TIMEOUT: "search:timeout"; readonly HISTOGRAM_BAR_TARGET: "histogram:barTarget"; readonly HISTOGRAM_MAX_BARS: "histogram:maxBars"; readonly HISTORY_LIMIT: "history:limit"; diff --git a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts index dd980abb2ed89..945a4f8fe2165 100644 --- a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts +++ b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts @@ -20,7 +20,7 @@ export class EnhancedSearchInterceptor extends SearchInterceptor { private uiSettingsSub: Subscription; /** - * @param deps `SearchInterceptorDeps` + * @internal */ constructor(deps: SearchInterceptorDeps) { super(deps, deps.uiSettings.get(UI_SETTINGS.SEARCH_TIMEOUT)); From 25aae3af14b922e0ec3ac531006f455d7e506710 Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Tue, 25 Aug 2020 14:47:05 -0700 Subject: [PATCH 09/77] Re-add toast when queries time out --- .../public/search/search_interceptor.test.ts | 1 + .../data/public/search/search_interceptor.ts | 42 +++++++++++++++---- .../data/public/search/search_service.ts | 1 + x-pack/plugins/data_enhanced/public/plugin.ts | 1 + .../public/search/search_interceptor.test.ts | 1 + .../public/search/search_interceptor.ts | 16 +++++++ 6 files changed, 55 insertions(+), 7 deletions(-) diff --git a/src/plugins/data/public/search/search_interceptor.test.ts b/src/plugins/data/public/search/search_interceptor.test.ts index 0737de28a2e87..13a5462d21585 100644 --- a/src/plugins/data/public/search/search_interceptor.test.ts +++ b/src/plugins/data/public/search/search_interceptor.test.ts @@ -37,6 +37,7 @@ describe('SearchInterceptor', () => { startServices: mockCoreSetup.getStartServices(), uiSettings: mockCoreSetup.uiSettings, http: mockCoreSetup.http, + toasts: mockCoreSetup.notifications.toasts, }, 1000 ); diff --git a/src/plugins/data/public/search/search_interceptor.ts b/src/plugins/data/public/search/search_interceptor.ts index 85704c0725164..f78c836fc701c 100644 --- a/src/plugins/data/public/search/search_interceptor.ts +++ b/src/plugins/data/public/search/search_interceptor.ts @@ -17,7 +17,7 @@ * under the License. */ -import { trimEnd } from 'lodash'; +import { trimEnd, debounce } from 'lodash'; import { BehaviorSubject, throwError, @@ -28,10 +28,15 @@ import { Observable, NEVER, } from 'rxjs'; -import { finalize } from 'rxjs/operators'; -import { CoreStart, CoreSetup } from 'kibana/public'; -import { getCombinedSignal, AbortError } from '../../common/utils'; -import { IEsSearchRequest, IEsSearchResponse, ES_SEARCH_STRATEGY } from '../../common/search'; +import { catchError, finalize } from 'rxjs/operators'; +import { CoreStart, CoreSetup, ToastsSetup } from 'kibana/public'; +import { + getCombinedSignal, + AbortError, + IEsSearchRequest, + IEsSearchResponse, + ES_SEARCH_STRATEGY, +} from '../../common'; import { ISearchOptions } from './types'; import { SearchUsageCollector } from './collectors'; @@ -39,6 +44,7 @@ export interface SearchInterceptorDeps { http: CoreSetup['http']; uiSettings: CoreSetup['uiSettings']; startServices: Promise<[CoreStart, any, unknown]>; + toasts: ToastsSetup; usageCollector?: SearchUsageCollector; } @@ -120,6 +126,12 @@ export class SearchInterceptor { this.pendingCount$.next(this.pendingCount$.getValue() + 1); return this.runSearch(request, combinedSignal, options?.strategy).pipe( + catchError((e: any) => { + if (e.body?.attributes?.error === 'Request timed out') { + this.showTimeoutError(e); + } + return throwError(e); + }), finalize(() => { this.pendingCount$.next(this.pendingCount$.getValue() - 1); cleanup(); @@ -132,10 +144,10 @@ export class SearchInterceptor { // Schedule this request to automatically timeout after some interval const timeoutController = new AbortController(); const { signal: timeoutSignal } = timeoutController; - const timeout$ = - this.requestTimeout != null && this.requestTimeout > 0 ? timer(this.requestTimeout) : NEVER; + const timeout$ = (this.requestTimeout ?? 0) > 0 ? timer(this.requestTimeout) : NEVER; const subscription = timeout$.subscribe(() => { timeoutController.abort(); + this.showTimeoutError(new AbortError()); }); this.timeoutSubscriptions.add(subscription); @@ -161,6 +173,22 @@ export class SearchInterceptor { cleanup, }; } + + // Right now we are debouncing but we will hook this up with background sessions to show only one + // error notification per session. + protected showTimeoutError = debounce( + (e: Error) => { + this.deps.toasts.addError(e, { + title: 'Timed out', + toastMessage: + 'One or more queries timed out. Upgrade to a free Basic license to allow queries to complete.', // TODO: Improve this message + }); + }, + 60000, + { + leading: true, + } + ); } export type ISearchInterceptor = PublicMethodsOf; diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts index 74a731ef60409..3dec2edfb9f3a 100644 --- a/src/plugins/data/public/search/search_service.ts +++ b/src/plugins/data/public/search/search_service.ts @@ -77,6 +77,7 @@ export class SearchService implements Plugin { { http, uiSettings, + toasts: notifications.toasts, startServices: getStartServices(), usageCollector: this.usageCollector!, }, diff --git a/x-pack/plugins/data_enhanced/public/plugin.ts b/x-pack/plugins/data_enhanced/public/plugin.ts index e50ea298e1234..064701eedd542 100644 --- a/x-pack/plugins/data_enhanced/public/plugin.ts +++ b/x-pack/plugins/data_enhanced/public/plugin.ts @@ -36,6 +36,7 @@ export class DataEnhancedPlugin { http: core.http, uiSettings: core.uiSettings, + toasts: core.notifications.toasts, startServices: core.getStartServices(), usageCollector: data.search.usageCollector, }, diff --git a/x-pack/plugins/data_enhanced/public/search/search_interceptor.test.ts b/x-pack/plugins/data_enhanced/public/search/search_interceptor.test.ts index 9b1b41ef1e3bf..25499697e99f1 100644 --- a/x-pack/plugins/data_enhanced/public/search/search_interceptor.test.ts +++ b/x-pack/plugins/data_enhanced/public/search/search_interceptor.test.ts @@ -66,6 +66,7 @@ describe('EnhancedSearchInterceptor', () => { startServices: mockPromise as any, http: mockCoreSetup.http, uiSettings: mockCoreSetup.uiSettings, + toasts: mockCoreSetup.notifications.toasts, usageCollector: mockUsageCollector, }, 1000 diff --git a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts index 62f988582f0f6..f4750db4123b7 100644 --- a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts +++ b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts @@ -6,6 +6,7 @@ import { throwError, EMPTY, timer, from } from 'rxjs'; import { mergeMap, expand, takeUntil, finalize, tap } from 'rxjs/operators'; +import { debounce } from 'lodash'; import { SearchInterceptor, SearchInterceptorDeps, @@ -89,4 +90,19 @@ export class EnhancedSearchInterceptor extends SearchInterceptor { }) ); } + + // Right now we are debouncing but we will hook this up with background sessions to show only one + // error notification per session. + protected showTimeoutError = debounce( + (e: Error) => { + this.deps.toasts.addError(e, { + title: 'Timed out', + toastMessage: 'One or more queries timed out.', // TODO: Improve this message + }); + }, + 60000, + { + leading: true, + } + ); } From 849ef85dd526bf97bd5e6e5b79ee86dc692c4538 Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Tue, 25 Aug 2020 15:25:44 -0700 Subject: [PATCH 10/77] Fix types --- src/plugins/data/public/search/search_interceptor.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/data/public/search/search_interceptor.test.ts b/src/plugins/data/public/search/search_interceptor.test.ts index 13a5462d21585..5f57f93001899 100644 --- a/src/plugins/data/public/search/search_interceptor.test.ts +++ b/src/plugins/data/public/search/search_interceptor.test.ts @@ -103,6 +103,7 @@ describe('SearchInterceptor', () => { startServices: mockCoreSetup.getStartServices(), uiSettings: mockCoreSetup.uiSettings, http: mockCoreSetup.http, + toasts: mockCoreSetup.notifications.toasts, }); mockCoreSetup.http.fetch.mockImplementationOnce((options: any) => { return new Promise((resolve, reject) => { From de8107d5ab12a83b2559de2ed1c4894a52b72e9e Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Tue, 25 Aug 2020 15:41:45 -0700 Subject: [PATCH 11/77] Update error message with capabilities --- .../data_enhanced/public/search/search_interceptor.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts index f4750db4123b7..0babc6913629f 100644 --- a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts +++ b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts @@ -95,9 +95,12 @@ export class EnhancedSearchInterceptor extends SearchInterceptor { // error notification per session. protected showTimeoutError = debounce( (e: Error) => { + const message = this.application.capabilities.advancedSettings.save + ? 'Increase the advanced setting timeout to ensure queries can run to completion.' + : 'Contact an administrator to increase the advanced setting.'; this.deps.toasts.addError(e, { title: 'Timed out', - toastMessage: 'One or more queries timed out.', // TODO: Improve this message + toastMessage: `One or more queries timed out. ${message}`, }); }, 60000, From d54b09a5f54f29a505e0048a4541ebf5a2d6f14c Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Tue, 25 Aug 2020 16:12:02 -0700 Subject: [PATCH 12/77] Update docs --- .../kibana-plugin-plugins-data-public.searchinterceptor.md | 1 + ...ibana-plugin-plugins-data-public.searchinterceptordeps.md | 1 + src/plugins/data/public/public.api.md | 5 +++++ 3 files changed, 7 insertions(+) diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md index 2cf4d17fa5162..cd4d082db2a64 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md @@ -22,6 +22,7 @@ export declare class SearchInterceptor | --- | --- | --- | --- | | [deps](./kibana-plugin-plugins-data-public.searchinterceptor.deps.md) | | SearchInterceptorDeps | | | [requestTimeout](./kibana-plugin-plugins-data-public.searchinterceptor.requesttimeout.md) | | number | undefined | | +| [showTimeoutError](./kibana-plugin-plugins-data-public.searchinterceptor.showtimeouterror.md) | | ((e: Error) => void) & import("lodash").Cancelable | | ## Methods diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.md index e4f262ed47961..63eb67ce48246 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.md @@ -16,6 +16,7 @@ export interface SearchInterceptorDeps | --- | --- | --- | | [http](./kibana-plugin-plugins-data-public.searchinterceptordeps.http.md) | CoreSetup['http'] | | | [startServices](./kibana-plugin-plugins-data-public.searchinterceptordeps.startservices.md) | Promise<[CoreStart, any, unknown]> | | +| [toasts](./kibana-plugin-plugins-data-public.searchinterceptordeps.toasts.md) | ToastsSetup | | | [uiSettings](./kibana-plugin-plugins-data-public.searchinterceptordeps.uisettings.md) | CoreSetup['uiSettings'] | | | [usageCollector](./kibana-plugin-plugins-data-public.searchinterceptordeps.usagecollector.md) | SearchUsageCollector | | diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index 7e5d44c320747..a045693ceafc2 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -65,6 +65,7 @@ import { SearchResponse } from 'elasticsearch'; import { SerializedFieldFormat as SerializedFieldFormat_2 } from 'src/plugins/expressions/common'; import { Subscription } from 'rxjs'; import { ToastInputFields } from 'src/core/public/notifications'; +import { ToastsSetup } from 'kibana/public'; import { TransportRequestOptions } from '@elastic/elasticsearch/lib/Transport'; import { TransportRequestParams } from '@elastic/elasticsearch/lib/Transport'; import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; @@ -1753,6 +1754,8 @@ export class SearchInterceptor { combinedSignal: AbortSignal; cleanup: () => void; }; + // (undocumented) + protected showTimeoutError: ((e: Error) => void) & import("lodash").Cancelable; // @internal protected timeoutSubscriptions: Subscription; } @@ -1766,6 +1769,8 @@ export interface SearchInterceptorDeps { // (undocumented) startServices: Promise<[CoreStart, any, unknown]>; // (undocumented) + toasts: ToastsSetup; + // (undocumented) uiSettings: CoreSetup_2['uiSettings']; // Warning: (ae-forgotten-export) The symbol "SearchUsageCollector" needs to be exported by the entry point index.d.ts // From 20ea649b1965249ebb087fba71eba76b54f63733 Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Tue, 25 Aug 2020 16:14:27 -0700 Subject: [PATCH 13/77] Update docs --- ...-data-public.searchinterceptor.showtimeouterror.md | 11 +++++++++++ ...lugins-data-public.searchinterceptordeps.toasts.md | 11 +++++++++++ 2 files changed, 22 insertions(+) create mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.showtimeouterror.md create mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.toasts.md diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.showtimeouterror.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.showtimeouterror.md new file mode 100644 index 0000000000000..91ecb2821acbf --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.showtimeouterror.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchInterceptor](./kibana-plugin-plugins-data-public.searchinterceptor.md) > [showTimeoutError](./kibana-plugin-plugins-data-public.searchinterceptor.showtimeouterror.md) + +## SearchInterceptor.showTimeoutError property + +Signature: + +```typescript +protected showTimeoutError: ((e: Error) => void) & import("lodash").Cancelable; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.toasts.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.toasts.md new file mode 100644 index 0000000000000..1f560dfa5cf7c --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.toasts.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchInterceptorDeps](./kibana-plugin-plugins-data-public.searchinterceptordeps.md) > [toasts](./kibana-plugin-plugins-data-public.searchinterceptordeps.toasts.md) + +## SearchInterceptorDeps.toasts property + +Signature: + +```typescript +toasts: ToastsSetup; +``` From 356281a6c1a45a5f4bd0145d54bf59360b10ffee Mon Sep 17 00:00:00 2001 From: Luke Elmers Date: Thu, 20 Aug 2020 14:44:36 -0600 Subject: [PATCH 14/77] Move search server routes into a directory. --- .../data/server/search/routes/index.ts | 20 +++++++++++++++++++ .../{routes.test.ts => routes/search.test.ts} | 18 +++++++++-------- .../search/{routes.ts => routes/search.ts} | 17 ++++++++-------- .../data/server/search/search_service.ts | 15 ++++++++++---- src/plugins/data/server/search/types.ts | 2 +- 5 files changed, 51 insertions(+), 21 deletions(-) create mode 100644 src/plugins/data/server/search/routes/index.ts rename src/plugins/data/server/search/{routes.test.ts => routes/search.test.ts} (82%) rename src/plugins/data/server/search/{routes.ts => routes/search.ts} (87%) diff --git a/src/plugins/data/server/search/routes/index.ts b/src/plugins/data/server/search/routes/index.ts new file mode 100644 index 0000000000000..220740d7cce6e --- /dev/null +++ b/src/plugins/data/server/search/routes/index.ts @@ -0,0 +1,20 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from './search'; diff --git a/src/plugins/data/server/search/routes.test.ts b/src/plugins/data/server/search/routes/search.test.ts similarity index 82% rename from src/plugins/data/server/search/routes.test.ts rename to src/plugins/data/server/search/routes/search.test.ts index d91aeee1fe818..a9c1b4427c2a1 100644 --- a/src/plugins/data/server/search/routes.test.ts +++ b/src/plugins/data/server/search/routes/search.test.ts @@ -17,19 +17,21 @@ * under the License. */ -import { CoreSetup, RequestHandlerContext } from '../../../../../src/core/server'; -import { coreMock, httpServerMock } from '../../../../../src/core/server/mocks'; -import { registerSearchRoute } from './routes'; -import { DataPluginStart } from '../plugin'; -import { dataPluginMock } from '../mocks'; +import { CoreSetup, RequestHandlerContext, StartServicesAccessor } from 'src/core/server'; +import { coreMock, httpServerMock } from '../../../../../../src/core/server/mocks'; +import { registerSearchRoute } from './search'; +import { DataPluginStart } from '../../plugin'; +import { dataPluginMock } from '../../mocks'; describe('Search service', () => { let mockDataStart: MockedKeys; - let mockCoreSetup: MockedKeys>; + let mockCoreSetup: MockedKeys>; + let getStartServices: jest.Mocked>; beforeEach(() => { mockDataStart = dataPluginMock.createStartContract(); mockCoreSetup = coreMock.createSetup({ pluginStartContract: mockDataStart }); + getStartServices = mockCoreSetup.getStartServices; }); it('handler calls context.search.search with the given request and strategy', async () => { @@ -44,7 +46,7 @@ describe('Search service', () => { }); const mockResponse = httpServerMock.createResponseFactory(); - registerSearchRoute(mockCoreSetup); + registerSearchRoute(mockCoreSetup.http.createRouter(), { getStartServices }); const mockRouter = mockCoreSetup.http.createRouter.mock.results[0].value; const handler = mockRouter.post.mock.calls[0][1]; @@ -75,7 +77,7 @@ describe('Search service', () => { }); const mockResponse = httpServerMock.createResponseFactory(); - registerSearchRoute(mockCoreSetup); + registerSearchRoute(mockCoreSetup.http.createRouter(), { getStartServices }); const mockRouter = mockCoreSetup.http.createRouter.mock.results[0].value; const handler = mockRouter.post.mock.calls[0][1]; diff --git a/src/plugins/data/server/search/routes.ts b/src/plugins/data/server/search/routes/search.ts similarity index 87% rename from src/plugins/data/server/search/routes.ts rename to src/plugins/data/server/search/routes/search.ts index 3d813f745305f..769093bc79a8c 100644 --- a/src/plugins/data/server/search/routes.ts +++ b/src/plugins/data/server/search/routes/search.ts @@ -18,13 +18,14 @@ */ import { schema } from '@kbn/config-schema'; -import { CoreSetup } from '../../../../core/server'; -import { getRequestAbortedSignal } from '../lib'; -import { DataPluginStart } from '../plugin'; - -export function registerSearchRoute(core: CoreSetup): void { - const router = core.http.createRouter(); +import { IRouter } from 'src/core/server'; +import { getRequestAbortedSignal } from '../../lib'; +import { SearchRouteDependencies } from '../search_service'; +export function registerSearchRoute( + router: IRouter, + { getStartServices }: SearchRouteDependencies +): void { router.post( { path: '/internal/search/{strategy}/{id?}', @@ -44,7 +45,7 @@ export function registerSearchRoute(core: CoreSetup): v const { strategy, id } = request.params; const signal = getRequestAbortedSignal(request.events.aborted$); - const [, , selfStart] = await core.getStartServices(); + const [, , selfStart] = await getStartServices(); try { const response = await selfStart.search.search( @@ -85,7 +86,7 @@ export function registerSearchRoute(core: CoreSetup): v async (context, request, res) => { const { strategy, id } = request.params; - const [, , selfStart] = await core.getStartServices(); + const [, , selfStart] = await getStartServices(); const searchStrategy = selfStart.search.getSearchStrategy(strategy); if (!searchStrategy.cancel) return res.ok(); diff --git a/src/plugins/data/server/search/search_service.ts b/src/plugins/data/server/search/search_service.ts index edc94961c79d8..7918960d66539 100644 --- a/src/plugins/data/server/search/search_service.ts +++ b/src/plugins/data/server/search/search_service.ts @@ -24,7 +24,8 @@ import { Plugin, PluginInitializerContext, RequestHandlerContext, -} from '../../../../core/server'; + StartServicesAccessor, +} from 'src/core/server'; import { ISearchSetup, ISearchStart, ISearchStrategy, SearchEnhancements } from './types'; import { AggsService, AggsSetupDependencies } from './aggs'; @@ -55,6 +56,11 @@ export interface SearchServiceStartDependencies { fieldFormats: FieldFormatsStart; } +/** @internal */ +export interface SearchRouteDependencies { + getStartServices: StartServicesAccessor<{}, DataPluginStart>; +} + export class SearchService implements Plugin { private readonly aggsService = new AggsService(); private defaultSearchStrategyName: string = ES_SEARCH_STRATEGY; @@ -66,11 +72,14 @@ export class SearchService implements Plugin { ) {} public setup( - core: CoreSetup, + core: CoreSetup<{}, DataPluginStart>, { registerFunction, usageCollection }: SearchServiceSetupDependencies ): ISearchSetup { const usage = usageCollection ? usageProvider(core) : undefined; + const router = core.http.createRouter(); + registerSearchRoute(router, { getStartServices: core.getStartServices }); + this.registerSearchStrategy( ES_SEARCH_STRATEGY, esSearchStrategyProvider( @@ -85,8 +94,6 @@ export class SearchService implements Plugin { registerUsageCollector(usageCollection, this.initializerContext); } - registerSearchRoute(core); - return { __enhance: (enhancements: SearchEnhancements) => { if (this.searchStrategies.hasOwnProperty(enhancements.defaultStrategy)) { diff --git a/src/plugins/data/server/search/types.ts b/src/plugins/data/server/search/types.ts index 5ce1bb3e6b9f8..ae83724b26209 100644 --- a/src/plugins/data/server/search/types.ts +++ b/src/plugins/data/server/search/types.ts @@ -17,7 +17,7 @@ * under the License. */ -import { RequestHandlerContext } from '../../../../core/server'; +import { RequestHandlerContext } from 'src/core/server'; import { IKibanaSearchResponse, IKibanaSearchRequest } from '../../common/search'; import { AggsSetup, AggsStart } from './aggs'; import { SearchUsage } from './collectors/usage'; From 84ad62f8589c329945bf607f2f96d42ac78c6456 Mon Sep 17 00:00:00 2001 From: Luke Elmers Date: Tue, 25 Aug 2020 20:56:09 -0600 Subject: [PATCH 15/77] Add internal/_msearch route. --- .../data/server/search/routes/index.ts | 1 + .../data/server/search/routes/msearch.test.ts | 127 ++++++++++++++++++ .../data/server/search/routes/msearch.ts | 116 ++++++++++++++++ .../data/server/search/search_service.ts | 3 +- 4 files changed, 246 insertions(+), 1 deletion(-) create mode 100644 src/plugins/data/server/search/routes/msearch.test.ts create mode 100644 src/plugins/data/server/search/routes/msearch.ts diff --git a/src/plugins/data/server/search/routes/index.ts b/src/plugins/data/server/search/routes/index.ts index 220740d7cce6e..2217890ff778e 100644 --- a/src/plugins/data/server/search/routes/index.ts +++ b/src/plugins/data/server/search/routes/index.ts @@ -17,4 +17,5 @@ * under the License. */ +export * from './msearch'; export * from './search'; diff --git a/src/plugins/data/server/search/routes/msearch.test.ts b/src/plugins/data/server/search/routes/msearch.test.ts new file mode 100644 index 0000000000000..3764a37a12ddf --- /dev/null +++ b/src/plugins/data/server/search/routes/msearch.test.ts @@ -0,0 +1,127 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { CoreSetup, RequestHandlerContext, StartServicesAccessor } from 'src/core/server'; +import { coreMock, httpServerMock } from '../../../../../../src/core/server/mocks'; +import { registerMsearchRoute, convertRequestBody } from './msearch'; +import { DataPluginStart } from '../../plugin'; +import { dataPluginMock } from '../../mocks'; + +describe('msearch route', () => { + let mockDataStart: MockedKeys; + let mockCoreSetup: MockedKeys>; + let getStartServices: jest.Mocked>; + + beforeEach(() => { + mockDataStart = dataPluginMock.createStartContract(); + mockCoreSetup = coreMock.createSetup({ pluginStartContract: mockDataStart }); + getStartServices = mockCoreSetup.getStartServices; + }); + + it('handler calls /_msearch with the given request', async () => { + const response = { id: 'yay' }; + const mockClient = { transport: { request: jest.fn().mockResolvedValue(response) } }; + const mockContext = { core: { elasticsearch: { client: { asCurrentUser: mockClient } } } }; + const mockBody = { searches: [{ header: {}, body: {} }] }; + const mockQuery = {}; + const mockRequest = httpServerMock.createKibanaRequest({ + body: mockBody, + query: mockQuery, + }); + const mockResponse = httpServerMock.createResponseFactory(); + + registerMsearchRoute(mockCoreSetup.http.createRouter(), { getStartServices }); + + const mockRouter = mockCoreSetup.http.createRouter.mock.results[0].value; + const handler = mockRouter.post.mock.calls[0][1]; + await handler((mockContext as unknown) as RequestHandlerContext, mockRequest, mockResponse); + + expect(mockClient.transport.request.mock.calls[0][0].method).toBe('GET'); + expect(mockClient.transport.request.mock.calls[0][0].path).toBe('/_msearch'); + expect(mockClient.transport.request.mock.calls[0][0].body).toEqual( + convertRequestBody(mockBody as any) + ); + expect(mockResponse.ok).toBeCalled(); + expect(mockResponse.ok.mock.calls[0][0]).toEqual({ + body: response, + }); + }); + + it('handler throws an error if the search throws an error', async () => { + const response = { + message: 'oh no', + body: { + error: 'oops', + }, + }; + const mockClient = { + transport: { request: jest.fn().mockReturnValue(Promise.reject(response)) }, + }; + const mockContext = { core: { elasticsearch: { client: { asCurrentUser: mockClient } } } }; + const mockBody = { searches: [{ header: {}, body: {} }] }; + const mockQuery = {}; + const mockRequest = httpServerMock.createKibanaRequest({ + body: mockBody, + query: mockQuery, + }); + const mockResponse = httpServerMock.createResponseFactory(); + + registerMsearchRoute(mockCoreSetup.http.createRouter(), { getStartServices }); + + const mockRouter = mockCoreSetup.http.createRouter.mock.results[0].value; + const handler = mockRouter.post.mock.calls[0][1]; + await handler((mockContext as unknown) as RequestHandlerContext, mockRequest, mockResponse); + + expect(mockClient.transport.request).toBeCalled(); + expect(mockResponse.customError).toBeCalled(); + + const error: any = mockResponse.customError.mock.calls[0][0]; + expect(error.body.message).toBe('oh no'); + expect(error.body.attributes.error).toBe('oops'); + }); + + describe('convertRequestBody', () => { + it('combines header & body into proper msearch request', () => { + const request = { + searches: [{ header: { index: 'foo', preference: 0 }, body: { test: true } }], + }; + expect(convertRequestBody(request)).toMatchInlineSnapshot(` + "{\\"index\\":\\"foo\\",\\"preference\\":0} + {\\"test\\":true} + " + `); + }); + + it('handles multiple searches', () => { + const request = { + searches: [ + { header: { index: 'foo', preference: 0 }, body: { test: true } }, + { header: { index: 'bar', preference: 1 }, body: { hello: 'world' } }, + ], + }; + expect(convertRequestBody(request)).toMatchInlineSnapshot(` + "{\\"index\\":\\"foo\\",\\"preference\\":0} + {\\"test\\":true} + {\\"index\\":\\"bar\\",\\"preference\\":1} + {\\"hello\\":\\"world\\"} + " + `); + }); + }); +}); diff --git a/src/plugins/data/server/search/routes/msearch.ts b/src/plugins/data/server/search/routes/msearch.ts new file mode 100644 index 0000000000000..6a15b707aae48 --- /dev/null +++ b/src/plugins/data/server/search/routes/msearch.ts @@ -0,0 +1,116 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { schema } from '@kbn/config-schema'; +import { IRouter } from 'src/core/server'; +import { SearchRouteDependencies } from '../search_service'; + +interface MsearchHeaders { + index: string; + preference: number; +} + +interface MsearchRequest { + header: MsearchHeaders; + body: any; +} + +interface RequestBody { + searches: MsearchRequest[]; +} + +/** @internal */ +export function convertRequestBody(requestBody: RequestBody): string { + return requestBody.searches.reduce((req, curr) => { + const header = JSON.stringify({ ...curr.header }); + const body = JSON.stringify({ ...curr.body }); + req += `${header}\n${body}\n`; + return req; + }, ''); +} + +/** + * The msearch route takes in an array of searches, each consisting of header + * and body json, and reformts them into a single request for the _msearch API. + * + * The reason for taking requests in a different format is so that we can + * inject values into each request without needing to manually parse each one. + * + * This route is internal and _should not be used_ in any new areas of code. + * It only exists as a means of removing remaining dependencies on the + * legacy ES client. + * + * @deprecated + */ +export function registerMsearchRoute(router: IRouter, deps: SearchRouteDependencies): void { + router.post( + { + path: '/internal/_msearch', + validate: { + body: schema.object({ + searches: schema.arrayOf( + schema.object({ + header: schema.object( + { + index: schema.string(), + preference: schema.number(), + }, + { unknowns: 'allow' } + ), + body: schema.object({}, { unknowns: 'allow' }), + }) + ), + }), + query: schema.object({ + // We don't use `schema.boolean` here, because all query string parameters are treated as + // strings and @kbn/config-schema doesn't coerce strings to booleans. + ignore_throttled: schema.oneOf([schema.literal('true'), schema.literal('false')]), + rest_total_hits_as_int: schema.oneOf([schema.literal('true'), schema.literal('false')]), + max_concurrent_shard_requests: schema.maybe(schema.number()), + }), + }, + }, + async (context, request, res) => { + const client = context.core.elasticsearch.client.asCurrentUser; + const body = convertRequestBody(request.body); + const querystring = request.query; + + try { + const response = await client.transport.request({ + method: 'GET', + path: '/_msearch', + body, + querystring, + }); + + return res.ok({ body: response }); + } catch (err) { + return res.customError({ + statusCode: err.statusCode || 500, + body: { + message: err.message, + attributes: { + error: err.body?.error || err.message, + }, + }, + }); + } + } + ); +} diff --git a/src/plugins/data/server/search/search_service.ts b/src/plugins/data/server/search/search_service.ts index 7918960d66539..80129c0429ba0 100644 --- a/src/plugins/data/server/search/search_service.ts +++ b/src/plugins/data/server/search/search_service.ts @@ -31,7 +31,7 @@ import { ISearchSetup, ISearchStart, ISearchStrategy, SearchEnhancements } from import { AggsService, AggsSetupDependencies } from './aggs'; import { FieldFormatsStart } from '../field_formats'; -import { registerSearchRoute } from './routes'; +import { registerMsearchRoute, registerSearchRoute } from './routes'; import { ES_SEARCH_STRATEGY, esSearchStrategyProvider } from './es_search'; import { DataPluginStart } from '../plugin'; import { UsageCollectionSetup } from '../../../usage_collection/server'; @@ -79,6 +79,7 @@ export class SearchService implements Plugin { const router = core.http.createRouter(); registerSearchRoute(router, { getStartServices: core.getStartServices }); + registerMsearchRoute(router, { getStartServices: core.getStartServices }); this.registerSearchStrategy( ES_SEARCH_STRATEGY, From 9a8de032ed328f8e583fe2babc9269d395fc8bb6 Mon Sep 17 00:00:00 2001 From: Luke Elmers Date: Tue, 25 Aug 2020 20:57:37 -0600 Subject: [PATCH 16/77] Remove legacy search API, rewrite default search strategy to use internal route. --- src/plugins/data/public/plugin.ts | 11 +-- src/plugins/data/public/search/fetch/types.ts | 4 +- .../public/search/legacy/call_client.test.ts | 8 ++- .../legacy/default_search_strategy.test.ts | 43 ++++-------- .../search/legacy/default_search_strategy.ts | 67 ++++++++++++------- src/plugins/data/public/search/mocks.ts | 6 -- .../data/public/search/search_service.ts | 26 ++----- .../create_search_source.test.ts | 6 +- .../data/public/search/search_source/mocks.ts | 9 +-- .../search_source/search_source.test.ts | 6 +- .../search/search_source/search_source.ts | 8 +-- src/plugins/data/public/search/types.ts | 10 --- 12 files changed, 81 insertions(+), 123 deletions(-) diff --git a/src/plugins/data/public/plugin.ts b/src/plugins/data/public/plugin.ts index 3bc19a578a417..3b18e0fbed537 100644 --- a/src/plugins/data/public/plugin.ts +++ b/src/plugins/data/public/plugin.ts @@ -19,13 +19,7 @@ import './index.scss'; -import { - PluginInitializerContext, - CoreSetup, - CoreStart, - Plugin, - PackageInfo, -} from 'src/core/public'; +import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from 'src/core/public'; import { ConfigSchema } from '../config'; import { Storage, IStorageWrapper, createStartServicesGetter } from '../../kibana_utils/public'; import { @@ -100,7 +94,6 @@ export class DataPublicPlugin private readonly fieldFormatsService: FieldFormatsService; private readonly queryService: QueryService; private readonly storage: IStorageWrapper; - private readonly packageInfo: PackageInfo; constructor(initializerContext: PluginInitializerContext) { this.searchService = new SearchService(); @@ -108,7 +101,6 @@ export class DataPublicPlugin this.fieldFormatsService = new FieldFormatsService(); this.autocomplete = new AutocompleteService(initializerContext); this.storage = new Storage(window.localStorage); - this.packageInfo = initializerContext.env.packageInfo; } public setup( @@ -145,7 +137,6 @@ export class DataPublicPlugin const searchService = this.searchService.setup(core, { usageCollection, - packageInfo: this.packageInfo, expressions, }); diff --git a/src/plugins/data/public/search/fetch/types.ts b/src/plugins/data/public/search/fetch/types.ts index 670c4f731971a..33a205b342ae8 100644 --- a/src/plugins/data/public/search/fetch/types.ts +++ b/src/plugins/data/public/search/fetch/types.ts @@ -17,8 +17,8 @@ * under the License. */ +import { HttpStart } from 'src/core/public'; import { GetConfigFn } from '../../../common'; -import { ISearchStartLegacy } from '../types'; /** * @internal @@ -35,9 +35,9 @@ export interface FetchOptions { } export interface FetchHandlers { - legacySearchService: ISearchStartLegacy; config: { get: GetConfigFn }; esShardTimeout: number; + http: HttpStart; } export interface SearchError { diff --git a/src/plugins/data/public/search/legacy/call_client.test.ts b/src/plugins/data/public/search/legacy/call_client.test.ts index a3c4e720b4cab..f0f36856e1b9a 100644 --- a/src/plugins/data/public/search/legacy/call_client.test.ts +++ b/src/plugins/data/public/search/legacy/call_client.test.ts @@ -17,6 +17,7 @@ * under the License. */ +import { coreMock } from '../../../../../core/public/mocks'; import { callClient } from './call_client'; import { SearchStrategySearchParams } from './types'; import { defaultSearchStrategy } from './default_search_strategy'; @@ -54,7 +55,12 @@ describe('callClient', () => { test('Passes the additional arguments it is given to the search strategy', () => { const searchRequests = [{ _searchStrategyId: 0 }]; - const args = { legacySearchService: {}, config: {}, esShardTimeout: 0 } as FetchHandlers; + const args = { + http: coreMock.createStart().http, + legacySearchService: {}, + config: { get: jest.fn() }, + esShardTimeout: 0, + } as FetchHandlers; callClient(searchRequests, [], args); diff --git a/src/plugins/data/public/search/legacy/default_search_strategy.test.ts b/src/plugins/data/public/search/legacy/default_search_strategy.test.ts index 4148055c1eb58..f1eb88f1c5671 100644 --- a/src/plugins/data/public/search/legacy/default_search_strategy.test.ts +++ b/src/plugins/data/public/search/legacy/default_search_strategy.test.ts @@ -17,9 +17,9 @@ * under the License. */ -import { IUiSettingsClient } from 'kibana/public'; +import { HttpStart, IUiSettingsClient } from 'src/core/public'; +import { coreMock } from '../../../../../core/public/mocks'; import { defaultSearchStrategy } from './default_search_strategy'; -import { searchServiceMock } from '../mocks'; import { SearchStrategySearchParams } from './types'; import { UI_SETTINGS } from '../../../common'; @@ -31,30 +31,19 @@ function getConfigStub(config: any = {}) { } as IUiSettingsClient; } -const msearchMockResponse: any = Promise.resolve([]); -msearchMockResponse.abort = jest.fn(); -const msearchMock = jest.fn().mockReturnValue(msearchMockResponse); - -const searchMockResponse: any = Promise.resolve([]); -searchMockResponse.abort = jest.fn(); -const searchMock = jest.fn().mockReturnValue(searchMockResponse); +const msearchMock = jest.fn().mockResolvedValue({ body: { responses: [] } }); describe('defaultSearchStrategy', function () { describe('search', function () { let searchArgs: MockedKeys>; let es: any; + let http: jest.Mocked; beforeEach(() => { - msearchMockResponse.abort.mockClear(); msearchMock.mockClear(); - searchMockResponse.abort.mockClear(); - searchMock.mockClear(); - - const searchService = searchServiceMock.createStartContract(); - searchService.aggs.calculateAutoTimeExpression = jest.fn().mockReturnValue('1d'); - searchService.__LEGACY.esClient.search = searchMock; - searchService.__LEGACY.esClient.msearch = msearchMock; + http = coreMock.createStart().http; + http.post.mockResolvedValue(msearchMock); searchArgs = { searchRequests: [ @@ -63,16 +52,16 @@ describe('defaultSearchStrategy', function () { }, ], esShardTimeout: 0, - legacySearchService: searchService.__LEGACY, + http, }; - es = searchArgs.legacySearchService.esClient; + es = http.post; }); test('does not send max_concurrent_shard_requests by default', async () => { const config = getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true }); await search({ ...searchArgs, config }); - expect(es.msearch.mock.calls[0][0].max_concurrent_shard_requests).toBe(undefined); + expect(es.mock.calls[0][1].query.max_concurrent_shard_requests).toBe(undefined); }); test('allows configuration of max_concurrent_shard_requests', async () => { @@ -81,13 +70,13 @@ describe('defaultSearchStrategy', function () { [UI_SETTINGS.COURIER_MAX_CONCURRENT_SHARD_REQUESTS]: 42, }); await search({ ...searchArgs, config }); - expect(es.msearch.mock.calls[0][0].max_concurrent_shard_requests).toBe(42); + expect(es.mock.calls[0][1].query.max_concurrent_shard_requests).toBe(42); }); test('should set rest_total_hits_as_int to true on a request', async () => { const config = getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true }); await search({ ...searchArgs, config }); - expect(es.msearch.mock.calls[0][0]).toHaveProperty('rest_total_hits_as_int', true); + expect(es.mock.calls[0][1].query).toHaveProperty('rest_total_hits_as_int', true); }); test('should set ignore_throttled=false when including frozen indices', async () => { @@ -96,15 +85,7 @@ describe('defaultSearchStrategy', function () { [UI_SETTINGS.SEARCH_INCLUDE_FROZEN]: true, }); await search({ ...searchArgs, config }); - expect(es.msearch.mock.calls[0][0]).toHaveProperty('ignore_throttled', false); - }); - - test('should properly call abort with msearch', () => { - const config = getConfigStub({ - [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true, - }); - search({ ...searchArgs, config }).abort(); - expect(msearchMockResponse.abort).toHaveBeenCalled(); + expect(es.mock.calls[0][1].query).toHaveProperty('ignore_throttled', false); }); }); }); diff --git a/src/plugins/data/public/search/legacy/default_search_strategy.ts b/src/plugins/data/public/search/legacy/default_search_strategy.ts index 6ccb0a01cf898..b32315163bb87 100644 --- a/src/plugins/data/public/search/legacy/default_search_strategy.ts +++ b/src/plugins/data/public/search/legacy/default_search_strategy.ts @@ -17,6 +17,8 @@ * under the License. */ +import { BehaviorSubject } from 'rxjs'; + import { getPreference, getTimeout } from '../fetch'; import { getMSearchParams } from './get_msearch_params'; import { SearchStrategyProvider, SearchStrategySearchParams } from './types'; @@ -30,34 +32,53 @@ export const defaultSearchStrategy: SearchStrategyProvider = { }, }; -function msearch({ - searchRequests, - legacySearchService, - config, - esShardTimeout, -}: SearchStrategySearchParams) { - const es = legacySearchService.esClient; - const inlineRequests = searchRequests.map(({ index, body, search_type: searchType }) => { - const inlineHeader = { - index: index.title || index, - search_type: searchType, - ignore_unavailable: true, - preference: getPreference(config.get), - }; - const inlineBody = { - ...body, - timeout: getTimeout(esShardTimeout), +function msearch({ searchRequests, config, http, esShardTimeout }: SearchStrategySearchParams) { + const requests = searchRequests.map(({ index, body, search_type: searchType }) => { + return { + header: { + index: index.title || index, + ignore_unavailable: true, + preference: getPreference(config.get), + search_type: searchType, + }, + body: { + ...body, + timeout: getTimeout(esShardTimeout), + }, }; - return `${JSON.stringify(inlineHeader)}\n${JSON.stringify(inlineBody)}`; }); - const searching = es.msearch({ - ...getMSearchParams(config.get), - body: `${inlineRequests.join('\n')}\n`, + const abortController = new AbortController(); + let resolved = false; + + const loadingCount$ = new BehaviorSubject(0); + http.addLoadingCountSource(loadingCount$); + + // Start LoadingIndicator + loadingCount$.next(loadingCount$.getValue() + 1); + + const cleanup = () => { + if (!resolved) { + resolved = true; + // Decrement loading counter & cleanup BehaviorSubject + loadingCount$.next(loadingCount$.getValue() - 1); + loadingCount$.complete(); + } + }; + + const searching = http.post('/internal/_msearch', { + query: getMSearchParams(config.get), + body: JSON.stringify({ searches: requests }), + signal: abortController.signal, }); + searching.finally(() => cleanup()); + return { - searching: searching.then(({ responses }: any) => responses), - abort: searching.abort, + abort: () => { + abortController.abort(); + cleanup(); + }, + searching: searching.then(({ body }) => body?.responses), }; } diff --git a/src/plugins/data/public/search/mocks.ts b/src/plugins/data/public/search/mocks.ts index 8ccf46fe7c97d..f4ed7d8b122b9 100644 --- a/src/plugins/data/public/search/mocks.ts +++ b/src/plugins/data/public/search/mocks.ts @@ -35,12 +35,6 @@ function createStartContract(): jest.Mocked { aggs: searchAggsStartMock(), search: jest.fn(), searchSource: searchSourceMock, - __LEGACY: { - esClient: { - search: jest.fn(), - msearch: jest.fn(), - }, - }, }; } diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts index 9a30a15936fe5..8caa4b3b0dd67 100644 --- a/src/plugins/data/public/search/search_service.ts +++ b/src/plugins/data/public/search/search_service.ts @@ -17,11 +17,10 @@ * under the License. */ -import { Plugin, CoreSetup, CoreStart, PackageInfo } from 'src/core/public'; +import { Plugin, CoreSetup, CoreStart } from 'src/core/public'; import { ISearchSetup, ISearchStart, SearchEnhancements } from './types'; import { createSearchSource, SearchSource, SearchSourceDependencies } from './search_source'; -import { getEsClient, LegacyApiCaller } from './legacy'; import { AggsService, AggsStartDependencies } from './aggs'; import { IndexPatternsContract } from '../index_patterns/index_patterns'; import { ISearchInterceptor, SearchInterceptor } from './search_interceptor'; @@ -33,9 +32,8 @@ import { ExpressionsSetup } from '../../../expressions/public'; /** @internal */ export interface SearchServiceSetupDependencies { - packageInfo: PackageInfo; - usageCollection?: UsageCollectionSetup; expressions: ExpressionsSetup; + usageCollection?: UsageCollectionSetup; } /** @internal */ @@ -45,28 +43,18 @@ export interface SearchServiceStartDependencies { } export class SearchService implements Plugin { - private esClient?: LegacyApiCaller; private readonly aggsService = new AggsService(); private searchInterceptor!: ISearchInterceptor; private usageCollector?: SearchUsageCollector; public setup( { http, getStartServices, injectedMetadata, notifications, uiSettings }: CoreSetup, - { expressions, packageInfo, usageCollection }: SearchServiceSetupDependencies + { expressions, usageCollection }: SearchServiceSetupDependencies ): ISearchSetup { - const esApiVersion = injectedMetadata.getInjectedVar('esApiVersion') as string; const esRequestTimeout = injectedMetadata.getInjectedVar('esRequestTimeout') as number; - const packageVersion = packageInfo.version; this.usageCollector = createUsageCollector(getStartServices, usageCollection); - this.esClient = getEsClient({ - esRequestTimeout, - esApiVersion, - http, - packageVersion, - }); - /** * A global object that intercepts all searches and provides convenience methods for cancelling * all pending search requests, as well as getting the number of pending search requests. @@ -107,15 +95,12 @@ export class SearchService implements Plugin { return this.searchInterceptor.search(request, options); }) as ISearchGeneric; - const legacySearch = { - esClient: this.esClient!, - }; - const searchSourceDependencies: SearchSourceDependencies = { getConfig: uiSettings.get.bind(uiSettings), + // TODO: we don't need this, apply on the server esShardTimeout: injectedMetadata.getInjectedVar('esShardTimeout') as number, search, - legacySearch, + http, }; return { @@ -127,7 +112,6 @@ export class SearchService implements Plugin { return new SearchSource({}, searchSourceDependencies); }, }, - __LEGACY: legacySearch, }; } diff --git a/src/plugins/data/public/search/search_source/create_search_source.test.ts b/src/plugins/data/public/search/search_source/create_search_source.test.ts index 56f6ca6c56270..1300c67d3c0fc 100644 --- a/src/plugins/data/public/search/search_source/create_search_source.test.ts +++ b/src/plugins/data/public/search/search_source/create_search_source.test.ts @@ -22,7 +22,7 @@ import { SearchSourceDependencies } from './search_source'; import { IIndexPattern } from '../../../common/index_patterns'; import { IndexPatternsContract } from '../../index_patterns/index_patterns'; import { Filter } from '../../../common/es_query/filters'; -import { dataPluginMock } from '../../mocks'; +import { coreMock } from '../../../../../core/public/mocks'; describe('createSearchSource', () => { const indexPatternMock: IIndexPattern = {} as IIndexPattern; @@ -31,13 +31,11 @@ describe('createSearchSource', () => { let createSearchSource: ReturnType; beforeEach(() => { - const data = dataPluginMock.createStartContract(); - dependencies = { getConfig: jest.fn(), search: jest.fn(), - legacySearch: data.search.__LEGACY, esShardTimeout: 30000, + http: coreMock.createStart().http, }; indexPatternContractMock = ({ diff --git a/src/plugins/data/public/search/search_source/mocks.ts b/src/plugins/data/public/search/search_source/mocks.ts index 4e1c35557ffa6..16f665994e3bd 100644 --- a/src/plugins/data/public/search/search_source/mocks.ts +++ b/src/plugins/data/public/search/search_source/mocks.ts @@ -17,7 +17,7 @@ * under the License. */ -import { uiSettingsServiceMock } from '../../../../../core/public/mocks'; +import { httpServiceMock, uiSettingsServiceMock } from '../../../../../core/public/mocks'; import { ISearchSource, SearchSource } from './search_source'; import { SearchSourceFields } from './types'; @@ -54,10 +54,5 @@ export const createSearchSourceMock = (fields?: SearchSourceFields) => getConfig: uiSettingsServiceMock.createStartContract().get, esShardTimeout: 30000, search: jest.fn(), - legacySearch: { - esClient: { - search: jest.fn(), - msearch: jest.fn(), - }, - }, + http: httpServiceMock.createStartContract(), }); diff --git a/src/plugins/data/public/search/search_source/search_source.test.ts b/src/plugins/data/public/search/search_source/search_source.test.ts index 2f0fa0765e25a..a5bf700624a33 100644 --- a/src/plugins/data/public/search/search_source/search_source.test.ts +++ b/src/plugins/data/public/search/search_source/search_source.test.ts @@ -22,7 +22,7 @@ import { GetConfigFn } from 'src/plugins/data/common'; import { SearchSource, SearchSourceDependencies } from './search_source'; import { IndexPattern, SortDirection } from '../..'; import { fetchSoon } from '../legacy'; -import { dataPluginMock } from '../../../../data/public/mocks'; +import { coreMock } from '../../../../../core/public/mocks'; jest.mock('../legacy', () => ({ fetchSoon: jest.fn().mockResolvedValue({}), @@ -54,8 +54,6 @@ describe('SearchSource', () => { let searchSourceDependencies: SearchSourceDependencies; beforeEach(() => { - const data = dataPluginMock.createStartContract(); - mockSearchMethod = jest.fn(() => { return new Observable((subscriber) => { setTimeout(() => { @@ -70,8 +68,8 @@ describe('SearchSource', () => { searchSourceDependencies = { getConfig: jest.fn(), search: mockSearchMethod, - legacySearch: data.search.__LEGACY, esShardTimeout: 30000, + http: coreMock.createStart().http, }; }); diff --git a/src/plugins/data/public/search/search_source/search_source.ts b/src/plugins/data/public/search/search_source/search_source.ts index d2e3370762059..ae6817510feaf 100644 --- a/src/plugins/data/public/search/search_source/search_source.ts +++ b/src/plugins/data/public/search/search_source/search_source.ts @@ -72,6 +72,7 @@ import { setWith } from '@elastic/safer-lodash-set'; import { uniqueId, uniq, extend, pick, difference, omit, isObject, keys, isFunction } from 'lodash'; import { map } from 'rxjs/operators'; +import { HttpStart } from 'src/core/public'; import { normalizeSortRequest } from './normalize_sort_request'; import { filterDocvalueFields } from './filter_docvalue_fields'; import { fieldWildcardFilter } from '../../../../kibana_utils/common'; @@ -90,7 +91,6 @@ import { getHighlightRequest } from '../../../common/field_formats'; import { GetConfigFn } from '../../../common/types'; import { fetchSoon } from '../legacy'; import { extractReferences } from './extract_references'; -import { ISearchStartLegacy } from '../types'; /** @internal */ export const searchSourceRequiredUiSettings = [ @@ -111,7 +111,7 @@ export const searchSourceRequiredUiSettings = [ export interface SearchSourceDependencies { getConfig: GetConfigFn; search: ISearchGeneric; - legacySearch: ISearchStartLegacy; + http: HttpStart; esShardTimeout: number; } @@ -243,7 +243,7 @@ export class SearchSource { * @return {Promise>} */ private async legacyFetch(searchRequest: SearchRequest, options: FetchOptions) { - const { esShardTimeout, legacySearch, getConfig } = this.dependencies; + const { esShardTimeout, http, getConfig } = this.dependencies; return await fetchSoon( searchRequest, @@ -252,7 +252,7 @@ export class SearchSource { ...options, }, { - legacySearchService: legacySearch, + http, config: { get: getConfig }, esShardTimeout, } diff --git a/src/plugins/data/public/search/types.ts b/src/plugins/data/public/search/types.ts index 55726e40f5a77..22f31308615d4 100644 --- a/src/plugins/data/public/search/types.ts +++ b/src/plugins/data/public/search/types.ts @@ -19,7 +19,6 @@ import { Observable } from 'rxjs'; import { PackageInfo } from 'kibana/server'; -import { LegacyApiCaller } from './legacy/es_client'; import { ISearchInterceptor } from './search_interceptor'; import { ISearchSource, SearchSourceFields } from './search_source'; import { SearchUsageCollector } from './collectors'; @@ -51,10 +50,6 @@ export type ISearchGeneric = < options?: ISearchOptions ) => Observable; -export interface ISearchStartLegacy { - esClient: LegacyApiCaller; -} - export interface SearchEnhancements { searchInterceptor: ISearchInterceptor; } @@ -78,11 +73,6 @@ export interface ISearchStart { create: (fields?: SearchSourceFields) => Promise; createEmpty: () => ISearchSource; }; - /** - * @deprecated - * @internal - */ - __LEGACY: ISearchStartLegacy; } export { SEARCH_EVENT_TYPE } from './collectors'; From 371a4dfe71bf497d788d711deae6b6844d25c861 Mon Sep 17 00:00:00 2001 From: Luke Elmers Date: Tue, 25 Aug 2020 21:03:43 -0600 Subject: [PATCH 17/77] Remove legacy es_client code. --- .../search/legacy/es_client/get_es_client.ts | 98 ------------------- .../public/search/legacy/es_client/index.ts | 21 ---- .../public/search/legacy/es_client/types.ts | 30 ------ .../data/public/search/legacy/index.ts | 1 - 4 files changed, 150 deletions(-) delete mode 100644 src/plugins/data/public/search/legacy/es_client/get_es_client.ts delete mode 100644 src/plugins/data/public/search/legacy/es_client/index.ts delete mode 100644 src/plugins/data/public/search/legacy/es_client/types.ts diff --git a/src/plugins/data/public/search/legacy/es_client/get_es_client.ts b/src/plugins/data/public/search/legacy/es_client/get_es_client.ts deleted file mode 100644 index 4367544ad9ff4..0000000000000 --- a/src/plugins/data/public/search/legacy/es_client/get_es_client.ts +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -// @ts-ignore -import { default as es } from 'elasticsearch-browser/elasticsearch'; -import { CoreStart, PackageInfo } from 'kibana/public'; -import { BehaviorSubject } from 'rxjs'; - -export function getEsClient({ - esRequestTimeout, - esApiVersion, - http, - packageVersion, -}: { - esRequestTimeout: number; - esApiVersion: string; - http: CoreStart['http']; - packageVersion: PackageInfo['version']; -}) { - // Use legacy es client for msearch. - const client = es.Client({ - host: getEsUrl(http, packageVersion), - log: 'info', - requestTimeout: esRequestTimeout, - apiVersion: esApiVersion, - }); - - const loadingCount$ = new BehaviorSubject(0); - http.addLoadingCountSource(loadingCount$); - - return { - search: wrapEsClientMethod(client, 'search', loadingCount$), - msearch: wrapEsClientMethod(client, 'msearch', loadingCount$), - create: wrapEsClientMethod(client, 'create', loadingCount$), - }; -} - -function wrapEsClientMethod(esClient: any, method: string, loadingCount$: BehaviorSubject) { - return (args: any) => { - // esClient returns a promise, with an additional abort handler - // To tap into the abort handling, we have to override that abort handler. - const customPromiseThingy = esClient[method](args); - const { abort } = customPromiseThingy; - let resolved = false; - - // Start LoadingIndicator - loadingCount$.next(loadingCount$.getValue() + 1); - - // Stop LoadingIndicator when user aborts - customPromiseThingy.abort = () => { - abort(); - if (!resolved) { - resolved = true; - loadingCount$.next(loadingCount$.getValue() - 1); - } - }; - - // Stop LoadingIndicator when promise finishes - customPromiseThingy.finally(() => { - resolved = true; - loadingCount$.next(loadingCount$.getValue() - 1); - }); - - return customPromiseThingy; - }; -} - -function getEsUrl(http: CoreStart['http'], packageVersion: PackageInfo['version']) { - const a = document.createElement('a'); - a.href = http.basePath.prepend('/elasticsearch'); - const protocolPort = /https/.test(a.protocol) ? 443 : 80; - const port = a.port || protocolPort; - return { - host: a.hostname, - port, - protocol: a.protocol, - pathname: a.pathname, - headers: { - 'kbn-version': packageVersion, - }, - }; -} diff --git a/src/plugins/data/public/search/legacy/es_client/index.ts b/src/plugins/data/public/search/legacy/es_client/index.ts deleted file mode 100644 index 78ac83af642d8..0000000000000 --- a/src/plugins/data/public/search/legacy/es_client/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export { getEsClient } from './get_es_client'; -export { LegacyApiCaller } from './types'; diff --git a/src/plugins/data/public/search/legacy/es_client/types.ts b/src/plugins/data/public/search/legacy/es_client/types.ts deleted file mode 100644 index 2d35188322a4e..0000000000000 --- a/src/plugins/data/public/search/legacy/es_client/types.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { SearchResponse } from 'elasticsearch'; -import { SearchRequest } from '../../fetch'; - -export interface LegacyApiCaller { - search: (searchRequest: SearchRequest) => LegacyApiCallerResponse; - msearch: (searchRequest: SearchRequest) => LegacyApiCallerResponse; -} - -interface LegacyApiCallerResponse extends Promise> { - abort: () => void; -} diff --git a/src/plugins/data/public/search/legacy/index.ts b/src/plugins/data/public/search/legacy/index.ts index e2ae72824f3f4..74e516f407e8c 100644 --- a/src/plugins/data/public/search/legacy/index.ts +++ b/src/plugins/data/public/search/legacy/index.ts @@ -18,4 +18,3 @@ */ export { fetchSoon } from './fetch_soon'; -export { getEsClient, LegacyApiCaller } from './es_client'; From 24754673a6af24ae5a0b30c29d70a11dd8bd4d30 Mon Sep 17 00:00:00 2001 From: Luke Elmers Date: Tue, 25 Aug 2020 22:15:04 -0600 Subject: [PATCH 18/77] Handle msearch options on server. --- src/plugins/data/public/search/fetch/types.ts | 1 - .../legacy/default_search_strategy.test.ts | 59 ++++++----------- .../search/legacy/default_search_strategy.ts | 15 ++--- .../search/legacy/get_msearch_params.test.ts | 64 ------------------- .../search/legacy/get_msearch_params.ts | 29 --------- .../search/search_source/search_source.ts | 3 +- .../data/server/search/routes/msearch.test.ts | 53 ++++++++++----- .../data/server/search/routes/msearch.ts | 47 ++++++++++---- .../data/server/search/routes/search.test.ts | 21 ++++-- .../data/server/search/search_service.ts | 11 +++- 10 files changed, 121 insertions(+), 182 deletions(-) delete mode 100644 src/plugins/data/public/search/legacy/get_msearch_params.test.ts delete mode 100644 src/plugins/data/public/search/legacy/get_msearch_params.ts diff --git a/src/plugins/data/public/search/fetch/types.ts b/src/plugins/data/public/search/fetch/types.ts index 33a205b342ae8..ec10961225efa 100644 --- a/src/plugins/data/public/search/fetch/types.ts +++ b/src/plugins/data/public/search/fetch/types.ts @@ -36,7 +36,6 @@ export interface FetchOptions { export interface FetchHandlers { config: { get: GetConfigFn }; - esShardTimeout: number; http: HttpStart; } diff --git a/src/plugins/data/public/search/legacy/default_search_strategy.test.ts b/src/plugins/data/public/search/legacy/default_search_strategy.test.ts index f1eb88f1c5671..e0916b23a4b48 100644 --- a/src/plugins/data/public/search/legacy/default_search_strategy.test.ts +++ b/src/plugins/data/public/search/legacy/default_search_strategy.test.ts @@ -17,26 +17,18 @@ * under the License. */ -import { HttpStart, IUiSettingsClient } from 'src/core/public'; +import { HttpStart } from 'src/core/public'; import { coreMock } from '../../../../../core/public/mocks'; import { defaultSearchStrategy } from './default_search_strategy'; import { SearchStrategySearchParams } from './types'; -import { UI_SETTINGS } from '../../../common'; const { search } = defaultSearchStrategy; -function getConfigStub(config: any = {}) { - return { - get: (key) => config[key], - } as IUiSettingsClient; -} - const msearchMock = jest.fn().mockResolvedValue({ body: { responses: [] } }); describe('defaultSearchStrategy', function () { describe('search', function () { - let searchArgs: MockedKeys>; - let es: any; + let searchArgs: MockedKeys; let http: jest.Mocked; beforeEach(() => { @@ -51,41 +43,26 @@ describe('defaultSearchStrategy', function () { index: { title: 'foo' }, }, ], - esShardTimeout: 0, http, + config: { + get: jest.fn(), + }, }; - - es = http.post; - }); - - test('does not send max_concurrent_shard_requests by default', async () => { - const config = getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true }); - await search({ ...searchArgs, config }); - expect(es.mock.calls[0][1].query.max_concurrent_shard_requests).toBe(undefined); - }); - - test('allows configuration of max_concurrent_shard_requests', async () => { - const config = getConfigStub({ - [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true, - [UI_SETTINGS.COURIER_MAX_CONCURRENT_SHARD_REQUESTS]: 42, - }); - await search({ ...searchArgs, config }); - expect(es.mock.calls[0][1].query.max_concurrent_shard_requests).toBe(42); - }); - - test('should set rest_total_hits_as_int to true on a request', async () => { - const config = getConfigStub({ [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true }); - await search({ ...searchArgs, config }); - expect(es.mock.calls[0][1].query).toHaveProperty('rest_total_hits_as_int', true); }); - test('should set ignore_throttled=false when including frozen indices', async () => { - const config = getConfigStub({ - [UI_SETTINGS.COURIER_BATCH_SEARCHES]: true, - [UI_SETTINGS.SEARCH_INCLUDE_FROZEN]: true, - }); - await search({ ...searchArgs, config }); - expect(es.mock.calls[0][1].query).toHaveProperty('ignore_throttled', false); + test('calls http.post with the correct arguments', async () => { + await search({ ...searchArgs }); + expect(http.post.mock.calls).toMatchInlineSnapshot(` + Array [ + Array [ + "/internal/_msearch", + Object { + "body": "{\\"searches\\":[{\\"header\\":{\\"index\\":\\"foo\\"}}]}", + "signal": AbortSignal {}, + }, + ], + ] + `); }); }); }); diff --git a/src/plugins/data/public/search/legacy/default_search_strategy.ts b/src/plugins/data/public/search/legacy/default_search_strategy.ts index b32315163bb87..8e45715b7cc38 100644 --- a/src/plugins/data/public/search/legacy/default_search_strategy.ts +++ b/src/plugins/data/public/search/legacy/default_search_strategy.ts @@ -19,8 +19,7 @@ import { BehaviorSubject } from 'rxjs'; -import { getPreference, getTimeout } from '../fetch'; -import { getMSearchParams } from './get_msearch_params'; +import { getPreference } from '../fetch'; import { SearchStrategyProvider, SearchStrategySearchParams } from './types'; // @deprecated @@ -32,19 +31,14 @@ export const defaultSearchStrategy: SearchStrategyProvider = { }, }; -function msearch({ searchRequests, config, http, esShardTimeout }: SearchStrategySearchParams) { - const requests = searchRequests.map(({ index, body, search_type: searchType }) => { +function msearch({ searchRequests, config, http }: SearchStrategySearchParams) { + const requests = searchRequests.map(({ index, body }) => { return { header: { index: index.title || index, - ignore_unavailable: true, preference: getPreference(config.get), - search_type: searchType, - }, - body: { - ...body, - timeout: getTimeout(esShardTimeout), }, + body, }; }); @@ -67,7 +61,6 @@ function msearch({ searchRequests, config, http, esShardTimeout }: SearchStrateg }; const searching = http.post('/internal/_msearch', { - query: getMSearchParams(config.get), body: JSON.stringify({ searches: requests }), signal: abortController.signal, }); diff --git a/src/plugins/data/public/search/legacy/get_msearch_params.test.ts b/src/plugins/data/public/search/legacy/get_msearch_params.test.ts deleted file mode 100644 index d3206950174c8..0000000000000 --- a/src/plugins/data/public/search/legacy/get_msearch_params.test.ts +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { getMSearchParams } from './get_msearch_params'; -import { GetConfigFn, UI_SETTINGS } from '../../../common'; - -function getConfigStub(config: any = {}): GetConfigFn { - return (key) => config[key]; -} - -describe('getMSearchParams', () => { - test('includes rest_total_hits_as_int', () => { - const config = getConfigStub(); - const msearchParams = getMSearchParams(config); - expect(msearchParams.rest_total_hits_as_int).toBe(true); - }); - - test('includes ignore_throttled according to search:includeFrozen', () => { - let config = getConfigStub({ [UI_SETTINGS.SEARCH_INCLUDE_FROZEN]: true }); - let msearchParams = getMSearchParams(config); - expect(msearchParams.ignore_throttled).toBe(false); - - config = getConfigStub({ [UI_SETTINGS.SEARCH_INCLUDE_FROZEN]: false }); - msearchParams = getMSearchParams(config); - expect(msearchParams.ignore_throttled).toBe(true); - }); - - test('includes max_concurrent_shard_requests according to courier:maxConcurrentShardRequests if greater than 0', () => { - let config = getConfigStub({ [UI_SETTINGS.COURIER_MAX_CONCURRENT_SHARD_REQUESTS]: 0 }); - let msearchParams = getMSearchParams(config); - expect(msearchParams.max_concurrent_shard_requests).toBe(undefined); - - config = getConfigStub({ [UI_SETTINGS.COURIER_MAX_CONCURRENT_SHARD_REQUESTS]: 5 }); - msearchParams = getMSearchParams(config); - expect(msearchParams.max_concurrent_shard_requests).toBe(5); - }); - - test('does not include other search params that are included in the msearch header or body', () => { - const config = getConfigStub({ - [UI_SETTINGS.SEARCH_INCLUDE_FROZEN]: false, - [UI_SETTINGS.COURIER_MAX_CONCURRENT_SHARD_REQUESTS]: 5, - }); - const msearchParams = getMSearchParams(config); - expect(msearchParams.hasOwnProperty('ignore_unavailable')).toBe(false); - expect(msearchParams.hasOwnProperty('preference')).toBe(false); - expect(msearchParams.hasOwnProperty('timeout')).toBe(false); - }); -}); diff --git a/src/plugins/data/public/search/legacy/get_msearch_params.ts b/src/plugins/data/public/search/legacy/get_msearch_params.ts deleted file mode 100644 index c4f77b25078cd..0000000000000 --- a/src/plugins/data/public/search/legacy/get_msearch_params.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { GetConfigFn } from '../../../common'; -import { getIgnoreThrottled, getMaxConcurrentShardRequests } from '../fetch'; - -export function getMSearchParams(getConfig: GetConfigFn) { - return { - rest_total_hits_as_int: true, - ignore_throttled: getIgnoreThrottled(getConfig), - max_concurrent_shard_requests: getMaxConcurrentShardRequests(getConfig), - }; -} diff --git a/src/plugins/data/public/search/search_source/search_source.ts b/src/plugins/data/public/search/search_source/search_source.ts index ae6817510feaf..2bd66abca80d4 100644 --- a/src/plugins/data/public/search/search_source/search_source.ts +++ b/src/plugins/data/public/search/search_source/search_source.ts @@ -243,7 +243,7 @@ export class SearchSource { * @return {Promise>} */ private async legacyFetch(searchRequest: SearchRequest, options: FetchOptions) { - const { esShardTimeout, http, getConfig } = this.dependencies; + const { http, getConfig } = this.dependencies; return await fetchSoon( searchRequest, @@ -254,7 +254,6 @@ export class SearchSource { { http, config: { get: getConfig }, - esShardTimeout, } ); } diff --git a/src/plugins/data/server/search/routes/msearch.test.ts b/src/plugins/data/server/search/routes/msearch.test.ts index 3764a37a12ddf..0a52cf23c5472 100644 --- a/src/plugins/data/server/search/routes/msearch.test.ts +++ b/src/plugins/data/server/search/routes/msearch.test.ts @@ -17,8 +17,19 @@ * under the License. */ -import { CoreSetup, RequestHandlerContext, StartServicesAccessor } from 'src/core/server'; -import { coreMock, httpServerMock } from '../../../../../../src/core/server/mocks'; +import { Observable } from 'rxjs'; + +import { + CoreSetup, + RequestHandlerContext, + SharedGlobalConfig, + StartServicesAccessor, +} from 'src/core/server'; +import { + coreMock, + httpServerMock, + pluginInitializerContextConfigMock, +} from '../../../../../../src/core/server/mocks'; import { registerMsearchRoute, convertRequestBody } from './msearch'; import { DataPluginStart } from '../../plugin'; import { dataPluginMock } from '../../mocks'; @@ -27,17 +38,24 @@ describe('msearch route', () => { let mockDataStart: MockedKeys; let mockCoreSetup: MockedKeys>; let getStartServices: jest.Mocked>; + let globalConfig$: Observable; beforeEach(() => { mockDataStart = dataPluginMock.createStartContract(); mockCoreSetup = coreMock.createSetup({ pluginStartContract: mockDataStart }); getStartServices = mockCoreSetup.getStartServices; + globalConfig$ = pluginInitializerContextConfigMock({}).legacy.globalConfig$; }); it('handler calls /_msearch with the given request', async () => { const response = { id: 'yay' }; const mockClient = { transport: { request: jest.fn().mockResolvedValue(response) } }; - const mockContext = { core: { elasticsearch: { client: { asCurrentUser: mockClient } } } }; + const mockContext = { + core: { + elasticsearch: { client: { asCurrentUser: mockClient } }, + uiSettings: { client: { get: jest.fn() } }, + }, + }; const mockBody = { searches: [{ header: {}, body: {} }] }; const mockQuery = {}; const mockRequest = httpServerMock.createKibanaRequest({ @@ -46,7 +64,7 @@ describe('msearch route', () => { }); const mockResponse = httpServerMock.createResponseFactory(); - registerMsearchRoute(mockCoreSetup.http.createRouter(), { getStartServices }); + registerMsearchRoute(mockCoreSetup.http.createRouter(), { getStartServices, globalConfig$ }); const mockRouter = mockCoreSetup.http.createRouter.mock.results[0].value; const handler = mockRouter.post.mock.calls[0][1]; @@ -55,7 +73,7 @@ describe('msearch route', () => { expect(mockClient.transport.request.mock.calls[0][0].method).toBe('GET'); expect(mockClient.transport.request.mock.calls[0][0].path).toBe('/_msearch'); expect(mockClient.transport.request.mock.calls[0][0].body).toEqual( - convertRequestBody(mockBody as any) + convertRequestBody(mockBody as any, { timeout: '0ms' }) ); expect(mockResponse.ok).toBeCalled(); expect(mockResponse.ok.mock.calls[0][0]).toEqual({ @@ -73,7 +91,12 @@ describe('msearch route', () => { const mockClient = { transport: { request: jest.fn().mockReturnValue(Promise.reject(response)) }, }; - const mockContext = { core: { elasticsearch: { client: { asCurrentUser: mockClient } } } }; + const mockContext = { + core: { + elasticsearch: { client: { asCurrentUser: mockClient } }, + uiSettings: { client: { get: jest.fn() } }, + }, + }; const mockBody = { searches: [{ header: {}, body: {} }] }; const mockQuery = {}; const mockRequest = httpServerMock.createKibanaRequest({ @@ -82,7 +105,7 @@ describe('msearch route', () => { }); const mockResponse = httpServerMock.createResponseFactory(); - registerMsearchRoute(mockCoreSetup.http.createRouter(), { getStartServices }); + registerMsearchRoute(mockCoreSetup.http.createRouter(), { getStartServices, globalConfig$ }); const mockRouter = mockCoreSetup.http.createRouter.mock.results[0].value; const handler = mockRouter.post.mock.calls[0][1]; @@ -101,9 +124,9 @@ describe('msearch route', () => { const request = { searches: [{ header: { index: 'foo', preference: 0 }, body: { test: true } }], }; - expect(convertRequestBody(request)).toMatchInlineSnapshot(` - "{\\"index\\":\\"foo\\",\\"preference\\":0} - {\\"test\\":true} + expect(convertRequestBody(request, { timeout: '30000ms' })).toMatchInlineSnapshot(` + "{\\"ignore_unavailable\\":true,\\"index\\":\\"foo\\",\\"preference\\":0} + {\\"timeout\\":\\"30000ms\\",\\"test\\":true} " `); }); @@ -115,11 +138,11 @@ describe('msearch route', () => { { header: { index: 'bar', preference: 1 }, body: { hello: 'world' } }, ], }; - expect(convertRequestBody(request)).toMatchInlineSnapshot(` - "{\\"index\\":\\"foo\\",\\"preference\\":0} - {\\"test\\":true} - {\\"index\\":\\"bar\\",\\"preference\\":1} - {\\"hello\\":\\"world\\"} + expect(convertRequestBody(request, { timeout: '30000ms' })).toMatchInlineSnapshot(` + "{\\"ignore_unavailable\\":true,\\"index\\":\\"foo\\",\\"preference\\":0} + {\\"timeout\\":\\"30000ms\\",\\"test\\":true} + {\\"ignore_unavailable\\":true,\\"index\\":\\"bar\\",\\"preference\\":1} + {\\"timeout\\":\\"30000ms\\",\\"hello\\":\\"world\\"} " `); }); diff --git a/src/plugins/data/server/search/routes/msearch.ts b/src/plugins/data/server/search/routes/msearch.ts index 6a15b707aae48..dce2fb0f30e8f 100644 --- a/src/plugins/data/server/search/routes/msearch.ts +++ b/src/plugins/data/server/search/routes/msearch.ts @@ -17,9 +17,13 @@ * under the License. */ +import { first } from 'rxjs/operators'; import { schema } from '@kbn/config-schema'; + import { IRouter } from 'src/core/server'; +import { UI_SETTINGS } from '../../../common'; import { SearchRouteDependencies } from '../search_service'; +import { getDefaultSearchParams } from '..'; interface MsearchHeaders { index: string; @@ -36,10 +40,19 @@ interface RequestBody { } /** @internal */ -export function convertRequestBody(requestBody: RequestBody): string { +export function convertRequestBody( + requestBody: RequestBody, + { timeout }: { timeout?: string } +): string { return requestBody.searches.reduce((req, curr) => { - const header = JSON.stringify({ ...curr.header }); - const body = JSON.stringify({ ...curr.body }); + const header = JSON.stringify({ + ignore_unavailable: true, + ...curr.header, + }); + const body = JSON.stringify({ + timeout, + ...curr.body, + }); req += `${header}\n${body}\n`; return req; }, ''); @@ -77,26 +90,34 @@ export function registerMsearchRoute(router: IRouter, deps: SearchRouteDependenc }) ), }), - query: schema.object({ - // We don't use `schema.boolean` here, because all query string parameters are treated as - // strings and @kbn/config-schema doesn't coerce strings to booleans. - ignore_throttled: schema.oneOf([schema.literal('true'), schema.literal('false')]), - rest_total_hits_as_int: schema.oneOf([schema.literal('true'), schema.literal('false')]), - max_concurrent_shard_requests: schema.maybe(schema.number()), - }), }, }, async (context, request, res) => { const client = context.core.elasticsearch.client.asCurrentUser; - const body = convertRequestBody(request.body); - const querystring = request.query; + + // get shardTimeout + const config = await deps.globalConfig$.pipe(first()).toPromise(); + const { timeout } = getDefaultSearchParams(config); + + const body = convertRequestBody(request.body, { timeout }); try { + const ignoreThrottled = !(await context.core.uiSettings.client.get( + UI_SETTINGS.SEARCH_INCLUDE_FROZEN + )); + const maxConcurrentShardRequests = await context.core.uiSettings.client.get( + UI_SETTINGS.COURIER_MAX_CONCURRENT_SHARD_REQUESTS + ); const response = await client.transport.request({ method: 'GET', path: '/_msearch', body, - querystring, + querystring: { + rest_total_hits_as_int: true, + ignore_throttled: ignoreThrottled, + max_concurrent_shard_requests: + maxConcurrentShardRequests > 0 ? maxConcurrentShardRequests : undefined, + }, }); return res.ok({ body: response }); diff --git a/src/plugins/data/server/search/routes/search.test.ts b/src/plugins/data/server/search/routes/search.test.ts index a9c1b4427c2a1..e2518acd7d505 100644 --- a/src/plugins/data/server/search/routes/search.test.ts +++ b/src/plugins/data/server/search/routes/search.test.ts @@ -17,8 +17,19 @@ * under the License. */ -import { CoreSetup, RequestHandlerContext, StartServicesAccessor } from 'src/core/server'; -import { coreMock, httpServerMock } from '../../../../../../src/core/server/mocks'; +import { Observable } from 'rxjs'; + +import { + CoreSetup, + RequestHandlerContext, + SharedGlobalConfig, + StartServicesAccessor, +} from 'src/core/server'; +import { + coreMock, + httpServerMock, + pluginInitializerContextConfigMock, +} from '../../../../../../src/core/server/mocks'; import { registerSearchRoute } from './search'; import { DataPluginStart } from '../../plugin'; import { dataPluginMock } from '../../mocks'; @@ -27,11 +38,13 @@ describe('Search service', () => { let mockDataStart: MockedKeys; let mockCoreSetup: MockedKeys>; let getStartServices: jest.Mocked>; + let globalConfig$: Observable; beforeEach(() => { mockDataStart = dataPluginMock.createStartContract(); mockCoreSetup = coreMock.createSetup({ pluginStartContract: mockDataStart }); getStartServices = mockCoreSetup.getStartServices; + globalConfig$ = pluginInitializerContextConfigMock({}).legacy.globalConfig$; }); it('handler calls context.search.search with the given request and strategy', async () => { @@ -46,7 +59,7 @@ describe('Search service', () => { }); const mockResponse = httpServerMock.createResponseFactory(); - registerSearchRoute(mockCoreSetup.http.createRouter(), { getStartServices }); + registerSearchRoute(mockCoreSetup.http.createRouter(), { getStartServices, globalConfig$ }); const mockRouter = mockCoreSetup.http.createRouter.mock.results[0].value; const handler = mockRouter.post.mock.calls[0][1]; @@ -77,7 +90,7 @@ describe('Search service', () => { }); const mockResponse = httpServerMock.createResponseFactory(); - registerSearchRoute(mockCoreSetup.http.createRouter(), { getStartServices }); + registerSearchRoute(mockCoreSetup.http.createRouter(), { getStartServices, globalConfig$ }); const mockRouter = mockCoreSetup.http.createRouter.mock.results[0].value; const handler = mockRouter.post.mock.calls[0][1]; diff --git a/src/plugins/data/server/search/search_service.ts b/src/plugins/data/server/search/search_service.ts index 80129c0429ba0..beb13c3ec59d6 100644 --- a/src/plugins/data/server/search/search_service.ts +++ b/src/plugins/data/server/search/search_service.ts @@ -17,6 +17,7 @@ * under the License. */ +import { Observable } from 'rxjs'; import { CoreSetup, CoreStart, @@ -24,6 +25,7 @@ import { Plugin, PluginInitializerContext, RequestHandlerContext, + SharedGlobalConfig, StartServicesAccessor, } from 'src/core/server'; import { ISearchSetup, ISearchStart, ISearchStrategy, SearchEnhancements } from './types'; @@ -59,6 +61,7 @@ export interface SearchServiceStartDependencies { /** @internal */ export interface SearchRouteDependencies { getStartServices: StartServicesAccessor<{}, DataPluginStart>; + globalConfig$: Observable; } export class SearchService implements Plugin { @@ -78,8 +81,12 @@ export class SearchService implements Plugin { const usage = usageCollection ? usageProvider(core) : undefined; const router = core.http.createRouter(); - registerSearchRoute(router, { getStartServices: core.getStartServices }); - registerMsearchRoute(router, { getStartServices: core.getStartServices }); + const routeDependencies = { + getStartServices: core.getStartServices, + globalConfig$: this.initializerContext.config.legacy.globalConfig$, + }; + registerSearchRoute(router, routeDependencies); + registerMsearchRoute(router, routeDependencies); this.registerSearchStrategy( ES_SEARCH_STRATEGY, From 775586ac7e7bcd0f8e66bd06fd23d41878be09b7 Mon Sep 17 00:00:00 2001 From: Luke Elmers Date: Tue, 25 Aug 2020 22:21:35 -0600 Subject: [PATCH 19/77] Remove elasticsearch-browser dependency. --- package.json | 1 - packages/kbn-optimizer/src/worker/webpack.config.ts | 1 - packages/kbn-ui-shared-deps/entry.js | 3 --- packages/kbn-ui-shared-deps/index.js | 7 ------- packages/kbn-ui-shared-deps/package.json | 1 - yarn.lock | 5 ----- 6 files changed, 18 deletions(-) diff --git a/package.json b/package.json index 84f6f30f064f9..5b8b38e2650bf 100644 --- a/package.json +++ b/package.json @@ -362,7 +362,6 @@ "dedent": "^0.7.0", "deepmerge": "^4.2.2", "delete-empty": "^2.0.0", - "elasticsearch-browser": "^16.7.0", "enzyme": "^3.11.0", "enzyme-adapter-react-16": "^1.15.2", "enzyme-adapter-utils": "^1.13.0", diff --git a/packages/kbn-optimizer/src/worker/webpack.config.ts b/packages/kbn-optimizer/src/worker/webpack.config.ts index 6b07384910abb..9f2c5654a8bd4 100644 --- a/packages/kbn-optimizer/src/worker/webpack.config.ts +++ b/packages/kbn-optimizer/src/worker/webpack.config.ts @@ -79,7 +79,6 @@ export function getWebpackConfig(bundle: Bundle, bundleRefs: BundleRefs, worker: // or which have require() statements that should be ignored because the file is // already bundled with all its necessary depedencies noParse: [ - /[\/\\]node_modules[\/\\]elasticsearch-browser[\/\\]/, /[\/\\]node_modules[\/\\]lodash[\/\\]index\.js$/, /[\/\\]node_modules[\/\\]vega[\/\\]build[\/\\]vega\.js$/, ], diff --git a/packages/kbn-ui-shared-deps/entry.js b/packages/kbn-ui-shared-deps/entry.js index 0f981f3d07610..365b84b83bd5f 100644 --- a/packages/kbn-ui-shared-deps/entry.js +++ b/packages/kbn-ui-shared-deps/entry.js @@ -54,6 +54,3 @@ export const ElasticEuiChartsTheme = require('@elastic/eui/dist/eui_charts_theme import * as Theme from './theme.ts'; export { Theme }; - -// massive deps that we should really get rid of or reduce in size substantially -export const ElasticsearchBrowser = require('elasticsearch-browser/elasticsearch.js'); diff --git a/packages/kbn-ui-shared-deps/index.js b/packages/kbn-ui-shared-deps/index.js index 40e89f199b6a1..84ca3435e02bc 100644 --- a/packages/kbn-ui-shared-deps/index.js +++ b/packages/kbn-ui-shared-deps/index.js @@ -62,12 +62,5 @@ exports.externals = { '@elastic/eui/dist/eui_charts_theme': '__kbnSharedDeps__.ElasticEuiChartsTheme', '@elastic/eui/dist/eui_theme_light.json': '__kbnSharedDeps__.Theme.euiLightVars', '@elastic/eui/dist/eui_theme_dark.json': '__kbnSharedDeps__.Theme.euiDarkVars', - - /** - * massive deps that we should really get rid of or reduce in size substantially - */ - elasticsearch: '__kbnSharedDeps__.ElasticsearchBrowser', - 'elasticsearch-browser': '__kbnSharedDeps__.ElasticsearchBrowser', - 'elasticsearch-browser/elasticsearch': '__kbnSharedDeps__.ElasticsearchBrowser', }; exports.publicPathLoader = require.resolve('./public_path_loader'); diff --git a/packages/kbn-ui-shared-deps/package.json b/packages/kbn-ui-shared-deps/package.json index 531513481b1d4..96f05c42df589 100644 --- a/packages/kbn-ui-shared-deps/package.json +++ b/packages/kbn-ui-shared-deps/package.json @@ -19,7 +19,6 @@ "compression-webpack-plugin": "^4.0.0", "core-js": "^3.6.4", "custom-event-polyfill": "^0.3.0", - "elasticsearch-browser": "^16.7.0", "jquery": "^3.5.0", "mini-css-extract-plugin": "0.8.0", "moment": "^2.24.0", diff --git a/yarn.lock b/yarn.lock index 845685ff36f7d..3af2990639c0e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11247,11 +11247,6 @@ elastic-apm-node@^3.7.0: traceparent "^1.0.0" unicode-byte-truncate "^1.0.0" -elasticsearch-browser@^16.7.0: - version "16.7.0" - resolved "https://registry.yarnpkg.com/elasticsearch-browser/-/elasticsearch-browser-16.7.0.tgz#1f32a402cd36a9bb14a9ea6cb70f8e126d4cb9b1" - integrity sha512-UES2Fbnzy4Ivq4QvES4sfk/a5UytJczeJdfxRWa4kuHEllKOffKQLTxJ8Ti86OREpACQxppqvYgzctJuEiIr7Q== - elasticsearch@^16.4.0: version "16.5.0" resolved "https://registry.yarnpkg.com/elasticsearch/-/elasticsearch-16.5.0.tgz#619a48040be25d345fdddf09fa6042a88c3974d6" From d7df81e3d3cb55a0f9c2d7196f9872f4ff35f1bd Mon Sep 17 00:00:00 2001 From: Luke Elmers Date: Tue, 25 Aug 2020 22:46:15 -0600 Subject: [PATCH 20/77] Update generated docs. --- src/plugins/data/public/public.api.md | 1 + src/plugins/data/server/server.api.md | 133 +------------------------- 2 files changed, 5 insertions(+), 129 deletions(-) diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index 261f16229460a..31c8279f91bcd 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -29,6 +29,7 @@ import { ExpressionsSetup } from 'src/plugins/expressions/public'; import { FetchOptions as FetchOptions_2 } from 'src/plugins/data/public'; import { History } from 'history'; import { Href } from 'history'; +import { HttpStart } from 'src/core/public'; import { IconType } from '@elastic/eui'; import { InjectedIntl } from '@kbn/i18n/react'; import { ISearchSource as ISearchSource_2 } from 'src/plugins/data/public'; diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md index 9f114f2132009..f2ba1d09b9bad 100644 --- a/src/plugins/data/server/server.api.md +++ b/src/plugins/data/server/server.api.md @@ -5,163 +5,40 @@ ```ts import { $Values } from '@kbn/utility-types'; -import { ApiResponse } from '@elastic/elasticsearch/lib/Transport'; import { Assign } from '@kbn/utility-types'; -import Boom from 'boom'; -import { BulkIndexDocumentsParams } from 'elasticsearch'; -import { CatAliasesParams } from 'elasticsearch'; -import { CatAllocationParams } from 'elasticsearch'; -import { CatCommonParams } from 'elasticsearch'; -import { CatFielddataParams } from 'elasticsearch'; -import { CatHealthParams } from 'elasticsearch'; -import { CatHelpParams } from 'elasticsearch'; -import { CatIndicesParams } from 'elasticsearch'; -import { CatRecoveryParams } from 'elasticsearch'; -import { CatSegmentsParams } from 'elasticsearch'; -import { CatShardsParams } from 'elasticsearch'; -import { CatSnapshotsParams } from 'elasticsearch'; -import { CatTasksParams } from 'elasticsearch'; -import { CatThreadPoolParams } from 'elasticsearch'; -import { ClearScrollParams } from 'elasticsearch'; -import { Client } from 'elasticsearch'; -import { ClusterAllocationExplainParams } from 'elasticsearch'; -import { ClusterGetSettingsParams } from 'elasticsearch'; -import { ClusterHealthParams } from 'elasticsearch'; -import { ClusterPendingTasksParams } from 'elasticsearch'; -import { ClusterPutSettingsParams } from 'elasticsearch'; -import { ClusterRerouteParams } from 'elasticsearch'; -import { ClusterStateParams } from 'elasticsearch'; -import { ClusterStatsParams } from 'elasticsearch'; import { CoreSetup } from 'src/core/server'; import { CoreSetup as CoreSetup_2 } from 'kibana/server'; import { CoreStart } from 'src/core/server'; -import { CountParams } from 'elasticsearch'; -import { CreateDocumentParams } from 'elasticsearch'; -import { DeleteDocumentByQueryParams } from 'elasticsearch'; -import { DeleteDocumentParams } from 'elasticsearch'; -import { DeleteScriptParams } from 'elasticsearch'; -import { DeleteTemplateParams } from 'elasticsearch'; import { Duration } from 'moment'; import { Ensure } from '@kbn/utility-types'; import { ErrorToastOptions } from 'src/core/public/notifications'; -import { ExistsParams } from 'elasticsearch'; -import { ExplainParams } from 'elasticsearch'; import { ExpressionAstFunction } from 'src/plugins/expressions/common'; import { ExpressionsServerSetup } from 'src/plugins/expressions/server'; import { FetchOptions } from 'src/plugins/data/public'; -import { FieldStatsParams } from 'elasticsearch'; -import { GenericParams } from 'elasticsearch'; -import { GetParams } from 'elasticsearch'; -import { GetResponse } from 'elasticsearch'; -import { GetScriptParams } from 'elasticsearch'; -import { GetSourceParams } from 'elasticsearch'; -import { GetTemplateParams } from 'elasticsearch'; -import { IncomingHttpHeaders } from 'http'; -import { IndexDocumentParams } from 'elasticsearch'; -import { IndicesAnalyzeParams } from 'elasticsearch'; -import { IndicesClearCacheParams } from 'elasticsearch'; -import { IndicesCloseParams } from 'elasticsearch'; -import { IndicesCreateParams } from 'elasticsearch'; -import { IndicesDeleteAliasParams } from 'elasticsearch'; -import { IndicesDeleteParams } from 'elasticsearch'; -import { IndicesDeleteTemplateParams } from 'elasticsearch'; -import { IndicesExistsAliasParams } from 'elasticsearch'; -import { IndicesExistsParams } from 'elasticsearch'; -import { IndicesExistsTemplateParams } from 'elasticsearch'; -import { IndicesExistsTypeParams } from 'elasticsearch'; -import { IndicesFlushParams } from 'elasticsearch'; -import { IndicesFlushSyncedParams } from 'elasticsearch'; -import { IndicesForcemergeParams } from 'elasticsearch'; -import { IndicesGetAliasParams } from 'elasticsearch'; -import { IndicesGetFieldMappingParams } from 'elasticsearch'; -import { IndicesGetMappingParams } from 'elasticsearch'; -import { IndicesGetParams } from 'elasticsearch'; -import { IndicesGetSettingsParams } from 'elasticsearch'; -import { IndicesGetTemplateParams } from 'elasticsearch'; -import { IndicesGetUpgradeParams } from 'elasticsearch'; -import { IndicesOpenParams } from 'elasticsearch'; -import { IndicesPutAliasParams } from 'elasticsearch'; -import { IndicesPutMappingParams } from 'elasticsearch'; -import { IndicesPutSettingsParams } from 'elasticsearch'; -import { IndicesPutTemplateParams } from 'elasticsearch'; -import { IndicesRecoveryParams } from 'elasticsearch'; -import { IndicesRefreshParams } from 'elasticsearch'; -import { IndicesRolloverParams } from 'elasticsearch'; -import { IndicesSegmentsParams } from 'elasticsearch'; -import { IndicesShardStoresParams } from 'elasticsearch'; -import { IndicesShrinkParams } from 'elasticsearch'; -import { IndicesStatsParams } from 'elasticsearch'; -import { IndicesUpdateAliasesParams } from 'elasticsearch'; -import { IndicesUpgradeParams } from 'elasticsearch'; -import { IndicesValidateQueryParams } from 'elasticsearch'; -import { InfoParams } from 'elasticsearch'; -import { IngestDeletePipelineParams } from 'elasticsearch'; -import { IngestGetPipelineParams } from 'elasticsearch'; -import { IngestPutPipelineParams } from 'elasticsearch'; -import { IngestSimulateParams } from 'elasticsearch'; import { ISearchSource } from 'src/plugins/data/public'; -import { KibanaClient } from '@elastic/elasticsearch/api/kibana'; -import { KibanaConfigType as KibanaConfigType_2 } from 'src/core/server/kibana_config'; import { KibanaRequest } from 'kibana/server'; -import { LegacyAPICaller as LegacyAPICaller_2 } from 'kibana/server'; +import { LegacyAPICaller } from 'kibana/server'; import { Logger as Logger_2 } from 'kibana/server'; -import { MGetParams } from 'elasticsearch'; -import { MGetResponse } from 'elasticsearch'; import { Moment } from 'moment'; import moment from 'moment'; -import { MSearchParams } from 'elasticsearch'; -import { MSearchResponse } from 'elasticsearch'; -import { MSearchTemplateParams } from 'elasticsearch'; -import { MTermVectorsParams } from 'elasticsearch'; -import { NodesHotThreadsParams } from 'elasticsearch'; -import { NodesInfoParams } from 'elasticsearch'; -import { NodesStatsParams } from 'elasticsearch'; import { Observable } from 'rxjs'; -import { PingParams } from 'elasticsearch'; import { Plugin as Plugin_2 } from 'src/core/server'; import { PluginInitializerContext as PluginInitializerContext_2 } from 'src/core/server'; -import { PutScriptParams } from 'elasticsearch'; -import { PutTemplateParams } from 'elasticsearch'; import { RecursiveReadonly } from '@kbn/utility-types'; -import { ReindexParams } from 'elasticsearch'; -import { ReindexRethrottleParams } from 'elasticsearch'; -import { RenderSearchTemplateParams } from 'elasticsearch'; import { RequestAdapter } from 'src/plugins/inspector/common'; +import { RequestHandlerContext } from 'src/core/server'; import { RequestStatistics } from 'src/plugins/inspector/common'; import { SavedObject } from 'src/core/server'; -import { SavedObjectsClientContract as SavedObjectsClientContract_2 } from 'src/core/server'; -import { ScrollParams } from 'elasticsearch'; +import { SavedObjectsClientContract } from 'src/core/server'; import { Search } from '@elastic/elasticsearch/api/requestParams'; -import { SearchParams } from 'elasticsearch'; import { SearchResponse } from 'elasticsearch'; -import { SearchShardsParams } from 'elasticsearch'; -import { SearchTemplateParams } from 'elasticsearch'; import { SerializedFieldFormat as SerializedFieldFormat_2 } from 'src/plugins/expressions/common'; import { ShardsResponse } from 'elasticsearch'; -import { SnapshotCreateParams } from 'elasticsearch'; -import { SnapshotCreateRepositoryParams } from 'elasticsearch'; -import { SnapshotDeleteParams } from 'elasticsearch'; -import { SnapshotDeleteRepositoryParams } from 'elasticsearch'; -import { SnapshotGetParams } from 'elasticsearch'; -import { SnapshotGetRepositoryParams } from 'elasticsearch'; -import { SnapshotRestoreParams } from 'elasticsearch'; -import { SnapshotStatusParams } from 'elasticsearch'; -import { SnapshotVerifyRepositoryParams } from 'elasticsearch'; -import { SuggestParams } from 'elasticsearch'; -import { TasksCancelParams } from 'elasticsearch'; -import { TasksGetParams } from 'elasticsearch'; -import { TasksListParams } from 'elasticsearch'; -import { TermvectorsParams } from 'elasticsearch'; import { ToastInputFields } from 'src/core/public/notifications'; -import { TransportRequestOptions } from '@elastic/elasticsearch/lib/Transport'; -import { TransportRequestParams } from '@elastic/elasticsearch/lib/Transport'; -import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; import { Type } from '@kbn/config-schema'; import { TypeOf } from '@kbn/config-schema'; import { Unit } from '@elastic/datemath'; import { UnwrapPromiseOrReturn } from '@kbn/utility-types'; -import { UpdateDocumentByQueryParams } from 'elasticsearch'; -import { UpdateDocumentParams } from 'elasticsearch'; // Warning: (ae-forgotten-export) The symbol "AggConfigSerialized" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "AggConfigOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -659,7 +536,7 @@ export const indexPatterns: { // // @public (undocumented) export class IndexPatternsFetcher { - constructor(callDataCluster: LegacyAPICaller_2); + constructor(callDataCluster: LegacyAPICaller); getFieldsForTimePattern(options: { pattern: string; metaFields: string[]; @@ -706,8 +583,6 @@ export interface ISearchStart ISearchStrategy; - // Warning: (ae-forgotten-export) The symbol "RequestHandlerContext" needs to be exported by the entry point index.d.ts - // // (undocumented) search: (context: RequestHandlerContext, request: IKibanaSearchRequest, options: ISearchOptions) => Promise; } From c07d9236398353fbf8d250951c5a09931667c37f Mon Sep 17 00:00:00 2001 From: Liza K Date: Wed, 26 Aug 2020 14:05:14 +0300 Subject: [PATCH 21/77] Rely on server timeout in OSS (?) Use UI setting in xpack. --- ...-public.searchinterceptor._constructor_.md | 3 +- ...n-plugins-data-public.searchinterceptor.md | 2 +- src/plugins/data/public/public.api.md | 11 +++--- .../public/search/search_interceptor.test.ts | 15 +++----- .../data/public/search/search_interceptor.ts | 37 +++++++++---------- .../data/public/search/search_service.ts | 21 ++++------- .../public/search/search_interceptor.test.ts | 28 ++++++++------ .../public/search/search_interceptor.ts | 13 +++++-- .../data_enhanced/server/ui_settings.ts | 4 +- 9 files changed, 65 insertions(+), 69 deletions(-) diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor._constructor_.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor._constructor_.md index dd613725470db..4c67639300883 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor._constructor_.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor._constructor_.md @@ -9,7 +9,7 @@ Constructs a new instance of the `SearchInterceptor` class Signature: ```typescript -constructor(deps: SearchInterceptorDeps, searchTimeout?: number); +constructor(deps: SearchInterceptorDeps); ``` ## Parameters @@ -17,5 +17,4 @@ constructor(deps: SearchInterceptorDeps, searchTimeout?: number); | Parameter | Type | Description | | --- | --- | --- | | deps | SearchInterceptorDeps | | -| searchTimeout | number | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md index f2e30a0c04cfc..fd9f23a7f0052 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md @@ -14,7 +14,7 @@ export declare class SearchInterceptor | Constructor | Modifiers | Description | | --- | --- | --- | -| [(constructor)(deps, searchTimeout)](./kibana-plugin-plugins-data-public.searchinterceptor._constructor_.md) | | Constructs a new instance of the SearchInterceptor class | +| [(constructor)(deps)](./kibana-plugin-plugins-data-public.searchinterceptor._constructor_.md) | | Constructs a new instance of the SearchInterceptor class | ## Properties diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index 337139d15f3e6..ced392ca940ba 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -1737,7 +1737,7 @@ export interface SearchError { // // @public (undocumented) export class SearchInterceptor { - constructor(deps: SearchInterceptorDeps, searchTimeout?: number); + constructor(deps: SearchInterceptorDeps); // @internal protected abortController: AbortController; // @internal (undocumented) @@ -1755,11 +1755,10 @@ export class SearchInterceptor { protected runSearch(request: IEsSearchRequest, signal: AbortSignal, strategy?: string): Observable; search(request: IEsSearchRequest, options?: ISearchOptions): Observable; // @internal (undocumented) - protected searchTimeout?: number; - // @internal (undocumented) - protected setSearchTimeout(timeout?: number): void; - // @internal (undocumented) - protected setupTimers(options?: ISearchOptions): { + protected setupTimers({ abortSignal, timeout }: { + abortSignal?: AbortSignal; + timeout?: number; + }): { combinedSignal: AbortSignal; cleanup: () => void; }; diff --git a/src/plugins/data/public/search/search_interceptor.test.ts b/src/plugins/data/public/search/search_interceptor.test.ts index 2eded17bda88c..6f609c14ea17d 100644 --- a/src/plugins/data/public/search/search_interceptor.test.ts +++ b/src/plugins/data/public/search/search_interceptor.test.ts @@ -32,15 +32,12 @@ jest.useFakeTimers(); describe('SearchInterceptor', () => { beforeEach(() => { mockCoreSetup = coreMock.createSetup(); - searchInterceptor = new SearchInterceptor( - { - toasts: mockCoreSetup.notifications.toasts, - startServices: mockCoreSetup.getStartServices(), - uiSettings: mockCoreSetup.uiSettings, - http: mockCoreSetup.http, - }, - 1000 - ); + searchInterceptor = new SearchInterceptor({ + toasts: mockCoreSetup.notifications.toasts, + startServices: mockCoreSetup.getStartServices(), + uiSettings: mockCoreSetup.uiSettings, + http: mockCoreSetup.http, + }); }); describe('search', () => { diff --git a/src/plugins/data/public/search/search_interceptor.ts b/src/plugins/data/public/search/search_interceptor.ts index b43e067ee84ae..e0c8d80b824c8 100644 --- a/src/plugins/data/public/search/search_interceptor.ts +++ b/src/plugins/data/public/search/search_interceptor.ts @@ -18,7 +18,16 @@ */ import { trimEnd } from 'lodash'; -import { BehaviorSubject, throwError, timer, Subscription, defer, from, Observable } from 'rxjs'; +import { + BehaviorSubject, + throwError, + timer, + Subscription, + defer, + from, + Observable, + NEVER, +} from 'rxjs'; import { finalize, filter } from 'rxjs/operators'; import { Toast, CoreStart, ToastsSetup, CoreSetup } from 'kibana/public'; import { getCombinedSignal, AbortError } from '../../common/utils'; @@ -67,17 +76,11 @@ export class SearchInterceptor { */ protected application!: CoreStart['application']; - /** - * @internal - */ - protected searchTimeout?: number; - /* * @internal */ - constructor(protected readonly deps: SearchInterceptorDeps, searchTimeout?: number) { + constructor(protected readonly deps: SearchInterceptorDeps) { this.deps.http.addLoadingCountSource(this.pendingCount$); - this.searchTimeout = searchTimeout; this.deps.startServices.then(([coreStart]) => { this.application = coreStart.application; @@ -89,14 +92,6 @@ export class SearchInterceptor { .pipe(filter((count) => count === 0)) .subscribe(this.hideToast); } - - /** - * @internal - */ - protected setSearchTimeout(timeout?: number) { - this.searchTimeout = timeout; - } - /** * Returns an `Observable` over the current number of pending searches. This could mean that one * of the search requests is still in flight, or that it has only received partial responses. @@ -141,7 +136,9 @@ export class SearchInterceptor { return throwError(new AbortError()); } - const { combinedSignal, cleanup } = this.setupTimers(options); + const { combinedSignal, cleanup } = this.setupTimers({ + abortSignal: options?.signal, + }); this.pendingCount$.next(this.pendingCount$.getValue() + 1); return this.runSearch(request, combinedSignal, options?.strategy).pipe( @@ -156,11 +153,11 @@ export class SearchInterceptor { /** * @internal */ - protected setupTimers(options?: ISearchOptions) { + protected setupTimers({ abortSignal, timeout }: { abortSignal?: AbortSignal; timeout?: number }) { // Schedule this request to automatically timeout after some interval const timeoutController = new AbortController(); const { signal: timeoutSignal } = timeoutController; - const timeout$ = timer(this.searchTimeout); + const timeout$ = timeout ? timer(timeout) : NEVER; const subscription = timeout$.subscribe(() => { timeoutController.abort(); }); @@ -176,7 +173,7 @@ export class SearchInterceptor { const signals = [ this.abortController.signal, timeoutSignal, - ...(options?.signal ? [options.signal] : []), + ...(abortSignal ? [abortSignal] : []), ]; const combinedSignal = getCombinedSignal(signals); diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts index 8caa4b3b0dd67..f90fb82788389 100644 --- a/src/plugins/data/public/search/search_service.ts +++ b/src/plugins/data/public/search/search_service.ts @@ -51,26 +51,19 @@ export class SearchService implements Plugin { { http, getStartServices, injectedMetadata, notifications, uiSettings }: CoreSetup, { expressions, usageCollection }: SearchServiceSetupDependencies ): ISearchSetup { - const esRequestTimeout = injectedMetadata.getInjectedVar('esRequestTimeout') as number; - this.usageCollector = createUsageCollector(getStartServices, usageCollection); /** * A global object that intercepts all searches and provides convenience methods for cancelling * all pending search requests, as well as getting the number of pending search requests. - * TODO: Make this modular so that apps can opt in/out of search collection, or even provide - * their own search collector instances */ - this.searchInterceptor = new SearchInterceptor( - { - toasts: notifications.toasts, - http, - uiSettings, - startServices: getStartServices(), - usageCollector: this.usageCollector!, - }, - esRequestTimeout - ); + this.searchInterceptor = new SearchInterceptor({ + toasts: notifications.toasts, + http, + uiSettings, + startServices: getStartServices(), + usageCollector: this.usageCollector!, + }); expressions.registerFunction(esdsl); expressions.registerType(esRawResponse); diff --git a/x-pack/plugins/data_enhanced/public/search/search_interceptor.test.ts b/x-pack/plugins/data_enhanced/public/search/search_interceptor.test.ts index fe954f1602cd3..df19352463648 100644 --- a/x-pack/plugins/data_enhanced/public/search/search_interceptor.test.ts +++ b/x-pack/plugins/data_enhanced/public/search/search_interceptor.test.ts @@ -7,7 +7,7 @@ import { coreMock } from '../../../../../src/core/public/mocks'; import { EnhancedSearchInterceptor } from './search_interceptor'; import { CoreSetup, CoreStart } from 'kibana/public'; -import { AbortError } from '../../../../../src/plugins/data/common'; +import { AbortError, UI_SETTINGS } from '../../../../../src/plugins/data/common'; const timeTravel = (msToRun = 0) => { jest.advanceTimersByTime(msToRun); @@ -43,6 +43,15 @@ describe('EnhancedSearchInterceptor', () => { mockCoreSetup = coreMock.createSetup(); mockCoreStart = coreMock.createStart(); + mockCoreSetup.uiSettings.get.mockImplementation((name: string) => { + switch (name) { + case UI_SETTINGS.SEARCH_TIMEOUT: + return 1000; + default: + return; + } + }); + next.mockClear(); error.mockClear(); complete.mockClear(); @@ -64,16 +73,13 @@ describe('EnhancedSearchInterceptor', () => { ]); }); - searchInterceptor = new EnhancedSearchInterceptor( - { - toasts: mockCoreSetup.notifications.toasts, - startServices: mockPromise as any, - http: mockCoreSetup.http, - uiSettings: mockCoreSetup.uiSettings, - usageCollector: mockUsageCollector, - }, - 1000 - ); + searchInterceptor = new EnhancedSearchInterceptor({ + toasts: mockCoreSetup.notifications.toasts, + startServices: mockPromise as any, + http: mockCoreSetup.http, + uiSettings: mockCoreSetup.uiSettings, + usageCollector: mockUsageCollector, + }); }); describe('search', () => { diff --git a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts index c484cf347317b..3fd35d3449bb5 100644 --- a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts +++ b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts @@ -18,17 +18,19 @@ import { IAsyncSearchRequest, ENHANCED_ES_SEARCH_STRATEGY } from '../../common'; export class EnhancedSearchInterceptor extends SearchInterceptor { private uiSettingsSub: Subscription; + private searchTimeout: number; /** * @internal */ constructor(deps: SearchInterceptorDeps) { - super(deps, deps.uiSettings.get(UI_SETTINGS.SEARCH_TIMEOUT)); + super(deps); + this.searchTimeout = deps.uiSettings.get(UI_SETTINGS.SEARCH_TIMEOUT); this.uiSettingsSub = deps.uiSettings .get$(UI_SETTINGS.SEARCH_TIMEOUT) .subscribe((timeout: number) => { - this.setSearchTimeout(timeout); + this.searchTimeout = timeout; }); } @@ -83,7 +85,10 @@ export class EnhancedSearchInterceptor extends SearchInterceptor { ...request.params, }; - const { combinedSignal, cleanup } = this.setupTimers(options); + const { combinedSignal, cleanup } = this.setupTimers({ + abortSignal: options.signal, + timeout: this.searchTimeout, + }); const aborted$ = from(toPromise(combinedSignal)); const strategy = options?.strategy || ENHANCED_ES_SEARCH_STRATEGY; @@ -117,7 +122,7 @@ export class EnhancedSearchInterceptor extends SearchInterceptor { // we don't need to send a follow-up request to delete this search. Otherwise, we // send the follow-up request to delete this search, then throw an abort error. if (id !== undefined) { - this.deps.http.delete(`/internal/search/es/${id}`); + this.deps.http.delete(`/internal/search/${strategy}/${id}`); } }, }), diff --git a/x-pack/plugins/data_enhanced/server/ui_settings.ts b/x-pack/plugins/data_enhanced/server/ui_settings.ts index 76b84a7d09fee..f2842da8b8337 100644 --- a/x-pack/plugins/data_enhanced/server/ui_settings.ts +++ b/x-pack/plugins/data_enhanced/server/ui_settings.ts @@ -12,11 +12,11 @@ import { UI_SETTINGS } from '../../../../src/plugins/data/server'; export function getUiSettings(): Record> { return { [UI_SETTINGS.SEARCH_TIMEOUT]: { - name: i18n.translate('kbn.advancedSettings.searchTimeout', { + name: i18n.translate('xpack.data.advancedSettings.searchTimeout', { defaultMessage: 'Search Timeout', }), value: 600000, - description: i18n.translate('kbn.advancedSettings.searchTimeoutDesc', { + description: i18n.translate('xpack.data.advancedSettings.searchTimeoutDesc', { defaultMessage: 'Change the maximum timeout for a search session or set to 0 to disable the timeout and allow queries to run to completion.', }), From 8c75c64c9c3ba5084d09721fa852d25541266498 Mon Sep 17 00:00:00 2001 From: Liza K Date: Wed, 26 Aug 2020 18:19:12 +0300 Subject: [PATCH 22/77] Rename function --- src/plugins/data/public/public.api.md | 2 +- src/plugins/data/public/search/search_interceptor.ts | 10 ++++++++-- .../data_enhanced/public/search/search_interceptor.ts | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index ced392ca940ba..de0a3399dc96b 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -1755,7 +1755,7 @@ export class SearchInterceptor { protected runSearch(request: IEsSearchRequest, signal: AbortSignal, strategy?: string): Observable; search(request: IEsSearchRequest, options?: ISearchOptions): Observable; // @internal (undocumented) - protected setupTimers({ abortSignal, timeout }: { + protected setupAbortSignal({ abortSignal, timeout }: { abortSignal?: AbortSignal; timeout?: number; }): { diff --git a/src/plugins/data/public/search/search_interceptor.ts b/src/plugins/data/public/search/search_interceptor.ts index e0c8d80b824c8..4206779540972 100644 --- a/src/plugins/data/public/search/search_interceptor.ts +++ b/src/plugins/data/public/search/search_interceptor.ts @@ -136,7 +136,7 @@ export class SearchInterceptor { return throwError(new AbortError()); } - const { combinedSignal, cleanup } = this.setupTimers({ + const { combinedSignal, cleanup } = this.setupAbortSignal({ abortSignal: options?.signal, }); this.pendingCount$.next(this.pendingCount$.getValue() + 1); @@ -153,7 +153,13 @@ export class SearchInterceptor { /** * @internal */ - protected setupTimers({ abortSignal, timeout }: { abortSignal?: AbortSignal; timeout?: number }) { + protected setupAbortSignal({ + abortSignal, + timeout, + }: { + abortSignal?: AbortSignal; + timeout?: number; + }) { // Schedule this request to automatically timeout after some interval const timeoutController = new AbortController(); const { signal: timeoutSignal } = timeoutController; diff --git a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts index 3fd35d3449bb5..d226b949e26b0 100644 --- a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts +++ b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts @@ -85,7 +85,7 @@ export class EnhancedSearchInterceptor extends SearchInterceptor { ...request.params, }; - const { combinedSignal, cleanup } = this.setupTimers({ + const { combinedSignal, cleanup } = this.setupAbortSignal({ abortSignal: options.signal, timeout: this.searchTimeout, }); From 742f3bae1970332469ceb5a07e78e5d1c5efb560 Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Wed, 26 Aug 2020 10:48:59 -0700 Subject: [PATCH 23/77] Add features to dependencies --- x-pack/plugins/data_enhanced/kibana.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/data_enhanced/kibana.json b/x-pack/plugins/data_enhanced/kibana.json index b3e438e2a356e..5ded0f8f0dec3 100644 --- a/x-pack/plugins/data_enhanced/kibana.json +++ b/x-pack/plugins/data_enhanced/kibana.json @@ -6,7 +6,8 @@ "xpack", "data_enhanced" ], "requiredPlugins": [ - "data" + "data", + "features" ], "optionalPlugins": ["kibanaUtils", "usageCollection"], "server": true, From 4056f40ea1fb67dde430604199e422107f19a6f1 Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Wed, 26 Aug 2020 11:10:42 -0700 Subject: [PATCH 24/77] Undefined check --- .../plugins/data_enhanced/public/search/search_interceptor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts index 0babc6913629f..1d40b38bf8696 100644 --- a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts +++ b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts @@ -95,7 +95,7 @@ export class EnhancedSearchInterceptor extends SearchInterceptor { // error notification per session. protected showTimeoutError = debounce( (e: Error) => { - const message = this.application.capabilities.advancedSettings.save + const message = this.application.capabilities.advancedSettings?.save ? 'Increase the advanced setting timeout to ensure queries can run to completion.' : 'Contact an administrator to increase the advanced setting.'; this.deps.toasts.addError(e, { From 059706ecebff65e39c8fe1a2af741cf9c304859e Mon Sep 17 00:00:00 2001 From: Liza K Date: Thu, 27 Aug 2020 11:34:09 +0300 Subject: [PATCH 25/77] doc --- src/plugins/data/public/public.api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index de0a3399dc96b..ce91c914f6bd6 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -1755,7 +1755,7 @@ export class SearchInterceptor { protected runSearch(request: IEsSearchRequest, signal: AbortSignal, strategy?: string): Observable; search(request: IEsSearchRequest, options?: ISearchOptions): Observable; // @internal (undocumented) - protected setupAbortSignal({ abortSignal, timeout }: { + protected setupAbortSignal({ abortSignal, timeout, }: { abortSignal?: AbortSignal; timeout?: number; }): { From 260d23c63abf3db9325cb362d90e3cc97bc7eea8 Mon Sep 17 00:00:00 2001 From: Liza K Date: Thu, 27 Aug 2020 12:41:08 +0300 Subject: [PATCH 26/77] Code review fixes --- src/plugins/data/public/search/fetch/types.ts | 2 ++ .../search/legacy/default_search_strategy.ts | 15 +++++---------- .../data/public/search/search_interceptor.ts | 5 +++-- src/plugins/data/public/search/search_service.ts | 6 ++++++ .../public/search/search_source/search_source.ts | 6 +++++- 5 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/plugins/data/public/search/fetch/types.ts b/src/plugins/data/public/search/fetch/types.ts index ec10961225efa..7560f2516bbc6 100644 --- a/src/plugins/data/public/search/fetch/types.ts +++ b/src/plugins/data/public/search/fetch/types.ts @@ -19,6 +19,7 @@ import { HttpStart } from 'src/core/public'; import { GetConfigFn } from '../../../common'; +import { BehaviorSubject } from 'rxjs'; /** * @internal @@ -37,6 +38,7 @@ export interface FetchOptions { export interface FetchHandlers { config: { get: GetConfigFn }; http: HttpStart; + loadingCount$: BehaviorSubject; } export interface SearchError { diff --git a/src/plugins/data/public/search/legacy/default_search_strategy.ts b/src/plugins/data/public/search/legacy/default_search_strategy.ts index 8e45715b7cc38..d491846d8929c 100644 --- a/src/plugins/data/public/search/legacy/default_search_strategy.ts +++ b/src/plugins/data/public/search/legacy/default_search_strategy.ts @@ -17,8 +17,6 @@ * under the License. */ -import { BehaviorSubject } from 'rxjs'; - import { getPreference } from '../fetch'; import { SearchStrategyProvider, SearchStrategySearchParams } from './types'; @@ -31,7 +29,7 @@ export const defaultSearchStrategy: SearchStrategyProvider = { }, }; -function msearch({ searchRequests, config, http }: SearchStrategySearchParams) { +function msearch({ searchRequests, config, http, loadingCount$ }: SearchStrategySearchParams) { const requests = searchRequests.map(({ index, body }) => { return { header: { @@ -45,9 +43,6 @@ function msearch({ searchRequests, config, http }: SearchStrategySearchParams) { const abortController = new AbortController(); let resolved = false; - const loadingCount$ = new BehaviorSubject(0); - http.addLoadingCountSource(loadingCount$); - // Start LoadingIndicator loadingCount$.next(loadingCount$.getValue() + 1); @@ -63,15 +58,15 @@ function msearch({ searchRequests, config, http }: SearchStrategySearchParams) { const searching = http.post('/internal/_msearch', { body: JSON.stringify({ searches: requests }), signal: abortController.signal, - }); - - searching.finally(() => cleanup()); + }) + .then(({ body }) => body?.responses) + .finally(() => cleanup()); return { abort: () => { abortController.abort(); cleanup(); }, - searching: searching.then(({ body }) => body?.responses), + searching, }; } diff --git a/src/plugins/data/public/search/search_interceptor.ts b/src/plugins/data/public/search/search_interceptor.ts index 30e509edd4987..51f7039a694eb 100644 --- a/src/plugins/data/public/search/search_interceptor.ts +++ b/src/plugins/data/public/search/search_interceptor.ts @@ -34,6 +34,7 @@ export interface SearchInterceptorDeps { http: CoreSetup['http']; uiSettings: CoreSetup['uiSettings']; startServices: Promise<[CoreStart, any, unknown]>; + loadingCount$: BehaviorSubject; usageCollector?: SearchUsageCollector; } @@ -48,7 +49,7 @@ export class SearchInterceptor { * Observable that emits when the number of pending requests changes. * @internal */ - protected pendingCount$ = new BehaviorSubject(0); + protected pendingCount$!: BehaviorSubject; /** * The subscriptions from scheduling the automatic timeout for each request. @@ -78,7 +79,7 @@ export class SearchInterceptor { protected readonly deps: SearchInterceptorDeps, protected readonly requestTimeout?: number ) { - this.deps.http.addLoadingCountSource(this.pendingCount$); + this.pendingCount$ = deps.loadingCount$; this.deps.startServices.then(([coreStart]) => { this.application = coreStart.application; diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts index 8caa4b3b0dd67..6d6bfad9a36be 100644 --- a/src/plugins/data/public/search/search_service.ts +++ b/src/plugins/data/public/search/search_service.ts @@ -29,6 +29,7 @@ import { SearchUsageCollector, createUsageCollector } from './collectors'; import { UsageCollectionSetup } from '../../../usage_collection/public'; import { esdsl, esRawResponse } from './expressions'; import { ExpressionsSetup } from '../../../expressions/public'; +import { BehaviorSubject } from 'rxjs'; /** @internal */ export interface SearchServiceSetupDependencies { @@ -46,6 +47,7 @@ export class SearchService implements Plugin { private readonly aggsService = new AggsService(); private searchInterceptor!: ISearchInterceptor; private usageCollector?: SearchUsageCollector; + private loadingCount$!: BehaviorSubject; public setup( { http, getStartServices, injectedMetadata, notifications, uiSettings }: CoreSetup, @@ -55,6 +57,8 @@ export class SearchService implements Plugin { this.usageCollector = createUsageCollector(getStartServices, usageCollection); + this.loadingCount$ = new BehaviorSubject(0); + /** * A global object that intercepts all searches and provides convenience methods for cancelling * all pending search requests, as well as getting the number of pending search requests. @@ -65,6 +69,7 @@ export class SearchService implements Plugin { { toasts: notifications.toasts, http, + loadingCount$: this.loadingCount$, uiSettings, startServices: getStartServices(), usageCollector: this.usageCollector!, @@ -101,6 +106,7 @@ export class SearchService implements Plugin { esShardTimeout: injectedMetadata.getInjectedVar('esShardTimeout') as number, search, http, + loadingCount$: this.loadingCount$, }; return { diff --git a/src/plugins/data/public/search/search_source/search_source.ts b/src/plugins/data/public/search/search_source/search_source.ts index 2bd66abca80d4..141649b071f05 100644 --- a/src/plugins/data/public/search/search_source/search_source.ts +++ b/src/plugins/data/public/search/search_source/search_source.ts @@ -91,6 +91,7 @@ import { getHighlightRequest } from '../../../common/field_formats'; import { GetConfigFn } from '../../../common/types'; import { fetchSoon } from '../legacy'; import { extractReferences } from './extract_references'; +import { BehaviorSubject } from 'rxjs'; /** @internal */ export const searchSourceRequiredUiSettings = [ @@ -113,6 +114,8 @@ export interface SearchSourceDependencies { search: ISearchGeneric; http: HttpStart; esShardTimeout: number; + loadingCount$: BehaviorSubject; + } /** @public **/ @@ -243,7 +246,7 @@ export class SearchSource { * @return {Promise>} */ private async legacyFetch(searchRequest: SearchRequest, options: FetchOptions) { - const { http, getConfig } = this.dependencies; + const { http, getConfig, loadingCount$ } = this.dependencies; return await fetchSoon( searchRequest, @@ -254,6 +257,7 @@ export class SearchSource { { http, config: { get: getConfig }, + loadingCount$, } ); } From 9540e4c3762d3a8f57b5b9261c7fe23d5bb626d6 Mon Sep 17 00:00:00 2001 From: Liza K Date: Thu, 27 Aug 2020 12:42:30 +0300 Subject: [PATCH 27/77] code review --- src/plugins/data/public/search/fetch/types.ts | 2 +- .../public/search/legacy/default_search_strategy.ts | 13 +++++++------ src/plugins/data/public/search/search_service.ts | 2 +- .../public/search/search_source/search_source.ts | 3 +-- src/plugins/data/server/search/routes/msearch.ts | 3 +-- 5 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/plugins/data/public/search/fetch/types.ts b/src/plugins/data/public/search/fetch/types.ts index 7560f2516bbc6..9ac4d0044c24d 100644 --- a/src/plugins/data/public/search/fetch/types.ts +++ b/src/plugins/data/public/search/fetch/types.ts @@ -18,8 +18,8 @@ */ import { HttpStart } from 'src/core/public'; -import { GetConfigFn } from '../../../common'; import { BehaviorSubject } from 'rxjs'; +import { GetConfigFn } from '../../../common'; /** * @internal diff --git a/src/plugins/data/public/search/legacy/default_search_strategy.ts b/src/plugins/data/public/search/legacy/default_search_strategy.ts index d491846d8929c..cbcd0da20207f 100644 --- a/src/plugins/data/public/search/legacy/default_search_strategy.ts +++ b/src/plugins/data/public/search/legacy/default_search_strategy.ts @@ -55,12 +55,13 @@ function msearch({ searchRequests, config, http, loadingCount$ }: SearchStrategy } }; - const searching = http.post('/internal/_msearch', { - body: JSON.stringify({ searches: requests }), - signal: abortController.signal, - }) - .then(({ body }) => body?.responses) - .finally(() => cleanup()); + const searching = http + .post('/internal/_msearch', { + body: JSON.stringify({ searches: requests }), + signal: abortController.signal, + }) + .then(({ body }) => body?.responses) + .finally(() => cleanup()); return { abort: () => { diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts index 6d6bfad9a36be..7ea800b9d819c 100644 --- a/src/plugins/data/public/search/search_service.ts +++ b/src/plugins/data/public/search/search_service.ts @@ -18,6 +18,7 @@ */ import { Plugin, CoreSetup, CoreStart } from 'src/core/public'; +import { BehaviorSubject } from 'rxjs'; import { ISearchSetup, ISearchStart, SearchEnhancements } from './types'; import { createSearchSource, SearchSource, SearchSourceDependencies } from './search_source'; @@ -29,7 +30,6 @@ import { SearchUsageCollector, createUsageCollector } from './collectors'; import { UsageCollectionSetup } from '../../../usage_collection/public'; import { esdsl, esRawResponse } from './expressions'; import { ExpressionsSetup } from '../../../expressions/public'; -import { BehaviorSubject } from 'rxjs'; /** @internal */ export interface SearchServiceSetupDependencies { diff --git a/src/plugins/data/public/search/search_source/search_source.ts b/src/plugins/data/public/search/search_source/search_source.ts index 141649b071f05..7b07c37429378 100644 --- a/src/plugins/data/public/search/search_source/search_source.ts +++ b/src/plugins/data/public/search/search_source/search_source.ts @@ -73,6 +73,7 @@ import { setWith } from '@elastic/safer-lodash-set'; import { uniqueId, uniq, extend, pick, difference, omit, isObject, keys, isFunction } from 'lodash'; import { map } from 'rxjs/operators'; import { HttpStart } from 'src/core/public'; +import { BehaviorSubject } from 'rxjs'; import { normalizeSortRequest } from './normalize_sort_request'; import { filterDocvalueFields } from './filter_docvalue_fields'; import { fieldWildcardFilter } from '../../../../kibana_utils/common'; @@ -91,7 +92,6 @@ import { getHighlightRequest } from '../../../common/field_formats'; import { GetConfigFn } from '../../../common/types'; import { fetchSoon } from '../legacy'; import { extractReferences } from './extract_references'; -import { BehaviorSubject } from 'rxjs'; /** @internal */ export const searchSourceRequiredUiSettings = [ @@ -115,7 +115,6 @@ export interface SearchSourceDependencies { http: HttpStart; esShardTimeout: number; loadingCount$: BehaviorSubject; - } /** @public **/ diff --git a/src/plugins/data/server/search/routes/msearch.ts b/src/plugins/data/server/search/routes/msearch.ts index dce2fb0f30e8f..c854a06b6b0dd 100644 --- a/src/plugins/data/server/search/routes/msearch.ts +++ b/src/plugins/data/server/search/routes/msearch.ts @@ -53,8 +53,7 @@ export function convertRequestBody( timeout, ...curr.body, }); - req += `${header}\n${body}\n`; - return req; + return `${req}${header}\n${body}\n`; }, ''); } From 6de42057aacf553fb4961bd622589761fd8bd2ed Mon Sep 17 00:00:00 2001 From: Liza K Date: Thu, 27 Aug 2020 12:48:45 +0300 Subject: [PATCH 28/77] doc --- ...data-public.searchinterceptordeps.loadingcount_.md | 11 +++++++++++ ...lugin-plugins-data-public.searchinterceptordeps.md | 1 + src/plugins/data/public/public.api.md | 2 ++ 3 files changed, 14 insertions(+) create mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.loadingcount_.md diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.loadingcount_.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.loadingcount_.md new file mode 100644 index 0000000000000..516ba8c11ee00 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.loadingcount_.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchInterceptorDeps](./kibana-plugin-plugins-data-public.searchinterceptordeps.md) > [loadingCount$](./kibana-plugin-plugins-data-public.searchinterceptordeps.loadingcount_.md) + +## SearchInterceptorDeps.loadingCount$ property + +Signature: + +```typescript +loadingCount$: BehaviorSubject; +``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.md index 63eb67ce48246..fb2090af5f3cc 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.md @@ -15,6 +15,7 @@ export interface SearchInterceptorDeps | Property | Type | Description | | --- | --- | --- | | [http](./kibana-plugin-plugins-data-public.searchinterceptordeps.http.md) | CoreSetup['http'] | | +| [loadingCount$](./kibana-plugin-plugins-data-public.searchinterceptordeps.loadingcount_.md) | BehaviorSubject<number> | | | [startServices](./kibana-plugin-plugins-data-public.searchinterceptordeps.startservices.md) | Promise<[CoreStart, any, unknown]> | | | [toasts](./kibana-plugin-plugins-data-public.searchinterceptordeps.toasts.md) | ToastsSetup | | | [uiSettings](./kibana-plugin-plugins-data-public.searchinterceptordeps.uisettings.md) | CoreSetup['uiSettings'] | | diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index 31c8279f91bcd..a44f4fd6c2c8c 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -1774,6 +1774,8 @@ export interface SearchInterceptorDeps { // (undocumented) http: CoreSetup_2['http']; // (undocumented) + loadingCount$: BehaviorSubject; + // (undocumented) startServices: Promise<[CoreStart, any, unknown]>; // (undocumented) toasts: ToastsSetup; From 5049b35f0cbae4fccda14f47624ee8aaa35b6d37 Mon Sep 17 00:00:00 2001 From: Liza K Date: Thu, 27 Aug 2020 12:59:15 +0300 Subject: [PATCH 29/77] loading count --- x-pack/plugins/data_enhanced/public/plugin.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x-pack/plugins/data_enhanced/public/plugin.ts b/x-pack/plugins/data_enhanced/public/plugin.ts index 7f6e3feac0671..e76a2af25cca3 100644 --- a/x-pack/plugins/data_enhanced/public/plugin.ts +++ b/x-pack/plugins/data_enhanced/public/plugin.ts @@ -5,6 +5,7 @@ */ import { CoreSetup, CoreStart, Plugin } from 'src/core/public'; +import { BehaviorSubject } from 'rxjs'; import { DataPublicPluginSetup, DataPublicPluginStart } from '../../../../src/plugins/data/public'; import { setAutocompleteService } from './services'; import { setupKqlQuerySuggestionProvider, KUERY_LANGUAGE_NAME } from './autocomplete'; @@ -39,6 +40,7 @@ export class DataEnhancedPlugin uiSettings: core.uiSettings, startServices: core.getStartServices(), usageCollector: data.search.usageCollector, + loadingCount$: new BehaviorSubject(0), }, core.injectedMetadata.getInjectedVar('esRequestTimeout') as number ); From 002c13c6c3dac2c5844f2594dbb268fbe75770be Mon Sep 17 00:00:00 2001 From: Liza K Date: Thu, 27 Aug 2020 13:31:37 +0300 Subject: [PATCH 30/77] simplify code review and fix jest tets --- ...data-public.searchinterceptordeps.loadingcount_.md | 11 ----------- ...lugin-plugins-data-public.searchinterceptordeps.md | 1 - src/plugins/data/public/public.api.md | 2 -- .../data/public/search/legacy/call_client.test.ts | 2 ++ .../search/legacy/default_search_strategy.test.ts | 2 ++ src/plugins/data/public/search/search_interceptor.ts | 5 ++--- src/plugins/data/public/search/search_service.ts | 9 ++++----- .../search/search_source/create_search_source.test.ts | 2 ++ src/plugins/data/public/search/search_source/mocks.ts | 2 ++ .../public/search/search_source/search_source.test.ts | 3 ++- x-pack/plugins/data_enhanced/public/plugin.ts | 1 - 11 files changed, 16 insertions(+), 24 deletions(-) delete mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.loadingcount_.md diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.loadingcount_.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.loadingcount_.md deleted file mode 100644 index 516ba8c11ee00..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.loadingcount_.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchInterceptorDeps](./kibana-plugin-plugins-data-public.searchinterceptordeps.md) > [loadingCount$](./kibana-plugin-plugins-data-public.searchinterceptordeps.loadingcount_.md) - -## SearchInterceptorDeps.loadingCount$ property - -Signature: - -```typescript -loadingCount$: BehaviorSubject; -``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.md index fb2090af5f3cc..63eb67ce48246 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptordeps.md @@ -15,7 +15,6 @@ export interface SearchInterceptorDeps | Property | Type | Description | | --- | --- | --- | | [http](./kibana-plugin-plugins-data-public.searchinterceptordeps.http.md) | CoreSetup['http'] | | -| [loadingCount$](./kibana-plugin-plugins-data-public.searchinterceptordeps.loadingcount_.md) | BehaviorSubject<number> | | | [startServices](./kibana-plugin-plugins-data-public.searchinterceptordeps.startservices.md) | Promise<[CoreStart, any, unknown]> | | | [toasts](./kibana-plugin-plugins-data-public.searchinterceptordeps.toasts.md) | ToastsSetup | | | [uiSettings](./kibana-plugin-plugins-data-public.searchinterceptordeps.uisettings.md) | CoreSetup['uiSettings'] | | diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index a44f4fd6c2c8c..31c8279f91bcd 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -1774,8 +1774,6 @@ export interface SearchInterceptorDeps { // (undocumented) http: CoreSetup_2['http']; // (undocumented) - loadingCount$: BehaviorSubject; - // (undocumented) startServices: Promise<[CoreStart, any, unknown]>; // (undocumented) toasts: ToastsSetup; diff --git a/src/plugins/data/public/search/legacy/call_client.test.ts b/src/plugins/data/public/search/legacy/call_client.test.ts index f0f36856e1b9a..38f3ab200da90 100644 --- a/src/plugins/data/public/search/legacy/call_client.test.ts +++ b/src/plugins/data/public/search/legacy/call_client.test.ts @@ -23,6 +23,7 @@ import { SearchStrategySearchParams } from './types'; import { defaultSearchStrategy } from './default_search_strategy'; import { FetchHandlers } from '../fetch'; import { handleResponse } from '../fetch/handle_response'; +import { BehaviorSubject } from 'rxjs'; const mockAbortFn = jest.fn(); jest.mock('../fetch/handle_response', () => ({ @@ -60,6 +61,7 @@ describe('callClient', () => { legacySearchService: {}, config: { get: jest.fn() }, esShardTimeout: 0, + loadingCount$: new BehaviorSubject(0), } as FetchHandlers; callClient(searchRequests, [], args); diff --git a/src/plugins/data/public/search/legacy/default_search_strategy.test.ts b/src/plugins/data/public/search/legacy/default_search_strategy.test.ts index e0916b23a4b48..e74ab49131430 100644 --- a/src/plugins/data/public/search/legacy/default_search_strategy.test.ts +++ b/src/plugins/data/public/search/legacy/default_search_strategy.test.ts @@ -21,6 +21,7 @@ import { HttpStart } from 'src/core/public'; import { coreMock } from '../../../../../core/public/mocks'; import { defaultSearchStrategy } from './default_search_strategy'; import { SearchStrategySearchParams } from './types'; +import { BehaviorSubject } from 'rxjs'; const { search } = defaultSearchStrategy; @@ -47,6 +48,7 @@ describe('defaultSearchStrategy', function () { config: { get: jest.fn(), }, + loadingCount$: new BehaviorSubject(0) as any, }; }); diff --git a/src/plugins/data/public/search/search_interceptor.ts b/src/plugins/data/public/search/search_interceptor.ts index 51f7039a694eb..30e509edd4987 100644 --- a/src/plugins/data/public/search/search_interceptor.ts +++ b/src/plugins/data/public/search/search_interceptor.ts @@ -34,7 +34,6 @@ export interface SearchInterceptorDeps { http: CoreSetup['http']; uiSettings: CoreSetup['uiSettings']; startServices: Promise<[CoreStart, any, unknown]>; - loadingCount$: BehaviorSubject; usageCollector?: SearchUsageCollector; } @@ -49,7 +48,7 @@ export class SearchInterceptor { * Observable that emits when the number of pending requests changes. * @internal */ - protected pendingCount$!: BehaviorSubject; + protected pendingCount$ = new BehaviorSubject(0); /** * The subscriptions from scheduling the automatic timeout for each request. @@ -79,7 +78,7 @@ export class SearchInterceptor { protected readonly deps: SearchInterceptorDeps, protected readonly requestTimeout?: number ) { - this.pendingCount$ = deps.loadingCount$; + this.deps.http.addLoadingCountSource(this.pendingCount$); this.deps.startServices.then(([coreStart]) => { this.application = coreStart.application; diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts index 7ea800b9d819c..a49d2ef0956ff 100644 --- a/src/plugins/data/public/search/search_service.ts +++ b/src/plugins/data/public/search/search_service.ts @@ -47,7 +47,6 @@ export class SearchService implements Plugin { private readonly aggsService = new AggsService(); private searchInterceptor!: ISearchInterceptor; private usageCollector?: SearchUsageCollector; - private loadingCount$!: BehaviorSubject; public setup( { http, getStartServices, injectedMetadata, notifications, uiSettings }: CoreSetup, @@ -57,8 +56,6 @@ export class SearchService implements Plugin { this.usageCollector = createUsageCollector(getStartServices, usageCollection); - this.loadingCount$ = new BehaviorSubject(0); - /** * A global object that intercepts all searches and provides convenience methods for cancelling * all pending search requests, as well as getting the number of pending search requests. @@ -69,7 +66,6 @@ export class SearchService implements Plugin { { toasts: notifications.toasts, http, - loadingCount$: this.loadingCount$, uiSettings, startServices: getStartServices(), usageCollector: this.usageCollector!, @@ -100,13 +96,16 @@ export class SearchService implements Plugin { return this.searchInterceptor.search(request, options); }) as ISearchGeneric; + const loadingCount$ = new BehaviorSubject(0); + http.addLoadingCountSource(loadingCount$); + const searchSourceDependencies: SearchSourceDependencies = { getConfig: uiSettings.get.bind(uiSettings), // TODO: we don't need this, apply on the server esShardTimeout: injectedMetadata.getInjectedVar('esShardTimeout') as number, search, http, - loadingCount$: this.loadingCount$, + loadingCount$, }; return { diff --git a/src/plugins/data/public/search/search_source/create_search_source.test.ts b/src/plugins/data/public/search/search_source/create_search_source.test.ts index 1300c67d3c0fc..2820aab67ea3a 100644 --- a/src/plugins/data/public/search/search_source/create_search_source.test.ts +++ b/src/plugins/data/public/search/search_source/create_search_source.test.ts @@ -23,6 +23,7 @@ import { IIndexPattern } from '../../../common/index_patterns'; import { IndexPatternsContract } from '../../index_patterns/index_patterns'; import { Filter } from '../../../common/es_query/filters'; import { coreMock } from '../../../../../core/public/mocks'; +import { BehaviorSubject } from 'rxjs'; describe('createSearchSource', () => { const indexPatternMock: IIndexPattern = {} as IIndexPattern; @@ -36,6 +37,7 @@ describe('createSearchSource', () => { search: jest.fn(), esShardTimeout: 30000, http: coreMock.createStart().http, + loadingCount$: new BehaviorSubject(0), }; indexPatternContractMock = ({ diff --git a/src/plugins/data/public/search/search_source/mocks.ts b/src/plugins/data/public/search/search_source/mocks.ts index 16f665994e3bd..bc3e287d9fe80 100644 --- a/src/plugins/data/public/search/search_source/mocks.ts +++ b/src/plugins/data/public/search/search_source/mocks.ts @@ -17,6 +17,7 @@ * under the License. */ +import { BehaviorSubject } from 'rxjs'; import { httpServiceMock, uiSettingsServiceMock } from '../../../../../core/public/mocks'; import { ISearchSource, SearchSource } from './search_source'; @@ -55,4 +56,5 @@ export const createSearchSourceMock = (fields?: SearchSourceFields) => esShardTimeout: 30000, search: jest.fn(), http: httpServiceMock.createStartContract(), + loadingCount$: new BehaviorSubject(0), }); diff --git a/src/plugins/data/public/search/search_source/search_source.test.ts b/src/plugins/data/public/search/search_source/search_source.test.ts index a5bf700624a33..a8baed9faa84d 100644 --- a/src/plugins/data/public/search/search_source/search_source.test.ts +++ b/src/plugins/data/public/search/search_source/search_source.test.ts @@ -17,7 +17,7 @@ * under the License. */ -import { Observable } from 'rxjs'; +import { Observable, BehaviorSubject } from 'rxjs'; import { GetConfigFn } from 'src/plugins/data/common'; import { SearchSource, SearchSourceDependencies } from './search_source'; import { IndexPattern, SortDirection } from '../..'; @@ -70,6 +70,7 @@ describe('SearchSource', () => { search: mockSearchMethod, esShardTimeout: 30000, http: coreMock.createStart().http, + loadingCount$: new BehaviorSubject(0), }; }); diff --git a/x-pack/plugins/data_enhanced/public/plugin.ts b/x-pack/plugins/data_enhanced/public/plugin.ts index e76a2af25cca3..34973c9a9a6a0 100644 --- a/x-pack/plugins/data_enhanced/public/plugin.ts +++ b/x-pack/plugins/data_enhanced/public/plugin.ts @@ -40,7 +40,6 @@ export class DataEnhancedPlugin uiSettings: core.uiSettings, startServices: core.getStartServices(), usageCollector: data.search.usageCollector, - loadingCount$: new BehaviorSubject(0), }, core.injectedMetadata.getInjectedVar('esRequestTimeout') as number ); From 1dded0abdd5527c3832e04117fa5b1180a16857d Mon Sep 17 00:00:00 2001 From: Liza K Date: Thu, 27 Aug 2020 13:56:51 +0300 Subject: [PATCH 31/77] type check --- x-pack/plugins/data_enhanced/public/plugin.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugins/data_enhanced/public/plugin.ts b/x-pack/plugins/data_enhanced/public/plugin.ts index 34973c9a9a6a0..7f6e3feac0671 100644 --- a/x-pack/plugins/data_enhanced/public/plugin.ts +++ b/x-pack/plugins/data_enhanced/public/plugin.ts @@ -5,7 +5,6 @@ */ import { CoreSetup, CoreStart, Plugin } from 'src/core/public'; -import { BehaviorSubject } from 'rxjs'; import { DataPublicPluginSetup, DataPublicPluginStart } from '../../../../src/plugins/data/public'; import { setAutocompleteService } from './services'; import { setupKqlQuerySuggestionProvider, KUERY_LANGUAGE_NAME } from './autocomplete'; From 05e9bdfccc6a1bcc8a6caba0c4da94c7e18aefbf Mon Sep 17 00:00:00 2001 From: Liza K Date: Thu, 27 Aug 2020 20:04:31 +0300 Subject: [PATCH 32/77] Remove esShard from client --- src/legacy/core_plugins/elasticsearch/index.js | 15 --------------- .../public/search/fetch/get_search_params.test.ts | 9 --------- .../data/public/search/fetch/get_search_params.ts | 13 ++++--------- src/plugins/data/public/search/fetch/index.ts | 1 - .../data/public/search/legacy/call_client.test.ts | 1 - src/plugins/data/public/search/search_service.ts | 2 -- .../search_source/create_search_source.test.ts | 1 - .../data/public/search/search_source/mocks.ts | 1 - .../search/search_source/search_source.test.ts | 1 - .../public/search/search_source/search_source.ts | 4 +--- .../vis_type_vega/public/data_model/search_api.ts | 3 --- src/plugins/vis_type_vega/public/plugin.ts | 1 - src/plugins/vis_type_vega/public/services.ts | 1 - .../public/vega_visualization.test.js | 1 - 14 files changed, 5 insertions(+), 49 deletions(-) diff --git a/src/legacy/core_plugins/elasticsearch/index.js b/src/legacy/core_plugins/elasticsearch/index.js index 599886788604b..f90f490d68035 100644 --- a/src/legacy/core_plugins/elasticsearch/index.js +++ b/src/legacy/core_plugins/elasticsearch/index.js @@ -16,18 +16,13 @@ * specific language governing permissions and limitations * under the License. */ -import { first } from 'rxjs/operators'; import { Cluster } from './server/lib/cluster'; import { createProxy } from './server/lib/create_proxy'; export default function (kibana) { - let defaultVars; - return new kibana.Plugin({ require: [], - uiExports: { injectDefaultVars: () => defaultVars }, - async init(server) { // All methods that ES plugin exposes are synchronous so we should get the first // value from all observables here to be able to synchronously return and create @@ -36,16 +31,6 @@ export default function (kibana) { const adminCluster = new Cluster(client); const dataCluster = new Cluster(client); - const esConfig = await server.newPlatform.__internals.elasticsearch.legacy.config$ - .pipe(first()) - .toPromise(); - - defaultVars = { - esRequestTimeout: esConfig.requestTimeout.asMilliseconds(), - esShardTimeout: esConfig.shardTimeout.asMilliseconds(), - esApiVersion: esConfig.apiVersion, - }; - const clusters = new Map(); server.expose('getCluster', (name) => { if (name === 'admin') { diff --git a/src/plugins/data/public/search/fetch/get_search_params.test.ts b/src/plugins/data/public/search/fetch/get_search_params.test.ts index 1ecb879b1602d..f8e8d95bc94f7 100644 --- a/src/plugins/data/public/search/fetch/get_search_params.test.ts +++ b/src/plugins/data/public/search/fetch/get_search_params.test.ts @@ -56,13 +56,4 @@ describe('getSearchParams', () => { searchParams = getSearchParams(config); expect(searchParams.max_concurrent_shard_requests).toBe(5); }); - - test('includes timeout according to esShardTimeout if greater than 0', () => { - const config = getConfigStub(); - let searchParams = getSearchParams(config, 0); - expect(searchParams.timeout).toBe(undefined); - - searchParams = getSearchParams(config, 100); - expect(searchParams.timeout).toBe('100ms'); - }); }); diff --git a/src/plugins/data/public/search/fetch/get_search_params.ts b/src/plugins/data/public/search/fetch/get_search_params.ts index 5e0395189f647..061ee9538c7da 100644 --- a/src/plugins/data/public/search/fetch/get_search_params.ts +++ b/src/plugins/data/public/search/fetch/get_search_params.ts @@ -22,14 +22,13 @@ import { SearchRequest } from './types'; const sessionId = Date.now(); -export function getSearchParams(getConfig: GetConfigFn, esShardTimeout: number = 0) { +export function getSearchParams(getConfig: GetConfigFn) { return { rest_total_hits_as_int: true, ignore_unavailable: true, ignore_throttled: getIgnoreThrottled(getConfig), max_concurrent_shard_requests: getMaxConcurrentShardRequests(getConfig), preference: getPreference(getConfig), - timeout: getTimeout(esShardTimeout), }; } @@ -50,19 +49,15 @@ export function getPreference(getConfig: GetConfigFn) { : undefined; } -export function getTimeout(esShardTimeout: number) { - return esShardTimeout > 0 ? `${esShardTimeout}ms` : undefined; -} - /** @public */ // TODO: Could provide this on runtime contract with dependencies // already wired up. export function getSearchParamsFromRequest( searchRequest: SearchRequest, - dependencies: { esShardTimeout: number; getConfig: GetConfigFn } + dependencies: { getConfig: GetConfigFn } ): ISearchRequestParams { - const { esShardTimeout, getConfig } = dependencies; - const searchParams = getSearchParams(getConfig, esShardTimeout); + const { getConfig } = dependencies; + const searchParams = getSearchParams(getConfig); return { index: searchRequest.index.title || searchRequest.index, diff --git a/src/plugins/data/public/search/fetch/index.ts b/src/plugins/data/public/search/fetch/index.ts index 79cdad1897f9c..4a88ca6ace481 100644 --- a/src/plugins/data/public/search/fetch/index.ts +++ b/src/plugins/data/public/search/fetch/index.ts @@ -22,7 +22,6 @@ export { getSearchParams, getSearchParamsFromRequest, getPreference, - getTimeout, getIgnoreThrottled, getMaxConcurrentShardRequests, } from './get_search_params'; diff --git a/src/plugins/data/public/search/legacy/call_client.test.ts b/src/plugins/data/public/search/legacy/call_client.test.ts index 38f3ab200da90..943a02d22088d 100644 --- a/src/plugins/data/public/search/legacy/call_client.test.ts +++ b/src/plugins/data/public/search/legacy/call_client.test.ts @@ -60,7 +60,6 @@ describe('callClient', () => { http: coreMock.createStart().http, legacySearchService: {}, config: { get: jest.fn() }, - esShardTimeout: 0, loadingCount$: new BehaviorSubject(0), } as FetchHandlers; diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts index a113d12a8089d..f8f4acbe43dfd 100644 --- a/src/plugins/data/public/search/search_service.ts +++ b/src/plugins/data/public/search/search_service.ts @@ -94,8 +94,6 @@ export class SearchService implements Plugin { const searchSourceDependencies: SearchSourceDependencies = { getConfig: uiSettings.get.bind(uiSettings), - // TODO: we don't need this, apply on the server - esShardTimeout: injectedMetadata.getInjectedVar('esShardTimeout') as number, search, http, loadingCount$, diff --git a/src/plugins/data/public/search/search_source/create_search_source.test.ts b/src/plugins/data/public/search/search_source/create_search_source.test.ts index 2820aab67ea3a..bc1c7c06c8806 100644 --- a/src/plugins/data/public/search/search_source/create_search_source.test.ts +++ b/src/plugins/data/public/search/search_source/create_search_source.test.ts @@ -35,7 +35,6 @@ describe('createSearchSource', () => { dependencies = { getConfig: jest.fn(), search: jest.fn(), - esShardTimeout: 30000, http: coreMock.createStart().http, loadingCount$: new BehaviorSubject(0), }; diff --git a/src/plugins/data/public/search/search_source/mocks.ts b/src/plugins/data/public/search/search_source/mocks.ts index bc3e287d9fe80..adf53bee33fe1 100644 --- a/src/plugins/data/public/search/search_source/mocks.ts +++ b/src/plugins/data/public/search/search_source/mocks.ts @@ -53,7 +53,6 @@ export const searchSourceMock = { export const createSearchSourceMock = (fields?: SearchSourceFields) => new SearchSource(fields, { getConfig: uiSettingsServiceMock.createStartContract().get, - esShardTimeout: 30000, search: jest.fn(), http: httpServiceMock.createStartContract(), loadingCount$: new BehaviorSubject(0), diff --git a/src/plugins/data/public/search/search_source/search_source.test.ts b/src/plugins/data/public/search/search_source/search_source.test.ts index a8baed9faa84d..282a33e6d01f7 100644 --- a/src/plugins/data/public/search/search_source/search_source.test.ts +++ b/src/plugins/data/public/search/search_source/search_source.test.ts @@ -68,7 +68,6 @@ describe('SearchSource', () => { searchSourceDependencies = { getConfig: jest.fn(), search: mockSearchMethod, - esShardTimeout: 30000, http: coreMock.createStart().http, loadingCount$: new BehaviorSubject(0), }; diff --git a/src/plugins/data/public/search/search_source/search_source.ts b/src/plugins/data/public/search/search_source/search_source.ts index 7b07c37429378..9699a880bca35 100644 --- a/src/plugins/data/public/search/search_source/search_source.ts +++ b/src/plugins/data/public/search/search_source/search_source.ts @@ -113,7 +113,6 @@ export interface SearchSourceDependencies { getConfig: GetConfigFn; search: ISearchGeneric; http: HttpStart; - esShardTimeout: number; loadingCount$: BehaviorSubject; } @@ -228,10 +227,9 @@ export class SearchSource { * @return {Observable>} */ private fetch$(searchRequest: SearchRequest, signal?: AbortSignal) { - const { search, esShardTimeout, getConfig } = this.dependencies; + const { search, getConfig } = this.dependencies; const params = getSearchParamsFromRequest(searchRequest, { - esShardTimeout, getConfig, }); diff --git a/src/plugins/vis_type_vega/public/data_model/search_api.ts b/src/plugins/vis_type_vega/public/data_model/search_api.ts index d2ce8c95b9f90..40c42c7eedee4 100644 --- a/src/plugins/vis_type_vega/public/data_model/search_api.ts +++ b/src/plugins/vis_type_vega/public/data_model/search_api.ts @@ -51,9 +51,6 @@ export class SearchAPI { searchRequests.map((request) => { const requestId = request.name; const params = getSearchParamsFromRequest(request, { - esShardTimeout: this.dependencies.injectedMetadata.getInjectedVar( - 'esShardTimeout' - ) as number, getConfig: this.dependencies.uiSettings.get.bind(this.dependencies.uiSettings), }); diff --git a/src/plugins/vis_type_vega/public/plugin.ts b/src/plugins/vis_type_vega/public/plugin.ts index 00c6b2e3c8d5b..4b8ff8e2cb43a 100644 --- a/src/plugins/vis_type_vega/public/plugin.ts +++ b/src/plugins/vis_type_vega/public/plugin.ts @@ -78,7 +78,6 @@ export class VegaPlugin implements Plugin, void> { ) { setInjectedVars({ enableExternalUrls: this.initializerContext.config.get().enableExternalUrls, - esShardTimeout: core.injectedMetadata.getInjectedVar('esShardTimeout') as number, emsTileLayerId: core.injectedMetadata.getInjectedVar('emsTileLayerId', true), }); setUISettings(core.uiSettings); diff --git a/src/plugins/vis_type_vega/public/services.ts b/src/plugins/vis_type_vega/public/services.ts index 7d988d464b52b..e754e15735bd7 100644 --- a/src/plugins/vis_type_vega/public/services.ts +++ b/src/plugins/vis_type_vega/public/services.ts @@ -48,7 +48,6 @@ export const [getSavedObjects, setSavedObjects] = createGetterSetter('InjectedVars'); diff --git a/src/plugins/vis_type_vega/public/vega_visualization.test.js b/src/plugins/vis_type_vega/public/vega_visualization.test.js index 0912edf9503a6..1bf625af76207 100644 --- a/src/plugins/vis_type_vega/public/vega_visualization.test.js +++ b/src/plugins/vis_type_vega/public/vega_visualization.test.js @@ -82,7 +82,6 @@ describe('VegaVisualizations', () => { setInjectedVars({ emsTileLayerId: {}, enableExternalUrls: true, - esShardTimeout: 10000, }); setData(dataPluginStart); setSavedObjects(coreStart.savedObjects); From dc198636e82a0a5a4fa3afd90920617d4942c1e7 Mon Sep 17 00:00:00 2001 From: Liza K Date: Mon, 31 Aug 2020 14:14:03 +0300 Subject: [PATCH 33/77] cleanup request parameters from FE --- .../search/fetch/get_search_params.test.ts | 12 ----- .../public/search/fetch/get_search_params.ts | 2 - src/plugins/data/server/index.ts | 1 + .../es_search/get_default_search_params.ts | 6 ++- .../data/server/search/es_search/index.ts | 2 +- src/plugins/data/server/search/index.ts | 2 +- .../data/server/search/routes/msearch.ts | 4 +- .../server/search/es_search_strategy.test.ts | 26 +++++++++-- .../server/search/es_search_strategy.ts | 46 +++++++++---------- 9 files changed, 53 insertions(+), 48 deletions(-) diff --git a/src/plugins/data/public/search/fetch/get_search_params.test.ts b/src/plugins/data/public/search/fetch/get_search_params.test.ts index f8e8d95bc94f7..8b693b1dff4ee 100644 --- a/src/plugins/data/public/search/fetch/get_search_params.test.ts +++ b/src/plugins/data/public/search/fetch/get_search_params.test.ts @@ -25,18 +25,6 @@ function getConfigStub(config: any = {}): GetConfigFn { } describe('getSearchParams', () => { - test('includes rest_total_hits_as_int', () => { - const config = getConfigStub(); - const searchParams = getSearchParams(config); - expect(searchParams.rest_total_hits_as_int).toBe(true); - }); - - test('includes ignore_unavailable', () => { - const config = getConfigStub(); - const searchParams = getSearchParams(config); - expect(searchParams.ignore_unavailable).toBe(true); - }); - test('includes ignore_throttled according to search:includeFrozen', () => { let config = getConfigStub({ [UI_SETTINGS.SEARCH_INCLUDE_FROZEN]: true }); let searchParams = getSearchParams(config); diff --git a/src/plugins/data/public/search/fetch/get_search_params.ts b/src/plugins/data/public/search/fetch/get_search_params.ts index 061ee9538c7da..97c69e8343f42 100644 --- a/src/plugins/data/public/search/fetch/get_search_params.ts +++ b/src/plugins/data/public/search/fetch/get_search_params.ts @@ -24,8 +24,6 @@ const sessionId = Date.now(); export function getSearchParams(getConfig: GetConfigFn) { return { - rest_total_hits_as_int: true, - ignore_unavailable: true, ignore_throttled: getIgnoreThrottled(getConfig), max_concurrent_shard_requests: getMaxConcurrentShardRequests(getConfig), preference: getPreference(getConfig), diff --git a/src/plugins/data/server/index.ts b/src/plugins/data/server/index.ts index c3b06992dba0e..302fe3703c271 100644 --- a/src/plugins/data/server/index.ts +++ b/src/plugins/data/server/index.ts @@ -212,6 +212,7 @@ export { ISearchSetup, ISearchStart, getDefaultSearchParams, + getShardTimeout, getTotalLoaded, usageProvider, SearchUsage, diff --git a/src/plugins/data/server/search/es_search/get_default_search_params.ts b/src/plugins/data/server/search/es_search/get_default_search_params.ts index b2341ccc0f3c8..5c5bf0ec08de3 100644 --- a/src/plugins/data/server/search/es_search/get_default_search_params.ts +++ b/src/plugins/data/server/search/es_search/get_default_search_params.ts @@ -19,9 +19,13 @@ import { SharedGlobalConfig } from '../../../../../core/server'; +export function getShardTimeout(config: SharedGlobalConfig) { + return `${config.elasticsearch.shardTimeout.asMilliseconds()}ms`; +} + export function getDefaultSearchParams(config: SharedGlobalConfig) { return { - timeout: `${config.elasticsearch.shardTimeout.asMilliseconds()}ms`, + timeout: getShardTimeout(config), ignoreUnavailable: true, // Don't fail if the index/indices don't exist restTotalHitsAsInt: true, // Get the number of hits as an int rather than a range }; diff --git a/src/plugins/data/server/search/es_search/index.ts b/src/plugins/data/server/search/es_search/index.ts index 20006b70730d8..a213d26501502 100644 --- a/src/plugins/data/server/search/es_search/index.ts +++ b/src/plugins/data/server/search/es_search/index.ts @@ -19,5 +19,5 @@ export { ES_SEARCH_STRATEGY, IEsSearchRequest, IEsSearchResponse } from '../../../common/search'; export { esSearchStrategyProvider } from './es_search_strategy'; -export { getDefaultSearchParams } from './get_default_search_params'; +export { getDefaultSearchParams, getShardTimeout } from './get_default_search_params'; export { getTotalLoaded } from './get_total_loaded'; diff --git a/src/plugins/data/server/search/index.ts b/src/plugins/data/server/search/index.ts index 02c21c3254645..37878a51e011a 100644 --- a/src/plugins/data/server/search/index.ts +++ b/src/plugins/data/server/search/index.ts @@ -25,7 +25,7 @@ export { SearchEnhancements, } from './types'; -export { getDefaultSearchParams, getTotalLoaded } from './es_search'; +export { getDefaultSearchParams, getTotalLoaded, getShardTimeout } from './es_search'; export { usageProvider, SearchUsage } from './collectors'; diff --git a/src/plugins/data/server/search/routes/msearch.ts b/src/plugins/data/server/search/routes/msearch.ts index c854a06b6b0dd..cfb0428fb7fa4 100644 --- a/src/plugins/data/server/search/routes/msearch.ts +++ b/src/plugins/data/server/search/routes/msearch.ts @@ -23,7 +23,7 @@ import { schema } from '@kbn/config-schema'; import { IRouter } from 'src/core/server'; import { UI_SETTINGS } from '../../../common'; import { SearchRouteDependencies } from '../search_service'; -import { getDefaultSearchParams } from '..'; +import { getShardTimeout } from '..'; interface MsearchHeaders { index: string; @@ -96,7 +96,7 @@ export function registerMsearchRoute(router: IRouter, deps: SearchRouteDependenc // get shardTimeout const config = await deps.globalConfig$.pipe(first()).toPromise(); - const { timeout } = getDefaultSearchParams(config); + const timeout = getShardTimeout(config); const body = convertRequestBody(request.body, { timeout }); diff --git a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts index 054baa6ac81d1..9d577a9e04dce 100644 --- a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts +++ b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts @@ -5,8 +5,8 @@ */ import { RequestHandlerContext } from '../../../../../src/core/server'; -import { pluginInitializerContextConfigMock } from '../../../../../src/core/server/mocks'; import { enhancedEsSearchStrategyProvider } from './es_search_strategy'; +import { BehaviorSubject } from 'rxjs'; const mockAsyncResponse = { body: { @@ -43,7 +43,15 @@ describe('ES search strategy', () => { elasticsearch: { client: { asCurrentUser: { transport: { request: mockApiCaller } } } }, }, }; - const mockConfig$ = pluginInitializerContextConfigMock({}).legacy.globalConfig$; + const mockConfig$ = new BehaviorSubject({ + elasticsearch: { + shardTimeout: { + asMilliseconds: () => { + return 100; + }, + }, + }, + }); beforeEach(() => { mockApiCaller.mockClear(); @@ -64,10 +72,17 @@ describe('ES search strategy', () => { await esSearch.search((mockContext as unknown) as RequestHandlerContext, { params }); expect(mockApiCaller).toBeCalled(); - const { method, path, body } = mockApiCaller.mock.calls[0][0]; + + const { method, path, body, querystring } = mockApiCaller.mock.calls[0][0]; + expect(method).toBe('POST'); expect(path).toBe('/logstash-*/_async_search'); expect(body).toEqual({ query: {} }); + expect(querystring).toHaveProperty('wait_for_completion_timeout'); + expect(querystring).toHaveProperty('track_total_hits'); + expect(querystring).toHaveProperty('ignore_unavailable'); + expect(querystring).toHaveProperty('keep_alive'); + expect(querystring).toHaveProperty('batched_reduce_size'); }); it('makes a GET request to async search with ID when ID is provided', async () => { @@ -79,10 +94,13 @@ describe('ES search strategy', () => { await esSearch.search((mockContext as unknown) as RequestHandlerContext, { id: 'foo', params }); expect(mockApiCaller).toBeCalled(); - const { method, path, body } = mockApiCaller.mock.calls[0][0]; + const { method, path, body, querystring } = mockApiCaller.mock.calls[0][0]; expect(method).toBe('GET'); expect(path).toBe('/_async_search/foo'); expect(body).toEqual(undefined); + expect(querystring).not.toHaveProperty('batched_reduce_size'); + expect(querystring).not.toHaveProperty('batched_reduce_size'); + expect(querystring).not.toHaveProperty('batched_reduce_size'); }); it('encodes special characters in the path', async () => { diff --git a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts index 46609af52d072..5d9ee4fbcd89e 100644 --- a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts +++ b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts @@ -15,11 +15,11 @@ import { Logger, } from '../../../../../src/core/server'; import { - getDefaultSearchParams, getTotalLoaded, ISearchStrategy, SearchUsage, ISearchOptions, + getDefaultSearchParams, } from '../../../../../src/plugins/data/server'; import { IEnhancedEsSearchRequest } from '../../common'; import { shimHitsTotal } from './shim_hits_total'; @@ -39,18 +39,16 @@ export const enhancedEsSearchStrategyProvider = ( request: IEnhancedEsSearchRequest, options?: ISearchOptions ) => { - logger.debug(`search ${JSON.stringify(request.params) || request.id}`); - const config = await config$.pipe(first()).toPromise(); const client = context.core.elasticsearch.client.asCurrentUser; - const defaultParams = getDefaultSearchParams(config); - const params = { ...defaultParams, ...request.params }; + + logger.debug(`search ${JSON.stringify(request.params) || request.id}`); const isAsync = request.indexType !== 'rollup'; try { const response = isAsync - ? await asyncSearch(client, { ...request, params }, options) - : await rollupSearch(client, { ...request, params }, options); + ? await asyncSearch(client, request) + : await rollupSearch(client, request, config$); if ( usage && @@ -82,14 +80,9 @@ export const enhancedEsSearchStrategyProvider = ( async function asyncSearch( client: ElasticsearchClient, - request: IEnhancedEsSearchRequest, - options?: ISearchOptions + request: IEnhancedEsSearchRequest ): Promise { - const { timeout = undefined, restTotalHitsAsInt = undefined, ...params } = { - ...request.params, - }; - - params.trackTotalHits = true; // Get the exact count of hits + const { params = {} } = request; // If we have an ID, then just poll for that ID, otherwise send the entire request body const { body = undefined, index = undefined, ...queryParams } = request.id ? {} : params; @@ -97,17 +90,16 @@ async function asyncSearch( const method = request.id ? 'GET' : 'POST'; const path = encodeURI(request.id ? `/_async_search/${request.id}` : `/${index}/_async_search`); - // Only report partial results every 64 shards; this should be reduced when we actually display partial results - const batchedReduceSize = request.id ? undefined : 64; - - const asyncOptions = { + const querystring = toSnakeCase({ waitForCompletionTimeout: '100ms', // Wait up to 100ms for the response to return keepAlive: '1m', // Extend the TTL for this search request by one minute - }; - - const querystring = toSnakeCase({ - ...asyncOptions, - ...(batchedReduceSize && { batchedReduceSize }), + ...(request.id + ? {} + : { + trackTotalHits: true, + ignoreUnavailable: true, + batchedReduceSize: 64, // Only report partial results every 64 shards; this should be reduced when we actually display partial results + }), ...queryParams, }); @@ -132,12 +124,16 @@ async function asyncSearch( async function rollupSearch( client: ElasticsearchClient, request: IEnhancedEsSearchRequest, - options?: ISearchOptions + config$: Observable ): Promise { + const config = await config$.pipe(first()).toPromise(); const { body, index, ...params } = request.params!; const method = 'POST'; const path = encodeURI(`/${index}/_rollup_search`); - const querystring = toSnakeCase(params); + const querystring = toSnakeCase({ + ...getDefaultSearchParams(config), + ...params, + }); const esResponse = await client.transport.request({ method, From 0499b213258b4b51e10d4d35252df0ff571572fa Mon Sep 17 00:00:00 2001 From: Liza K Date: Mon, 31 Aug 2020 14:35:19 +0300 Subject: [PATCH 34/77] doc --- ...-data-public.getsearchparamsfromrequest.md | 3 +- .../kibana-plugin-plugins-data-server.md | 1 + src/plugins/data/public/public.api.md | 1 - src/plugins/data/server/server.api.md | 31 +++++++++++-------- 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.getsearchparamsfromrequest.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.getsearchparamsfromrequest.md index 337b4b3302cc3..d32e9a955f890 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.getsearchparamsfromrequest.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.getsearchparamsfromrequest.md @@ -9,7 +9,6 @@ ```typescript export declare function getSearchParamsFromRequest(searchRequest: SearchRequest, dependencies: { - esShardTimeout: number; getConfig: GetConfigFn; }): ISearchRequestParams; ``` @@ -19,7 +18,7 @@ export declare function getSearchParamsFromRequest(searchRequest: SearchRequest, | Parameter | Type | Description | | --- | --- | --- | | searchRequest | SearchRequest | | -| dependencies | {
esShardTimeout: number;
getConfig: GetConfigFn;
} | | +| dependencies | {
getConfig: GetConfigFn;
} | | Returns: diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md index 0292e08063fbb..d3761e3d1ae9f 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md @@ -27,6 +27,7 @@ | Function | Description | | --- | --- | | [getDefaultSearchParams(config)](./kibana-plugin-plugins-data-server.getdefaultsearchparams.md) | | +| [getShardTimeout(config)](./kibana-plugin-plugins-data-server.getshardtimeout.md) | | | [getTime(indexPattern, timeRange, options)](./kibana-plugin-plugins-data-server.gettime.md) | | | [parseInterval(interval)](./kibana-plugin-plugins-data-server.parseinterval.md) | | | [plugin(initializerContext)](./kibana-plugin-plugins-data-server.plugin.md) | Static code to be shared externally | diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index aabb498dd0e14..b1eb743fbe8cd 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -738,7 +738,6 @@ export const getKbnTypeNames: () => string[]; // // @public (undocumented) export function getSearchParamsFromRequest(searchRequest: SearchRequest, dependencies: { - esShardTimeout: number; getConfig: GetConfigFn; }): ISearchRequestParams; diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md index ed6896ccf4114..86da3d3281ac9 100644 --- a/src/plugins/data/server/server.api.md +++ b/src/plugins/data/server/server.api.md @@ -328,6 +328,11 @@ export function getDefaultSearchParams(config: SharedGlobalConfig): { restTotalHitsAsInt: boolean; }; +// Warning: (ae-missing-release-tag) "getShardTimeout" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function getShardTimeout(config: SharedGlobalConfig): string; + // Warning: (ae-missing-release-tag) "getTime" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -960,19 +965,19 @@ export function usageProvider(core: CoreSetup_2): SearchUsage; // src/plugins/data/server/index.ts:101:26 - (ae-forgotten-export) The symbol "TruncateFormat" needs to be exported by the entry point index.d.ts // src/plugins/data/server/index.ts:127:27 - (ae-forgotten-export) The symbol "isFilterable" needs to be exported by the entry point index.d.ts // src/plugins/data/server/index.ts:127:27 - (ae-forgotten-export) The symbol "isNestedField" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:221:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:221:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:221:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:221:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:223:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:224:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:233:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:234:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:235:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:239:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:240:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:244:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:247:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:222:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:222:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:222:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:222:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:224:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:225:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:234:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:235:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:236:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:240:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:241:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:245:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:248:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts // src/plugins/data/server/plugin.ts:88:66 - (ae-forgotten-export) The symbol "DataEnhancements" needs to be exported by the entry point index.d.ts // (No @packageDocumentation comment for this package) From 05c51b874118cb95a938e6cb05a5cc3487223596 Mon Sep 17 00:00:00 2001 From: Liza K Date: Mon, 31 Aug 2020 15:08:01 +0300 Subject: [PATCH 35/77] doc --- ...gin-plugins-data-server.getshardtimeout.md | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getshardtimeout.md diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getshardtimeout.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getshardtimeout.md new file mode 100644 index 0000000000000..7968379249bed --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getshardtimeout.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [getShardTimeout](./kibana-plugin-plugins-data-server.getshardtimeout.md) + +## getShardTimeout() function + +Signature: + +```typescript +export declare function getShardTimeout(config: SharedGlobalConfig): string; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| config | SharedGlobalConfig | | + +Returns: + +`string` + From 735ac5cbd431b1ef0a483b90c7a3e076791de9a1 Mon Sep 17 00:00:00 2001 From: Liza K Date: Tue, 1 Sep 2020 15:51:13 +0300 Subject: [PATCH 36/77] Align request parameters on server, Remove leftover parameters from client Shim responses for search and msearch routes --- .../public/search/fetch/get_search_params.ts | 11 -- src/plugins/data/public/search/fetch/index.ts | 8 +- src/plugins/data/server/index.ts | 1 + .../search/es_search/es_search_strategy.ts | 7 +- .../es_search/get_default_search_params.ts | 25 ++- .../data/server/search/es_search/index.ts | 2 +- src/plugins/data/server/search/index.ts | 2 +- .../data/server/search/routes/msearch.ts | 35 ++-- .../data/server/search/routes/search.ts | 4 + .../search/routes}/shim_hits_total.test.ts | 19 ++- .../server/search/routes/shim_hits_total.ts | 33 ++++ .../data_enhanced/common/search/types.ts | 8 +- .../public/search/search_interceptor.ts | 5 - .../server/search/es_search_strategy.test.ts | 2 + .../server/search/es_search_strategy.ts | 160 +++++++++--------- .../server/search/shim_hits_total.ts | 18 -- 16 files changed, 179 insertions(+), 161 deletions(-) rename {x-pack/plugins/data_enhanced/server/search => src/plugins/data/server/search/routes}/shim_hits_total.test.ts (54%) create mode 100644 src/plugins/data/server/search/routes/shim_hits_total.ts delete mode 100644 x-pack/plugins/data_enhanced/server/search/shim_hits_total.ts diff --git a/src/plugins/data/public/search/fetch/get_search_params.ts b/src/plugins/data/public/search/fetch/get_search_params.ts index 97c69e8343f42..ed87c4813951c 100644 --- a/src/plugins/data/public/search/fetch/get_search_params.ts +++ b/src/plugins/data/public/search/fetch/get_search_params.ts @@ -24,21 +24,10 @@ const sessionId = Date.now(); export function getSearchParams(getConfig: GetConfigFn) { return { - ignore_throttled: getIgnoreThrottled(getConfig), - max_concurrent_shard_requests: getMaxConcurrentShardRequests(getConfig), preference: getPreference(getConfig), }; } -export function getIgnoreThrottled(getConfig: GetConfigFn) { - return !getConfig(UI_SETTINGS.SEARCH_INCLUDE_FROZEN); -} - -export function getMaxConcurrentShardRequests(getConfig: GetConfigFn) { - const maxConcurrentShardRequests = getConfig(UI_SETTINGS.COURIER_MAX_CONCURRENT_SHARD_REQUESTS); - return maxConcurrentShardRequests > 0 ? maxConcurrentShardRequests : undefined; -} - export function getPreference(getConfig: GetConfigFn) { const setRequestPreference = getConfig(UI_SETTINGS.COURIER_SET_REQUEST_PREFERENCE); if (setRequestPreference === 'sessionId') return sessionId; diff --git a/src/plugins/data/public/search/fetch/index.ts b/src/plugins/data/public/search/fetch/index.ts index 4a88ca6ace481..4b8511edfc26f 100644 --- a/src/plugins/data/public/search/fetch/index.ts +++ b/src/plugins/data/public/search/fetch/index.ts @@ -18,13 +18,7 @@ */ export * from './types'; -export { - getSearchParams, - getSearchParamsFromRequest, - getPreference, - getIgnoreThrottled, - getMaxConcurrentShardRequests, -} from './get_search_params'; +export { getSearchParams, getSearchParamsFromRequest, getPreference } from './get_search_params'; export { RequestFailure } from './request_error'; export { handleResponse } from './handle_response'; diff --git a/src/plugins/data/server/index.ts b/src/plugins/data/server/index.ts index 302fe3703c271..3df265c0b4fdd 100644 --- a/src/plugins/data/server/index.ts +++ b/src/plugins/data/server/index.ts @@ -214,6 +214,7 @@ export { getDefaultSearchParams, getShardTimeout, getTotalLoaded, + toSnakeCase, usageProvider, SearchUsage, } from './search'; diff --git a/src/plugins/data/server/search/es_search/es_search_strategy.ts b/src/plugins/data/server/search/es_search/es_search_strategy.ts index eabbf3e3e2600..05933bd646ccc 100644 --- a/src/plugins/data/server/search/es_search/es_search_strategy.ts +++ b/src/plugins/data/server/search/es_search/es_search_strategy.ts @@ -22,7 +22,7 @@ import { SearchResponse } from 'elasticsearch'; import { Observable } from 'rxjs'; import { ApiResponse } from '@elastic/elasticsearch'; import { SearchUsage } from '../collectors/usage'; -import { ISearchStrategy, getDefaultSearchParams, getTotalLoaded } from '..'; +import { ISearchStrategy, getDefaultSearchParams, getTotalLoaded, getShardTimeout } from '..'; export const esSearchStrategyProvider = ( config$: Observable, @@ -33,7 +33,7 @@ export const esSearchStrategyProvider = ( search: async (context, request, options) => { logger.debug(`search ${request.params?.index}`); const config = await config$.pipe(first()).toPromise(); - const defaultParams = getDefaultSearchParams(config); + const uiSettingsClient = await context.core.uiSettings.client; // Only default index pattern type is supported here. // See data_enhanced for other type support. @@ -42,7 +42,8 @@ export const esSearchStrategyProvider = ( } const params = { - ...defaultParams, + ...(await getDefaultSearchParams(uiSettingsClient)), + ...getShardTimeout(config), ...request.params, }; diff --git a/src/plugins/data/server/search/es_search/get_default_search_params.ts b/src/plugins/data/server/search/es_search/get_default_search_params.ts index 5c5bf0ec08de3..0e09c56741c43 100644 --- a/src/plugins/data/server/search/es_search/get_default_search_params.ts +++ b/src/plugins/data/server/search/es_search/get_default_search_params.ts @@ -17,16 +17,31 @@ * under the License. */ -import { SharedGlobalConfig } from '../../../../../core/server'; +import { mapKeys, snakeCase } from 'lodash'; +import { SharedGlobalConfig, IUiSettingsClient } from '../../../../../core/server'; +import { UI_SETTINGS } from '../..'; export function getShardTimeout(config: SharedGlobalConfig) { - return `${config.elasticsearch.shardTimeout.asMilliseconds()}ms`; + return { + timeout: `${config.elasticsearch.shardTimeout.asMilliseconds()}ms`, + }; } -export function getDefaultSearchParams(config: SharedGlobalConfig) { +export async function getDefaultSearchParams(uiSettingsClient: IUiSettingsClient) { + const ignoreThrottled = !(await uiSettingsClient.get(UI_SETTINGS.SEARCH_INCLUDE_FROZEN)); + const maxConcurrentShardRequests = await uiSettingsClient.get( + UI_SETTINGS.COURIER_MAX_CONCURRENT_SHARD_REQUESTS + ); return { - timeout: getShardTimeout(config), + maxConcurrentShardRequests: + maxConcurrentShardRequests > 0 ? maxConcurrentShardRequests : undefined, + ignoreThrottled, ignoreUnavailable: true, // Don't fail if the index/indices don't exist - restTotalHitsAsInt: true, // Get the number of hits as an int rather than a range + trackTotalHits: true, + // restTotalHitsAsInt: true, // Get the number of hits as an int rather than a range }; } + +export function toSnakeCase(obj: Record) { + return mapKeys(obj, (value, key) => snakeCase(key)); +} diff --git a/src/plugins/data/server/search/es_search/index.ts b/src/plugins/data/server/search/es_search/index.ts index a213d26501502..3418a6a987828 100644 --- a/src/plugins/data/server/search/es_search/index.ts +++ b/src/plugins/data/server/search/es_search/index.ts @@ -19,5 +19,5 @@ export { ES_SEARCH_STRATEGY, IEsSearchRequest, IEsSearchResponse } from '../../../common/search'; export { esSearchStrategyProvider } from './es_search_strategy'; -export { getDefaultSearchParams, getShardTimeout } from './get_default_search_params'; +export * from './get_default_search_params'; export { getTotalLoaded } from './get_total_loaded'; diff --git a/src/plugins/data/server/search/index.ts b/src/plugins/data/server/search/index.ts index 37878a51e011a..747cb3893d92e 100644 --- a/src/plugins/data/server/search/index.ts +++ b/src/plugins/data/server/search/index.ts @@ -25,7 +25,7 @@ export { SearchEnhancements, } from './types'; -export { getDefaultSearchParams, getTotalLoaded, getShardTimeout } from './es_search'; +export * from './es_search'; export { usageProvider, SearchUsage } from './collectors'; diff --git a/src/plugins/data/server/search/routes/msearch.ts b/src/plugins/data/server/search/routes/msearch.ts index cfb0428fb7fa4..7e37f69950a10 100644 --- a/src/plugins/data/server/search/routes/msearch.ts +++ b/src/plugins/data/server/search/routes/msearch.ts @@ -20,10 +20,12 @@ import { first } from 'rxjs/operators'; import { schema } from '@kbn/config-schema'; +import { SearchResponse } from 'elasticsearch'; import { IRouter } from 'src/core/server'; import { UI_SETTINGS } from '../../../common'; import { SearchRouteDependencies } from '../search_service'; -import { getShardTimeout } from '..'; +import { shimHitsTotal } from './shim_hits_total'; +import { getShardTimeout, getDefaultSearchParams, toSnakeCase } from '..'; interface MsearchHeaders { index: string; @@ -98,28 +100,29 @@ export function registerMsearchRoute(router: IRouter, deps: SearchRouteDependenc const config = await deps.globalConfig$.pipe(first()).toPromise(); const timeout = getShardTimeout(config); - const body = convertRequestBody(request.body, { timeout }); + const body = convertRequestBody(request.body, timeout); + + // trackTotalHits is not supported by msearch + const { trackTotalHits, ...params } = await getDefaultSearchParams( + context.core.uiSettings.client + ); try { - const ignoreThrottled = !(await context.core.uiSettings.client.get( - UI_SETTINGS.SEARCH_INCLUDE_FROZEN - )); - const maxConcurrentShardRequests = await context.core.uiSettings.client.get( - UI_SETTINGS.COURIER_MAX_CONCURRENT_SHARD_REQUESTS - ); - const response = await client.transport.request({ + const response: Array> = await client.transport.request({ method: 'GET', path: '/_msearch', body, - querystring: { - rest_total_hits_as_int: true, - ignore_throttled: ignoreThrottled, - max_concurrent_shard_requests: - maxConcurrentShardRequests > 0 ? maxConcurrentShardRequests : undefined, - }, + querystring: toSnakeCase(params), }); - return res.ok({ body: response }); + return res.ok({ + body: { + ...response, + body: { + responses: response.body.responses.map((r) => shimHitsTotal(r)), + }, + }, + }); } catch (err) { return res.customError({ statusCode: err.statusCode || 500, diff --git a/src/plugins/data/server/search/routes/search.ts b/src/plugins/data/server/search/routes/search.ts index 769093bc79a8c..0745c4c65d303 100644 --- a/src/plugins/data/server/search/routes/search.ts +++ b/src/plugins/data/server/search/routes/search.ts @@ -21,6 +21,7 @@ import { schema } from '@kbn/config-schema'; import { IRouter } from 'src/core/server'; import { getRequestAbortedSignal } from '../../lib'; import { SearchRouteDependencies } from '../search_service'; +import { shimHitsTotal } from './shim_hits_total'; export function registerSearchRoute( router: IRouter, @@ -56,6 +57,9 @@ export function registerSearchRoute( strategy, } ); + + response.rawResponse = shimHitsTotal(response.rawResponse); + return res.ok({ body: response }); } catch (err) { return res.customError({ diff --git a/x-pack/plugins/data_enhanced/server/search/shim_hits_total.test.ts b/src/plugins/data/server/search/routes/shim_hits_total.test.ts similarity index 54% rename from x-pack/plugins/data_enhanced/server/search/shim_hits_total.test.ts rename to src/plugins/data/server/search/routes/shim_hits_total.test.ts index 61740b97299da..0f24735386121 100644 --- a/x-pack/plugins/data_enhanced/server/search/shim_hits_total.test.ts +++ b/src/plugins/data/server/search/routes/shim_hits_total.test.ts @@ -1,7 +1,20 @@ /* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ import { shimHitsTotal } from './shim_hits_total'; diff --git a/src/plugins/data/server/search/routes/shim_hits_total.ts b/src/plugins/data/server/search/routes/shim_hits_total.ts new file mode 100644 index 0000000000000..5f95b21358978 --- /dev/null +++ b/src/plugins/data/server/search/routes/shim_hits_total.ts @@ -0,0 +1,33 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { SearchResponse } from 'elasticsearch'; + +/** + * Temporary workaround until https://github.com/elastic/kibana/issues/26356 is addressed. + * Since we are setting `track_total_hits` in the request, `hits.total` will be an object + * containing the `value`. + * + * @internal + */ +export function shimHitsTotal(response: SearchResponse) { + const total = (response.hits?.total as any)?.value ?? response.hits?.total; + const hits = { ...response.hits, total }; + return { ...response, hits }; +} diff --git a/x-pack/plugins/data_enhanced/common/search/types.ts b/x-pack/plugins/data_enhanced/common/search/types.ts index 0d3d3a69e1e57..24d459ade4bf9 100644 --- a/x-pack/plugins/data_enhanced/common/search/types.ts +++ b/x-pack/plugins/data_enhanced/common/search/types.ts @@ -4,21 +4,15 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IEsSearchRequest, ISearchRequestParams } from '../../../../../src/plugins/data/common'; +import { IEsSearchRequest } from '../../../../../src/plugins/data/common'; export const ENHANCED_ES_SEARCH_STRATEGY = 'ese'; -export interface EnhancedSearchParams extends ISearchRequestParams { - ignoreThrottled: boolean; -} - export interface IAsyncSearchRequest extends IEsSearchRequest { /** * The ID received from the response from the initial request */ id?: string; - - params?: EnhancedSearchParams; } export interface IEnhancedEsSearchRequest extends IEsSearchRequest { diff --git a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts index d226b949e26b0..92f1a0f217688 100644 --- a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts +++ b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts @@ -80,11 +80,6 @@ export class EnhancedSearchInterceptor extends SearchInterceptor { ) { let { id } = request; - request.params = { - ignoreThrottled: !this.deps.uiSettings.get(UI_SETTINGS.SEARCH_INCLUDE_FROZEN), - ...request.params, - }; - const { combinedSignal, cleanup } = this.setupAbortSignal({ abortSignal: options.signal, timeout: this.searchTimeout, diff --git a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts index 9d577a9e04dce..e5aa694fe9ee6 100644 --- a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts +++ b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts @@ -81,6 +81,8 @@ describe('ES search strategy', () => { expect(querystring).toHaveProperty('wait_for_completion_timeout'); expect(querystring).toHaveProperty('track_total_hits'); expect(querystring).toHaveProperty('ignore_unavailable'); + expect(querystring).toHaveProperty('ignore_throttled'); + expect(querystring).toHaveProperty('ignore_unavailable'); expect(querystring).toHaveProperty('keep_alive'); expect(querystring).toHaveProperty('batched_reduce_size'); }); diff --git a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts index 5d9ee4fbcd89e..94fa9b3b6266d 100644 --- a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts +++ b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts @@ -5,24 +5,19 @@ */ import { first } from 'rxjs/operators'; -import { mapKeys, snakeCase } from 'lodash'; import { Observable } from 'rxjs'; import { SearchResponse } from 'elasticsearch'; -import { - SharedGlobalConfig, - RequestHandlerContext, - ElasticsearchClient, - Logger, -} from '../../../../../src/core/server'; +import { SharedGlobalConfig, RequestHandlerContext, Logger } from '../../../../../src/core/server'; import { getTotalLoaded, ISearchStrategy, SearchUsage, ISearchOptions, getDefaultSearchParams, + getShardTimeout, + toSnakeCase, } from '../../../../../src/plugins/data/server'; import { IEnhancedEsSearchRequest } from '../../common'; -import { shimHitsTotal } from './shim_hits_total'; import { IEsSearchResponse } from '../../../../../src/plugins/data/common/search/es_search'; function isEnhancedEsSearchResponse(response: any): response is IEsSearchResponse { @@ -39,16 +34,14 @@ export const enhancedEsSearchStrategyProvider = ( request: IEnhancedEsSearchRequest, options?: ISearchOptions ) => { - const client = context.core.elasticsearch.client.asCurrentUser; - logger.debug(`search ${JSON.stringify(request.params) || request.id}`); const isAsync = request.indexType !== 'rollup'; try { const response = isAsync - ? await asyncSearch(client, request) - : await rollupSearch(client, request, config$); + ? await asyncSearch(context, request) + : await rollupSearch(context, request); if ( usage && @@ -75,80 +68,79 @@ export const enhancedEsSearchStrategyProvider = ( }); }; - return { search, cancel }; -}; + const asyncSearch = async function ( + context: RequestHandlerContext, + request: IEnhancedEsSearchRequest + ): Promise { + const esClient = context.core.elasticsearch.client.asCurrentUser; + const uiSettingsClient = await context.core.uiSettings.client; + + const { params = {} } = request; + + // If we have an ID, then just poll for that ID, otherwise send the entire request body + const { body = undefined, index = undefined, ...queryParams } = request.id ? {} : params; + + const method = request.id ? 'GET' : 'POST'; + const path = encodeURI(request.id ? `/_async_search/${request.id}` : `/${index}/_async_search`); + + const querystring = toSnakeCase({ + waitForCompletionTimeout: '100ms', // Wait up to 100ms for the response to return + keepAlive: '1m', // Extend the TTL for this search request by one minute + ...(request.id + ? {} + : { + ...(await getDefaultSearchParams(uiSettingsClient)), + batchedReduceSize: 64, // Only report partial results every 64 shards; this should be reduced when we actually display partial results + }), + ...queryParams, + }); + // TODO: replace with async endpoints once https://github.com/elastic/elasticsearch-js/issues/1280 is resolved + const esResponse = await esClient.transport.request({ + method, + path, + body, + querystring, + }); -async function asyncSearch( - client: ElasticsearchClient, - request: IEnhancedEsSearchRequest -): Promise { - const { params = {} } = request; - - // If we have an ID, then just poll for that ID, otherwise send the entire request body - const { body = undefined, index = undefined, ...queryParams } = request.id ? {} : params; - - const method = request.id ? 'GET' : 'POST'; - const path = encodeURI(request.id ? `/_async_search/${request.id}` : `/${index}/_async_search`); - - const querystring = toSnakeCase({ - waitForCompletionTimeout: '100ms', // Wait up to 100ms for the response to return - keepAlive: '1m', // Extend the TTL for this search request by one minute - ...(request.id - ? {} - : { - trackTotalHits: true, - ignoreUnavailable: true, - batchedReduceSize: 64, // Only report partial results every 64 shards; this should be reduced when we actually display partial results - }), - ...queryParams, - }); - - // TODO: replace with async endpoints once https://github.com/elastic/elasticsearch-js/issues/1280 is resolved - const esResponse = await client.transport.request({ - method, - path, - body, - querystring, - }); - - const { id, response, is_partial: isPartial, is_running: isRunning } = esResponse.body; - return { - id, - isPartial, - isRunning, - rawResponse: shimHitsTotal(response), - ...getTotalLoaded(response._shards), + const { id, response, is_partial: isPartial, is_running: isRunning } = esResponse.body; + return { + id, + isPartial, + isRunning, + rawResponse: response, + ...getTotalLoaded(response._shards), + }; }; -} -async function rollupSearch( - client: ElasticsearchClient, - request: IEnhancedEsSearchRequest, - config$: Observable -): Promise { - const config = await config$.pipe(first()).toPromise(); - const { body, index, ...params } = request.params!; - const method = 'POST'; - const path = encodeURI(`/${index}/_rollup_search`); - const querystring = toSnakeCase({ - ...getDefaultSearchParams(config), - ...params, - }); - - const esResponse = await client.transport.request({ - method, - path, - body, - querystring, - }); - - const response = esResponse.body as SearchResponse; - return { - rawResponse: shimHitsTotal(response), - ...getTotalLoaded(response._shards), + const rollupSearch = async function ( + context: RequestHandlerContext, + request: IEnhancedEsSearchRequest + ): Promise { + const esClient = context.core.elasticsearch.client.asCurrentUser; + const uiSettingsClient = await context.core.uiSettings.client; + const config = await config$.pipe(first()).toPromise(); + const { body, index, ...params } = request.params!; + const method = 'POST'; + const path = encodeURI(`/${index}/_rollup_search`); + const querystring = toSnakeCase({ + ...getShardTimeout(config), + ...(await getDefaultSearchParams(uiSettingsClient)), + ...params, + }); + + const esResponse = await esClient.transport.request({ + method, + path, + body, + querystring, + }); + + const response = esResponse.body as SearchResponse; + return { + rawResponse: shimresponse, + ...getTotalLoaded(response._shards), + }; }; -} -function toSnakeCase(obj: Record) { - return mapKeys(obj, (value, key) => snakeCase(key)); -} + return { search, cancel }; +}; diff --git a/x-pack/plugins/data_enhanced/server/search/shim_hits_total.ts b/x-pack/plugins/data_enhanced/server/search/shim_hits_total.ts deleted file mode 100644 index 10d45be01563a..0000000000000 --- a/x-pack/plugins/data_enhanced/server/search/shim_hits_total.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { SearchResponse } from 'elasticsearch'; - -/** - * Temporary workaround until https://github.com/elastic/kibana/issues/26356 is addressed. - * Since we are setting `track_total_hits` in the request, `hits.total` will be an object - * containing the `value`. - */ -export function shimHitsTotal(response: SearchResponse) { - const total = (response.hits?.total as any)?.value ?? response.hits?.total; - const hits = { ...response.hits, total }; - return { ...response, hits }; -} From 0edd897af57ae54baa2275bd048bf9617cfc935e Mon Sep 17 00:00:00 2001 From: Liza K Date: Tue, 1 Sep 2020 16:43:09 +0300 Subject: [PATCH 37/77] docs Stop using toSnakeCase Updates jest tests --- ...gins-data-server.getdefaultsearchparams.md | 20 ++++---- ...gin-plugins-data-server.getshardtimeout.md | 8 ++- .../kibana-plugin-plugins-data-server.md | 2 +- ...plugin-plugins-data-server.plugin.start.md | 4 +- .../data/common/search/es_search/index.ts | 7 +-- .../data/common/search/es_search/types.ts | 3 ++ src/plugins/data/common/search/index.ts | 7 +-- .../search/fetch/get_search_params.test.ts | 25 +++------- src/plugins/data/server/index.ts | 1 - .../es_search/es_search_strategy.test.ts | 13 +++-- .../search/es_search/es_search_strategy.ts | 5 +- .../es_search/get_default_search_params.ts | 5 -- .../data/server/search/routes/msearch.ts | 11 ++--- .../data/server/search/routes/search.ts | 14 ++++-- src/plugins/data/server/server.api.md | 49 +++++++++++-------- .../server/search/es_search_strategy.test.ts | 35 ++++++++----- .../server/search/es_search_strategy.ts | 11 ++--- 17 files changed, 118 insertions(+), 102 deletions(-) diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getdefaultsearchparams.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getdefaultsearchparams.md index 9de005c1fd0dd..e718ca42ca30f 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getdefaultsearchparams.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getdefaultsearchparams.md @@ -7,24 +7,26 @@ Signature: ```typescript -export declare function getDefaultSearchParams(config: SharedGlobalConfig): { - timeout: string; +export declare function getDefaultSearchParams(uiSettingsClient: IUiSettingsClient): Promise<{ + maxConcurrentShardRequests: number | undefined; + ignoreThrottled: boolean; ignoreUnavailable: boolean; - restTotalHitsAsInt: boolean; -}; + trackTotalHits: boolean; +}>; ``` ## Parameters | Parameter | Type | Description | | --- | --- | --- | -| config | SharedGlobalConfig | | +| uiSettingsClient | IUiSettingsClient | | Returns: -`{ - timeout: string; +`Promise<{ + maxConcurrentShardRequests: number | undefined; + ignoreThrottled: boolean; ignoreUnavailable: boolean; - restTotalHitsAsInt: boolean; -}` + trackTotalHits: boolean; +}>` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getshardtimeout.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getshardtimeout.md index 7968379249bed..ca60c39a8e413 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getshardtimeout.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getshardtimeout.md @@ -7,7 +7,9 @@ Signature: ```typescript -export declare function getShardTimeout(config: SharedGlobalConfig): string; +export declare function getShardTimeout(config: SharedGlobalConfig): { + timeout: string; +}; ``` ## Parameters @@ -18,5 +20,7 @@ export declare function getShardTimeout(config: SharedGlobalConfig): string; Returns: -`string` +`{ + timeout: string; +}` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md index d3761e3d1ae9f..e7bfd44093f19 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md @@ -26,7 +26,7 @@ | Function | Description | | --- | --- | -| [getDefaultSearchParams(config)](./kibana-plugin-plugins-data-server.getdefaultsearchparams.md) | | +| [getDefaultSearchParams(uiSettingsClient)](./kibana-plugin-plugins-data-server.getdefaultsearchparams.md) | | | [getShardTimeout(config)](./kibana-plugin-plugins-data-server.getshardtimeout.md) | | | [getTime(indexPattern, timeRange, options)](./kibana-plugin-plugins-data-server.gettime.md) | | | [parseInterval(interval)](./kibana-plugin-plugins-data-server.parseinterval.md) | | diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.start.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.start.md index 2d9104ef894bc..455c5ecdd8195 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.start.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.start.md @@ -8,7 +8,7 @@ ```typescript start(core: CoreStart): { - search: ISearchStart>; + search: ISearchStart>; fieldFormats: { fieldFormatServiceFactory: (uiSettings: import("../../../core/server").IUiSettingsClient) => Promise; }; @@ -27,7 +27,7 @@ start(core: CoreStart): { Returns: `{ - search: ISearchStart>; + search: ISearchStart>; fieldFormats: { fieldFormatServiceFactory: (uiSettings: import("../../../core/server").IUiSettingsClient) => Promise; }; diff --git a/src/plugins/data/common/search/es_search/index.ts b/src/plugins/data/common/search/es_search/index.ts index 7bc9cada8f0ee..d8f7b5091eb8f 100644 --- a/src/plugins/data/common/search/es_search/index.ts +++ b/src/plugins/data/common/search/es_search/index.ts @@ -17,9 +17,4 @@ * under the License. */ -export { - ISearchRequestParams, - IEsSearchRequest, - IEsSearchResponse, - ES_SEARCH_STRATEGY, -} from './types'; +export * from './types'; diff --git a/src/plugins/data/common/search/es_search/types.ts b/src/plugins/data/common/search/es_search/types.ts index 3184fbe341705..9bb28c4fc9e62 100644 --- a/src/plugins/data/common/search/es_search/types.ts +++ b/src/plugins/data/common/search/es_search/types.ts @@ -42,3 +42,6 @@ export interface IEsSearchResponse extends IKibanaSearchResponse { isPartial?: boolean; rawResponse: SearchResponse; } + +export const isEsResponse = (response: any): response is IEsSearchResponse => + response && response.rawResponse; diff --git a/src/plugins/data/common/search/index.ts b/src/plugins/data/common/search/index.ts index d8184551b7f3d..ad962764b150f 100644 --- a/src/plugins/data/common/search/index.ts +++ b/src/plugins/data/common/search/index.ts @@ -23,9 +23,4 @@ export * from './expressions'; export * from './tabify'; export * from './types'; -export { - IEsSearchRequest, - IEsSearchResponse, - ES_SEARCH_STRATEGY, - ISearchRequestParams, -} from './es_search'; +export * from './es_search'; diff --git a/src/plugins/data/public/search/fetch/get_search_params.test.ts b/src/plugins/data/public/search/fetch/get_search_params.test.ts index 8b693b1dff4ee..5e83e1f57bb6d 100644 --- a/src/plugins/data/public/search/fetch/get_search_params.test.ts +++ b/src/plugins/data/public/search/fetch/get_search_params.test.ts @@ -25,23 +25,12 @@ function getConfigStub(config: any = {}): GetConfigFn { } describe('getSearchParams', () => { - test('includes ignore_throttled according to search:includeFrozen', () => { - let config = getConfigStub({ [UI_SETTINGS.SEARCH_INCLUDE_FROZEN]: true }); - let searchParams = getSearchParams(config); - expect(searchParams.ignore_throttled).toBe(false); - - config = getConfigStub({ [UI_SETTINGS.SEARCH_INCLUDE_FROZEN]: false }); - searchParams = getSearchParams(config); - expect(searchParams.ignore_throttled).toBe(true); - }); - - test('includes max_concurrent_shard_requests according to courier:maxConcurrentShardRequests', () => { - let config = getConfigStub({ [UI_SETTINGS.COURIER_MAX_CONCURRENT_SHARD_REQUESTS]: 0 }); - let searchParams = getSearchParams(config); - expect(searchParams.max_concurrent_shard_requests).toBe(undefined); - - config = getConfigStub({ [UI_SETTINGS.COURIER_MAX_CONCURRENT_SHARD_REQUESTS]: 5 }); - searchParams = getSearchParams(config); - expect(searchParams.max_concurrent_shard_requests).toBe(5); + test('includes custom preference', () => { + const config = getConfigStub({ + [UI_SETTINGS.COURIER_SET_REQUEST_PREFERENCE]: 'custom', + [UI_SETTINGS.COURIER_CUSTOM_REQUEST_PREFERENCE]: 'aaa', + }); + const searchParams = getSearchParams(config); + expect(searchParams.preference).toBe('aaa'); }); }); diff --git a/src/plugins/data/server/index.ts b/src/plugins/data/server/index.ts index 3df265c0b4fdd..302fe3703c271 100644 --- a/src/plugins/data/server/index.ts +++ b/src/plugins/data/server/index.ts @@ -214,7 +214,6 @@ export { getDefaultSearchParams, getShardTimeout, getTotalLoaded, - toSnakeCase, usageProvider, SearchUsage, } from './search'; diff --git a/src/plugins/data/server/search/es_search/es_search_strategy.test.ts b/src/plugins/data/server/search/es_search/es_search_strategy.test.ts index c34c3a310814c..87874ced7afff 100644 --- a/src/plugins/data/server/search/es_search/es_search_strategy.test.ts +++ b/src/plugins/data/server/search/es_search/es_search_strategy.test.ts @@ -36,7 +36,14 @@ describe('ES search strategy', () => { }, }); const mockContext = { - core: { elasticsearch: { client: { asCurrentUser: { search: mockApiCaller } } } }, + core: { + uiSettings: { + client: { + get: () => {}, + }, + }, + elasticsearch: { client: { asCurrentUser: { search: mockApiCaller } } }, + }, }; const mockConfig$ = pluginInitializerContextConfigMock({}).legacy.globalConfig$; @@ -61,7 +68,7 @@ describe('ES search strategy', () => { ...params, timeout: '0ms', ignoreUnavailable: true, - restTotalHitsAsInt: true, + trackTotalHits: true, }); }); @@ -74,7 +81,7 @@ describe('ES search strategy', () => { expect(mockApiCaller).toBeCalled(); expect(mockApiCaller.mock.calls[0][0]).toEqual({ ...params, - restTotalHitsAsInt: true, + trackTotalHits: true, }); }); diff --git a/src/plugins/data/server/search/es_search/es_search_strategy.ts b/src/plugins/data/server/search/es_search/es_search_strategy.ts index 05933bd646ccc..fb80cd492949d 100644 --- a/src/plugins/data/server/search/es_search/es_search_strategy.ts +++ b/src/plugins/data/server/search/es_search/es_search_strategy.ts @@ -41,8 +41,11 @@ export const esSearchStrategyProvider = ( throw new Error(`Unsupported index pattern type ${request.indexType}`); } + // ignoreThrottled is not supported in OSS + const { ignoreThrottled, ...defaultParams } = await getDefaultSearchParams(uiSettingsClient); + const params = { - ...(await getDefaultSearchParams(uiSettingsClient)), + ...defaultParams, ...getShardTimeout(config), ...request.params, }; diff --git a/src/plugins/data/server/search/es_search/get_default_search_params.ts b/src/plugins/data/server/search/es_search/get_default_search_params.ts index 0e09c56741c43..13b9bd28c854b 100644 --- a/src/plugins/data/server/search/es_search/get_default_search_params.ts +++ b/src/plugins/data/server/search/es_search/get_default_search_params.ts @@ -38,10 +38,5 @@ export async function getDefaultSearchParams(uiSettingsClient: IUiSettingsClient ignoreThrottled, ignoreUnavailable: true, // Don't fail if the index/indices don't exist trackTotalHits: true, - // restTotalHitsAsInt: true, // Get the number of hits as an int rather than a range }; } - -export function toSnakeCase(obj: Record) { - return mapKeys(obj, (value, key) => snakeCase(key)); -} diff --git a/src/plugins/data/server/search/routes/msearch.ts b/src/plugins/data/server/search/routes/msearch.ts index 7e37f69950a10..7f4563be3129f 100644 --- a/src/plugins/data/server/search/routes/msearch.ts +++ b/src/plugins/data/server/search/routes/msearch.ts @@ -22,10 +22,9 @@ import { schema } from '@kbn/config-schema'; import { SearchResponse } from 'elasticsearch'; import { IRouter } from 'src/core/server'; -import { UI_SETTINGS } from '../../../common'; import { SearchRouteDependencies } from '../search_service'; import { shimHitsTotal } from './shim_hits_total'; -import { getShardTimeout, getDefaultSearchParams, toSnakeCase } from '..'; +import { getShardTimeout, getDefaultSearchParams } from '..'; interface MsearchHeaders { index: string; @@ -103,23 +102,23 @@ export function registerMsearchRoute(router: IRouter, deps: SearchRouteDependenc const body = convertRequestBody(request.body, timeout); // trackTotalHits is not supported by msearch - const { trackTotalHits, ...params } = await getDefaultSearchParams( + const { trackTotalHits, ...defaultParams } = await getDefaultSearchParams( context.core.uiSettings.client ); try { - const response: Array> = await client.transport.request({ + const response = await client.transport.request({ method: 'GET', path: '/_msearch', body, - querystring: toSnakeCase(params), + querystring: defaultParams, }); return res.ok({ body: { ...response, body: { - responses: response.body.responses.map((r) => shimHitsTotal(r)), + responses: response.body.responses.map((r: SearchResponse) => shimHitsTotal(r)), }, }, }); diff --git a/src/plugins/data/server/search/routes/search.ts b/src/plugins/data/server/search/routes/search.ts index 0745c4c65d303..4743583b55c4b 100644 --- a/src/plugins/data/server/search/routes/search.ts +++ b/src/plugins/data/server/search/routes/search.ts @@ -19,6 +19,7 @@ import { schema } from '@kbn/config-schema'; import { IRouter } from 'src/core/server'; +import { isEsResponse } from 'src/plugins/data/common'; import { getRequestAbortedSignal } from '../../lib'; import { SearchRouteDependencies } from '../search_service'; import { shimHitsTotal } from './shim_hits_total'; @@ -58,9 +59,16 @@ export function registerSearchRoute( } ); - response.rawResponse = shimHitsTotal(response.rawResponse); - - return res.ok({ body: response }); + return res.ok({ + body: { + ...response, + ...(isEsResponse(response) + ? { + rawResponse: shimHitsTotal(response.rawResponse), + } + : {}), + }, + }); } catch (err) { return res.customError({ statusCode: err.statusCode || 500, diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md index 86da3d3281ac9..e64a6df9e79d3 100644 --- a/src/plugins/data/server/server.api.md +++ b/src/plugins/data/server/server.api.md @@ -318,20 +318,24 @@ export interface Filter { query?: any; } -// Warning: (ae-forgotten-export) The symbol "SharedGlobalConfig" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "IUiSettingsClient" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "getDefaultSearchParams" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export function getDefaultSearchParams(config: SharedGlobalConfig): { - timeout: string; +export function getDefaultSearchParams(uiSettingsClient: IUiSettingsClient): Promise<{ + maxConcurrentShardRequests: number | undefined; + ignoreThrottled: boolean; ignoreUnavailable: boolean; - restTotalHitsAsInt: boolean; -}; + trackTotalHits: boolean; +}>; +// Warning: (ae-forgotten-export) The symbol "SharedGlobalConfig" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "getShardTimeout" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export function getShardTimeout(config: SharedGlobalConfig): string; +export function getShardTimeout(config: SharedGlobalConfig): { + timeout: string; +}; // Warning: (ae-missing-release-tag) "getTime" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -747,7 +751,7 @@ export class Plugin implements Plugin_2>; + search: ISearchStart>; fieldFormats: { fieldFormatServiceFactory: (uiSettings: import("../../../core/server").IUiSettingsClient) => Promise; }; @@ -901,6 +905,11 @@ export interface TimeRange { to: string; } +// Warning: (ae-missing-release-tag) "toSnakeCase" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function toSnakeCase(obj: Record): import("lodash").Dictionary; + // Warning: (ae-missing-release-tag) "UI_SETTINGS" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -965,19 +974,19 @@ export function usageProvider(core: CoreSetup_2): SearchUsage; // src/plugins/data/server/index.ts:101:26 - (ae-forgotten-export) The symbol "TruncateFormat" needs to be exported by the entry point index.d.ts // src/plugins/data/server/index.ts:127:27 - (ae-forgotten-export) The symbol "isFilterable" needs to be exported by the entry point index.d.ts // src/plugins/data/server/index.ts:127:27 - (ae-forgotten-export) The symbol "isNestedField" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:222:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:222:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:222:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:222:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:224:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:225:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:234:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:235:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:236:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:240:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:241:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:245:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:248:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:223:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:223:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:223:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:223:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:225:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:226:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:235:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:236:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:237:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:241:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:242:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:246:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:249:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts // src/plugins/data/server/plugin.ts:88:66 - (ae-forgotten-export) The symbol "DataEnhancements" needs to be exported by the entry point index.d.ts // (No @packageDocumentation comment for this package) diff --git a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts index e5aa694fe9ee6..fdf886633f5b8 100644 --- a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts +++ b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts @@ -40,6 +40,11 @@ describe('ES search strategy', () => { }; const mockContext = { core: { + uiSettings: { + client: { + get: () => {}, + }, + }, elasticsearch: { client: { asCurrentUser: { transport: { request: mockApiCaller } } } }, }, }; @@ -78,13 +83,13 @@ describe('ES search strategy', () => { expect(method).toBe('POST'); expect(path).toBe('/logstash-*/_async_search'); expect(body).toEqual({ query: {} }); - expect(querystring).toHaveProperty('wait_for_completion_timeout'); - expect(querystring).toHaveProperty('track_total_hits'); - expect(querystring).toHaveProperty('ignore_unavailable'); - expect(querystring).toHaveProperty('ignore_throttled'); - expect(querystring).toHaveProperty('ignore_unavailable'); - expect(querystring).toHaveProperty('keep_alive'); - expect(querystring).toHaveProperty('batched_reduce_size'); + expect(querystring).toHaveProperty('batchedReduceSize'); + expect(querystring).toHaveProperty('ignoreThrottled'); + expect(querystring).toHaveProperty('ignoreUnavailable'); + expect(querystring).toHaveProperty('keepAlive'); + expect(querystring).toHaveProperty('maxConcurrentShardRequests'); + expect(querystring).toHaveProperty('trackTotalHits'); + expect(querystring).toHaveProperty('waitForCompletionTimeout'); }); it('makes a GET request to async search with ID when ID is provided', async () => { @@ -100,9 +105,13 @@ describe('ES search strategy', () => { expect(method).toBe('GET'); expect(path).toBe('/_async_search/foo'); expect(body).toEqual(undefined); - expect(querystring).not.toHaveProperty('batched_reduce_size'); - expect(querystring).not.toHaveProperty('batched_reduce_size'); - expect(querystring).not.toHaveProperty('batched_reduce_size'); + expect(querystring).not.toHaveProperty('batchedReduceSize'); + expect(querystring).not.toHaveProperty('ignoreThrottled'); + expect(querystring).not.toHaveProperty('ignoreUnavailable'); + expect(querystring).not.toHaveProperty('maxConcurrentShardRequests'); + expect(querystring).not.toHaveProperty('trackTotalHits'); + expect(querystring).toHaveProperty('keepAlive'); + expect(querystring).toHaveProperty('waitForCompletionTimeout'); }); it('encodes special characters in the path', async () => { @@ -136,7 +145,7 @@ describe('ES search strategy', () => { expect(path).toBe('/foo-%E7%A8%8B/_rollup_search'); }); - it('sets wait_for_completion_timeout and keep_alive in the request', async () => { + it('sets waitForCompletionTimeout and keepAlive in the request', async () => { mockApiCaller.mockResolvedValueOnce(mockAsyncResponse); const params = { index: 'foo-*', body: {} }; @@ -146,7 +155,7 @@ describe('ES search strategy', () => { expect(mockApiCaller).toBeCalled(); const { querystring } = mockApiCaller.mock.calls[0][0]; - expect(querystring).toHaveProperty('wait_for_completion_timeout'); - expect(querystring).toHaveProperty('keep_alive'); + expect(querystring).toHaveProperty('keepAlive'); + expect(querystring).toHaveProperty('waitForCompletionTimeout'); }); }); diff --git a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts index 94fa9b3b6266d..7e3474e2cf8d7 100644 --- a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts +++ b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts @@ -15,7 +15,6 @@ import { ISearchOptions, getDefaultSearchParams, getShardTimeout, - toSnakeCase, } from '../../../../../src/plugins/data/server'; import { IEnhancedEsSearchRequest } from '../../common'; import { IEsSearchResponse } from '../../../../../src/plugins/data/common/search/es_search'; @@ -83,7 +82,7 @@ export const enhancedEsSearchStrategyProvider = ( const method = request.id ? 'GET' : 'POST'; const path = encodeURI(request.id ? `/_async_search/${request.id}` : `/${index}/_async_search`); - const querystring = toSnakeCase({ + const querystring = { waitForCompletionTimeout: '100ms', // Wait up to 100ms for the response to return keepAlive: '1m', // Extend the TTL for this search request by one minute ...(request.id @@ -93,7 +92,7 @@ export const enhancedEsSearchStrategyProvider = ( batchedReduceSize: 64, // Only report partial results every 64 shards; this should be reduced when we actually display partial results }), ...queryParams, - }); + }; // TODO: replace with async endpoints once https://github.com/elastic/elasticsearch-js/issues/1280 is resolved const esResponse = await esClient.transport.request({ method, @@ -122,11 +121,11 @@ export const enhancedEsSearchStrategyProvider = ( const { body, index, ...params } = request.params!; const method = 'POST'; const path = encodeURI(`/${index}/_rollup_search`); - const querystring = toSnakeCase({ + const querystring = { ...getShardTimeout(config), ...(await getDefaultSearchParams(uiSettingsClient)), ...params, - }); + }; const esResponse = await esClient.transport.request({ method, @@ -137,7 +136,7 @@ export const enhancedEsSearchStrategyProvider = ( const response = esResponse.body as SearchResponse; return { - rawResponse: shimresponse, + rawResponse: response, ...getTotalLoaded(response._shards), }; }; From 34a008f9a5b1675a18778bde673c61ab822e08b0 Mon Sep 17 00:00:00 2001 From: Liza K Date: Tue, 1 Sep 2020 16:48:21 +0300 Subject: [PATCH 38/77] add management docs --- docs/management/advanced-options.asciidoc | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/management/advanced-options.asciidoc b/docs/management/advanced-options.asciidoc index 9f13c152b4cbe..c2cbeda7588d3 100644 --- a/docs/management/advanced-options.asciidoc +++ b/docs/management/advanced-options.asciidoc @@ -219,6 +219,7 @@ be inconsistent because different shards might be in different refresh states. `search:includeFrozen`:: Includes {ref}/frozen-indices.html[frozen indices] in results. Searching through frozen indices might increase the search time. This setting is off by default. Users must opt-in to include frozen indices. +`search:timeout`:: Change the maximum timeout for a search session or set to 0 to disable the timeout and allow queries to run to completion. [float] [[kibana-siem-settings]] From f9fab220da248266f6ac635727bd2d538cb1491c Mon Sep 17 00:00:00 2001 From: Liza K Date: Tue, 1 Sep 2020 17:06:21 +0300 Subject: [PATCH 39/77] docs --- .../es_search/get_default_search_params.ts | 1 - .../data/server/search/routes/search.ts | 2 +- src/plugins/data/server/server.api.md | 31 ++++++++----------- 3 files changed, 14 insertions(+), 20 deletions(-) diff --git a/src/plugins/data/server/search/es_search/get_default_search_params.ts b/src/plugins/data/server/search/es_search/get_default_search_params.ts index 13b9bd28c854b..d69c7153f797d 100644 --- a/src/plugins/data/server/search/es_search/get_default_search_params.ts +++ b/src/plugins/data/server/search/es_search/get_default_search_params.ts @@ -17,7 +17,6 @@ * under the License. */ -import { mapKeys, snakeCase } from 'lodash'; import { SharedGlobalConfig, IUiSettingsClient } from '../../../../../core/server'; import { UI_SETTINGS } from '../..'; diff --git a/src/plugins/data/server/search/routes/search.ts b/src/plugins/data/server/search/routes/search.ts index 4743583b55c4b..57366a6ca5083 100644 --- a/src/plugins/data/server/search/routes/search.ts +++ b/src/plugins/data/server/search/routes/search.ts @@ -19,10 +19,10 @@ import { schema } from '@kbn/config-schema'; import { IRouter } from 'src/core/server'; -import { isEsResponse } from 'src/plugins/data/common'; import { getRequestAbortedSignal } from '../../lib'; import { SearchRouteDependencies } from '../search_service'; import { shimHitsTotal } from './shim_hits_total'; +import { isEsResponse } from '../../../common'; export function registerSearchRoute( router: IRouter, diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md index e64a6df9e79d3..0e0dd70f3e85c 100644 --- a/src/plugins/data/server/server.api.md +++ b/src/plugins/data/server/server.api.md @@ -905,11 +905,6 @@ export interface TimeRange { to: string; } -// Warning: (ae-missing-release-tag) "toSnakeCase" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export function toSnakeCase(obj: Record): import("lodash").Dictionary; - // Warning: (ae-missing-release-tag) "UI_SETTINGS" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -974,19 +969,19 @@ export function usageProvider(core: CoreSetup_2): SearchUsage; // src/plugins/data/server/index.ts:101:26 - (ae-forgotten-export) The symbol "TruncateFormat" needs to be exported by the entry point index.d.ts // src/plugins/data/server/index.ts:127:27 - (ae-forgotten-export) The symbol "isFilterable" needs to be exported by the entry point index.d.ts // src/plugins/data/server/index.ts:127:27 - (ae-forgotten-export) The symbol "isNestedField" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:223:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:223:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:223:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:223:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:225:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:226:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:235:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:236:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:237:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:241:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:242:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:246:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:249:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:222:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:222:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:222:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:222:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:224:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:225:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:234:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:235:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:236:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:240:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:241:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:245:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:248:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts // src/plugins/data/server/plugin.ts:88:66 - (ae-forgotten-export) The symbol "DataEnhancements" needs to be exported by the entry point index.d.ts // (No @packageDocumentation comment for this package) From a601601875e5c6046864eaeb3e05fda358bbc87e Mon Sep 17 00:00:00 2001 From: Liza K Date: Tue, 1 Sep 2020 17:58:13 +0300 Subject: [PATCH 40/77] Remove import --- x-pack/plugins/data_enhanced/common/search/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugins/data_enhanced/common/search/index.ts b/x-pack/plugins/data_enhanced/common/search/index.ts index 2ae422bd6b7d7..696938a403e89 100644 --- a/x-pack/plugins/data_enhanced/common/search/index.ts +++ b/x-pack/plugins/data_enhanced/common/search/index.ts @@ -5,7 +5,6 @@ */ export { - EnhancedSearchParams, IEnhancedEsSearchRequest, IAsyncSearchRequest, ENHANCED_ES_SEARCH_STRATEGY, From cb1951e4a1098293c2f8ff0a7dfc3613359ec957 Mon Sep 17 00:00:00 2001 From: Liza K Date: Tue, 1 Sep 2020 19:35:43 +0300 Subject: [PATCH 41/77] Break circular dep + fix msearch test --- .../data/server/search/es_search/get_default_search_params.ts | 2 +- src/plugins/data/server/search/es_search/index.ts | 3 ++- src/plugins/data/server/search/routes/msearch.test.ts | 2 +- src/plugins/data/server/search/routes/msearch.ts | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/plugins/data/server/search/es_search/get_default_search_params.ts b/src/plugins/data/server/search/es_search/get_default_search_params.ts index d69c7153f797d..f6267ebfbf4d0 100644 --- a/src/plugins/data/server/search/es_search/get_default_search_params.ts +++ b/src/plugins/data/server/search/es_search/get_default_search_params.ts @@ -18,7 +18,7 @@ */ import { SharedGlobalConfig, IUiSettingsClient } from '../../../../../core/server'; -import { UI_SETTINGS } from '../..'; +import { UI_SETTINGS } from '../../../common/constants'; export function getShardTimeout(config: SharedGlobalConfig) { return { diff --git a/src/plugins/data/server/search/es_search/index.ts b/src/plugins/data/server/search/es_search/index.ts index 3418a6a987828..038622cbae36e 100644 --- a/src/plugins/data/server/search/es_search/index.ts +++ b/src/plugins/data/server/search/es_search/index.ts @@ -17,7 +17,8 @@ * under the License. */ -export { ES_SEARCH_STRATEGY, IEsSearchRequest, IEsSearchResponse } from '../../../common/search'; export { esSearchStrategyProvider } from './es_search_strategy'; export * from './get_default_search_params'; export { getTotalLoaded } from './get_total_loaded'; + +export { ES_SEARCH_STRATEGY, IEsSearchRequest, IEsSearchResponse } from '../../../common'; diff --git a/src/plugins/data/server/search/routes/msearch.test.ts b/src/plugins/data/server/search/routes/msearch.test.ts index 0a52cf23c5472..f069ec17b42fa 100644 --- a/src/plugins/data/server/search/routes/msearch.test.ts +++ b/src/plugins/data/server/search/routes/msearch.test.ts @@ -48,7 +48,7 @@ describe('msearch route', () => { }); it('handler calls /_msearch with the given request', async () => { - const response = { id: 'yay' }; + const response = { id: 'yay', body: { responses: [{}] } }; const mockClient = { transport: { request: jest.fn().mockResolvedValue(response) } }; const mockContext = { core: { diff --git a/src/plugins/data/server/search/routes/msearch.ts b/src/plugins/data/server/search/routes/msearch.ts index 7f4563be3129f..a788e6ac55e31 100644 --- a/src/plugins/data/server/search/routes/msearch.ts +++ b/src/plugins/data/server/search/routes/msearch.ts @@ -118,7 +118,7 @@ export function registerMsearchRoute(router: IRouter, deps: SearchRouteDependenc body: { ...response, body: { - responses: response.body.responses.map((r: SearchResponse) => shimHitsTotal(r)), + responses: response.body.responses?.map((r: SearchResponse) => shimHitsTotal(r)), }, }, }); From 4921152199baaed788a23d687e4d890225c01531 Mon Sep 17 00:00:00 2001 From: Liza K Date: Tue, 1 Sep 2020 19:36:58 +0300 Subject: [PATCH 42/77] Remove deleted type --- x-pack/plugins/data_enhanced/common/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugins/data_enhanced/common/index.ts b/x-pack/plugins/data_enhanced/common/index.ts index d6a3c73aaf363..012f1204da46a 100644 --- a/x-pack/plugins/data_enhanced/common/index.ts +++ b/x-pack/plugins/data_enhanced/common/index.ts @@ -5,7 +5,6 @@ */ export { - EnhancedSearchParams, IEnhancedEsSearchRequest, IAsyncSearchRequest, ENHANCED_ES_SEARCH_STRATEGY, From 0b954df1527a8d02920f680862640879b8a192df Mon Sep 17 00:00:00 2001 From: Liza K Date: Tue, 1 Sep 2020 20:02:17 +0300 Subject: [PATCH 43/77] Fix jest --- src/plugins/data/server/search/routes/msearch.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/data/server/search/routes/msearch.test.ts b/src/plugins/data/server/search/routes/msearch.test.ts index f069ec17b42fa..f1b99a41c8532 100644 --- a/src/plugins/data/server/search/routes/msearch.test.ts +++ b/src/plugins/data/server/search/routes/msearch.test.ts @@ -48,7 +48,7 @@ describe('msearch route', () => { }); it('handler calls /_msearch with the given request', async () => { - const response = { id: 'yay', body: { responses: [{}] } }; + const response = { id: 'yay', body: { responses: [{ hits: { total: 5 } }] } }; const mockClient = { transport: { request: jest.fn().mockResolvedValue(response) } }; const mockContext = { core: { From 3f8b19a7be2b0294edd4fbc8c6e7e6ecf00b7cf2 Mon Sep 17 00:00:00 2001 From: Liza K Date: Wed, 2 Sep 2020 16:54:15 +0300 Subject: [PATCH 44/77] Bring toSnakeCase back --- src/plugins/data/server/index.ts | 1 + .../search/es_search/es_search_strategy.ts | 5 ++-- .../data/server/search/es_search/index.ts | 1 + .../server/search/es_search/to_snake_case.ts | 24 +++++++++++++++++++ .../data/server/search/routes/msearch.ts | 4 ++-- .../server/search/es_search_strategy.ts | 9 +++---- 6 files changed, 36 insertions(+), 8 deletions(-) create mode 100644 src/plugins/data/server/search/es_search/to_snake_case.ts diff --git a/src/plugins/data/server/index.ts b/src/plugins/data/server/index.ts index 302fe3703c271..7e59084bf2862 100644 --- a/src/plugins/data/server/index.ts +++ b/src/plugins/data/server/index.ts @@ -211,6 +211,7 @@ export { ISearchOptions, ISearchSetup, ISearchStart, + toSnakeCase, getDefaultSearchParams, getShardTimeout, getTotalLoaded, diff --git a/src/plugins/data/server/search/es_search/es_search_strategy.ts b/src/plugins/data/server/search/es_search/es_search_strategy.ts index fb80cd492949d..106f974ed3457 100644 --- a/src/plugins/data/server/search/es_search/es_search_strategy.ts +++ b/src/plugins/data/server/search/es_search/es_search_strategy.ts @@ -22,6 +22,7 @@ import { SearchResponse } from 'elasticsearch'; import { Observable } from 'rxjs'; import { ApiResponse } from '@elastic/elasticsearch'; import { SearchUsage } from '../collectors/usage'; +import { toSnakeCase } from './to_snake_case'; import { ISearchStrategy, getDefaultSearchParams, getTotalLoaded, getShardTimeout } from '..'; export const esSearchStrategyProvider = ( @@ -44,11 +45,11 @@ export const esSearchStrategyProvider = ( // ignoreThrottled is not supported in OSS const { ignoreThrottled, ...defaultParams } = await getDefaultSearchParams(uiSettingsClient); - const params = { + const params = toSnakeCase({ ...defaultParams, ...getShardTimeout(config), ...request.params, - }; + }); try { const esResponse = (await context.core.elasticsearch.client.asCurrentUser.search( diff --git a/src/plugins/data/server/search/es_search/index.ts b/src/plugins/data/server/search/es_search/index.ts index 038622cbae36e..1bd17fc986168 100644 --- a/src/plugins/data/server/search/es_search/index.ts +++ b/src/plugins/data/server/search/es_search/index.ts @@ -20,5 +20,6 @@ export { esSearchStrategyProvider } from './es_search_strategy'; export * from './get_default_search_params'; export { getTotalLoaded } from './get_total_loaded'; +export * from './to_snake_case'; export { ES_SEARCH_STRATEGY, IEsSearchRequest, IEsSearchResponse } from '../../../common'; diff --git a/src/plugins/data/server/search/es_search/to_snake_case.ts b/src/plugins/data/server/search/es_search/to_snake_case.ts new file mode 100644 index 0000000000000..74f156274cbc6 --- /dev/null +++ b/src/plugins/data/server/search/es_search/to_snake_case.ts @@ -0,0 +1,24 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { mapKeys, snakeCase } from 'lodash'; + +export function toSnakeCase(obj: Record) { + return mapKeys(obj, (value, key) => snakeCase(key)); +} diff --git a/src/plugins/data/server/search/routes/msearch.ts b/src/plugins/data/server/search/routes/msearch.ts index a788e6ac55e31..cbb2621594c0e 100644 --- a/src/plugins/data/server/search/routes/msearch.ts +++ b/src/plugins/data/server/search/routes/msearch.ts @@ -24,7 +24,7 @@ import { SearchResponse } from 'elasticsearch'; import { IRouter } from 'src/core/server'; import { SearchRouteDependencies } from '../search_service'; import { shimHitsTotal } from './shim_hits_total'; -import { getShardTimeout, getDefaultSearchParams } from '..'; +import { getShardTimeout, getDefaultSearchParams, toSnakeCase } from '..'; interface MsearchHeaders { index: string; @@ -111,7 +111,7 @@ export function registerMsearchRoute(router: IRouter, deps: SearchRouteDependenc method: 'GET', path: '/_msearch', body, - querystring: defaultParams, + querystring: toSnakeCase(defaultParams), }); return res.ok({ diff --git a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts index 7e3474e2cf8d7..8f3b70c6dfe47 100644 --- a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts +++ b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts @@ -15,6 +15,7 @@ import { ISearchOptions, getDefaultSearchParams, getShardTimeout, + toSnakeCase, } from '../../../../../src/plugins/data/server'; import { IEnhancedEsSearchRequest } from '../../common'; import { IEsSearchResponse } from '../../../../../src/plugins/data/common/search/es_search'; @@ -82,7 +83,7 @@ export const enhancedEsSearchStrategyProvider = ( const method = request.id ? 'GET' : 'POST'; const path = encodeURI(request.id ? `/_async_search/${request.id}` : `/${index}/_async_search`); - const querystring = { + const querystring = toSnakeCase({ waitForCompletionTimeout: '100ms', // Wait up to 100ms for the response to return keepAlive: '1m', // Extend the TTL for this search request by one minute ...(request.id @@ -92,7 +93,7 @@ export const enhancedEsSearchStrategyProvider = ( batchedReduceSize: 64, // Only report partial results every 64 shards; this should be reduced when we actually display partial results }), ...queryParams, - }; + }); // TODO: replace with async endpoints once https://github.com/elastic/elasticsearch-js/issues/1280 is resolved const esResponse = await esClient.transport.request({ method, @@ -121,11 +122,11 @@ export const enhancedEsSearchStrategyProvider = ( const { body, index, ...params } = request.params!; const method = 'POST'; const path = encodeURI(`/${index}/_rollup_search`); - const querystring = { + const querystring = toSnakeCase({ ...getShardTimeout(config), ...(await getDefaultSearchParams(uiSettingsClient)), ...params, - }; + }); const esResponse = await esClient.transport.request({ method, From b000274490dd2bb29823119210185d37d37023de Mon Sep 17 00:00:00 2001 From: Liza K Date: Wed, 2 Sep 2020 16:59:15 +0300 Subject: [PATCH 45/77] docs --- .../kibana-plugin-plugins-data-server.md | 1 + ...-plugin-plugins-data-server.tosnakecase.md | 22 +++++++++++++ src/plugins/data/server/server.api.md | 31 +++++++++++-------- 3 files changed, 41 insertions(+), 13 deletions(-) create mode 100644 docs/development/plugins/data/server/kibana-plugin-plugins-data-server.tosnakecase.md diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md index e7bfd44093f19..04bfb492178a3 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md @@ -32,6 +32,7 @@ | [parseInterval(interval)](./kibana-plugin-plugins-data-server.parseinterval.md) | | | [plugin(initializerContext)](./kibana-plugin-plugins-data-server.plugin.md) | Static code to be shared externally | | [shouldReadFieldFromDocValues(aggregatable, esType)](./kibana-plugin-plugins-data-server.shouldreadfieldfromdocvalues.md) | | +| [toSnakeCase(obj)](./kibana-plugin-plugins-data-server.tosnakecase.md) | | | [usageProvider(core)](./kibana-plugin-plugins-data-server.usageprovider.md) | | ## Interfaces diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.tosnakecase.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.tosnakecase.md new file mode 100644 index 0000000000000..eda9e9c312e59 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.tosnakecase.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [toSnakeCase](./kibana-plugin-plugins-data-server.tosnakecase.md) + +## toSnakeCase() function + +Signature: + +```typescript +export declare function toSnakeCase(obj: Record): import("lodash").Dictionary; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| obj | Record<string, any> | | + +Returns: + +`import("lodash").Dictionary` + diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md index 0e0dd70f3e85c..e64a6df9e79d3 100644 --- a/src/plugins/data/server/server.api.md +++ b/src/plugins/data/server/server.api.md @@ -905,6 +905,11 @@ export interface TimeRange { to: string; } +// Warning: (ae-missing-release-tag) "toSnakeCase" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function toSnakeCase(obj: Record): import("lodash").Dictionary; + // Warning: (ae-missing-release-tag) "UI_SETTINGS" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -969,19 +974,19 @@ export function usageProvider(core: CoreSetup_2): SearchUsage; // src/plugins/data/server/index.ts:101:26 - (ae-forgotten-export) The symbol "TruncateFormat" needs to be exported by the entry point index.d.ts // src/plugins/data/server/index.ts:127:27 - (ae-forgotten-export) The symbol "isFilterable" needs to be exported by the entry point index.d.ts // src/plugins/data/server/index.ts:127:27 - (ae-forgotten-export) The symbol "isNestedField" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:222:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:222:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:222:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:222:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:224:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:225:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:234:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:235:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:236:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:240:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:241:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:245:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:248:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:223:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:223:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:223:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:223:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:225:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:226:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:235:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:236:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:237:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:241:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:242:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:246:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:249:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts // src/plugins/data/server/plugin.ts:88:66 - (ae-forgotten-export) The symbol "DataEnhancements" needs to be exported by the entry point index.d.ts // (No @packageDocumentation comment for this package) From 504814d30beea1dfb55dfe2837bc67c5cb76c284 Mon Sep 17 00:00:00 2001 From: Liza K Date: Wed, 2 Sep 2020 18:42:20 +0300 Subject: [PATCH 46/77] fix jest --- .../es_search/es_search_strategy.test.ts | 8 ++--- .../server/search/es_search_strategy.test.ts | 32 +++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/plugins/data/server/search/es_search/es_search_strategy.test.ts b/src/plugins/data/server/search/es_search/es_search_strategy.test.ts index 87874ced7afff..c5c193ee04b2f 100644 --- a/src/plugins/data/server/search/es_search/es_search_strategy.test.ts +++ b/src/plugins/data/server/search/es_search/es_search_strategy.test.ts @@ -67,13 +67,13 @@ describe('ES search strategy', () => { expect(mockApiCaller.mock.calls[0][0]).toEqual({ ...params, timeout: '0ms', - ignoreUnavailable: true, - trackTotalHits: true, + ignore_unavailable: true, + track_total_hits: true, }); }); it('calls the API caller with overridden defaults', async () => { - const params = { index: 'logstash-*', ignoreUnavailable: false, timeout: '1000ms' }; + const params = { index: 'logstash-*', ignore_unavailable: false, timeout: '1000ms' }; const esSearch = await esSearchStrategyProvider(mockConfig$, mockLogger); await esSearch.search((mockContext as unknown) as RequestHandlerContext, { params }); @@ -81,7 +81,7 @@ describe('ES search strategy', () => { expect(mockApiCaller).toBeCalled(); expect(mockApiCaller.mock.calls[0][0]).toEqual({ ...params, - trackTotalHits: true, + track_total_hits: true, }); }); diff --git a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts index fdf886633f5b8..5afd00df24cf6 100644 --- a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts +++ b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts @@ -83,13 +83,13 @@ describe('ES search strategy', () => { expect(method).toBe('POST'); expect(path).toBe('/logstash-*/_async_search'); expect(body).toEqual({ query: {} }); - expect(querystring).toHaveProperty('batchedReduceSize'); - expect(querystring).toHaveProperty('ignoreThrottled'); - expect(querystring).toHaveProperty('ignoreUnavailable'); - expect(querystring).toHaveProperty('keepAlive'); - expect(querystring).toHaveProperty('maxConcurrentShardRequests'); - expect(querystring).toHaveProperty('trackTotalHits'); - expect(querystring).toHaveProperty('waitForCompletionTimeout'); + expect(querystring).toHaveProperty('batched_reduce_size'); + expect(querystring).toHaveProperty('ignore_throttled'); + expect(querystring).toHaveProperty('ignore_unavailable'); + expect(querystring).toHaveProperty('max_concurrent_shard_requests'); + expect(querystring).toHaveProperty('track_total_hits'); + expect(querystring).toHaveProperty('keep_alive'); + expect(querystring).toHaveProperty('wait_for_completion_timeout'); }); it('makes a GET request to async search with ID when ID is provided', async () => { @@ -105,13 +105,13 @@ describe('ES search strategy', () => { expect(method).toBe('GET'); expect(path).toBe('/_async_search/foo'); expect(body).toEqual(undefined); - expect(querystring).not.toHaveProperty('batchedReduceSize'); - expect(querystring).not.toHaveProperty('ignoreThrottled'); - expect(querystring).not.toHaveProperty('ignoreUnavailable'); - expect(querystring).not.toHaveProperty('maxConcurrentShardRequests'); - expect(querystring).not.toHaveProperty('trackTotalHits'); - expect(querystring).toHaveProperty('keepAlive'); - expect(querystring).toHaveProperty('waitForCompletionTimeout'); + expect(querystring).not.toHaveProperty('batched_reduce_size'); + expect(querystring).not.toHaveProperty('ignore_throttled'); + expect(querystring).not.toHaveProperty('ignore_unavailable'); + expect(querystring).not.toHaveProperty('max_concurrent_shard_requests'); + expect(querystring).not.toHaveProperty('track_total_hits'); + expect(querystring).toHaveProperty('keep_alive'); + expect(querystring).toHaveProperty('wait_for_completion_timeout'); }); it('encodes special characters in the path', async () => { @@ -155,7 +155,7 @@ describe('ES search strategy', () => { expect(mockApiCaller).toBeCalled(); const { querystring } = mockApiCaller.mock.calls[0][0]; - expect(querystring).toHaveProperty('keepAlive'); - expect(querystring).toHaveProperty('waitForCompletionTimeout'); + expect(querystring).toHaveProperty('keep_alive'); + expect(querystring).toHaveProperty('wait_for_completion_timeout'); }); }); From 5e0959ac3b82bc80c303611f844eca641a51ceec Mon Sep 17 00:00:00 2001 From: Liza K Date: Sun, 23 Aug 2020 18:38:02 +0300 Subject: [PATCH 47/77] Add new x-pack advanced setting searchTimeout and use it in the EnhancedSearchInterceptor --- src/plugins/data/common/constants.ts | 1 + .../data/public/search/search_interceptor.ts | 15 +++++----- x-pack/plugins/data_enhanced/public/plugin.ts | 25 +++++++++-------- .../public/search/search_interceptor.ts | 21 ++++++++++---- x-pack/plugins/data_enhanced/server/plugin.ts | 3 ++ .../data_enhanced/server/ui_settings.ts | 28 +++++++++++++++++++ 6 files changed, 69 insertions(+), 24 deletions(-) create mode 100644 x-pack/plugins/data_enhanced/server/ui_settings.ts diff --git a/src/plugins/data/common/constants.ts b/src/plugins/data/common/constants.ts index 22db1552e4303..43120583bd3a4 100644 --- a/src/plugins/data/common/constants.ts +++ b/src/plugins/data/common/constants.ts @@ -32,6 +32,7 @@ export const UI_SETTINGS = { COURIER_MAX_CONCURRENT_SHARD_REQUESTS: 'courier:maxConcurrentShardRequests', COURIER_BATCH_SEARCHES: 'courier:batchSearches', SEARCH_INCLUDE_FROZEN: 'search:includeFrozen', + SEARCH_TIMEOUT: 'search:timeout', HISTOGRAM_BAR_TARGET: 'histogram:barTarget', HISTOGRAM_MAX_BARS: 'histogram:maxBars', HISTORY_LIMIT: 'history:limit', diff --git a/src/plugins/data/public/search/search_interceptor.ts b/src/plugins/data/public/search/search_interceptor.ts index c6c03267163c9..943d7a86c1a62 100644 --- a/src/plugins/data/public/search/search_interceptor.ts +++ b/src/plugins/data/public/search/search_interceptor.ts @@ -72,16 +72,13 @@ export class SearchInterceptor { protected application!: CoreStart['application']; /** - * This class should be instantiated with a `requestTimeout` corresponding with how many ms after + * This class should be instantiated with a `searchTimeout` corresponding with how many ms after * requests are initiated that they should automatically cancel. * @param toasts The `core.notifications.toasts` service * @param application The `core.application` service - * @param requestTimeout Usually config value `elasticsearch.requestTimeout` + * @param searchTimeout Timeout for running search requests */ - constructor( - protected readonly deps: SearchInterceptorDeps, - protected readonly requestTimeout?: number - ) { + constructor(protected readonly deps: SearchInterceptorDeps, protected searchTimeout?: number) { this.deps.http.addLoadingCountSource(this.pendingCount$); this.deps.startServices.then(([coreStart]) => { @@ -95,6 +92,10 @@ export class SearchInterceptor { .subscribe(this.hideToast); } + protected setSearchTimeout(timeout?: number) { + this.searchTimeout = timeout; + } + /** * Returns an `Observable` over the current number of pending searches. This could mean that one * of the search requests is still in flight, or that it has only received partial responses. @@ -152,7 +153,7 @@ export class SearchInterceptor { // Schedule this request to automatically timeout after some interval const timeoutController = new AbortController(); const { signal: timeoutSignal } = timeoutController; - const timeout$ = timer(this.requestTimeout); + const timeout$ = timer(this.searchTimeout); const subscription = timeout$.subscribe(() => { timeoutController.abort(); }); diff --git a/x-pack/plugins/data_enhanced/public/plugin.ts b/x-pack/plugins/data_enhanced/public/plugin.ts index 7f6e3feac0671..ccc93316482c2 100644 --- a/x-pack/plugins/data_enhanced/public/plugin.ts +++ b/x-pack/plugins/data_enhanced/public/plugin.ts @@ -23,6 +23,8 @@ export type DataEnhancedStart = ReturnType; export class DataEnhancedPlugin implements Plugin { + private enhancedSearchInterceptor!: EnhancedSearchInterceptor; + public setup( core: CoreSetup, { data }: DataEnhancedSetupDependencies @@ -32,20 +34,17 @@ export class DataEnhancedPlugin setupKqlQuerySuggestionProvider(core) ); - const enhancedSearchInterceptor = new EnhancedSearchInterceptor( - { - toasts: core.notifications.toasts, - http: core.http, - uiSettings: core.uiSettings, - startServices: core.getStartServices(), - usageCollector: data.search.usageCollector, - }, - core.injectedMetadata.getInjectedVar('esRequestTimeout') as number - ); + this.enhancedSearchInterceptor = new EnhancedSearchInterceptor({ + toasts: core.notifications.toasts, + http: core.http, + uiSettings: core.uiSettings, + startServices: core.getStartServices(), + usageCollector: data.search.usageCollector, + }); data.__enhance({ search: { - searchInterceptor: enhancedSearchInterceptor, + searchInterceptor: this.enhancedSearchInterceptor, }, }); } @@ -53,4 +52,8 @@ export class DataEnhancedPlugin public start(core: CoreStart, plugins: DataEnhancedStartDependencies) { setAutocompleteService(plugins.data.autocomplete); } + + public stop() { + this.enhancedSearchInterceptor.stop(); + } } diff --git a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts index 6f7899d1188b4..bddae2edfdf54 100644 --- a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts +++ b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { throwError, EMPTY, timer, from } from 'rxjs'; +import { throwError, EMPTY, timer, from, Subscription } from 'rxjs'; import { mergeMap, expand, takeUntil, finalize, tap } from 'rxjs/operators'; import { getLongQueryNotification } from './long_query_notification'; import { @@ -17,14 +17,23 @@ import { IAsyncSearchOptions } from '.'; import { IAsyncSearchRequest, ENHANCED_ES_SEARCH_STRATEGY } from '../../common'; export class EnhancedSearchInterceptor extends SearchInterceptor { + private uiSettingsSub: Subscription; + /** - * This class should be instantiated with a `requestTimeout` corresponding with how many ms after - * requests are initiated that they should automatically cancel. * @param deps `SearchInterceptorDeps` - * @param requestTimeout Usually config value `elasticsearch.requestTimeout` */ - constructor(deps: SearchInterceptorDeps, requestTimeout?: number) { - super(deps, requestTimeout); + constructor(deps: SearchInterceptorDeps) { + super(deps, deps.uiSettings.get(UI_SETTINGS.SEARCH_TIMEOUT)); + + this.uiSettingsSub = deps.uiSettings + .get$(UI_SETTINGS.SEARCH_TIMEOUT) + .subscribe((timeout: number) => { + this.setSearchTimeout(timeout); + }); + } + + public stop() { + this.uiSettingsSub.unsubscribe(); } /** diff --git a/x-pack/plugins/data_enhanced/server/plugin.ts b/x-pack/plugins/data_enhanced/server/plugin.ts index f9b6fd4e9ad64..3b05e83d208b7 100644 --- a/x-pack/plugins/data_enhanced/server/plugin.ts +++ b/x-pack/plugins/data_enhanced/server/plugin.ts @@ -19,6 +19,7 @@ import { import { enhancedEsSearchStrategyProvider } from './search'; import { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/server'; import { ENHANCED_ES_SEARCH_STRATEGY } from '../common'; +import { getUiSettings } from './ui_settings'; interface SetupDependencies { data: DataPluginSetup; @@ -35,6 +36,8 @@ export class EnhancedDataServerPlugin implements Plugin, deps: SetupDependencies) { const usage = deps.usageCollection ? usageProvider(core) : undefined; + core.uiSettings.register(getUiSettings()); + deps.data.search.registerSearchStrategy( ENHANCED_ES_SEARCH_STRATEGY, enhancedEsSearchStrategyProvider( diff --git a/x-pack/plugins/data_enhanced/server/ui_settings.ts b/x-pack/plugins/data_enhanced/server/ui_settings.ts new file mode 100644 index 0000000000000..76b84a7d09fee --- /dev/null +++ b/x-pack/plugins/data_enhanced/server/ui_settings.ts @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { i18n } from '@kbn/i18n'; +import { schema } from '@kbn/config-schema'; +import { UiSettingsParams } from 'kibana/server'; +import { UI_SETTINGS } from '../../../../src/plugins/data/server'; + +export function getUiSettings(): Record> { + return { + [UI_SETTINGS.SEARCH_TIMEOUT]: { + name: i18n.translate('kbn.advancedSettings.searchTimeout', { + defaultMessage: 'Search Timeout', + }), + value: 600000, + description: i18n.translate('kbn.advancedSettings.searchTimeoutDesc', { + defaultMessage: + 'Change the maximum timeout for a search session or set to 0 to disable the timeout and allow queries to run to completion.', + }), + type: 'number', + category: ['search'], + schema: schema.number(), + }, + }; +} From a682fb70cbd934c4bd5b9764174613f8bd0b0729 Mon Sep 17 00:00:00 2001 From: Liza K Date: Sun, 23 Aug 2020 18:58:10 +0300 Subject: [PATCH 48/77] docs --- ...-public.searchinterceptor._constructor_.md | 6 ++-- ...n-plugins-data-public.searchinterceptor.md | 5 +--- ...public.searchinterceptor.requesttimeout.md | 11 -------- ...data-public.searchinterceptor.runsearch.md | 24 ---------------- ...ta-public.searchinterceptor.setuptimers.md | 28 ------------------- ...-plugin-plugins-data-public.ui_settings.md | 1 + ...-plugin-plugins-data-server.ui_settings.md | 1 + src/plugins/data/public/public.api.md | 13 +++++---- .../data/public/search/search_interceptor.ts | 23 +++++++++++---- src/plugins/data/server/server.api.md | 1 + .../public/search/search_interceptor.ts | 2 +- 11 files changed, 33 insertions(+), 82 deletions(-) delete mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.requesttimeout.md delete mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.runsearch.md delete mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.setuptimers.md diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor._constructor_.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor._constructor_.md index 6f5dd1076fb40..dd613725470db 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor._constructor_.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor._constructor_.md @@ -4,12 +4,12 @@ ## SearchInterceptor.(constructor) -This class should be instantiated with a `requestTimeout` corresponding with how many ms after requests are initiated that they should automatically cancel. +Constructs a new instance of the `SearchInterceptor` class Signature: ```typescript -constructor(deps: SearchInterceptorDeps, requestTimeout?: number | undefined); +constructor(deps: SearchInterceptorDeps, searchTimeout?: number); ``` ## Parameters @@ -17,5 +17,5 @@ constructor(deps: SearchInterceptorDeps, requestTimeout?: number | undefined); | Parameter | Type | Description | | --- | --- | --- | | deps | SearchInterceptorDeps | | -| requestTimeout | number | undefined | | +| searchTimeout | number | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md index 32954927504ae..f2e30a0c04cfc 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md @@ -14,21 +14,18 @@ export declare class SearchInterceptor | Constructor | Modifiers | Description | | --- | --- | --- | -| [(constructor)(deps, requestTimeout)](./kibana-plugin-plugins-data-public.searchinterceptor._constructor_.md) | | This class should be instantiated with a requestTimeout corresponding with how many ms after requests are initiated that they should automatically cancel. | +| [(constructor)(deps, searchTimeout)](./kibana-plugin-plugins-data-public.searchinterceptor._constructor_.md) | | Constructs a new instance of the SearchInterceptor class | ## Properties | Property | Modifiers | Type | Description | | --- | --- | --- | --- | | [deps](./kibana-plugin-plugins-data-public.searchinterceptor.deps.md) | | SearchInterceptorDeps | | -| [requestTimeout](./kibana-plugin-plugins-data-public.searchinterceptor.requesttimeout.md) | | number | undefined | | ## Methods | Method | Modifiers | Description | | --- | --- | --- | | [getPendingCount$()](./kibana-plugin-plugins-data-public.searchinterceptor.getpendingcount_.md) | | Returns an Observable over the current number of pending searches. This could mean that one of the search requests is still in flight, or that it has only received partial responses. | -| [runSearch(request, signal, strategy)](./kibana-plugin-plugins-data-public.searchinterceptor.runsearch.md) | | | | [search(request, options)](./kibana-plugin-plugins-data-public.searchinterceptor.search.md) | | Searches using the given search method. Overrides the AbortSignal with one that will abort either when cancelPending is called, when the request times out, or when the original AbortSignal is aborted. Updates pendingCount$ when the request is started/finalized. | -| [setupTimers(options)](./kibana-plugin-plugins-data-public.searchinterceptor.setuptimers.md) | | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.requesttimeout.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.requesttimeout.md deleted file mode 100644 index 3123433762991..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.requesttimeout.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchInterceptor](./kibana-plugin-plugins-data-public.searchinterceptor.md) > [requestTimeout](./kibana-plugin-plugins-data-public.searchinterceptor.requesttimeout.md) - -## SearchInterceptor.requestTimeout property - -Signature: - -```typescript -protected readonly requestTimeout?: number | undefined; -``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.runsearch.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.runsearch.md deleted file mode 100644 index ad1d1dcb59d7b..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.runsearch.md +++ /dev/null @@ -1,24 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchInterceptor](./kibana-plugin-plugins-data-public.searchinterceptor.md) > [runSearch](./kibana-plugin-plugins-data-public.searchinterceptor.runsearch.md) - -## SearchInterceptor.runSearch() method - -Signature: - -```typescript -protected runSearch(request: IEsSearchRequest, signal: AbortSignal, strategy?: string): Observable; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| request | IEsSearchRequest | | -| signal | AbortSignal | | -| strategy | string | | - -Returns: - -`Observable` - diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.setuptimers.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.setuptimers.md deleted file mode 100644 index fe35655258b4c..0000000000000 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.setuptimers.md +++ /dev/null @@ -1,28 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [SearchInterceptor](./kibana-plugin-plugins-data-public.searchinterceptor.md) > [setupTimers](./kibana-plugin-plugins-data-public.searchinterceptor.setuptimers.md) - -## SearchInterceptor.setupTimers() method - -Signature: - -```typescript -protected setupTimers(options?: ISearchOptions): { - combinedSignal: AbortSignal; - cleanup: () => void; - }; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| options | ISearchOptions | | - -Returns: - -`{ - combinedSignal: AbortSignal; - cleanup: () => void; - }` - diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ui_settings.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ui_settings.md index e515c3513df6c..6ed20beb396f1 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ui_settings.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.ui_settings.md @@ -20,6 +20,7 @@ UI_SETTINGS: { readonly COURIER_MAX_CONCURRENT_SHARD_REQUESTS: "courier:maxConcurrentShardRequests"; readonly COURIER_BATCH_SEARCHES: "courier:batchSearches"; readonly SEARCH_INCLUDE_FROZEN: "search:includeFrozen"; + readonly SEARCH_TIMEOUT: "search:timeout"; readonly HISTOGRAM_BAR_TARGET: "histogram:barTarget"; readonly HISTOGRAM_MAX_BARS: "histogram:maxBars"; readonly HISTORY_LIMIT: "history:limit"; diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.ui_settings.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.ui_settings.md index e419b64cd43aa..2d4ce75b956df 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.ui_settings.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.ui_settings.md @@ -20,6 +20,7 @@ UI_SETTINGS: { readonly COURIER_MAX_CONCURRENT_SHARD_REQUESTS: "courier:maxConcurrentShardRequests"; readonly COURIER_BATCH_SEARCHES: "courier:batchSearches"; readonly SEARCH_INCLUDE_FROZEN: "search:includeFrozen"; + readonly SEARCH_TIMEOUT: "search:timeout"; readonly HISTOGRAM_BAR_TARGET: "histogram:barTarget"; readonly HISTOGRAM_MAX_BARS: "histogram:maxBars"; readonly HISTORY_LIMIT: "history:limit"; diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index b7e7e81ae2cef..d623880c496ff 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -1711,7 +1711,7 @@ export interface SearchError { // // @public (undocumented) export class SearchInterceptor { - constructor(deps: SearchInterceptorDeps, requestTimeout?: number | undefined); + constructor(deps: SearchInterceptorDeps, searchTimeout?: number); // @internal protected abortController: AbortController; // @internal (undocumented) @@ -1725,12 +1725,14 @@ export class SearchInterceptor { protected longRunningToast?: Toast; // @internal protected pendingCount$: BehaviorSubject; - // (undocumented) - protected readonly requestTimeout?: number | undefined; - // (undocumented) + // @internal (undocumented) protected runSearch(request: IEsSearchRequest, signal: AbortSignal, strategy?: string): Observable; search(request: IEsSearchRequest, options?: ISearchOptions): Observable; - // (undocumented) + // @internal (undocumented) + protected searchTimeout?: number; + // @internal (undocumented) + protected setSearchTimeout(timeout?: number): void; + // @internal (undocumented) protected setupTimers(options?: ISearchOptions): { combinedSignal: AbortSignal; cleanup: () => void; @@ -1902,6 +1904,7 @@ export const UI_SETTINGS: { readonly COURIER_MAX_CONCURRENT_SHARD_REQUESTS: "courier:maxConcurrentShardRequests"; readonly COURIER_BATCH_SEARCHES: "courier:batchSearches"; readonly SEARCH_INCLUDE_FROZEN: "search:includeFrozen"; + readonly SEARCH_TIMEOUT: "search:timeout"; readonly HISTOGRAM_BAR_TARGET: "histogram:barTarget"; readonly HISTOGRAM_MAX_BARS: "histogram:maxBars"; readonly HISTORY_LIMIT: "history:limit"; diff --git a/src/plugins/data/public/search/search_interceptor.ts b/src/plugins/data/public/search/search_interceptor.ts index 943d7a86c1a62..51294c25c4968 100644 --- a/src/plugins/data/public/search/search_interceptor.ts +++ b/src/plugins/data/public/search/search_interceptor.ts @@ -72,14 +72,16 @@ export class SearchInterceptor { protected application!: CoreStart['application']; /** - * This class should be instantiated with a `searchTimeout` corresponding with how many ms after - * requests are initiated that they should automatically cancel. - * @param toasts The `core.notifications.toasts` service - * @param application The `core.application` service - * @param searchTimeout Timeout for running search requests + * @internal + */ + protected searchTimeout?: number; + + /* + * @internal */ - constructor(protected readonly deps: SearchInterceptorDeps, protected searchTimeout?: number) { + constructor(protected readonly deps: SearchInterceptorDeps, searchTimeout?: number) { this.deps.http.addLoadingCountSource(this.pendingCount$); + this.searchTimeout = searchTimeout; this.deps.startServices.then(([coreStart]) => { this.application = coreStart.application; @@ -92,6 +94,9 @@ export class SearchInterceptor { .subscribe(this.hideToast); } + /** + * @internal + */ protected setSearchTimeout(timeout?: number) { this.searchTimeout = timeout; } @@ -104,6 +109,9 @@ export class SearchInterceptor { return this.pendingCount$.asObservable(); } + /** + * @internal + */ protected runSearch( request: IEsSearchRequest, signal: AbortSignal, @@ -149,6 +157,9 @@ export class SearchInterceptor { }); } + /** + * @internal + */ protected setupTimers(options?: ISearchOptions) { // Schedule this request to automatically timeout after some interval const timeoutController = new AbortController(); diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md index 93f924493c3b4..d62873a1c3114 100644 --- a/src/plugins/data/server/server.api.md +++ b/src/plugins/data/server/server.api.md @@ -1038,6 +1038,7 @@ export const UI_SETTINGS: { readonly COURIER_MAX_CONCURRENT_SHARD_REQUESTS: "courier:maxConcurrentShardRequests"; readonly COURIER_BATCH_SEARCHES: "courier:batchSearches"; readonly SEARCH_INCLUDE_FROZEN: "search:includeFrozen"; + readonly SEARCH_TIMEOUT: "search:timeout"; readonly HISTOGRAM_BAR_TARGET: "histogram:barTarget"; readonly HISTOGRAM_MAX_BARS: "histogram:maxBars"; readonly HISTORY_LIMIT: "history:limit"; diff --git a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts index bddae2edfdf54..c484cf347317b 100644 --- a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts +++ b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts @@ -20,7 +20,7 @@ export class EnhancedSearchInterceptor extends SearchInterceptor { private uiSettingsSub: Subscription; /** - * @param deps `SearchInterceptorDeps` + * @internal */ constructor(deps: SearchInterceptorDeps) { super(deps, deps.uiSettings.get(UI_SETTINGS.SEARCH_TIMEOUT)); From f2c4c164beedc724e15bf526bfe41b08790e416c Mon Sep 17 00:00:00 2001 From: Liza K Date: Wed, 26 Aug 2020 14:05:14 +0300 Subject: [PATCH 49/77] Rely on server timeout in OSS (?) Use UI setting in xpack. --- ...-public.searchinterceptor._constructor_.md | 3 +- ...n-plugins-data-public.searchinterceptor.md | 2 +- src/plugins/data/public/public.api.md | 11 +++--- .../public/search/search_interceptor.test.ts | 15 +++----- .../data/public/search/search_interceptor.ts | 37 +++++++++---------- .../data/public/search/search_service.ts | 21 ++++------- .../public/search/search_interceptor.test.ts | 28 ++++++++------ .../public/search/search_interceptor.ts | 13 +++++-- .../data_enhanced/server/ui_settings.ts | 4 +- 9 files changed, 65 insertions(+), 69 deletions(-) diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor._constructor_.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor._constructor_.md index dd613725470db..4c67639300883 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor._constructor_.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor._constructor_.md @@ -9,7 +9,7 @@ Constructs a new instance of the `SearchInterceptor` class Signature: ```typescript -constructor(deps: SearchInterceptorDeps, searchTimeout?: number); +constructor(deps: SearchInterceptorDeps); ``` ## Parameters @@ -17,5 +17,4 @@ constructor(deps: SearchInterceptorDeps, searchTimeout?: number); | Parameter | Type | Description | | --- | --- | --- | | deps | SearchInterceptorDeps | | -| searchTimeout | number | | diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md index f2e30a0c04cfc..fd9f23a7f0052 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchinterceptor.md @@ -14,7 +14,7 @@ export declare class SearchInterceptor | Constructor | Modifiers | Description | | --- | --- | --- | -| [(constructor)(deps, searchTimeout)](./kibana-plugin-plugins-data-public.searchinterceptor._constructor_.md) | | Constructs a new instance of the SearchInterceptor class | +| [(constructor)(deps)](./kibana-plugin-plugins-data-public.searchinterceptor._constructor_.md) | | Constructs a new instance of the SearchInterceptor class | ## Properties diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index d623880c496ff..c7992d2d19b60 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -1711,7 +1711,7 @@ export interface SearchError { // // @public (undocumented) export class SearchInterceptor { - constructor(deps: SearchInterceptorDeps, searchTimeout?: number); + constructor(deps: SearchInterceptorDeps); // @internal protected abortController: AbortController; // @internal (undocumented) @@ -1729,11 +1729,10 @@ export class SearchInterceptor { protected runSearch(request: IEsSearchRequest, signal: AbortSignal, strategy?: string): Observable; search(request: IEsSearchRequest, options?: ISearchOptions): Observable; // @internal (undocumented) - protected searchTimeout?: number; - // @internal (undocumented) - protected setSearchTimeout(timeout?: number): void; - // @internal (undocumented) - protected setupTimers(options?: ISearchOptions): { + protected setupTimers({ abortSignal, timeout }: { + abortSignal?: AbortSignal; + timeout?: number; + }): { combinedSignal: AbortSignal; cleanup: () => void; }; diff --git a/src/plugins/data/public/search/search_interceptor.test.ts b/src/plugins/data/public/search/search_interceptor.test.ts index da60f39b522ac..84db69a83a005 100644 --- a/src/plugins/data/public/search/search_interceptor.test.ts +++ b/src/plugins/data/public/search/search_interceptor.test.ts @@ -32,15 +32,12 @@ jest.useFakeTimers(); describe('SearchInterceptor', () => { beforeEach(() => { mockCoreSetup = coreMock.createSetup(); - searchInterceptor = new SearchInterceptor( - { - toasts: mockCoreSetup.notifications.toasts, - startServices: mockCoreSetup.getStartServices(), - uiSettings: mockCoreSetup.uiSettings, - http: mockCoreSetup.http, - }, - 1000 - ); + searchInterceptor = new SearchInterceptor({ + toasts: mockCoreSetup.notifications.toasts, + startServices: mockCoreSetup.getStartServices(), + uiSettings: mockCoreSetup.uiSettings, + http: mockCoreSetup.http, + }); }); describe('search', () => { diff --git a/src/plugins/data/public/search/search_interceptor.ts b/src/plugins/data/public/search/search_interceptor.ts index 51294c25c4968..38a0ef292f96b 100644 --- a/src/plugins/data/public/search/search_interceptor.ts +++ b/src/plugins/data/public/search/search_interceptor.ts @@ -18,7 +18,16 @@ */ import { trimEnd } from 'lodash'; -import { BehaviorSubject, throwError, timer, Subscription, defer, from, Observable } from 'rxjs'; +import { + BehaviorSubject, + throwError, + timer, + Subscription, + defer, + from, + Observable, + NEVER, +} from 'rxjs'; import { finalize, filter } from 'rxjs/operators'; import { Toast, CoreStart, ToastsSetup, CoreSetup } from 'kibana/public'; import { getCombinedSignal, AbortError } from '../../common/utils'; @@ -71,17 +80,11 @@ export class SearchInterceptor { */ protected application!: CoreStart['application']; - /** - * @internal - */ - protected searchTimeout?: number; - /* * @internal */ - constructor(protected readonly deps: SearchInterceptorDeps, searchTimeout?: number) { + constructor(protected readonly deps: SearchInterceptorDeps) { this.deps.http.addLoadingCountSource(this.pendingCount$); - this.searchTimeout = searchTimeout; this.deps.startServices.then(([coreStart]) => { this.application = coreStart.application; @@ -93,14 +96,6 @@ export class SearchInterceptor { .pipe(filter((count) => count === 0)) .subscribe(this.hideToast); } - - /** - * @internal - */ - protected setSearchTimeout(timeout?: number) { - this.searchTimeout = timeout; - } - /** * Returns an `Observable` over the current number of pending searches. This could mean that one * of the search requests is still in flight, or that it has only received partial responses. @@ -145,7 +140,9 @@ export class SearchInterceptor { return throwError(new AbortError()); } - const { combinedSignal, cleanup } = this.setupTimers(options); + const { combinedSignal, cleanup } = this.setupTimers({ + abortSignal: options?.signal, + }); this.pendingCount$.next(this.pendingCount$.getValue() + 1); return this.runSearch(request, combinedSignal, options?.strategy).pipe( @@ -160,11 +157,11 @@ export class SearchInterceptor { /** * @internal */ - protected setupTimers(options?: ISearchOptions) { + protected setupTimers({ abortSignal, timeout }: { abortSignal?: AbortSignal; timeout?: number }) { // Schedule this request to automatically timeout after some interval const timeoutController = new AbortController(); const { signal: timeoutSignal } = timeoutController; - const timeout$ = timer(this.searchTimeout); + const timeout$ = timeout ? timer(timeout) : NEVER; const subscription = timeout$.subscribe(() => { timeoutController.abort(); }); @@ -180,7 +177,7 @@ export class SearchInterceptor { const signals = [ this.abortController.signal, timeoutSignal, - ...(options?.abortSignal ? [options.abortSignal] : []), + ...(abortSignal ? [abortSignal] : []), ]; const combinedSignal = getCombinedSignal(signals); diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts index a49d2ef0956ff..a113d12a8089d 100644 --- a/src/plugins/data/public/search/search_service.ts +++ b/src/plugins/data/public/search/search_service.ts @@ -52,26 +52,19 @@ export class SearchService implements Plugin { { http, getStartServices, injectedMetadata, notifications, uiSettings }: CoreSetup, { expressions, usageCollection }: SearchServiceSetupDependencies ): ISearchSetup { - const esRequestTimeout = injectedMetadata.getInjectedVar('esRequestTimeout') as number; - this.usageCollector = createUsageCollector(getStartServices, usageCollection); /** * A global object that intercepts all searches and provides convenience methods for cancelling * all pending search requests, as well as getting the number of pending search requests. - * TODO: Make this modular so that apps can opt in/out of search collection, or even provide - * their own search collector instances */ - this.searchInterceptor = new SearchInterceptor( - { - toasts: notifications.toasts, - http, - uiSettings, - startServices: getStartServices(), - usageCollector: this.usageCollector!, - }, - esRequestTimeout - ); + this.searchInterceptor = new SearchInterceptor({ + toasts: notifications.toasts, + http, + uiSettings, + startServices: getStartServices(), + usageCollector: this.usageCollector!, + }); expressions.registerFunction(esdsl); expressions.registerType(esRawResponse); diff --git a/x-pack/plugins/data_enhanced/public/search/search_interceptor.test.ts b/x-pack/plugins/data_enhanced/public/search/search_interceptor.test.ts index 1e2c7987b7041..261e03887acdb 100644 --- a/x-pack/plugins/data_enhanced/public/search/search_interceptor.test.ts +++ b/x-pack/plugins/data_enhanced/public/search/search_interceptor.test.ts @@ -7,7 +7,7 @@ import { coreMock } from '../../../../../src/core/public/mocks'; import { EnhancedSearchInterceptor } from './search_interceptor'; import { CoreSetup, CoreStart } from 'kibana/public'; -import { AbortError } from '../../../../../src/plugins/data/common'; +import { AbortError, UI_SETTINGS } from '../../../../../src/plugins/data/common'; const timeTravel = (msToRun = 0) => { jest.advanceTimersByTime(msToRun); @@ -43,6 +43,15 @@ describe('EnhancedSearchInterceptor', () => { mockCoreSetup = coreMock.createSetup(); mockCoreStart = coreMock.createStart(); + mockCoreSetup.uiSettings.get.mockImplementation((name: string) => { + switch (name) { + case UI_SETTINGS.SEARCH_TIMEOUT: + return 1000; + default: + return; + } + }); + next.mockClear(); error.mockClear(); complete.mockClear(); @@ -64,16 +73,13 @@ describe('EnhancedSearchInterceptor', () => { ]); }); - searchInterceptor = new EnhancedSearchInterceptor( - { - toasts: mockCoreSetup.notifications.toasts, - startServices: mockPromise as any, - http: mockCoreSetup.http, - uiSettings: mockCoreSetup.uiSettings, - usageCollector: mockUsageCollector, - }, - 1000 - ); + searchInterceptor = new EnhancedSearchInterceptor({ + toasts: mockCoreSetup.notifications.toasts, + startServices: mockPromise as any, + http: mockCoreSetup.http, + uiSettings: mockCoreSetup.uiSettings, + usageCollector: mockUsageCollector, + }); }); describe('search', () => { diff --git a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts index c484cf347317b..3fd35d3449bb5 100644 --- a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts +++ b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts @@ -18,17 +18,19 @@ import { IAsyncSearchRequest, ENHANCED_ES_SEARCH_STRATEGY } from '../../common'; export class EnhancedSearchInterceptor extends SearchInterceptor { private uiSettingsSub: Subscription; + private searchTimeout: number; /** * @internal */ constructor(deps: SearchInterceptorDeps) { - super(deps, deps.uiSettings.get(UI_SETTINGS.SEARCH_TIMEOUT)); + super(deps); + this.searchTimeout = deps.uiSettings.get(UI_SETTINGS.SEARCH_TIMEOUT); this.uiSettingsSub = deps.uiSettings .get$(UI_SETTINGS.SEARCH_TIMEOUT) .subscribe((timeout: number) => { - this.setSearchTimeout(timeout); + this.searchTimeout = timeout; }); } @@ -83,7 +85,10 @@ export class EnhancedSearchInterceptor extends SearchInterceptor { ...request.params, }; - const { combinedSignal, cleanup } = this.setupTimers(options); + const { combinedSignal, cleanup } = this.setupTimers({ + abortSignal: options.signal, + timeout: this.searchTimeout, + }); const aborted$ = from(toPromise(combinedSignal)); const strategy = options?.strategy || ENHANCED_ES_SEARCH_STRATEGY; @@ -117,7 +122,7 @@ export class EnhancedSearchInterceptor extends SearchInterceptor { // we don't need to send a follow-up request to delete this search. Otherwise, we // send the follow-up request to delete this search, then throw an abort error. if (id !== undefined) { - this.deps.http.delete(`/internal/search/es/${id}`); + this.deps.http.delete(`/internal/search/${strategy}/${id}`); } }, }), diff --git a/x-pack/plugins/data_enhanced/server/ui_settings.ts b/x-pack/plugins/data_enhanced/server/ui_settings.ts index 76b84a7d09fee..f2842da8b8337 100644 --- a/x-pack/plugins/data_enhanced/server/ui_settings.ts +++ b/x-pack/plugins/data_enhanced/server/ui_settings.ts @@ -12,11 +12,11 @@ import { UI_SETTINGS } from '../../../../src/plugins/data/server'; export function getUiSettings(): Record> { return { [UI_SETTINGS.SEARCH_TIMEOUT]: { - name: i18n.translate('kbn.advancedSettings.searchTimeout', { + name: i18n.translate('xpack.data.advancedSettings.searchTimeout', { defaultMessage: 'Search Timeout', }), value: 600000, - description: i18n.translate('kbn.advancedSettings.searchTimeoutDesc', { + description: i18n.translate('xpack.data.advancedSettings.searchTimeoutDesc', { defaultMessage: 'Change the maximum timeout for a search session or set to 0 to disable the timeout and allow queries to run to completion.', }), From 2497e0054a50b79039a8c2ee8b2f726351934513 Mon Sep 17 00:00:00 2001 From: Liza K Date: Wed, 26 Aug 2020 18:19:12 +0300 Subject: [PATCH 50/77] Rename function --- src/plugins/data/public/public.api.md | 2 +- src/plugins/data/public/search/search_interceptor.ts | 10 ++++++++-- .../data_enhanced/public/search/search_interceptor.ts | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index c7992d2d19b60..e9e2fa5df1104 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -1729,7 +1729,7 @@ export class SearchInterceptor { protected runSearch(request: IEsSearchRequest, signal: AbortSignal, strategy?: string): Observable; search(request: IEsSearchRequest, options?: ISearchOptions): Observable; // @internal (undocumented) - protected setupTimers({ abortSignal, timeout }: { + protected setupAbortSignal({ abortSignal, timeout }: { abortSignal?: AbortSignal; timeout?: number; }): { diff --git a/src/plugins/data/public/search/search_interceptor.ts b/src/plugins/data/public/search/search_interceptor.ts index 38a0ef292f96b..742bb974d2f5b 100644 --- a/src/plugins/data/public/search/search_interceptor.ts +++ b/src/plugins/data/public/search/search_interceptor.ts @@ -140,7 +140,7 @@ export class SearchInterceptor { return throwError(new AbortError()); } - const { combinedSignal, cleanup } = this.setupTimers({ + const { combinedSignal, cleanup } = this.setupAbortSignal({ abortSignal: options?.signal, }); this.pendingCount$.next(this.pendingCount$.getValue() + 1); @@ -157,7 +157,13 @@ export class SearchInterceptor { /** * @internal */ - protected setupTimers({ abortSignal, timeout }: { abortSignal?: AbortSignal; timeout?: number }) { + protected setupAbortSignal({ + abortSignal, + timeout, + }: { + abortSignal?: AbortSignal; + timeout?: number; + }) { // Schedule this request to automatically timeout after some interval const timeoutController = new AbortController(); const { signal: timeoutSignal } = timeoutController; diff --git a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts index 3fd35d3449bb5..d226b949e26b0 100644 --- a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts +++ b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts @@ -85,7 +85,7 @@ export class EnhancedSearchInterceptor extends SearchInterceptor { ...request.params, }; - const { combinedSignal, cleanup } = this.setupTimers({ + const { combinedSignal, cleanup } = this.setupAbortSignal({ abortSignal: options.signal, timeout: this.searchTimeout, }); From a65596fd0157e885c43ed76cf4aa1fc140505c33 Mon Sep 17 00:00:00 2001 From: Liza K Date: Thu, 27 Aug 2020 11:34:09 +0300 Subject: [PATCH 51/77] doc --- src/plugins/data/public/public.api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index e9e2fa5df1104..b1e4016a1ca41 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -1729,7 +1729,7 @@ export class SearchInterceptor { protected runSearch(request: IEsSearchRequest, signal: AbortSignal, strategy?: string): Observable; search(request: IEsSearchRequest, options?: ISearchOptions): Observable; // @internal (undocumented) - protected setupAbortSignal({ abortSignal, timeout }: { + protected setupAbortSignal({ abortSignal, timeout, }: { abortSignal?: AbortSignal; timeout?: number; }): { From 1e9e9a028a7fcbf12c1e8a2d32f4a46e43351f06 Mon Sep 17 00:00:00 2001 From: Liza K Date: Thu, 27 Aug 2020 20:04:31 +0300 Subject: [PATCH 52/77] Remove esShard from client --- src/legacy/core_plugins/elasticsearch/index.js | 15 --------------- .../public/search/fetch/get_search_params.test.ts | 9 --------- .../data/public/search/fetch/get_search_params.ts | 13 ++++--------- src/plugins/data/public/search/fetch/index.ts | 1 - .../data/public/search/legacy/call_client.test.ts | 1 - src/plugins/data/public/search/search_service.ts | 2 -- .../search_source/create_search_source.test.ts | 1 - .../data/public/search/search_source/mocks.ts | 1 - .../search/search_source/search_source.test.ts | 1 - .../public/search/search_source/search_source.ts | 4 +--- .../vis_type_vega/public/data_model/search_api.ts | 3 --- src/plugins/vis_type_vega/public/plugin.ts | 1 - src/plugins/vis_type_vega/public/services.ts | 1 - .../public/vega_visualization.test.js | 1 - 14 files changed, 5 insertions(+), 49 deletions(-) diff --git a/src/legacy/core_plugins/elasticsearch/index.js b/src/legacy/core_plugins/elasticsearch/index.js index 599886788604b..f90f490d68035 100644 --- a/src/legacy/core_plugins/elasticsearch/index.js +++ b/src/legacy/core_plugins/elasticsearch/index.js @@ -16,18 +16,13 @@ * specific language governing permissions and limitations * under the License. */ -import { first } from 'rxjs/operators'; import { Cluster } from './server/lib/cluster'; import { createProxy } from './server/lib/create_proxy'; export default function (kibana) { - let defaultVars; - return new kibana.Plugin({ require: [], - uiExports: { injectDefaultVars: () => defaultVars }, - async init(server) { // All methods that ES plugin exposes are synchronous so we should get the first // value from all observables here to be able to synchronously return and create @@ -36,16 +31,6 @@ export default function (kibana) { const adminCluster = new Cluster(client); const dataCluster = new Cluster(client); - const esConfig = await server.newPlatform.__internals.elasticsearch.legacy.config$ - .pipe(first()) - .toPromise(); - - defaultVars = { - esRequestTimeout: esConfig.requestTimeout.asMilliseconds(), - esShardTimeout: esConfig.shardTimeout.asMilliseconds(), - esApiVersion: esConfig.apiVersion, - }; - const clusters = new Map(); server.expose('getCluster', (name) => { if (name === 'admin') { diff --git a/src/plugins/data/public/search/fetch/get_search_params.test.ts b/src/plugins/data/public/search/fetch/get_search_params.test.ts index 1ecb879b1602d..f8e8d95bc94f7 100644 --- a/src/plugins/data/public/search/fetch/get_search_params.test.ts +++ b/src/plugins/data/public/search/fetch/get_search_params.test.ts @@ -56,13 +56,4 @@ describe('getSearchParams', () => { searchParams = getSearchParams(config); expect(searchParams.max_concurrent_shard_requests).toBe(5); }); - - test('includes timeout according to esShardTimeout if greater than 0', () => { - const config = getConfigStub(); - let searchParams = getSearchParams(config, 0); - expect(searchParams.timeout).toBe(undefined); - - searchParams = getSearchParams(config, 100); - expect(searchParams.timeout).toBe('100ms'); - }); }); diff --git a/src/plugins/data/public/search/fetch/get_search_params.ts b/src/plugins/data/public/search/fetch/get_search_params.ts index 5e0395189f647..061ee9538c7da 100644 --- a/src/plugins/data/public/search/fetch/get_search_params.ts +++ b/src/plugins/data/public/search/fetch/get_search_params.ts @@ -22,14 +22,13 @@ import { SearchRequest } from './types'; const sessionId = Date.now(); -export function getSearchParams(getConfig: GetConfigFn, esShardTimeout: number = 0) { +export function getSearchParams(getConfig: GetConfigFn) { return { rest_total_hits_as_int: true, ignore_unavailable: true, ignore_throttled: getIgnoreThrottled(getConfig), max_concurrent_shard_requests: getMaxConcurrentShardRequests(getConfig), preference: getPreference(getConfig), - timeout: getTimeout(esShardTimeout), }; } @@ -50,19 +49,15 @@ export function getPreference(getConfig: GetConfigFn) { : undefined; } -export function getTimeout(esShardTimeout: number) { - return esShardTimeout > 0 ? `${esShardTimeout}ms` : undefined; -} - /** @public */ // TODO: Could provide this on runtime contract with dependencies // already wired up. export function getSearchParamsFromRequest( searchRequest: SearchRequest, - dependencies: { esShardTimeout: number; getConfig: GetConfigFn } + dependencies: { getConfig: GetConfigFn } ): ISearchRequestParams { - const { esShardTimeout, getConfig } = dependencies; - const searchParams = getSearchParams(getConfig, esShardTimeout); + const { getConfig } = dependencies; + const searchParams = getSearchParams(getConfig); return { index: searchRequest.index.title || searchRequest.index, diff --git a/src/plugins/data/public/search/fetch/index.ts b/src/plugins/data/public/search/fetch/index.ts index 79cdad1897f9c..4a88ca6ace481 100644 --- a/src/plugins/data/public/search/fetch/index.ts +++ b/src/plugins/data/public/search/fetch/index.ts @@ -22,7 +22,6 @@ export { getSearchParams, getSearchParamsFromRequest, getPreference, - getTimeout, getIgnoreThrottled, getMaxConcurrentShardRequests, } from './get_search_params'; diff --git a/src/plugins/data/public/search/legacy/call_client.test.ts b/src/plugins/data/public/search/legacy/call_client.test.ts index 38f3ab200da90..943a02d22088d 100644 --- a/src/plugins/data/public/search/legacy/call_client.test.ts +++ b/src/plugins/data/public/search/legacy/call_client.test.ts @@ -60,7 +60,6 @@ describe('callClient', () => { http: coreMock.createStart().http, legacySearchService: {}, config: { get: jest.fn() }, - esShardTimeout: 0, loadingCount$: new BehaviorSubject(0), } as FetchHandlers; diff --git a/src/plugins/data/public/search/search_service.ts b/src/plugins/data/public/search/search_service.ts index a113d12a8089d..f8f4acbe43dfd 100644 --- a/src/plugins/data/public/search/search_service.ts +++ b/src/plugins/data/public/search/search_service.ts @@ -94,8 +94,6 @@ export class SearchService implements Plugin { const searchSourceDependencies: SearchSourceDependencies = { getConfig: uiSettings.get.bind(uiSettings), - // TODO: we don't need this, apply on the server - esShardTimeout: injectedMetadata.getInjectedVar('esShardTimeout') as number, search, http, loadingCount$, diff --git a/src/plugins/data/public/search/search_source/create_search_source.test.ts b/src/plugins/data/public/search/search_source/create_search_source.test.ts index 2820aab67ea3a..bc1c7c06c8806 100644 --- a/src/plugins/data/public/search/search_source/create_search_source.test.ts +++ b/src/plugins/data/public/search/search_source/create_search_source.test.ts @@ -35,7 +35,6 @@ describe('createSearchSource', () => { dependencies = { getConfig: jest.fn(), search: jest.fn(), - esShardTimeout: 30000, http: coreMock.createStart().http, loadingCount$: new BehaviorSubject(0), }; diff --git a/src/plugins/data/public/search/search_source/mocks.ts b/src/plugins/data/public/search/search_source/mocks.ts index bc3e287d9fe80..adf53bee33fe1 100644 --- a/src/plugins/data/public/search/search_source/mocks.ts +++ b/src/plugins/data/public/search/search_source/mocks.ts @@ -53,7 +53,6 @@ export const searchSourceMock = { export const createSearchSourceMock = (fields?: SearchSourceFields) => new SearchSource(fields, { getConfig: uiSettingsServiceMock.createStartContract().get, - esShardTimeout: 30000, search: jest.fn(), http: httpServiceMock.createStartContract(), loadingCount$: new BehaviorSubject(0), diff --git a/src/plugins/data/public/search/search_source/search_source.test.ts b/src/plugins/data/public/search/search_source/search_source.test.ts index a8baed9faa84d..282a33e6d01f7 100644 --- a/src/plugins/data/public/search/search_source/search_source.test.ts +++ b/src/plugins/data/public/search/search_source/search_source.test.ts @@ -68,7 +68,6 @@ describe('SearchSource', () => { searchSourceDependencies = { getConfig: jest.fn(), search: mockSearchMethod, - esShardTimeout: 30000, http: coreMock.createStart().http, loadingCount$: new BehaviorSubject(0), }; diff --git a/src/plugins/data/public/search/search_source/search_source.ts b/src/plugins/data/public/search/search_source/search_source.ts index eec2d9b50eafe..68c7b663b3628 100644 --- a/src/plugins/data/public/search/search_source/search_source.ts +++ b/src/plugins/data/public/search/search_source/search_source.ts @@ -118,7 +118,6 @@ export interface SearchSourceDependencies { getConfig: GetConfigFn; search: ISearchGeneric; http: HttpStart; - esShardTimeout: number; loadingCount$: BehaviorSubject; } @@ -233,10 +232,9 @@ export class SearchSource { * @return {Observable>} */ private fetch$(searchRequest: SearchRequest, options: ISearchOptions) { - const { search, esShardTimeout, getConfig } = this.dependencies; + const { search, getConfig } = this.dependencies; const params = getSearchParamsFromRequest(searchRequest, { - esShardTimeout, getConfig, }); diff --git a/src/plugins/vis_type_vega/public/data_model/search_api.ts b/src/plugins/vis_type_vega/public/data_model/search_api.ts index 8a1541ecae0d4..4ea25af549249 100644 --- a/src/plugins/vis_type_vega/public/data_model/search_api.ts +++ b/src/plugins/vis_type_vega/public/data_model/search_api.ts @@ -51,9 +51,6 @@ export class SearchAPI { searchRequests.map((request) => { const requestId = request.name; const params = getSearchParamsFromRequest(request, { - esShardTimeout: this.dependencies.injectedMetadata.getInjectedVar( - 'esShardTimeout' - ) as number, getConfig: this.dependencies.uiSettings.get.bind(this.dependencies.uiSettings), }); diff --git a/src/plugins/vis_type_vega/public/plugin.ts b/src/plugins/vis_type_vega/public/plugin.ts index 00c6b2e3c8d5b..4b8ff8e2cb43a 100644 --- a/src/plugins/vis_type_vega/public/plugin.ts +++ b/src/plugins/vis_type_vega/public/plugin.ts @@ -78,7 +78,6 @@ export class VegaPlugin implements Plugin, void> { ) { setInjectedVars({ enableExternalUrls: this.initializerContext.config.get().enableExternalUrls, - esShardTimeout: core.injectedMetadata.getInjectedVar('esShardTimeout') as number, emsTileLayerId: core.injectedMetadata.getInjectedVar('emsTileLayerId', true), }); setUISettings(core.uiSettings); diff --git a/src/plugins/vis_type_vega/public/services.ts b/src/plugins/vis_type_vega/public/services.ts index acd02a6dd42f8..dfb2c96e9f894 100644 --- a/src/plugins/vis_type_vega/public/services.ts +++ b/src/plugins/vis_type_vega/public/services.ts @@ -48,7 +48,6 @@ export const [getSavedObjects, setSavedObjects] = createGetterSetter('InjectedVars'); diff --git a/src/plugins/vis_type_vega/public/vega_visualization.test.js b/src/plugins/vis_type_vega/public/vega_visualization.test.js index 0912edf9503a6..1bf625af76207 100644 --- a/src/plugins/vis_type_vega/public/vega_visualization.test.js +++ b/src/plugins/vis_type_vega/public/vega_visualization.test.js @@ -82,7 +82,6 @@ describe('VegaVisualizations', () => { setInjectedVars({ emsTileLayerId: {}, enableExternalUrls: true, - esShardTimeout: 10000, }); setData(dataPluginStart); setSavedObjects(coreStart.savedObjects); From 6d718c50edaff8a180676ec9fbb07b19a0f5efaf Mon Sep 17 00:00:00 2001 From: Liza K Date: Mon, 31 Aug 2020 14:14:03 +0300 Subject: [PATCH 53/77] cleanup request parameters from FE --- .../search/fetch/get_search_params.test.ts | 12 ----- .../public/search/fetch/get_search_params.ts | 2 - src/plugins/data/server/index.ts | 1 + .../es_search/get_default_search_params.ts | 6 ++- .../data/server/search/es_search/index.ts | 2 +- src/plugins/data/server/search/index.ts | 2 +- .../data/server/search/routes/msearch.ts | 4 +- .../server/search/es_search_strategy.test.ts | 26 +++++++++-- .../server/search/es_search_strategy.ts | 46 +++++++++---------- 9 files changed, 53 insertions(+), 48 deletions(-) diff --git a/src/plugins/data/public/search/fetch/get_search_params.test.ts b/src/plugins/data/public/search/fetch/get_search_params.test.ts index f8e8d95bc94f7..8b693b1dff4ee 100644 --- a/src/plugins/data/public/search/fetch/get_search_params.test.ts +++ b/src/plugins/data/public/search/fetch/get_search_params.test.ts @@ -25,18 +25,6 @@ function getConfigStub(config: any = {}): GetConfigFn { } describe('getSearchParams', () => { - test('includes rest_total_hits_as_int', () => { - const config = getConfigStub(); - const searchParams = getSearchParams(config); - expect(searchParams.rest_total_hits_as_int).toBe(true); - }); - - test('includes ignore_unavailable', () => { - const config = getConfigStub(); - const searchParams = getSearchParams(config); - expect(searchParams.ignore_unavailable).toBe(true); - }); - test('includes ignore_throttled according to search:includeFrozen', () => { let config = getConfigStub({ [UI_SETTINGS.SEARCH_INCLUDE_FROZEN]: true }); let searchParams = getSearchParams(config); diff --git a/src/plugins/data/public/search/fetch/get_search_params.ts b/src/plugins/data/public/search/fetch/get_search_params.ts index 061ee9538c7da..97c69e8343f42 100644 --- a/src/plugins/data/public/search/fetch/get_search_params.ts +++ b/src/plugins/data/public/search/fetch/get_search_params.ts @@ -24,8 +24,6 @@ const sessionId = Date.now(); export function getSearchParams(getConfig: GetConfigFn) { return { - rest_total_hits_as_int: true, - ignore_unavailable: true, ignore_throttled: getIgnoreThrottled(getConfig), max_concurrent_shard_requests: getMaxConcurrentShardRequests(getConfig), preference: getPreference(getConfig), diff --git a/src/plugins/data/server/index.ts b/src/plugins/data/server/index.ts index f300fb0779e38..2a19a8b46db55 100644 --- a/src/plugins/data/server/index.ts +++ b/src/plugins/data/server/index.ts @@ -212,6 +212,7 @@ export { ISearchSetup, ISearchStart, getDefaultSearchParams, + getShardTimeout, getTotalLoaded, usageProvider, SearchUsage, diff --git a/src/plugins/data/server/search/es_search/get_default_search_params.ts b/src/plugins/data/server/search/es_search/get_default_search_params.ts index b2341ccc0f3c8..5c5bf0ec08de3 100644 --- a/src/plugins/data/server/search/es_search/get_default_search_params.ts +++ b/src/plugins/data/server/search/es_search/get_default_search_params.ts @@ -19,9 +19,13 @@ import { SharedGlobalConfig } from '../../../../../core/server'; +export function getShardTimeout(config: SharedGlobalConfig) { + return `${config.elasticsearch.shardTimeout.asMilliseconds()}ms`; +} + export function getDefaultSearchParams(config: SharedGlobalConfig) { return { - timeout: `${config.elasticsearch.shardTimeout.asMilliseconds()}ms`, + timeout: getShardTimeout(config), ignoreUnavailable: true, // Don't fail if the index/indices don't exist restTotalHitsAsInt: true, // Get the number of hits as an int rather than a range }; diff --git a/src/plugins/data/server/search/es_search/index.ts b/src/plugins/data/server/search/es_search/index.ts index 20006b70730d8..a213d26501502 100644 --- a/src/plugins/data/server/search/es_search/index.ts +++ b/src/plugins/data/server/search/es_search/index.ts @@ -19,5 +19,5 @@ export { ES_SEARCH_STRATEGY, IEsSearchRequest, IEsSearchResponse } from '../../../common/search'; export { esSearchStrategyProvider } from './es_search_strategy'; -export { getDefaultSearchParams } from './get_default_search_params'; +export { getDefaultSearchParams, getShardTimeout } from './get_default_search_params'; export { getTotalLoaded } from './get_total_loaded'; diff --git a/src/plugins/data/server/search/index.ts b/src/plugins/data/server/search/index.ts index 8a74c51f52f51..ccaf912e28e53 100644 --- a/src/plugins/data/server/search/index.ts +++ b/src/plugins/data/server/search/index.ts @@ -19,7 +19,7 @@ export { ISearchStrategy, ISearchSetup, ISearchStart, SearchEnhancements } from './types'; -export { getDefaultSearchParams, getTotalLoaded } from './es_search'; +export { getDefaultSearchParams, getTotalLoaded, getShardTimeout } from './es_search'; export { usageProvider, SearchUsage } from './collectors'; diff --git a/src/plugins/data/server/search/routes/msearch.ts b/src/plugins/data/server/search/routes/msearch.ts index efb40edd90d58..0073eae06947b 100644 --- a/src/plugins/data/server/search/routes/msearch.ts +++ b/src/plugins/data/server/search/routes/msearch.ts @@ -23,7 +23,7 @@ import { schema } from '@kbn/config-schema'; import { IRouter } from 'src/core/server'; import { UI_SETTINGS } from '../../../common'; import { SearchRouteDependencies } from '../search_service'; -import { getDefaultSearchParams } from '..'; +import { getShardTimeout } from '..'; interface MsearchHeaders { index: string; @@ -96,7 +96,7 @@ export function registerMsearchRoute(router: IRouter, deps: SearchRouteDependenc // get shardTimeout const config = await deps.globalConfig$.pipe(first()).toPromise(); - const { timeout } = getDefaultSearchParams(config); + const timeout = getShardTimeout(config); const body = convertRequestBody(request.body, { timeout }); diff --git a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts index 054baa6ac81d1..9d577a9e04dce 100644 --- a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts +++ b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts @@ -5,8 +5,8 @@ */ import { RequestHandlerContext } from '../../../../../src/core/server'; -import { pluginInitializerContextConfigMock } from '../../../../../src/core/server/mocks'; import { enhancedEsSearchStrategyProvider } from './es_search_strategy'; +import { BehaviorSubject } from 'rxjs'; const mockAsyncResponse = { body: { @@ -43,7 +43,15 @@ describe('ES search strategy', () => { elasticsearch: { client: { asCurrentUser: { transport: { request: mockApiCaller } } } }, }, }; - const mockConfig$ = pluginInitializerContextConfigMock({}).legacy.globalConfig$; + const mockConfig$ = new BehaviorSubject({ + elasticsearch: { + shardTimeout: { + asMilliseconds: () => { + return 100; + }, + }, + }, + }); beforeEach(() => { mockApiCaller.mockClear(); @@ -64,10 +72,17 @@ describe('ES search strategy', () => { await esSearch.search((mockContext as unknown) as RequestHandlerContext, { params }); expect(mockApiCaller).toBeCalled(); - const { method, path, body } = mockApiCaller.mock.calls[0][0]; + + const { method, path, body, querystring } = mockApiCaller.mock.calls[0][0]; + expect(method).toBe('POST'); expect(path).toBe('/logstash-*/_async_search'); expect(body).toEqual({ query: {} }); + expect(querystring).toHaveProperty('wait_for_completion_timeout'); + expect(querystring).toHaveProperty('track_total_hits'); + expect(querystring).toHaveProperty('ignore_unavailable'); + expect(querystring).toHaveProperty('keep_alive'); + expect(querystring).toHaveProperty('batched_reduce_size'); }); it('makes a GET request to async search with ID when ID is provided', async () => { @@ -79,10 +94,13 @@ describe('ES search strategy', () => { await esSearch.search((mockContext as unknown) as RequestHandlerContext, { id: 'foo', params }); expect(mockApiCaller).toBeCalled(); - const { method, path, body } = mockApiCaller.mock.calls[0][0]; + const { method, path, body, querystring } = mockApiCaller.mock.calls[0][0]; expect(method).toBe('GET'); expect(path).toBe('/_async_search/foo'); expect(body).toEqual(undefined); + expect(querystring).not.toHaveProperty('batched_reduce_size'); + expect(querystring).not.toHaveProperty('batched_reduce_size'); + expect(querystring).not.toHaveProperty('batched_reduce_size'); }); it('encodes special characters in the path', async () => { diff --git a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts index 67a42b9954c9d..dd83fa7bc40ee 100644 --- a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts +++ b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts @@ -15,10 +15,10 @@ import { Logger, } from '../../../../../src/core/server'; import { - getDefaultSearchParams, getTotalLoaded, ISearchStrategy, SearchUsage, + getDefaultSearchParams, } from '../../../../../src/plugins/data/server'; import { IEnhancedEsSearchRequest } from '../../common'; import { shimHitsTotal } from './shim_hits_total'; @@ -38,18 +38,16 @@ export const enhancedEsSearchStrategyProvider = ( request: IEnhancedEsSearchRequest, options?: ISearchOptions ) => { - logger.debug(`search ${JSON.stringify(request.params) || request.id}`); - const config = await config$.pipe(first()).toPromise(); const client = context.core.elasticsearch.client.asCurrentUser; - const defaultParams = getDefaultSearchParams(config); - const params = { ...defaultParams, ...request.params }; + + logger.debug(`search ${JSON.stringify(request.params) || request.id}`); const isAsync = request.indexType !== 'rollup'; try { const response = isAsync - ? await asyncSearch(client, { ...request, params }, options) - : await rollupSearch(client, { ...request, params }, options); + ? await asyncSearch(client, request) + : await rollupSearch(client, request, config$); if ( usage && @@ -81,14 +79,9 @@ export const enhancedEsSearchStrategyProvider = ( async function asyncSearch( client: ElasticsearchClient, - request: IEnhancedEsSearchRequest, - options?: ISearchOptions + request: IEnhancedEsSearchRequest ): Promise { - const { timeout = undefined, restTotalHitsAsInt = undefined, ...params } = { - ...request.params, - }; - - params.trackTotalHits = true; // Get the exact count of hits + const { params = {} } = request; // If we have an ID, then just poll for that ID, otherwise send the entire request body const { body = undefined, index = undefined, ...queryParams } = request.id ? {} : params; @@ -96,17 +89,16 @@ async function asyncSearch( const method = request.id ? 'GET' : 'POST'; const path = encodeURI(request.id ? `/_async_search/${request.id}` : `/${index}/_async_search`); - // Only report partial results every 64 shards; this should be reduced when we actually display partial results - const batchedReduceSize = request.id ? undefined : 64; - - const asyncOptions = { + const querystring = toSnakeCase({ waitForCompletionTimeout: '100ms', // Wait up to 100ms for the response to return keepAlive: '1m', // Extend the TTL for this search request by one minute - }; - - const querystring = toSnakeCase({ - ...asyncOptions, - ...(batchedReduceSize && { batchedReduceSize }), + ...(request.id + ? {} + : { + trackTotalHits: true, + ignoreUnavailable: true, + batchedReduceSize: 64, // Only report partial results every 64 shards; this should be reduced when we actually display partial results + }), ...queryParams, }); @@ -131,12 +123,16 @@ async function asyncSearch( async function rollupSearch( client: ElasticsearchClient, request: IEnhancedEsSearchRequest, - options?: ISearchOptions + config$: Observable ): Promise { + const config = await config$.pipe(first()).toPromise(); const { body, index, ...params } = request.params!; const method = 'POST'; const path = encodeURI(`/${index}/_rollup_search`); - const querystring = toSnakeCase(params); + const querystring = toSnakeCase({ + ...getDefaultSearchParams(config), + ...params, + }); const esResponse = await client.transport.request({ method, From 060ce08e85850be956c3b277a2a01ed026b2d387 Mon Sep 17 00:00:00 2001 From: Liza K Date: Mon, 31 Aug 2020 14:35:19 +0300 Subject: [PATCH 54/77] doc --- ...-data-public.getsearchparamsfromrequest.md | 3 +- .../kibana-plugin-plugins-data-server.md | 1 + src/plugins/data/public/public.api.md | 1 - src/plugins/data/server/server.api.md | 31 +++++++++++-------- 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.getsearchparamsfromrequest.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.getsearchparamsfromrequest.md index 337b4b3302cc3..d32e9a955f890 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.getsearchparamsfromrequest.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.getsearchparamsfromrequest.md @@ -9,7 +9,6 @@ ```typescript export declare function getSearchParamsFromRequest(searchRequest: SearchRequest, dependencies: { - esShardTimeout: number; getConfig: GetConfigFn; }): ISearchRequestParams; ``` @@ -19,7 +18,7 @@ export declare function getSearchParamsFromRequest(searchRequest: SearchRequest, | Parameter | Type | Description | | --- | --- | --- | | searchRequest | SearchRequest | | -| dependencies | {
esShardTimeout: number;
getConfig: GetConfigFn;
} | | +| dependencies | {
getConfig: GetConfigFn;
} | | Returns: diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md index 0292e08063fbb..d3761e3d1ae9f 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md @@ -27,6 +27,7 @@ | Function | Description | | --- | --- | | [getDefaultSearchParams(config)](./kibana-plugin-plugins-data-server.getdefaultsearchparams.md) | | +| [getShardTimeout(config)](./kibana-plugin-plugins-data-server.getshardtimeout.md) | | | [getTime(indexPattern, timeRange, options)](./kibana-plugin-plugins-data-server.gettime.md) | | | [parseInterval(interval)](./kibana-plugin-plugins-data-server.parseinterval.md) | | | [plugin(initializerContext)](./kibana-plugin-plugins-data-server.plugin.md) | Static code to be shared externally | diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index b1e4016a1ca41..9933500cf22af 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -693,7 +693,6 @@ export const getKbnTypeNames: () => string[]; // // @public (undocumented) export function getSearchParamsFromRequest(searchRequest: SearchRequest, dependencies: { - esShardTimeout: number; getConfig: GetConfigFn; }): ISearchRequestParams; diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md index d62873a1c3114..9d0d4a549d501 100644 --- a/src/plugins/data/server/server.api.md +++ b/src/plugins/data/server/server.api.md @@ -451,6 +451,11 @@ export function getDefaultSearchParams(config: SharedGlobalConfig): { restTotalHitsAsInt: boolean; }; +// Warning: (ae-missing-release-tag) "getShardTimeout" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function getShardTimeout(config: SharedGlobalConfig): string; + // Warning: (ae-missing-release-tag) "getTime" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -1087,19 +1092,19 @@ export function usageProvider(core: CoreSetup_2): SearchUsage; // src/plugins/data/server/index.ts:101:26 - (ae-forgotten-export) The symbol "TruncateFormat" needs to be exported by the entry point index.d.ts // src/plugins/data/server/index.ts:127:27 - (ae-forgotten-export) The symbol "isFilterable" needs to be exported by the entry point index.d.ts // src/plugins/data/server/index.ts:127:27 - (ae-forgotten-export) The symbol "isNestedField" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:221:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:221:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:221:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:221:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:223:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:224:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:233:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:234:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:235:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:239:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:240:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:244:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:247:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:222:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:222:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:222:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:222:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:224:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:225:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:234:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:235:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:236:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:240:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:241:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:245:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:248:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts // src/plugins/data/server/plugin.ts:88:66 - (ae-forgotten-export) The symbol "DataEnhancements" needs to be exported by the entry point index.d.ts // (No @packageDocumentation comment for this package) From 0310fb194ca33c2dacb422525f0c30e77beaca57 Mon Sep 17 00:00:00 2001 From: Liza K Date: Mon, 31 Aug 2020 15:08:01 +0300 Subject: [PATCH 55/77] doc --- ...gin-plugins-data-server.getshardtimeout.md | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getshardtimeout.md diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getshardtimeout.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getshardtimeout.md new file mode 100644 index 0000000000000..7968379249bed --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getshardtimeout.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [getShardTimeout](./kibana-plugin-plugins-data-server.getshardtimeout.md) + +## getShardTimeout() function + +Signature: + +```typescript +export declare function getShardTimeout(config: SharedGlobalConfig): string; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| config | SharedGlobalConfig | | + +Returns: + +`string` + From 1b4770ab905c08f9f060a8e6394623b3e9e37bf9 Mon Sep 17 00:00:00 2001 From: Liza K Date: Tue, 1 Sep 2020 15:51:13 +0300 Subject: [PATCH 56/77] Align request parameters on server, Remove leftover parameters from client Shim responses for search and msearch routes --- .../public/search/fetch/get_search_params.ts | 11 -- src/plugins/data/public/search/fetch/index.ts | 8 +- src/plugins/data/server/index.ts | 1 + .../search/es_search/es_search_strategy.ts | 7 +- .../es_search/get_default_search_params.ts | 25 ++- .../data/server/search/es_search/index.ts | 2 +- src/plugins/data/server/search/index.ts | 2 +- .../data/server/search/routes/msearch.ts | 35 ++-- .../data/server/search/routes/search.ts | 4 + .../search/routes}/shim_hits_total.test.ts | 19 ++- .../server/search/routes/shim_hits_total.ts | 33 ++++ .../data_enhanced/common/search/types.ts | 8 +- .../public/search/search_interceptor.ts | 5 - .../server/search/es_search_strategy.test.ts | 2 + .../server/search/es_search_strategy.ts | 160 +++++++++--------- .../server/search/shim_hits_total.ts | 18 -- 16 files changed, 179 insertions(+), 161 deletions(-) rename {x-pack/plugins/data_enhanced/server/search => src/plugins/data/server/search/routes}/shim_hits_total.test.ts (54%) create mode 100644 src/plugins/data/server/search/routes/shim_hits_total.ts delete mode 100644 x-pack/plugins/data_enhanced/server/search/shim_hits_total.ts diff --git a/src/plugins/data/public/search/fetch/get_search_params.ts b/src/plugins/data/public/search/fetch/get_search_params.ts index 97c69e8343f42..ed87c4813951c 100644 --- a/src/plugins/data/public/search/fetch/get_search_params.ts +++ b/src/plugins/data/public/search/fetch/get_search_params.ts @@ -24,21 +24,10 @@ const sessionId = Date.now(); export function getSearchParams(getConfig: GetConfigFn) { return { - ignore_throttled: getIgnoreThrottled(getConfig), - max_concurrent_shard_requests: getMaxConcurrentShardRequests(getConfig), preference: getPreference(getConfig), }; } -export function getIgnoreThrottled(getConfig: GetConfigFn) { - return !getConfig(UI_SETTINGS.SEARCH_INCLUDE_FROZEN); -} - -export function getMaxConcurrentShardRequests(getConfig: GetConfigFn) { - const maxConcurrentShardRequests = getConfig(UI_SETTINGS.COURIER_MAX_CONCURRENT_SHARD_REQUESTS); - return maxConcurrentShardRequests > 0 ? maxConcurrentShardRequests : undefined; -} - export function getPreference(getConfig: GetConfigFn) { const setRequestPreference = getConfig(UI_SETTINGS.COURIER_SET_REQUEST_PREFERENCE); if (setRequestPreference === 'sessionId') return sessionId; diff --git a/src/plugins/data/public/search/fetch/index.ts b/src/plugins/data/public/search/fetch/index.ts index 4a88ca6ace481..4b8511edfc26f 100644 --- a/src/plugins/data/public/search/fetch/index.ts +++ b/src/plugins/data/public/search/fetch/index.ts @@ -18,13 +18,7 @@ */ export * from './types'; -export { - getSearchParams, - getSearchParamsFromRequest, - getPreference, - getIgnoreThrottled, - getMaxConcurrentShardRequests, -} from './get_search_params'; +export { getSearchParams, getSearchParamsFromRequest, getPreference } from './get_search_params'; export { RequestFailure } from './request_error'; export { handleResponse } from './handle_response'; diff --git a/src/plugins/data/server/index.ts b/src/plugins/data/server/index.ts index 2a19a8b46db55..63a5617d8c3fd 100644 --- a/src/plugins/data/server/index.ts +++ b/src/plugins/data/server/index.ts @@ -214,6 +214,7 @@ export { getDefaultSearchParams, getShardTimeout, getTotalLoaded, + toSnakeCase, usageProvider, SearchUsage, } from './search'; diff --git a/src/plugins/data/server/search/es_search/es_search_strategy.ts b/src/plugins/data/server/search/es_search/es_search_strategy.ts index eabbf3e3e2600..05933bd646ccc 100644 --- a/src/plugins/data/server/search/es_search/es_search_strategy.ts +++ b/src/plugins/data/server/search/es_search/es_search_strategy.ts @@ -22,7 +22,7 @@ import { SearchResponse } from 'elasticsearch'; import { Observable } from 'rxjs'; import { ApiResponse } from '@elastic/elasticsearch'; import { SearchUsage } from '../collectors/usage'; -import { ISearchStrategy, getDefaultSearchParams, getTotalLoaded } from '..'; +import { ISearchStrategy, getDefaultSearchParams, getTotalLoaded, getShardTimeout } from '..'; export const esSearchStrategyProvider = ( config$: Observable, @@ -33,7 +33,7 @@ export const esSearchStrategyProvider = ( search: async (context, request, options) => { logger.debug(`search ${request.params?.index}`); const config = await config$.pipe(first()).toPromise(); - const defaultParams = getDefaultSearchParams(config); + const uiSettingsClient = await context.core.uiSettings.client; // Only default index pattern type is supported here. // See data_enhanced for other type support. @@ -42,7 +42,8 @@ export const esSearchStrategyProvider = ( } const params = { - ...defaultParams, + ...(await getDefaultSearchParams(uiSettingsClient)), + ...getShardTimeout(config), ...request.params, }; diff --git a/src/plugins/data/server/search/es_search/get_default_search_params.ts b/src/plugins/data/server/search/es_search/get_default_search_params.ts index 5c5bf0ec08de3..0e09c56741c43 100644 --- a/src/plugins/data/server/search/es_search/get_default_search_params.ts +++ b/src/plugins/data/server/search/es_search/get_default_search_params.ts @@ -17,16 +17,31 @@ * under the License. */ -import { SharedGlobalConfig } from '../../../../../core/server'; +import { mapKeys, snakeCase } from 'lodash'; +import { SharedGlobalConfig, IUiSettingsClient } from '../../../../../core/server'; +import { UI_SETTINGS } from '../..'; export function getShardTimeout(config: SharedGlobalConfig) { - return `${config.elasticsearch.shardTimeout.asMilliseconds()}ms`; + return { + timeout: `${config.elasticsearch.shardTimeout.asMilliseconds()}ms`, + }; } -export function getDefaultSearchParams(config: SharedGlobalConfig) { +export async function getDefaultSearchParams(uiSettingsClient: IUiSettingsClient) { + const ignoreThrottled = !(await uiSettingsClient.get(UI_SETTINGS.SEARCH_INCLUDE_FROZEN)); + const maxConcurrentShardRequests = await uiSettingsClient.get( + UI_SETTINGS.COURIER_MAX_CONCURRENT_SHARD_REQUESTS + ); return { - timeout: getShardTimeout(config), + maxConcurrentShardRequests: + maxConcurrentShardRequests > 0 ? maxConcurrentShardRequests : undefined, + ignoreThrottled, ignoreUnavailable: true, // Don't fail if the index/indices don't exist - restTotalHitsAsInt: true, // Get the number of hits as an int rather than a range + trackTotalHits: true, + // restTotalHitsAsInt: true, // Get the number of hits as an int rather than a range }; } + +export function toSnakeCase(obj: Record) { + return mapKeys(obj, (value, key) => snakeCase(key)); +} diff --git a/src/plugins/data/server/search/es_search/index.ts b/src/plugins/data/server/search/es_search/index.ts index a213d26501502..3418a6a987828 100644 --- a/src/plugins/data/server/search/es_search/index.ts +++ b/src/plugins/data/server/search/es_search/index.ts @@ -19,5 +19,5 @@ export { ES_SEARCH_STRATEGY, IEsSearchRequest, IEsSearchResponse } from '../../../common/search'; export { esSearchStrategyProvider } from './es_search_strategy'; -export { getDefaultSearchParams, getShardTimeout } from './get_default_search_params'; +export * from './get_default_search_params'; export { getTotalLoaded } from './get_total_loaded'; diff --git a/src/plugins/data/server/search/index.ts b/src/plugins/data/server/search/index.ts index ccaf912e28e53..5edeaf87f0965 100644 --- a/src/plugins/data/server/search/index.ts +++ b/src/plugins/data/server/search/index.ts @@ -19,7 +19,7 @@ export { ISearchStrategy, ISearchSetup, ISearchStart, SearchEnhancements } from './types'; -export { getDefaultSearchParams, getTotalLoaded, getShardTimeout } from './es_search'; +export * from './es_search'; export { usageProvider, SearchUsage } from './collectors'; diff --git a/src/plugins/data/server/search/routes/msearch.ts b/src/plugins/data/server/search/routes/msearch.ts index 0073eae06947b..87c1a3920add1 100644 --- a/src/plugins/data/server/search/routes/msearch.ts +++ b/src/plugins/data/server/search/routes/msearch.ts @@ -20,10 +20,12 @@ import { first } from 'rxjs/operators'; import { schema } from '@kbn/config-schema'; +import { SearchResponse } from 'elasticsearch'; import { IRouter } from 'src/core/server'; import { UI_SETTINGS } from '../../../common'; import { SearchRouteDependencies } from '../search_service'; -import { getShardTimeout } from '..'; +import { shimHitsTotal } from './shim_hits_total'; +import { getShardTimeout, getDefaultSearchParams, toSnakeCase } from '..'; interface MsearchHeaders { index: string; @@ -98,28 +100,29 @@ export function registerMsearchRoute(router: IRouter, deps: SearchRouteDependenc const config = await deps.globalConfig$.pipe(first()).toPromise(); const timeout = getShardTimeout(config); - const body = convertRequestBody(request.body, { timeout }); + const body = convertRequestBody(request.body, timeout); + + // trackTotalHits is not supported by msearch + const { trackTotalHits, ...params } = await getDefaultSearchParams( + context.core.uiSettings.client + ); try { - const ignoreThrottled = !(await context.core.uiSettings.client.get( - UI_SETTINGS.SEARCH_INCLUDE_FROZEN - )); - const maxConcurrentShardRequests = await context.core.uiSettings.client.get( - UI_SETTINGS.COURIER_MAX_CONCURRENT_SHARD_REQUESTS - ); - const response = await client.transport.request({ + const response: Array> = await client.transport.request({ method: 'GET', path: '/_msearch', body, - querystring: { - rest_total_hits_as_int: true, - ignore_throttled: ignoreThrottled, - max_concurrent_shard_requests: - maxConcurrentShardRequests > 0 ? maxConcurrentShardRequests : undefined, - }, + querystring: toSnakeCase(params), }); - return res.ok({ body: response }); + return res.ok({ + body: { + ...response, + body: { + responses: response.body.responses.map((r) => shimHitsTotal(r)), + }, + }, + }); } catch (err) { return res.customError({ statusCode: err.statusCode || 500, diff --git a/src/plugins/data/server/search/routes/search.ts b/src/plugins/data/server/search/routes/search.ts index 4340285583489..9b79aeae805a9 100644 --- a/src/plugins/data/server/search/routes/search.ts +++ b/src/plugins/data/server/search/routes/search.ts @@ -21,6 +21,7 @@ import { schema } from '@kbn/config-schema'; import { IRouter } from 'src/core/server'; import { getRequestAbortedSignal } from '../../lib'; import { SearchRouteDependencies } from '../search_service'; +import { shimHitsTotal } from './shim_hits_total'; export function registerSearchRoute( router: IRouter, @@ -56,6 +57,9 @@ export function registerSearchRoute( strategy, } ); + + response.rawResponse = shimHitsTotal(response.rawResponse); + return res.ok({ body: response }); } catch (err) { return res.customError({ diff --git a/x-pack/plugins/data_enhanced/server/search/shim_hits_total.test.ts b/src/plugins/data/server/search/routes/shim_hits_total.test.ts similarity index 54% rename from x-pack/plugins/data_enhanced/server/search/shim_hits_total.test.ts rename to src/plugins/data/server/search/routes/shim_hits_total.test.ts index 61740b97299da..0f24735386121 100644 --- a/x-pack/plugins/data_enhanced/server/search/shim_hits_total.test.ts +++ b/src/plugins/data/server/search/routes/shim_hits_total.test.ts @@ -1,7 +1,20 @@ /* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ import { shimHitsTotal } from './shim_hits_total'; diff --git a/src/plugins/data/server/search/routes/shim_hits_total.ts b/src/plugins/data/server/search/routes/shim_hits_total.ts new file mode 100644 index 0000000000000..5f95b21358978 --- /dev/null +++ b/src/plugins/data/server/search/routes/shim_hits_total.ts @@ -0,0 +1,33 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { SearchResponse } from 'elasticsearch'; + +/** + * Temporary workaround until https://github.com/elastic/kibana/issues/26356 is addressed. + * Since we are setting `track_total_hits` in the request, `hits.total` will be an object + * containing the `value`. + * + * @internal + */ +export function shimHitsTotal(response: SearchResponse) { + const total = (response.hits?.total as any)?.value ?? response.hits?.total; + const hits = { ...response.hits, total }; + return { ...response, hits }; +} diff --git a/x-pack/plugins/data_enhanced/common/search/types.ts b/x-pack/plugins/data_enhanced/common/search/types.ts index 0d3d3a69e1e57..24d459ade4bf9 100644 --- a/x-pack/plugins/data_enhanced/common/search/types.ts +++ b/x-pack/plugins/data_enhanced/common/search/types.ts @@ -4,21 +4,15 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IEsSearchRequest, ISearchRequestParams } from '../../../../../src/plugins/data/common'; +import { IEsSearchRequest } from '../../../../../src/plugins/data/common'; export const ENHANCED_ES_SEARCH_STRATEGY = 'ese'; -export interface EnhancedSearchParams extends ISearchRequestParams { - ignoreThrottled: boolean; -} - export interface IAsyncSearchRequest extends IEsSearchRequest { /** * The ID received from the response from the initial request */ id?: string; - - params?: EnhancedSearchParams; } export interface IEnhancedEsSearchRequest extends IEsSearchRequest { diff --git a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts index d226b949e26b0..92f1a0f217688 100644 --- a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts +++ b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts @@ -80,11 +80,6 @@ export class EnhancedSearchInterceptor extends SearchInterceptor { ) { let { id } = request; - request.params = { - ignoreThrottled: !this.deps.uiSettings.get(UI_SETTINGS.SEARCH_INCLUDE_FROZEN), - ...request.params, - }; - const { combinedSignal, cleanup } = this.setupAbortSignal({ abortSignal: options.signal, timeout: this.searchTimeout, diff --git a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts index 9d577a9e04dce..e5aa694fe9ee6 100644 --- a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts +++ b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts @@ -81,6 +81,8 @@ describe('ES search strategy', () => { expect(querystring).toHaveProperty('wait_for_completion_timeout'); expect(querystring).toHaveProperty('track_total_hits'); expect(querystring).toHaveProperty('ignore_unavailable'); + expect(querystring).toHaveProperty('ignore_throttled'); + expect(querystring).toHaveProperty('ignore_unavailable'); expect(querystring).toHaveProperty('keep_alive'); expect(querystring).toHaveProperty('batched_reduce_size'); }); diff --git a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts index dd83fa7bc40ee..4d0566474ccbe 100644 --- a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts +++ b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts @@ -5,23 +5,18 @@ */ import { first } from 'rxjs/operators'; -import { mapKeys, snakeCase } from 'lodash'; import { Observable } from 'rxjs'; import { SearchResponse } from 'elasticsearch'; -import { - SharedGlobalConfig, - RequestHandlerContext, - ElasticsearchClient, - Logger, -} from '../../../../../src/core/server'; +import { SharedGlobalConfig, RequestHandlerContext, Logger } from '../../../../../src/core/server'; import { getTotalLoaded, ISearchStrategy, SearchUsage, getDefaultSearchParams, + getShardTimeout, + toSnakeCase, } from '../../../../../src/plugins/data/server'; import { IEnhancedEsSearchRequest } from '../../common'; -import { shimHitsTotal } from './shim_hits_total'; import { ISearchOptions, IEsSearchResponse } from '../../../../../src/plugins/data/common/search'; function isEnhancedEsSearchResponse(response: any): response is IEsSearchResponse { @@ -38,16 +33,14 @@ export const enhancedEsSearchStrategyProvider = ( request: IEnhancedEsSearchRequest, options?: ISearchOptions ) => { - const client = context.core.elasticsearch.client.asCurrentUser; - logger.debug(`search ${JSON.stringify(request.params) || request.id}`); const isAsync = request.indexType !== 'rollup'; try { const response = isAsync - ? await asyncSearch(client, request) - : await rollupSearch(client, request, config$); + ? await asyncSearch(context, request) + : await rollupSearch(context, request); if ( usage && @@ -74,80 +67,79 @@ export const enhancedEsSearchStrategyProvider = ( }); }; - return { search, cancel }; -}; + const asyncSearch = async function ( + context: RequestHandlerContext, + request: IEnhancedEsSearchRequest + ): Promise { + const esClient = context.core.elasticsearch.client.asCurrentUser; + const uiSettingsClient = await context.core.uiSettings.client; + + const { params = {} } = request; + + // If we have an ID, then just poll for that ID, otherwise send the entire request body + const { body = undefined, index = undefined, ...queryParams } = request.id ? {} : params; + + const method = request.id ? 'GET' : 'POST'; + const path = encodeURI(request.id ? `/_async_search/${request.id}` : `/${index}/_async_search`); + + const querystring = toSnakeCase({ + waitForCompletionTimeout: '100ms', // Wait up to 100ms for the response to return + keepAlive: '1m', // Extend the TTL for this search request by one minute + ...(request.id + ? {} + : { + ...(await getDefaultSearchParams(uiSettingsClient)), + batchedReduceSize: 64, // Only report partial results every 64 shards; this should be reduced when we actually display partial results + }), + ...queryParams, + }); + // TODO: replace with async endpoints once https://github.com/elastic/elasticsearch-js/issues/1280 is resolved + const esResponse = await esClient.transport.request({ + method, + path, + body, + querystring, + }); -async function asyncSearch( - client: ElasticsearchClient, - request: IEnhancedEsSearchRequest -): Promise { - const { params = {} } = request; - - // If we have an ID, then just poll for that ID, otherwise send the entire request body - const { body = undefined, index = undefined, ...queryParams } = request.id ? {} : params; - - const method = request.id ? 'GET' : 'POST'; - const path = encodeURI(request.id ? `/_async_search/${request.id}` : `/${index}/_async_search`); - - const querystring = toSnakeCase({ - waitForCompletionTimeout: '100ms', // Wait up to 100ms for the response to return - keepAlive: '1m', // Extend the TTL for this search request by one minute - ...(request.id - ? {} - : { - trackTotalHits: true, - ignoreUnavailable: true, - batchedReduceSize: 64, // Only report partial results every 64 shards; this should be reduced when we actually display partial results - }), - ...queryParams, - }); - - // TODO: replace with async endpoints once https://github.com/elastic/elasticsearch-js/issues/1280 is resolved - const esResponse = await client.transport.request({ - method, - path, - body, - querystring, - }); - - const { id, response, is_partial: isPartial, is_running: isRunning } = esResponse.body; - return { - id, - isPartial, - isRunning, - rawResponse: shimHitsTotal(response), - ...getTotalLoaded(response._shards), + const { id, response, is_partial: isPartial, is_running: isRunning } = esResponse.body; + return { + id, + isPartial, + isRunning, + rawResponse: response, + ...getTotalLoaded(response._shards), + }; }; -} -async function rollupSearch( - client: ElasticsearchClient, - request: IEnhancedEsSearchRequest, - config$: Observable -): Promise { - const config = await config$.pipe(first()).toPromise(); - const { body, index, ...params } = request.params!; - const method = 'POST'; - const path = encodeURI(`/${index}/_rollup_search`); - const querystring = toSnakeCase({ - ...getDefaultSearchParams(config), - ...params, - }); - - const esResponse = await client.transport.request({ - method, - path, - body, - querystring, - }); - - const response = esResponse.body as SearchResponse; - return { - rawResponse: shimHitsTotal(response), - ...getTotalLoaded(response._shards), + const rollupSearch = async function ( + context: RequestHandlerContext, + request: IEnhancedEsSearchRequest + ): Promise { + const esClient = context.core.elasticsearch.client.asCurrentUser; + const uiSettingsClient = await context.core.uiSettings.client; + const config = await config$.pipe(first()).toPromise(); + const { body, index, ...params } = request.params!; + const method = 'POST'; + const path = encodeURI(`/${index}/_rollup_search`); + const querystring = toSnakeCase({ + ...getShardTimeout(config), + ...(await getDefaultSearchParams(uiSettingsClient)), + ...params, + }); + + const esResponse = await esClient.transport.request({ + method, + path, + body, + querystring, + }); + + const response = esResponse.body as SearchResponse; + return { + rawResponse: shimresponse, + ...getTotalLoaded(response._shards), + }; }; -} -function toSnakeCase(obj: Record) { - return mapKeys(obj, (value, key) => snakeCase(key)); -} + return { search, cancel }; +}; diff --git a/x-pack/plugins/data_enhanced/server/search/shim_hits_total.ts b/x-pack/plugins/data_enhanced/server/search/shim_hits_total.ts deleted file mode 100644 index 10d45be01563a..0000000000000 --- a/x-pack/plugins/data_enhanced/server/search/shim_hits_total.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { SearchResponse } from 'elasticsearch'; - -/** - * Temporary workaround until https://github.com/elastic/kibana/issues/26356 is addressed. - * Since we are setting `track_total_hits` in the request, `hits.total` will be an object - * containing the `value`. - */ -export function shimHitsTotal(response: SearchResponse) { - const total = (response.hits?.total as any)?.value ?? response.hits?.total; - const hits = { ...response.hits, total }; - return { ...response, hits }; -} From 70b58096a2231f86fe199a80cb2b9299f4ae10a3 Mon Sep 17 00:00:00 2001 From: Liza K Date: Tue, 1 Sep 2020 16:43:09 +0300 Subject: [PATCH 57/77] docs Stop using toSnakeCase Updates jest tests --- ...gins-data-server.getdefaultsearchparams.md | 20 ++++---- ...gin-plugins-data-server.getshardtimeout.md | 8 ++- .../kibana-plugin-plugins-data-server.md | 2 +- ...plugin-plugins-data-server.plugin.start.md | 4 +- .../data/common/search/es_search/index.ts | 8 +-- .../data/common/search/es_search/types.ts | 3 ++ src/plugins/data/common/search/index.ts | 9 +--- .../search/fetch/get_search_params.test.ts | 25 +++------- src/plugins/data/server/index.ts | 1 - .../es_search/es_search_strategy.test.ts | 13 +++-- .../search/es_search/es_search_strategy.ts | 5 +- .../es_search/get_default_search_params.ts | 5 -- .../data/server/search/routes/msearch.ts | 11 ++--- .../data/server/search/routes/search.ts | 14 ++++-- src/plugins/data/server/server.api.md | 49 +++++++++++-------- .../server/search/es_search_strategy.test.ts | 35 ++++++++----- .../server/search/es_search_strategy.ts | 11 ++--- 17 files changed, 118 insertions(+), 105 deletions(-) diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getdefaultsearchparams.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getdefaultsearchparams.md index 9de005c1fd0dd..e718ca42ca30f 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getdefaultsearchparams.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getdefaultsearchparams.md @@ -7,24 +7,26 @@ Signature: ```typescript -export declare function getDefaultSearchParams(config: SharedGlobalConfig): { - timeout: string; +export declare function getDefaultSearchParams(uiSettingsClient: IUiSettingsClient): Promise<{ + maxConcurrentShardRequests: number | undefined; + ignoreThrottled: boolean; ignoreUnavailable: boolean; - restTotalHitsAsInt: boolean; -}; + trackTotalHits: boolean; +}>; ``` ## Parameters | Parameter | Type | Description | | --- | --- | --- | -| config | SharedGlobalConfig | | +| uiSettingsClient | IUiSettingsClient | | Returns: -`{ - timeout: string; +`Promise<{ + maxConcurrentShardRequests: number | undefined; + ignoreThrottled: boolean; ignoreUnavailable: boolean; - restTotalHitsAsInt: boolean; -}` + trackTotalHits: boolean; +}>` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getshardtimeout.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getshardtimeout.md index 7968379249bed..ca60c39a8e413 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getshardtimeout.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getshardtimeout.md @@ -7,7 +7,9 @@ Signature: ```typescript -export declare function getShardTimeout(config: SharedGlobalConfig): string; +export declare function getShardTimeout(config: SharedGlobalConfig): { + timeout: string; +}; ``` ## Parameters @@ -18,5 +20,7 @@ export declare function getShardTimeout(config: SharedGlobalConfig): string; Returns: -`string` +`{ + timeout: string; +}` diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md index d3761e3d1ae9f..e7bfd44093f19 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md @@ -26,7 +26,7 @@ | Function | Description | | --- | --- | -| [getDefaultSearchParams(config)](./kibana-plugin-plugins-data-server.getdefaultsearchparams.md) | | +| [getDefaultSearchParams(uiSettingsClient)](./kibana-plugin-plugins-data-server.getdefaultsearchparams.md) | | | [getShardTimeout(config)](./kibana-plugin-plugins-data-server.getshardtimeout.md) | | | [getTime(indexPattern, timeRange, options)](./kibana-plugin-plugins-data-server.gettime.md) | | | [parseInterval(interval)](./kibana-plugin-plugins-data-server.parseinterval.md) | | diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.start.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.start.md index 2d9104ef894bc..455c5ecdd8195 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.start.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.plugin.start.md @@ -8,7 +8,7 @@ ```typescript start(core: CoreStart): { - search: ISearchStart>; + search: ISearchStart>; fieldFormats: { fieldFormatServiceFactory: (uiSettings: import("../../../core/server").IUiSettingsClient) => Promise; }; @@ -27,7 +27,7 @@ start(core: CoreStart): { Returns: `{ - search: ISearchStart>; + search: ISearchStart>; fieldFormats: { fieldFormatServiceFactory: (uiSettings: import("../../../core/server").IUiSettingsClient) => Promise; }; diff --git a/src/plugins/data/common/search/es_search/index.ts b/src/plugins/data/common/search/es_search/index.ts index 54757b53b8665..d8f7b5091eb8f 100644 --- a/src/plugins/data/common/search/es_search/index.ts +++ b/src/plugins/data/common/search/es_search/index.ts @@ -17,10 +17,4 @@ * under the License. */ -export { - ISearchRequestParams, - IEsSearchRequest, - IEsSearchResponse, - ES_SEARCH_STRATEGY, - ISearchOptions, -} from './types'; +export * from './types'; diff --git a/src/plugins/data/common/search/es_search/types.ts b/src/plugins/data/common/search/es_search/types.ts index 89faa5b7119c8..81124c1e095f7 100644 --- a/src/plugins/data/common/search/es_search/types.ts +++ b/src/plugins/data/common/search/es_search/types.ts @@ -53,3 +53,6 @@ export interface IEsSearchResponse extends IKibanaSearchResponse { isPartial?: boolean; rawResponse: SearchResponse; } + +export const isEsResponse = (response: any): response is IEsSearchResponse => + response && response.rawResponse; diff --git a/src/plugins/data/common/search/index.ts b/src/plugins/data/common/search/index.ts index 3bfb0ddb89aa9..061974d860246 100644 --- a/src/plugins/data/common/search/index.ts +++ b/src/plugins/data/common/search/index.ts @@ -22,11 +22,4 @@ export * from './es_search'; export * from './expressions'; export * from './tabify'; export * from './types'; - -export { - IEsSearchRequest, - IEsSearchResponse, - ES_SEARCH_STRATEGY, - ISearchRequestParams, - ISearchOptions, -} from './es_search'; +export * from './es_search'; diff --git a/src/plugins/data/public/search/fetch/get_search_params.test.ts b/src/plugins/data/public/search/fetch/get_search_params.test.ts index 8b693b1dff4ee..5e83e1f57bb6d 100644 --- a/src/plugins/data/public/search/fetch/get_search_params.test.ts +++ b/src/plugins/data/public/search/fetch/get_search_params.test.ts @@ -25,23 +25,12 @@ function getConfigStub(config: any = {}): GetConfigFn { } describe('getSearchParams', () => { - test('includes ignore_throttled according to search:includeFrozen', () => { - let config = getConfigStub({ [UI_SETTINGS.SEARCH_INCLUDE_FROZEN]: true }); - let searchParams = getSearchParams(config); - expect(searchParams.ignore_throttled).toBe(false); - - config = getConfigStub({ [UI_SETTINGS.SEARCH_INCLUDE_FROZEN]: false }); - searchParams = getSearchParams(config); - expect(searchParams.ignore_throttled).toBe(true); - }); - - test('includes max_concurrent_shard_requests according to courier:maxConcurrentShardRequests', () => { - let config = getConfigStub({ [UI_SETTINGS.COURIER_MAX_CONCURRENT_SHARD_REQUESTS]: 0 }); - let searchParams = getSearchParams(config); - expect(searchParams.max_concurrent_shard_requests).toBe(undefined); - - config = getConfigStub({ [UI_SETTINGS.COURIER_MAX_CONCURRENT_SHARD_REQUESTS]: 5 }); - searchParams = getSearchParams(config); - expect(searchParams.max_concurrent_shard_requests).toBe(5); + test('includes custom preference', () => { + const config = getConfigStub({ + [UI_SETTINGS.COURIER_SET_REQUEST_PREFERENCE]: 'custom', + [UI_SETTINGS.COURIER_CUSTOM_REQUEST_PREFERENCE]: 'aaa', + }); + const searchParams = getSearchParams(config); + expect(searchParams.preference).toBe('aaa'); }); }); diff --git a/src/plugins/data/server/index.ts b/src/plugins/data/server/index.ts index 63a5617d8c3fd..2a19a8b46db55 100644 --- a/src/plugins/data/server/index.ts +++ b/src/plugins/data/server/index.ts @@ -214,7 +214,6 @@ export { getDefaultSearchParams, getShardTimeout, getTotalLoaded, - toSnakeCase, usageProvider, SearchUsage, } from './search'; diff --git a/src/plugins/data/server/search/es_search/es_search_strategy.test.ts b/src/plugins/data/server/search/es_search/es_search_strategy.test.ts index c34c3a310814c..87874ced7afff 100644 --- a/src/plugins/data/server/search/es_search/es_search_strategy.test.ts +++ b/src/plugins/data/server/search/es_search/es_search_strategy.test.ts @@ -36,7 +36,14 @@ describe('ES search strategy', () => { }, }); const mockContext = { - core: { elasticsearch: { client: { asCurrentUser: { search: mockApiCaller } } } }, + core: { + uiSettings: { + client: { + get: () => {}, + }, + }, + elasticsearch: { client: { asCurrentUser: { search: mockApiCaller } } }, + }, }; const mockConfig$ = pluginInitializerContextConfigMock({}).legacy.globalConfig$; @@ -61,7 +68,7 @@ describe('ES search strategy', () => { ...params, timeout: '0ms', ignoreUnavailable: true, - restTotalHitsAsInt: true, + trackTotalHits: true, }); }); @@ -74,7 +81,7 @@ describe('ES search strategy', () => { expect(mockApiCaller).toBeCalled(); expect(mockApiCaller.mock.calls[0][0]).toEqual({ ...params, - restTotalHitsAsInt: true, + trackTotalHits: true, }); }); diff --git a/src/plugins/data/server/search/es_search/es_search_strategy.ts b/src/plugins/data/server/search/es_search/es_search_strategy.ts index 05933bd646ccc..fb80cd492949d 100644 --- a/src/plugins/data/server/search/es_search/es_search_strategy.ts +++ b/src/plugins/data/server/search/es_search/es_search_strategy.ts @@ -41,8 +41,11 @@ export const esSearchStrategyProvider = ( throw new Error(`Unsupported index pattern type ${request.indexType}`); } + // ignoreThrottled is not supported in OSS + const { ignoreThrottled, ...defaultParams } = await getDefaultSearchParams(uiSettingsClient); + const params = { - ...(await getDefaultSearchParams(uiSettingsClient)), + ...defaultParams, ...getShardTimeout(config), ...request.params, }; diff --git a/src/plugins/data/server/search/es_search/get_default_search_params.ts b/src/plugins/data/server/search/es_search/get_default_search_params.ts index 0e09c56741c43..13b9bd28c854b 100644 --- a/src/plugins/data/server/search/es_search/get_default_search_params.ts +++ b/src/plugins/data/server/search/es_search/get_default_search_params.ts @@ -38,10 +38,5 @@ export async function getDefaultSearchParams(uiSettingsClient: IUiSettingsClient ignoreThrottled, ignoreUnavailable: true, // Don't fail if the index/indices don't exist trackTotalHits: true, - // restTotalHitsAsInt: true, // Get the number of hits as an int rather than a range }; } - -export function toSnakeCase(obj: Record) { - return mapKeys(obj, (value, key) => snakeCase(key)); -} diff --git a/src/plugins/data/server/search/routes/msearch.ts b/src/plugins/data/server/search/routes/msearch.ts index 87c1a3920add1..5b9e4418a9cb8 100644 --- a/src/plugins/data/server/search/routes/msearch.ts +++ b/src/plugins/data/server/search/routes/msearch.ts @@ -22,10 +22,9 @@ import { schema } from '@kbn/config-schema'; import { SearchResponse } from 'elasticsearch'; import { IRouter } from 'src/core/server'; -import { UI_SETTINGS } from '../../../common'; import { SearchRouteDependencies } from '../search_service'; import { shimHitsTotal } from './shim_hits_total'; -import { getShardTimeout, getDefaultSearchParams, toSnakeCase } from '..'; +import { getShardTimeout, getDefaultSearchParams } from '..'; interface MsearchHeaders { index: string; @@ -103,23 +102,23 @@ export function registerMsearchRoute(router: IRouter, deps: SearchRouteDependenc const body = convertRequestBody(request.body, timeout); // trackTotalHits is not supported by msearch - const { trackTotalHits, ...params } = await getDefaultSearchParams( + const { trackTotalHits, ...defaultParams } = await getDefaultSearchParams( context.core.uiSettings.client ); try { - const response: Array> = await client.transport.request({ + const response = await client.transport.request({ method: 'GET', path: '/_msearch', body, - querystring: toSnakeCase(params), + querystring: defaultParams, }); return res.ok({ body: { ...response, body: { - responses: response.body.responses.map((r) => shimHitsTotal(r)), + responses: response.body.responses.map((r: SearchResponse) => shimHitsTotal(r)), }, }, }); diff --git a/src/plugins/data/server/search/routes/search.ts b/src/plugins/data/server/search/routes/search.ts index 9b79aeae805a9..cffdd9dd32c96 100644 --- a/src/plugins/data/server/search/routes/search.ts +++ b/src/plugins/data/server/search/routes/search.ts @@ -19,6 +19,7 @@ import { schema } from '@kbn/config-schema'; import { IRouter } from 'src/core/server'; +import { isEsResponse } from 'src/plugins/data/common'; import { getRequestAbortedSignal } from '../../lib'; import { SearchRouteDependencies } from '../search_service'; import { shimHitsTotal } from './shim_hits_total'; @@ -58,9 +59,16 @@ export function registerSearchRoute( } ); - response.rawResponse = shimHitsTotal(response.rawResponse); - - return res.ok({ body: response }); + return res.ok({ + body: { + ...response, + ...(isEsResponse(response) + ? { + rawResponse: shimHitsTotal(response.rawResponse), + } + : {}), + }, + }); } catch (err) { return res.customError({ statusCode: err.statusCode || 500, diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md index 9d0d4a549d501..a0bfc19499abb 100644 --- a/src/plugins/data/server/server.api.md +++ b/src/plugins/data/server/server.api.md @@ -441,20 +441,24 @@ export interface Filter { query?: any; } -// Warning: (ae-forgotten-export) The symbol "SharedGlobalConfig" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "IUiSettingsClient" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "getDefaultSearchParams" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export function getDefaultSearchParams(config: SharedGlobalConfig): { - timeout: string; +export function getDefaultSearchParams(uiSettingsClient: IUiSettingsClient): Promise<{ + maxConcurrentShardRequests: number | undefined; + ignoreThrottled: boolean; ignoreUnavailable: boolean; - restTotalHitsAsInt: boolean; -}; + trackTotalHits: boolean; +}>; +// Warning: (ae-forgotten-export) The symbol "SharedGlobalConfig" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "getShardTimeout" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export function getShardTimeout(config: SharedGlobalConfig): string; +export function getShardTimeout(config: SharedGlobalConfig): { + timeout: string; +}; // Warning: (ae-missing-release-tag) "getTime" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -873,7 +877,7 @@ export class Plugin implements Plugin_2>; + search: ISearchStart>; fieldFormats: { fieldFormatServiceFactory: (uiSettings: import("../../../core/server").IUiSettingsClient) => Promise; }; @@ -1027,6 +1031,11 @@ export interface TimeRange { to: string; } +// Warning: (ae-missing-release-tag) "toSnakeCase" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function toSnakeCase(obj: Record): import("lodash").Dictionary; + // Warning: (ae-missing-release-tag) "UI_SETTINGS" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -1092,19 +1101,19 @@ export function usageProvider(core: CoreSetup_2): SearchUsage; // src/plugins/data/server/index.ts:101:26 - (ae-forgotten-export) The symbol "TruncateFormat" needs to be exported by the entry point index.d.ts // src/plugins/data/server/index.ts:127:27 - (ae-forgotten-export) The symbol "isFilterable" needs to be exported by the entry point index.d.ts // src/plugins/data/server/index.ts:127:27 - (ae-forgotten-export) The symbol "isNestedField" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:222:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:222:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:222:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:222:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:224:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:225:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:234:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:235:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:236:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:240:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:241:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:245:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:248:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:223:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:223:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:223:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:223:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:225:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:226:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:235:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:236:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:237:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:241:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:242:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:246:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:249:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts // src/plugins/data/server/plugin.ts:88:66 - (ae-forgotten-export) The symbol "DataEnhancements" needs to be exported by the entry point index.d.ts // (No @packageDocumentation comment for this package) diff --git a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts index e5aa694fe9ee6..fdf886633f5b8 100644 --- a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts +++ b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts @@ -40,6 +40,11 @@ describe('ES search strategy', () => { }; const mockContext = { core: { + uiSettings: { + client: { + get: () => {}, + }, + }, elasticsearch: { client: { asCurrentUser: { transport: { request: mockApiCaller } } } }, }, }; @@ -78,13 +83,13 @@ describe('ES search strategy', () => { expect(method).toBe('POST'); expect(path).toBe('/logstash-*/_async_search'); expect(body).toEqual({ query: {} }); - expect(querystring).toHaveProperty('wait_for_completion_timeout'); - expect(querystring).toHaveProperty('track_total_hits'); - expect(querystring).toHaveProperty('ignore_unavailable'); - expect(querystring).toHaveProperty('ignore_throttled'); - expect(querystring).toHaveProperty('ignore_unavailable'); - expect(querystring).toHaveProperty('keep_alive'); - expect(querystring).toHaveProperty('batched_reduce_size'); + expect(querystring).toHaveProperty('batchedReduceSize'); + expect(querystring).toHaveProperty('ignoreThrottled'); + expect(querystring).toHaveProperty('ignoreUnavailable'); + expect(querystring).toHaveProperty('keepAlive'); + expect(querystring).toHaveProperty('maxConcurrentShardRequests'); + expect(querystring).toHaveProperty('trackTotalHits'); + expect(querystring).toHaveProperty('waitForCompletionTimeout'); }); it('makes a GET request to async search with ID when ID is provided', async () => { @@ -100,9 +105,13 @@ describe('ES search strategy', () => { expect(method).toBe('GET'); expect(path).toBe('/_async_search/foo'); expect(body).toEqual(undefined); - expect(querystring).not.toHaveProperty('batched_reduce_size'); - expect(querystring).not.toHaveProperty('batched_reduce_size'); - expect(querystring).not.toHaveProperty('batched_reduce_size'); + expect(querystring).not.toHaveProperty('batchedReduceSize'); + expect(querystring).not.toHaveProperty('ignoreThrottled'); + expect(querystring).not.toHaveProperty('ignoreUnavailable'); + expect(querystring).not.toHaveProperty('maxConcurrentShardRequests'); + expect(querystring).not.toHaveProperty('trackTotalHits'); + expect(querystring).toHaveProperty('keepAlive'); + expect(querystring).toHaveProperty('waitForCompletionTimeout'); }); it('encodes special characters in the path', async () => { @@ -136,7 +145,7 @@ describe('ES search strategy', () => { expect(path).toBe('/foo-%E7%A8%8B/_rollup_search'); }); - it('sets wait_for_completion_timeout and keep_alive in the request', async () => { + it('sets waitForCompletionTimeout and keepAlive in the request', async () => { mockApiCaller.mockResolvedValueOnce(mockAsyncResponse); const params = { index: 'foo-*', body: {} }; @@ -146,7 +155,7 @@ describe('ES search strategy', () => { expect(mockApiCaller).toBeCalled(); const { querystring } = mockApiCaller.mock.calls[0][0]; - expect(querystring).toHaveProperty('wait_for_completion_timeout'); - expect(querystring).toHaveProperty('keep_alive'); + expect(querystring).toHaveProperty('keepAlive'); + expect(querystring).toHaveProperty('waitForCompletionTimeout'); }); }); diff --git a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts index 4d0566474ccbe..b214a6c99b598 100644 --- a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts +++ b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts @@ -14,7 +14,6 @@ import { SearchUsage, getDefaultSearchParams, getShardTimeout, - toSnakeCase, } from '../../../../../src/plugins/data/server'; import { IEnhancedEsSearchRequest } from '../../common'; import { ISearchOptions, IEsSearchResponse } from '../../../../../src/plugins/data/common/search'; @@ -82,7 +81,7 @@ export const enhancedEsSearchStrategyProvider = ( const method = request.id ? 'GET' : 'POST'; const path = encodeURI(request.id ? `/_async_search/${request.id}` : `/${index}/_async_search`); - const querystring = toSnakeCase({ + const querystring = { waitForCompletionTimeout: '100ms', // Wait up to 100ms for the response to return keepAlive: '1m', // Extend the TTL for this search request by one minute ...(request.id @@ -92,7 +91,7 @@ export const enhancedEsSearchStrategyProvider = ( batchedReduceSize: 64, // Only report partial results every 64 shards; this should be reduced when we actually display partial results }), ...queryParams, - }); + }; // TODO: replace with async endpoints once https://github.com/elastic/elasticsearch-js/issues/1280 is resolved const esResponse = await esClient.transport.request({ method, @@ -121,11 +120,11 @@ export const enhancedEsSearchStrategyProvider = ( const { body, index, ...params } = request.params!; const method = 'POST'; const path = encodeURI(`/${index}/_rollup_search`); - const querystring = toSnakeCase({ + const querystring = { ...getShardTimeout(config), ...(await getDefaultSearchParams(uiSettingsClient)), ...params, - }); + }; const esResponse = await esClient.transport.request({ method, @@ -136,7 +135,7 @@ export const enhancedEsSearchStrategyProvider = ( const response = esResponse.body as SearchResponse; return { - rawResponse: shimresponse, + rawResponse: response, ...getTotalLoaded(response._shards), }; }; From f8aba5d3fbb9c936c5cdedce55b53a60e832c8a0 Mon Sep 17 00:00:00 2001 From: Liza K Date: Tue, 1 Sep 2020 16:48:21 +0300 Subject: [PATCH 58/77] add management docs --- docs/management/advanced-options.asciidoc | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/management/advanced-options.asciidoc b/docs/management/advanced-options.asciidoc index 9f13c152b4cbe..c2cbeda7588d3 100644 --- a/docs/management/advanced-options.asciidoc +++ b/docs/management/advanced-options.asciidoc @@ -219,6 +219,7 @@ be inconsistent because different shards might be in different refresh states. `search:includeFrozen`:: Includes {ref}/frozen-indices.html[frozen indices] in results. Searching through frozen indices might increase the search time. This setting is off by default. Users must opt-in to include frozen indices. +`search:timeout`:: Change the maximum timeout for a search session or set to 0 to disable the timeout and allow queries to run to completion. [float] [[kibana-siem-settings]] From f4d0064e54b17bd548ec3062fc2b110bf72026ff Mon Sep 17 00:00:00 2001 From: Liza K Date: Tue, 1 Sep 2020 17:06:21 +0300 Subject: [PATCH 59/77] docs --- .../es_search/get_default_search_params.ts | 1 - .../data/server/search/routes/search.ts | 2 +- src/plugins/data/server/server.api.md | 31 ++++++++----------- 3 files changed, 14 insertions(+), 20 deletions(-) diff --git a/src/plugins/data/server/search/es_search/get_default_search_params.ts b/src/plugins/data/server/search/es_search/get_default_search_params.ts index 13b9bd28c854b..d69c7153f797d 100644 --- a/src/plugins/data/server/search/es_search/get_default_search_params.ts +++ b/src/plugins/data/server/search/es_search/get_default_search_params.ts @@ -17,7 +17,6 @@ * under the License. */ -import { mapKeys, snakeCase } from 'lodash'; import { SharedGlobalConfig, IUiSettingsClient } from '../../../../../core/server'; import { UI_SETTINGS } from '../..'; diff --git a/src/plugins/data/server/search/routes/search.ts b/src/plugins/data/server/search/routes/search.ts index cffdd9dd32c96..b5d5ec283767d 100644 --- a/src/plugins/data/server/search/routes/search.ts +++ b/src/plugins/data/server/search/routes/search.ts @@ -19,10 +19,10 @@ import { schema } from '@kbn/config-schema'; import { IRouter } from 'src/core/server'; -import { isEsResponse } from 'src/plugins/data/common'; import { getRequestAbortedSignal } from '../../lib'; import { SearchRouteDependencies } from '../search_service'; import { shimHitsTotal } from './shim_hits_total'; +import { isEsResponse } from '../../../common'; export function registerSearchRoute( router: IRouter, diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md index a0bfc19499abb..ab0ee90a05780 100644 --- a/src/plugins/data/server/server.api.md +++ b/src/plugins/data/server/server.api.md @@ -1031,11 +1031,6 @@ export interface TimeRange { to: string; } -// Warning: (ae-missing-release-tag) "toSnakeCase" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export function toSnakeCase(obj: Record): import("lodash").Dictionary; - // Warning: (ae-missing-release-tag) "UI_SETTINGS" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -1101,19 +1096,19 @@ export function usageProvider(core: CoreSetup_2): SearchUsage; // src/plugins/data/server/index.ts:101:26 - (ae-forgotten-export) The symbol "TruncateFormat" needs to be exported by the entry point index.d.ts // src/plugins/data/server/index.ts:127:27 - (ae-forgotten-export) The symbol "isFilterable" needs to be exported by the entry point index.d.ts // src/plugins/data/server/index.ts:127:27 - (ae-forgotten-export) The symbol "isNestedField" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:223:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:223:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:223:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:223:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:225:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:226:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:235:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:236:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:237:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:241:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:242:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:246:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:249:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:222:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:222:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:222:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:222:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:224:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:225:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:234:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:235:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:236:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:240:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:241:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:245:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:248:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts // src/plugins/data/server/plugin.ts:88:66 - (ae-forgotten-export) The symbol "DataEnhancements" needs to be exported by the entry point index.d.ts // (No @packageDocumentation comment for this package) From 9c5c0ec2b770388326d9c4894abfda7ba86058e6 Mon Sep 17 00:00:00 2001 From: Liza K Date: Tue, 1 Sep 2020 17:58:13 +0300 Subject: [PATCH 60/77] Remove import --- x-pack/plugins/data_enhanced/common/search/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugins/data_enhanced/common/search/index.ts b/x-pack/plugins/data_enhanced/common/search/index.ts index 2ae422bd6b7d7..696938a403e89 100644 --- a/x-pack/plugins/data_enhanced/common/search/index.ts +++ b/x-pack/plugins/data_enhanced/common/search/index.ts @@ -5,7 +5,6 @@ */ export { - EnhancedSearchParams, IEnhancedEsSearchRequest, IAsyncSearchRequest, ENHANCED_ES_SEARCH_STRATEGY, From befdf100bb92826dc567311a5c9a831cce01e589 Mon Sep 17 00:00:00 2001 From: Liza K Date: Tue, 1 Sep 2020 19:35:43 +0300 Subject: [PATCH 61/77] Break circular dep + fix msearch test --- .../data/server/search/es_search/get_default_search_params.ts | 2 +- src/plugins/data/server/search/es_search/index.ts | 3 ++- src/plugins/data/server/search/routes/msearch.test.ts | 2 +- src/plugins/data/server/search/routes/msearch.ts | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/plugins/data/server/search/es_search/get_default_search_params.ts b/src/plugins/data/server/search/es_search/get_default_search_params.ts index d69c7153f797d..f6267ebfbf4d0 100644 --- a/src/plugins/data/server/search/es_search/get_default_search_params.ts +++ b/src/plugins/data/server/search/es_search/get_default_search_params.ts @@ -18,7 +18,7 @@ */ import { SharedGlobalConfig, IUiSettingsClient } from '../../../../../core/server'; -import { UI_SETTINGS } from '../..'; +import { UI_SETTINGS } from '../../../common/constants'; export function getShardTimeout(config: SharedGlobalConfig) { return { diff --git a/src/plugins/data/server/search/es_search/index.ts b/src/plugins/data/server/search/es_search/index.ts index 3418a6a987828..038622cbae36e 100644 --- a/src/plugins/data/server/search/es_search/index.ts +++ b/src/plugins/data/server/search/es_search/index.ts @@ -17,7 +17,8 @@ * under the License. */ -export { ES_SEARCH_STRATEGY, IEsSearchRequest, IEsSearchResponse } from '../../../common/search'; export { esSearchStrategyProvider } from './es_search_strategy'; export * from './get_default_search_params'; export { getTotalLoaded } from './get_total_loaded'; + +export { ES_SEARCH_STRATEGY, IEsSearchRequest, IEsSearchResponse } from '../../../common'; diff --git a/src/plugins/data/server/search/routes/msearch.test.ts b/src/plugins/data/server/search/routes/msearch.test.ts index 0a52cf23c5472..f069ec17b42fa 100644 --- a/src/plugins/data/server/search/routes/msearch.test.ts +++ b/src/plugins/data/server/search/routes/msearch.test.ts @@ -48,7 +48,7 @@ describe('msearch route', () => { }); it('handler calls /_msearch with the given request', async () => { - const response = { id: 'yay' }; + const response = { id: 'yay', body: { responses: [{}] } }; const mockClient = { transport: { request: jest.fn().mockResolvedValue(response) } }; const mockContext = { core: { diff --git a/src/plugins/data/server/search/routes/msearch.ts b/src/plugins/data/server/search/routes/msearch.ts index 5b9e4418a9cb8..af2e47c6ecd72 100644 --- a/src/plugins/data/server/search/routes/msearch.ts +++ b/src/plugins/data/server/search/routes/msearch.ts @@ -118,7 +118,7 @@ export function registerMsearchRoute(router: IRouter, deps: SearchRouteDependenc body: { ...response, body: { - responses: response.body.responses.map((r: SearchResponse) => shimHitsTotal(r)), + responses: response.body.responses?.map((r: SearchResponse) => shimHitsTotal(r)), }, }, }); From 098a9ad7a3a4f6395d4b56f511b15f67321a5c17 Mon Sep 17 00:00:00 2001 From: Liza K Date: Tue, 1 Sep 2020 19:36:58 +0300 Subject: [PATCH 62/77] Remove deleted type --- x-pack/plugins/data_enhanced/common/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugins/data_enhanced/common/index.ts b/x-pack/plugins/data_enhanced/common/index.ts index d6a3c73aaf363..012f1204da46a 100644 --- a/x-pack/plugins/data_enhanced/common/index.ts +++ b/x-pack/plugins/data_enhanced/common/index.ts @@ -5,7 +5,6 @@ */ export { - EnhancedSearchParams, IEnhancedEsSearchRequest, IAsyncSearchRequest, ENHANCED_ES_SEARCH_STRATEGY, From dac9d7a5183259ed72a2a4948fece94cee7be2f6 Mon Sep 17 00:00:00 2001 From: Liza K Date: Tue, 1 Sep 2020 20:02:17 +0300 Subject: [PATCH 63/77] Fix jest --- src/plugins/data/server/search/routes/msearch.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/data/server/search/routes/msearch.test.ts b/src/plugins/data/server/search/routes/msearch.test.ts index f069ec17b42fa..f1b99a41c8532 100644 --- a/src/plugins/data/server/search/routes/msearch.test.ts +++ b/src/plugins/data/server/search/routes/msearch.test.ts @@ -48,7 +48,7 @@ describe('msearch route', () => { }); it('handler calls /_msearch with the given request', async () => { - const response = { id: 'yay', body: { responses: [{}] } }; + const response = { id: 'yay', body: { responses: [{ hits: { total: 5 } }] } }; const mockClient = { transport: { request: jest.fn().mockResolvedValue(response) } }; const mockContext = { core: { From f9273d6e94aeb659860249fd3ae3cb7307d5c2ee Mon Sep 17 00:00:00 2001 From: Liza K Date: Wed, 2 Sep 2020 16:54:15 +0300 Subject: [PATCH 64/77] Bring toSnakeCase back --- src/plugins/data/server/index.ts | 1 + .../search/es_search/es_search_strategy.ts | 5 ++-- .../data/server/search/es_search/index.ts | 1 + .../server/search/es_search/to_snake_case.ts | 24 +++++++++++++++++++ .../data/server/search/routes/msearch.ts | 4 ++-- .../server/search/es_search_strategy.ts | 9 +++---- 6 files changed, 36 insertions(+), 8 deletions(-) create mode 100644 src/plugins/data/server/search/es_search/to_snake_case.ts diff --git a/src/plugins/data/server/index.ts b/src/plugins/data/server/index.ts index 2a19a8b46db55..948dcf7684c1b 100644 --- a/src/plugins/data/server/index.ts +++ b/src/plugins/data/server/index.ts @@ -211,6 +211,7 @@ export { ISearchStrategy, ISearchSetup, ISearchStart, + toSnakeCase, getDefaultSearchParams, getShardTimeout, getTotalLoaded, diff --git a/src/plugins/data/server/search/es_search/es_search_strategy.ts b/src/plugins/data/server/search/es_search/es_search_strategy.ts index fb80cd492949d..106f974ed3457 100644 --- a/src/plugins/data/server/search/es_search/es_search_strategy.ts +++ b/src/plugins/data/server/search/es_search/es_search_strategy.ts @@ -22,6 +22,7 @@ import { SearchResponse } from 'elasticsearch'; import { Observable } from 'rxjs'; import { ApiResponse } from '@elastic/elasticsearch'; import { SearchUsage } from '../collectors/usage'; +import { toSnakeCase } from './to_snake_case'; import { ISearchStrategy, getDefaultSearchParams, getTotalLoaded, getShardTimeout } from '..'; export const esSearchStrategyProvider = ( @@ -44,11 +45,11 @@ export const esSearchStrategyProvider = ( // ignoreThrottled is not supported in OSS const { ignoreThrottled, ...defaultParams } = await getDefaultSearchParams(uiSettingsClient); - const params = { + const params = toSnakeCase({ ...defaultParams, ...getShardTimeout(config), ...request.params, - }; + }); try { const esResponse = (await context.core.elasticsearch.client.asCurrentUser.search( diff --git a/src/plugins/data/server/search/es_search/index.ts b/src/plugins/data/server/search/es_search/index.ts index 038622cbae36e..1bd17fc986168 100644 --- a/src/plugins/data/server/search/es_search/index.ts +++ b/src/plugins/data/server/search/es_search/index.ts @@ -20,5 +20,6 @@ export { esSearchStrategyProvider } from './es_search_strategy'; export * from './get_default_search_params'; export { getTotalLoaded } from './get_total_loaded'; +export * from './to_snake_case'; export { ES_SEARCH_STRATEGY, IEsSearchRequest, IEsSearchResponse } from '../../../common'; diff --git a/src/plugins/data/server/search/es_search/to_snake_case.ts b/src/plugins/data/server/search/es_search/to_snake_case.ts new file mode 100644 index 0000000000000..74f156274cbc6 --- /dev/null +++ b/src/plugins/data/server/search/es_search/to_snake_case.ts @@ -0,0 +1,24 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { mapKeys, snakeCase } from 'lodash'; + +export function toSnakeCase(obj: Record) { + return mapKeys(obj, (value, key) => snakeCase(key)); +} diff --git a/src/plugins/data/server/search/routes/msearch.ts b/src/plugins/data/server/search/routes/msearch.ts index af2e47c6ecd72..e1ddb06e4fb6f 100644 --- a/src/plugins/data/server/search/routes/msearch.ts +++ b/src/plugins/data/server/search/routes/msearch.ts @@ -24,7 +24,7 @@ import { SearchResponse } from 'elasticsearch'; import { IRouter } from 'src/core/server'; import { SearchRouteDependencies } from '../search_service'; import { shimHitsTotal } from './shim_hits_total'; -import { getShardTimeout, getDefaultSearchParams } from '..'; +import { getShardTimeout, getDefaultSearchParams, toSnakeCase } from '..'; interface MsearchHeaders { index: string; @@ -111,7 +111,7 @@ export function registerMsearchRoute(router: IRouter, deps: SearchRouteDependenc method: 'GET', path: '/_msearch', body, - querystring: defaultParams, + querystring: toSnakeCase(defaultParams), }); return res.ok({ diff --git a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts index b214a6c99b598..13a91ad78519c 100644 --- a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts +++ b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts @@ -14,6 +14,7 @@ import { SearchUsage, getDefaultSearchParams, getShardTimeout, + toSnakeCase, } from '../../../../../src/plugins/data/server'; import { IEnhancedEsSearchRequest } from '../../common'; import { ISearchOptions, IEsSearchResponse } from '../../../../../src/plugins/data/common/search'; @@ -81,7 +82,7 @@ export const enhancedEsSearchStrategyProvider = ( const method = request.id ? 'GET' : 'POST'; const path = encodeURI(request.id ? `/_async_search/${request.id}` : `/${index}/_async_search`); - const querystring = { + const querystring = toSnakeCase({ waitForCompletionTimeout: '100ms', // Wait up to 100ms for the response to return keepAlive: '1m', // Extend the TTL for this search request by one minute ...(request.id @@ -91,7 +92,7 @@ export const enhancedEsSearchStrategyProvider = ( batchedReduceSize: 64, // Only report partial results every 64 shards; this should be reduced when we actually display partial results }), ...queryParams, - }; + }); // TODO: replace with async endpoints once https://github.com/elastic/elasticsearch-js/issues/1280 is resolved const esResponse = await esClient.transport.request({ method, @@ -120,11 +121,11 @@ export const enhancedEsSearchStrategyProvider = ( const { body, index, ...params } = request.params!; const method = 'POST'; const path = encodeURI(`/${index}/_rollup_search`); - const querystring = { + const querystring = toSnakeCase({ ...getShardTimeout(config), ...(await getDefaultSearchParams(uiSettingsClient)), ...params, - }; + }); const esResponse = await esClient.transport.request({ method, From 3dc393e193dfd9b2cf4d5549f664c7cf8c7feb34 Mon Sep 17 00:00:00 2001 From: Liza K Date: Wed, 2 Sep 2020 16:59:15 +0300 Subject: [PATCH 65/77] docs --- .../kibana-plugin-plugins-data-server.md | 1 + ...-plugin-plugins-data-server.tosnakecase.md | 22 +++++++++++++ src/plugins/data/server/server.api.md | 31 +++++++++++-------- 3 files changed, 41 insertions(+), 13 deletions(-) create mode 100644 docs/development/plugins/data/server/kibana-plugin-plugins-data-server.tosnakecase.md diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md index e7bfd44093f19..04bfb492178a3 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.md @@ -32,6 +32,7 @@ | [parseInterval(interval)](./kibana-plugin-plugins-data-server.parseinterval.md) | | | [plugin(initializerContext)](./kibana-plugin-plugins-data-server.plugin.md) | Static code to be shared externally | | [shouldReadFieldFromDocValues(aggregatable, esType)](./kibana-plugin-plugins-data-server.shouldreadfieldfromdocvalues.md) | | +| [toSnakeCase(obj)](./kibana-plugin-plugins-data-server.tosnakecase.md) | | | [usageProvider(core)](./kibana-plugin-plugins-data-server.usageprovider.md) | | ## Interfaces diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.tosnakecase.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.tosnakecase.md new file mode 100644 index 0000000000000..eda9e9c312e59 --- /dev/null +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.tosnakecase.md @@ -0,0 +1,22 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) > [toSnakeCase](./kibana-plugin-plugins-data-server.tosnakecase.md) + +## toSnakeCase() function + +Signature: + +```typescript +export declare function toSnakeCase(obj: Record): import("lodash").Dictionary; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| obj | Record<string, any> | | + +Returns: + +`import("lodash").Dictionary` + diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md index ab0ee90a05780..a0bfc19499abb 100644 --- a/src/plugins/data/server/server.api.md +++ b/src/plugins/data/server/server.api.md @@ -1031,6 +1031,11 @@ export interface TimeRange { to: string; } +// Warning: (ae-missing-release-tag) "toSnakeCase" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export function toSnakeCase(obj: Record): import("lodash").Dictionary; + // Warning: (ae-missing-release-tag) "UI_SETTINGS" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -1096,19 +1101,19 @@ export function usageProvider(core: CoreSetup_2): SearchUsage; // src/plugins/data/server/index.ts:101:26 - (ae-forgotten-export) The symbol "TruncateFormat" needs to be exported by the entry point index.d.ts // src/plugins/data/server/index.ts:127:27 - (ae-forgotten-export) The symbol "isFilterable" needs to be exported by the entry point index.d.ts // src/plugins/data/server/index.ts:127:27 - (ae-forgotten-export) The symbol "isNestedField" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:222:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:222:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:222:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:222:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:224:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:225:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:234:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:235:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:236:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:240:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:241:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:245:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts -// src/plugins/data/server/index.ts:248:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:223:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:223:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:223:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:223:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:225:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:226:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:235:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:236:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:237:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:241:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:242:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:246:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts +// src/plugins/data/server/index.ts:249:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts // src/plugins/data/server/plugin.ts:88:66 - (ae-forgotten-export) The symbol "DataEnhancements" needs to be exported by the entry point index.d.ts // (No @packageDocumentation comment for this package) From 59f5cc1eaf437629c415044ab89cb842a4bfe861 Mon Sep 17 00:00:00 2001 From: Liza K Date: Wed, 2 Sep 2020 18:42:20 +0300 Subject: [PATCH 66/77] fix jest --- .../es_search/es_search_strategy.test.ts | 8 ++--- .../server/search/es_search_strategy.test.ts | 32 +++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/plugins/data/server/search/es_search/es_search_strategy.test.ts b/src/plugins/data/server/search/es_search/es_search_strategy.test.ts index 87874ced7afff..c5c193ee04b2f 100644 --- a/src/plugins/data/server/search/es_search/es_search_strategy.test.ts +++ b/src/plugins/data/server/search/es_search/es_search_strategy.test.ts @@ -67,13 +67,13 @@ describe('ES search strategy', () => { expect(mockApiCaller.mock.calls[0][0]).toEqual({ ...params, timeout: '0ms', - ignoreUnavailable: true, - trackTotalHits: true, + ignore_unavailable: true, + track_total_hits: true, }); }); it('calls the API caller with overridden defaults', async () => { - const params = { index: 'logstash-*', ignoreUnavailable: false, timeout: '1000ms' }; + const params = { index: 'logstash-*', ignore_unavailable: false, timeout: '1000ms' }; const esSearch = await esSearchStrategyProvider(mockConfig$, mockLogger); await esSearch.search((mockContext as unknown) as RequestHandlerContext, { params }); @@ -81,7 +81,7 @@ describe('ES search strategy', () => { expect(mockApiCaller).toBeCalled(); expect(mockApiCaller.mock.calls[0][0]).toEqual({ ...params, - trackTotalHits: true, + track_total_hits: true, }); }); diff --git a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts index fdf886633f5b8..5afd00df24cf6 100644 --- a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts +++ b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts @@ -83,13 +83,13 @@ describe('ES search strategy', () => { expect(method).toBe('POST'); expect(path).toBe('/logstash-*/_async_search'); expect(body).toEqual({ query: {} }); - expect(querystring).toHaveProperty('batchedReduceSize'); - expect(querystring).toHaveProperty('ignoreThrottled'); - expect(querystring).toHaveProperty('ignoreUnavailable'); - expect(querystring).toHaveProperty('keepAlive'); - expect(querystring).toHaveProperty('maxConcurrentShardRequests'); - expect(querystring).toHaveProperty('trackTotalHits'); - expect(querystring).toHaveProperty('waitForCompletionTimeout'); + expect(querystring).toHaveProperty('batched_reduce_size'); + expect(querystring).toHaveProperty('ignore_throttled'); + expect(querystring).toHaveProperty('ignore_unavailable'); + expect(querystring).toHaveProperty('max_concurrent_shard_requests'); + expect(querystring).toHaveProperty('track_total_hits'); + expect(querystring).toHaveProperty('keep_alive'); + expect(querystring).toHaveProperty('wait_for_completion_timeout'); }); it('makes a GET request to async search with ID when ID is provided', async () => { @@ -105,13 +105,13 @@ describe('ES search strategy', () => { expect(method).toBe('GET'); expect(path).toBe('/_async_search/foo'); expect(body).toEqual(undefined); - expect(querystring).not.toHaveProperty('batchedReduceSize'); - expect(querystring).not.toHaveProperty('ignoreThrottled'); - expect(querystring).not.toHaveProperty('ignoreUnavailable'); - expect(querystring).not.toHaveProperty('maxConcurrentShardRequests'); - expect(querystring).not.toHaveProperty('trackTotalHits'); - expect(querystring).toHaveProperty('keepAlive'); - expect(querystring).toHaveProperty('waitForCompletionTimeout'); + expect(querystring).not.toHaveProperty('batched_reduce_size'); + expect(querystring).not.toHaveProperty('ignore_throttled'); + expect(querystring).not.toHaveProperty('ignore_unavailable'); + expect(querystring).not.toHaveProperty('max_concurrent_shard_requests'); + expect(querystring).not.toHaveProperty('track_total_hits'); + expect(querystring).toHaveProperty('keep_alive'); + expect(querystring).toHaveProperty('wait_for_completion_timeout'); }); it('encodes special characters in the path', async () => { @@ -155,7 +155,7 @@ describe('ES search strategy', () => { expect(mockApiCaller).toBeCalled(); const { querystring } = mockApiCaller.mock.calls[0][0]; - expect(querystring).toHaveProperty('keepAlive'); - expect(querystring).toHaveProperty('waitForCompletionTimeout'); + expect(querystring).toHaveProperty('keep_alive'); + expect(querystring).toHaveProperty('wait_for_completion_timeout'); }); }); From 2841d57f2003eb85173c5ed274819c127e85a951 Mon Sep 17 00:00:00 2001 From: Liza K Date: Thu, 3 Sep 2020 15:26:48 +0300 Subject: [PATCH 67/77] Fix merge --- .../plugins/data_enhanced/public/search/search_interceptor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts index 92f1a0f217688..61cf579d3136b 100644 --- a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts +++ b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts @@ -81,7 +81,7 @@ export class EnhancedSearchInterceptor extends SearchInterceptor { let { id } = request; const { combinedSignal, cleanup } = this.setupAbortSignal({ - abortSignal: options.signal, + abortSignal: options.abortSignal, timeout: this.searchTimeout, }); const aborted$ = from(toPromise(combinedSignal)); From 313bbd7a2ca2dc9352162686d5b75937a38479a5 Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Fri, 4 Sep 2020 18:34:32 -0700 Subject: [PATCH 68/77] Fix types --- src/plugins/data/public/search/search_interceptor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/data/public/search/search_interceptor.ts b/src/plugins/data/public/search/search_interceptor.ts index 742bb974d2f5b..0a6d60afed2f7 100644 --- a/src/plugins/data/public/search/search_interceptor.ts +++ b/src/plugins/data/public/search/search_interceptor.ts @@ -141,7 +141,7 @@ export class SearchInterceptor { } const { combinedSignal, cleanup } = this.setupAbortSignal({ - abortSignal: options?.signal, + abortSignal: options?.abortSignal, }); this.pendingCount$.next(this.pendingCount$.getValue() + 1); From 6111ac708afcc6646baeae4fb8de85e85725abeb Mon Sep 17 00:00:00 2001 From: Liza K Date: Sun, 6 Sep 2020 11:37:20 +0300 Subject: [PATCH 69/77] Allow timeout to be undefined --- .../server/search/es_search/get_default_search_params.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/plugins/data/server/search/es_search/get_default_search_params.ts b/src/plugins/data/server/search/es_search/get_default_search_params.ts index f6267ebfbf4d0..13607fce51670 100644 --- a/src/plugins/data/server/search/es_search/get_default_search_params.ts +++ b/src/plugins/data/server/search/es_search/get_default_search_params.ts @@ -21,9 +21,12 @@ import { SharedGlobalConfig, IUiSettingsClient } from '../../../../../core/serve import { UI_SETTINGS } from '../../../common/constants'; export function getShardTimeout(config: SharedGlobalConfig) { - return { - timeout: `${config.elasticsearch.shardTimeout.asMilliseconds()}ms`, - }; + const timeout = config.elasticsearch.shardTimeout.asMilliseconds(); + return timeout + ? { + timeout: `${timeout}ms`, + } + : {}; } export async function getDefaultSearchParams(uiSettingsClient: IUiSettingsClient) { From b1b466cbdc058c344a2206ab4d800e3db7316357 Mon Sep 17 00:00:00 2001 From: Liza K Date: Sun, 6 Sep 2020 13:18:06 +0300 Subject: [PATCH 70/77] Fix jest test --- .../data/server/search/es_search/es_search_strategy.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/data/server/search/es_search/es_search_strategy.test.ts b/src/plugins/data/server/search/es_search/es_search_strategy.test.ts index c5c193ee04b2f..504ce728481f0 100644 --- a/src/plugins/data/server/search/es_search/es_search_strategy.test.ts +++ b/src/plugins/data/server/search/es_search/es_search_strategy.test.ts @@ -66,7 +66,6 @@ describe('ES search strategy', () => { expect(mockApiCaller).toBeCalled(); expect(mockApiCaller.mock.calls[0][0]).toEqual({ ...params, - timeout: '0ms', ignore_unavailable: true, track_total_hits: true, }); From 5a7c9e0d8d6a1b93b4c98d8045e3b0e71984e416 Mon Sep 17 00:00:00 2001 From: Liza K Date: Sun, 6 Sep 2020 13:20:52 +0300 Subject: [PATCH 71/77] Upldate docs --- .../kibana-plugin-plugins-data-server.getshardtimeout.md | 4 ++++ src/plugins/data/server/server.api.md | 2 ++ 2 files changed, 6 insertions(+) diff --git a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getshardtimeout.md b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getshardtimeout.md index ca60c39a8e413..d7e2a597ff33d 100644 --- a/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getshardtimeout.md +++ b/docs/development/plugins/data/server/kibana-plugin-plugins-data-server.getshardtimeout.md @@ -9,6 +9,8 @@ ```typescript export declare function getShardTimeout(config: SharedGlobalConfig): { timeout: string; +} | { + timeout?: undefined; }; ``` @@ -22,5 +24,7 @@ export declare function getShardTimeout(config: SharedGlobalConfig): { `{ timeout: string; +} | { + timeout?: undefined; }` diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md index a0bfc19499abb..f8f2ae1fa0117 100644 --- a/src/plugins/data/server/server.api.md +++ b/src/plugins/data/server/server.api.md @@ -458,6 +458,8 @@ export function getDefaultSearchParams(uiSettingsClient: IUiSettingsClient): Pro // @public (undocumented) export function getShardTimeout(config: SharedGlobalConfig): { timeout: string; +} | { + timeout?: undefined; }; // Warning: (ae-missing-release-tag) "getTime" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) From 882c4fdfd9d0495d515d474413515e1f98177c15 Mon Sep 17 00:00:00 2001 From: Liza K Date: Sun, 6 Sep 2020 14:12:41 +0300 Subject: [PATCH 72/77] Fix msearch jest --- src/plugins/data/server/search/routes/msearch.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/data/server/search/routes/msearch.test.ts b/src/plugins/data/server/search/routes/msearch.test.ts index f1b99a41c8532..3a7d67c31b8be 100644 --- a/src/plugins/data/server/search/routes/msearch.test.ts +++ b/src/plugins/data/server/search/routes/msearch.test.ts @@ -73,7 +73,7 @@ describe('msearch route', () => { expect(mockClient.transport.request.mock.calls[0][0].method).toBe('GET'); expect(mockClient.transport.request.mock.calls[0][0].path).toBe('/_msearch'); expect(mockClient.transport.request.mock.calls[0][0].body).toEqual( - convertRequestBody(mockBody as any, { timeout: '0ms' }) + convertRequestBody(mockBody as any, {}) ); expect(mockResponse.ok).toBeCalled(); expect(mockResponse.ok.mock.calls[0][0]).toEqual({ From 95f0e9bd60ccd4d1eed6e8f9a2e6c293e84eb507 Mon Sep 17 00:00:00 2001 From: Liza K Date: Sun, 6 Sep 2020 14:38:30 +0300 Subject: [PATCH 73/77] Merge correction --- x-pack/plugins/data_enhanced/server/plugin.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugins/data_enhanced/server/plugin.ts b/x-pack/plugins/data_enhanced/server/plugin.ts index a8380836c717b..a1dff00ddfdd3 100644 --- a/x-pack/plugins/data_enhanced/server/plugin.ts +++ b/x-pack/plugins/data_enhanced/server/plugin.ts @@ -20,7 +20,6 @@ import { enhancedEsSearchStrategyProvider } from './search'; import { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/server'; import { getUiSettings } from './ui_settings'; import { ENHANCED_ES_SEARCH_STRATEGY } from '../common'; -import { getUiSettings } from './ui_settings'; interface SetupDependencies { data: DataPluginSetup; From 887b3eabd57528bc9ce1f856089da02aa649b4cb Mon Sep 17 00:00:00 2001 From: Liza K Date: Mon, 7 Sep 2020 19:59:09 +0300 Subject: [PATCH 74/77] docs --- ...lugin-plugins-data-public.baseformatterspublic.md | 2 +- .../kibana-plugin-plugins-data-public.filterbar.md | 2 +- ...plugins-data-public.indexpattern.refreshfields.md | 4 ++-- ...na-plugin-plugins-data-public.querystringinput.md | 2 +- .../kibana-plugin-plugins-data-public.searchbar.md | 4 ++-- src/plugins/data/public/public.api.md | 12 ++++++------ 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.baseformatterspublic.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.baseformatterspublic.md index 1aa9f460c4fac..3c558e821ea0a 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.baseformatterspublic.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.baseformatterspublic.md @@ -7,5 +7,5 @@ Signature: ```typescript -baseFormattersPublic: (import("../../common").FieldFormatInstanceType | typeof DateFormat | typeof DateNanosFormat)[] +baseFormattersPublic: (typeof DateFormat | typeof DateNanosFormat | import("../../common").FieldFormatInstanceType)[] ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.filterbar.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.filterbar.md index 6d8862323792a..88a4448e1592f 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.filterbar.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.filterbar.md @@ -7,7 +7,7 @@ Signature: ```typescript -FilterBar: React.ComponentClass, any> & { +FilterBar: React.ComponentClass, any> & { WrappedComponent: React.ComponentType; } ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.refreshfields.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.refreshfields.md index 271d0c45a4244..345449f663924 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.refreshfields.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.indexpattern.refreshfields.md @@ -7,9 +7,9 @@ Signature: ```typescript -refreshFields(): Promise; +refreshFields(): Promise; ``` Returns: -`Promise` +`Promise` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md index 9f3ed8c1263ba..65dd3839041cb 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md @@ -7,5 +7,5 @@ Signature: ```typescript -QueryStringInput: React.FC> +QueryStringInput: React.FC> ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchbar.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchbar.md index 498691c06285d..3a963f7fc2d42 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchbar.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchbar.md @@ -7,7 +7,7 @@ Signature: ```typescript -SearchBar: React.ComponentClass, "query" | "isLoading" | "filters" | "onRefresh" | "onRefreshChange" | "refreshInterval" | "indexPatterns" | "dataTestSubj" | "customSubmitButton" | "screenTitle" | "showQueryBar" | "showQueryInput" | "showFilterBar" | "showDatePicker" | "showAutoRefreshOnly" | "isRefreshPaused" | "dateRangeFrom" | "dateRangeTo" | "showSaveQuery" | "savedQuery" | "onQueryChange" | "onQuerySubmit" | "onSaved" | "onSavedQueryUpdated" | "onClearSavedQuery" | "indicateNoData" | "timeHistory" | "onFiltersUpdated">, any> & { - WrappedComponent: React.ComponentType & ReactIntl.InjectedIntlProps>; +SearchBar: React.ComponentClass, "indexPatterns" | "query" | "screenTitle" | "dataTestSubj" | "isLoading" | "onRefresh" | "onRefreshChange" | "refreshInterval" | "filters" | "customSubmitButton" | "showQueryBar" | "showQueryInput" | "showFilterBar" | "showDatePicker" | "showAutoRefreshOnly" | "isRefreshPaused" | "dateRangeFrom" | "dateRangeTo" | "showSaveQuery" | "savedQuery" | "onQueryChange" | "onQuerySubmit" | "onSaved" | "onSavedQueryUpdated" | "onClearSavedQuery" | "indicateNoData" | "timeHistory" | "onFiltersUpdated">, any> & { + WrappedComponent: React.ComponentType & ReactIntl.InjectedIntlProps>; } ``` diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index c68f580de14f4..f42f5133e954d 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -165,7 +165,7 @@ export interface ApplyGlobalFilterActionContext { // Warning: (ae-missing-release-tag) "baseFormattersPublic" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const baseFormattersPublic: (import("../../common").FieldFormatInstanceType | typeof DateFormat | typeof DateNanosFormat)[]; +export const baseFormattersPublic: (typeof DateFormat | typeof DateNanosFormat | import("../../common").FieldFormatInstanceType)[]; // Warning: (ae-missing-release-tag) "BUCKET_TYPES" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -631,7 +631,7 @@ export interface Filter { // Warning: (ae-missing-release-tag) "FilterBar" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const FilterBar: React.ComponentClass, any> & { +export const FilterBar: React.ComponentClass, any> & { WrappedComponent: React.ComponentType; }; @@ -998,7 +998,7 @@ export class IndexPattern implements IIndexPattern { typeMeta: string | undefined; }; // (undocumented) - refreshFields(): Promise; + refreshFields(): Promise; // (undocumented) removeScriptedField(fieldName: string): Promise; // (undocumented) @@ -1464,7 +1464,7 @@ export interface QueryState { // Warning: (ae-missing-release-tag) "QueryStringInput" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const QueryStringInput: React.FC>; +export const QueryStringInput: React.FC>; // @public (undocumented) export type QuerySuggestion = QuerySuggestionBasic | QuerySuggestionField; @@ -1677,8 +1677,8 @@ export const search: { // Warning: (ae-missing-release-tag) "SearchBar" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const SearchBar: React.ComponentClass, "query" | "isLoading" | "filters" | "onRefresh" | "onRefreshChange" | "refreshInterval" | "indexPatterns" | "dataTestSubj" | "customSubmitButton" | "screenTitle" | "showQueryBar" | "showQueryInput" | "showFilterBar" | "showDatePicker" | "showAutoRefreshOnly" | "isRefreshPaused" | "dateRangeFrom" | "dateRangeTo" | "showSaveQuery" | "savedQuery" | "onQueryChange" | "onQuerySubmit" | "onSaved" | "onSavedQueryUpdated" | "onClearSavedQuery" | "indicateNoData" | "timeHistory" | "onFiltersUpdated">, any> & { - WrappedComponent: React.ComponentType & ReactIntl.InjectedIntlProps>; +export const SearchBar: React.ComponentClass, "indexPatterns" | "query" | "screenTitle" | "dataTestSubj" | "isLoading" | "onRefresh" | "onRefreshChange" | "refreshInterval" | "filters" | "customSubmitButton" | "showQueryBar" | "showQueryInput" | "showFilterBar" | "showDatePicker" | "showAutoRefreshOnly" | "isRefreshPaused" | "dateRangeFrom" | "dateRangeTo" | "showSaveQuery" | "savedQuery" | "onQueryChange" | "onQuerySubmit" | "onSaved" | "onSavedQueryUpdated" | "onClearSavedQuery" | "indicateNoData" | "timeHistory" | "onFiltersUpdated">, any> & { + WrappedComponent: React.ComponentType & ReactIntl.InjectedIntlProps>; }; // Warning: (ae-forgotten-export) The symbol "SearchBarOwnProps" needs to be exported by the entry point index.d.ts From 4405680f67388618b52e210ec406084ac7eb99e3 Mon Sep 17 00:00:00 2001 From: Liza K Date: Tue, 8 Sep 2020 15:18:40 +0300 Subject: [PATCH 75/77] Fix rollup search merge --- ...in-plugins-data-public.querystringinput.md | 2 +- ...na-plugin-plugins-data-public.searchbar.md | 4 +- src/plugins/data/public/public.api.md | 6 +- .../server/search/es_search_strategy.test.ts | 5 ++ .../server/search/es_search_strategy.ts | 64 +++++++++---------- 5 files changed, 42 insertions(+), 39 deletions(-) diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md index 1f2f7fbfc739d..8526b3062194e 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.querystringinput.md @@ -7,5 +7,5 @@ Signature: ```typescript -QueryStringInput: React.FC> +QueryStringInput: React.FC> ``` diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchbar.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchbar.md index d1cf3c26526e6..19b6e215a9357 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchbar.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.searchbar.md @@ -7,7 +7,7 @@ Signature: ```typescript -SearchBar: React.ComponentClass, "query" | "indexPatterns" | "dataTestSubj" | "isLoading" | "filters" | "customSubmitButton" | "screenTitle" | "showQueryBar" | "showQueryInput" | "showFilterBar" | "showDatePicker" | "showAutoRefreshOnly" | "isRefreshPaused" | "refreshInterval" | "dateRangeFrom" | "dateRangeTo" | "showSaveQuery" | "savedQuery" | "onQueryChange" | "onQuerySubmit" | "onSaved" | "onSavedQueryUpdated" | "onClearSavedQuery" | "onRefresh" | "indicateNoData" | "timeHistory" | "onFiltersUpdated" | "onRefreshChange">, any> & { - WrappedComponent: React.ComponentType & ReactIntl.InjectedIntlProps>; +SearchBar: React.ComponentClass, "query" | "indexPatterns" | "filters" | "isLoading" | "customSubmitButton" | "screenTitle" | "dataTestSubj" | "showQueryBar" | "showQueryInput" | "showFilterBar" | "showDatePicker" | "showAutoRefreshOnly" | "isRefreshPaused" | "refreshInterval" | "dateRangeFrom" | "dateRangeTo" | "showSaveQuery" | "savedQuery" | "onQueryChange" | "onQuerySubmit" | "onSaved" | "onSavedQueryUpdated" | "onClearSavedQuery" | "onRefresh" | "indicateNoData" | "timeHistory" | "onFiltersUpdated" | "onRefreshChange">, any> & { + WrappedComponent: React.ComponentType & ReactIntl.InjectedIntlProps>; } ``` diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index c9e696573caa2..f5969f45a947c 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -1464,7 +1464,7 @@ export interface QueryState { // Warning: (ae-missing-release-tag) "QueryStringInput" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const QueryStringInput: React.FC>; +export const QueryStringInput: React.FC>; // @public (undocumented) export type QuerySuggestion = QuerySuggestionBasic | QuerySuggestionField; @@ -1677,8 +1677,8 @@ export const search: { // Warning: (ae-missing-release-tag) "SearchBar" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const SearchBar: React.ComponentClass, "query" | "indexPatterns" | "dataTestSubj" | "isLoading" | "filters" | "customSubmitButton" | "screenTitle" | "showQueryBar" | "showQueryInput" | "showFilterBar" | "showDatePicker" | "showAutoRefreshOnly" | "isRefreshPaused" | "refreshInterval" | "dateRangeFrom" | "dateRangeTo" | "showSaveQuery" | "savedQuery" | "onQueryChange" | "onQuerySubmit" | "onSaved" | "onSavedQueryUpdated" | "onClearSavedQuery" | "onRefresh" | "indicateNoData" | "timeHistory" | "onFiltersUpdated" | "onRefreshChange">, any> & { - WrappedComponent: React.ComponentType & ReactIntl.InjectedIntlProps>; +export const SearchBar: React.ComponentClass, "query" | "indexPatterns" | "filters" | "isLoading" | "customSubmitButton" | "screenTitle" | "dataTestSubj" | "showQueryBar" | "showQueryInput" | "showFilterBar" | "showDatePicker" | "showAutoRefreshOnly" | "isRefreshPaused" | "refreshInterval" | "dateRangeFrom" | "dateRangeTo" | "showSaveQuery" | "savedQuery" | "onQueryChange" | "onQuerySubmit" | "onSaved" | "onSavedQueryUpdated" | "onClearSavedQuery" | "onRefresh" | "indicateNoData" | "timeHistory" | "onFiltersUpdated" | "onRefreshChange">, any> & { + WrappedComponent: React.ComponentType & ReactIntl.InjectedIntlProps>; }; // Warning: (ae-forgotten-export) The symbol "SearchBarOwnProps" needs to be exported by the entry point index.d.ts diff --git a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts index 692d3e67a160e..f4f3d894a4576 100644 --- a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts +++ b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.test.ts @@ -42,6 +42,11 @@ describe('ES search strategy', () => { }; const mockContext = { core: { + uiSettings: { + client: { + get: jest.fn(), + }, + }, elasticsearch: { client: { asCurrentUser: { diff --git a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts index 8312a75c1d0fc..eda6178dc8e5b 100644 --- a/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts +++ b/x-pack/plugins/data_enhanced/server/search/es_search_strategy.ts @@ -5,6 +5,7 @@ */ import { first } from 'rxjs/operators'; +import { SearchResponse } from 'elasticsearch'; import { Observable } from 'rxjs'; import { SharedGlobalConfig, RequestHandlerContext, Logger } from '../../../../../src/core/server'; import { @@ -66,39 +67,6 @@ export const enhancedEsSearchStrategyProvider = ( }); }; - const rollupSearch = async function ( - context: RequestHandlerContext, - request: IEnhancedEsSearchRequest - ): Promise { - const esClient = context.core.elasticsearch.client.asCurrentUser; - const uiSettingsClient = await context.core.uiSettings.client; - const config = await config$.pipe(first()).toPromise(); - const { body, index, ...params } = request.params!; - const method = 'POST'; - const path = encodeURI(`/${index}/_rollup_search`); - const querystring = toSnakeCase({ - ...getShardTimeout(config), - ...(await getDefaultSearchParams(uiSettingsClient)), - ...params, - }); - - const esResponse = await esClient.transport.request({ - method, - path, - body, - querystring, - }); - - const { id, response, is_partial: isPartial, is_running: isRunning } = esResponse.body; - return { - id, - isPartial, - isRunning, - rawResponse: response, - ...getTotalLoaded(response._shards), - }; - }; - async function asyncSearch( context: RequestHandlerContext, request: IEnhancedEsSearchRequest @@ -139,5 +107,35 @@ export const enhancedEsSearchStrategyProvider = ( }; } + const rollupSearch = async function ( + context: RequestHandlerContext, + request: IEnhancedEsSearchRequest + ): Promise { + const esClient = context.core.elasticsearch.client.asCurrentUser; + const uiSettingsClient = await context.core.uiSettings.client; + const config = await config$.pipe(first()).toPromise(); + const { body, index, ...params } = request.params!; + const method = 'POST'; + const path = encodeURI(`/${index}/_rollup_search`); + const querystring = toSnakeCase({ + ...getShardTimeout(config), + ...(await getDefaultSearchParams(uiSettingsClient)), + ...params, + }); + + const esResponse = await esClient.transport.request({ + method, + path, + body, + querystring, + }); + + const response = esResponse.body as SearchResponse; + return { + rawResponse: response, + ...getTotalLoaded(response._shards), + }; + }; + return { search, cancel }; }; From 25d5e378c52f3d775f55cf3a9653f6f3baaf386d Mon Sep 17 00:00:00 2001 From: Liza K Date: Wed, 9 Sep 2020 12:13:35 +0300 Subject: [PATCH 76/77] Fix merge --- x-pack/plugins/data_enhanced/server/plugin.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugins/data_enhanced/server/plugin.ts b/x-pack/plugins/data_enhanced/server/plugin.ts index a8380836c717b..a1dff00ddfdd3 100644 --- a/x-pack/plugins/data_enhanced/server/plugin.ts +++ b/x-pack/plugins/data_enhanced/server/plugin.ts @@ -20,7 +20,6 @@ import { enhancedEsSearchStrategyProvider } from './search'; import { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/server'; import { getUiSettings } from './ui_settings'; import { ENHANCED_ES_SEARCH_STRATEGY } from '../common'; -import { getUiSettings } from './ui_settings'; interface SetupDependencies { data: DataPluginSetup; From c6508b0f03d47d4506dddcc5d057ea512a15dfb1 Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Thu, 10 Sep 2020 15:47:32 -0700 Subject: [PATCH 77/77] Use i18n --- .../data/public/search/search_interceptor.ts | 7 +++++-- .../public/search/search_interceptor.ts | 13 ++++++++++--- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/plugins/data/public/search/search_interceptor.ts b/src/plugins/data/public/search/search_interceptor.ts index b7ca321690c44..888e12a4285b1 100644 --- a/src/plugins/data/public/search/search_interceptor.ts +++ b/src/plugins/data/public/search/search_interceptor.ts @@ -30,6 +30,7 @@ import { } from 'rxjs'; import { catchError, finalize } from 'rxjs/operators'; import { CoreStart, CoreSetup, ToastsSetup } from 'kibana/public'; +import { i18n } from '@kbn/i18n'; import { getCombinedSignal, AbortError, @@ -188,8 +189,10 @@ export class SearchInterceptor { (e: Error) => { this.deps.toasts.addError(e, { title: 'Timed out', - toastMessage: - 'One or more queries timed out. Upgrade to a free Basic license to allow queries to complete.', // TODO: Improve this message + toastMessage: i18n.translate('data.search.upgradeLicense', { + defaultMessage: + 'One or more queries timed out. With our free Basic tier, your queries never time out.', + }), }); }, 60000, diff --git a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts index 3a82b50320226..f7ae9fc6d0f91 100644 --- a/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts +++ b/x-pack/plugins/data_enhanced/public/search/search_interceptor.ts @@ -7,6 +7,7 @@ import { throwError, EMPTY, timer, from, Subscription } from 'rxjs'; import { mergeMap, expand, takeUntil, finalize, tap } from 'rxjs/operators'; import { debounce } from 'lodash'; +import { i18n } from '@kbn/i18n'; import { SearchInterceptor, SearchInterceptorDeps, @@ -106,11 +107,17 @@ export class EnhancedSearchInterceptor extends SearchInterceptor { protected showTimeoutError = debounce( (e: Error) => { const message = this.application.capabilities.advancedSettings?.save - ? 'Increase the advanced setting timeout to ensure queries can run to completion.' - : 'Contact an administrator to increase the advanced setting.'; + ? i18n.translate('xpack.data.search.timeoutIncreaseSetting', { + defaultMessage: + 'One or more queries timed out. Increase run time with the search.timeout advanced setting.', + }) + : i18n.translate('xpack.data.search.timeoutContactAdmin', { + defaultMessage: + 'One or more queries timed out. Contact your system administrator to increase the run time.', + }); this.deps.toasts.addError(e, { title: 'Timed out', - toastMessage: `One or more queries timed out. ${message}`, + toastMessage: message, }); }, 60000,