mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
Add configuration to search without bfetch
(#123942)
This commit is contained in:
parent
78643f495c
commit
b6d2149e99
9 changed files with 149 additions and 68 deletions
|
@ -7,3 +7,4 @@
|
|||
*/
|
||||
|
||||
export const DISABLE_BFETCH_COMPRESSION = 'bfetch:disableCompression';
|
||||
export const DISABLE_BFETCH = 'bfetch:disable';
|
||||
|
|
|
@ -11,4 +11,4 @@ export type { StreamingResponseHandler } from './streaming';
|
|||
export type { ItemBufferParams, TimedItemBufferParams, BatchedFunctionParams } from './buffer';
|
||||
export { ItemBuffer, TimedItemBuffer, createBatchedFunction } from './buffer';
|
||||
export type { ErrorLike, BatchRequestData, BatchResponseItem, BatchItemWrapper } from './batch';
|
||||
export { DISABLE_BFETCH_COMPRESSION } from './constants';
|
||||
export { DISABLE_BFETCH_COMPRESSION, DISABLE_BFETCH } from './constants';
|
||||
|
|
|
@ -14,6 +14,8 @@ export { split } from './streaming';
|
|||
|
||||
export type { BatchedFunc } from './batching/types';
|
||||
|
||||
export { DISABLE_BFETCH } from '../common/constants';
|
||||
|
||||
export function plugin(initializerContext: PluginInitializerContext) {
|
||||
return new BfetchPublicPlugin(initializerContext);
|
||||
}
|
||||
|
|
|
@ -9,13 +9,25 @@
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { UiSettingsParams } from 'src/core/server';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { DISABLE_BFETCH_COMPRESSION } from '../common';
|
||||
import { DISABLE_BFETCH_COMPRESSION, DISABLE_BFETCH } from '../common';
|
||||
|
||||
export function getUiSettings(): Record<string, UiSettingsParams<unknown>> {
|
||||
return {
|
||||
[DISABLE_BFETCH]: {
|
||||
name: i18n.translate('bfetch.disableBfetch', {
|
||||
defaultMessage: 'Disable request batching',
|
||||
}),
|
||||
value: false,
|
||||
description: i18n.translate('bfetch.disableBfetchDesc', {
|
||||
defaultMessage:
|
||||
'Disables requests batching. This increases number of HTTP requests from Kibana, but allows to debug requests individually.',
|
||||
}),
|
||||
schema: schema.boolean(),
|
||||
category: [],
|
||||
},
|
||||
[DISABLE_BFETCH_COMPRESSION]: {
|
||||
name: i18n.translate('bfetch.disableBfetchCompression', {
|
||||
defaultMessage: 'Disable Batch Compression',
|
||||
defaultMessage: 'Disable batch compression',
|
||||
}),
|
||||
value: false,
|
||||
description: i18n.translate('bfetch.disableBfetchCompressionDesc', {
|
||||
|
|
|
@ -21,9 +21,15 @@ import {
|
|||
tap,
|
||||
} from 'rxjs/operators';
|
||||
import { PublicMethodsOf } from '@kbn/utility-types';
|
||||
import { CoreSetup, CoreStart, ThemeServiceSetup, ToastsSetup } from 'kibana/public';
|
||||
import {
|
||||
CoreSetup,
|
||||
CoreStart,
|
||||
IHttpFetchError,
|
||||
ThemeServiceSetup,
|
||||
ToastsSetup,
|
||||
} from 'kibana/public';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { BatchedFunc, BfetchPublicSetup } from 'src/plugins/bfetch/public';
|
||||
import { BatchedFunc, BfetchPublicSetup, DISABLE_BFETCH } from '../../../../bfetch/public';
|
||||
import {
|
||||
ENHANCED_ES_SEARCH_STRATEGY,
|
||||
IAsyncSearchOptions,
|
||||
|
@ -67,8 +73,9 @@ const MAX_CACHE_ITEMS = 50;
|
|||
const MAX_CACHE_SIZE_MB = 10;
|
||||
|
||||
export class SearchInterceptor {
|
||||
private uiSettingsSub: Subscription;
|
||||
private uiSettingsSubs: Subscription[] = [];
|
||||
private searchTimeout: number;
|
||||
private bFetchDisabled: boolean;
|
||||
private readonly responseCache: SearchResponseCache = new SearchResponseCache(
|
||||
MAX_CACHE_ITEMS,
|
||||
MAX_CACHE_SIZE_MB
|
||||
|
@ -106,17 +113,21 @@ export class SearchInterceptor {
|
|||
});
|
||||
|
||||
this.searchTimeout = deps.uiSettings.get(UI_SETTINGS.SEARCH_TIMEOUT);
|
||||
this.bFetchDisabled = deps.uiSettings.get(DISABLE_BFETCH);
|
||||
|
||||
this.uiSettingsSub = deps.uiSettings
|
||||
.get$(UI_SETTINGS.SEARCH_TIMEOUT)
|
||||
.subscribe((timeout: number) => {
|
||||
this.uiSettingsSubs.push(
|
||||
deps.uiSettings.get$(UI_SETTINGS.SEARCH_TIMEOUT).subscribe((timeout: number) => {
|
||||
this.searchTimeout = timeout;
|
||||
});
|
||||
}),
|
||||
deps.uiSettings.get$(DISABLE_BFETCH).subscribe((bFetchDisabled: boolean) => {
|
||||
this.bFetchDisabled = bFetchDisabled;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
public stop() {
|
||||
this.responseCache.clear();
|
||||
this.uiSettingsSub.unsubscribe();
|
||||
this.uiSettingsSubs.forEach((s) => s.unsubscribe());
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -266,13 +277,34 @@ export class SearchInterceptor {
|
|||
options?: ISearchOptions
|
||||
): Promise<IKibanaSearchResponse> {
|
||||
const { abortSignal } = options || {};
|
||||
return this.batchedFetch(
|
||||
{
|
||||
request,
|
||||
options: this.getSerializableOptions(options),
|
||||
},
|
||||
abortSignal
|
||||
);
|
||||
|
||||
if (this.bFetchDisabled) {
|
||||
const { executionContext, strategy, ...searchOptions } = this.getSerializableOptions(options);
|
||||
return this.deps.http
|
||||
.post(`/internal/search/${strategy}${request.id ? `/${request.id}` : ''}`, {
|
||||
signal: abortSignal,
|
||||
context: executionContext,
|
||||
body: JSON.stringify({
|
||||
...request,
|
||||
...searchOptions,
|
||||
}),
|
||||
})
|
||||
.catch((e: IHttpFetchError<KibanaServerError>) => {
|
||||
if (e?.body) {
|
||||
throw e.body;
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}) as Promise<IKibanaSearchResponse>;
|
||||
} else {
|
||||
return this.batchedFetch(
|
||||
{
|
||||
request,
|
||||
options: this.getSerializableOptions(options),
|
||||
},
|
||||
abortSignal
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -319,9 +351,12 @@ export class SearchInterceptor {
|
|||
*/
|
||||
public search({ id, ...request }: IKibanaSearchRequest, options: IAsyncSearchOptions = {}) {
|
||||
const searchOptions = {
|
||||
strategy: ENHANCED_ES_SEARCH_STRATEGY,
|
||||
...options,
|
||||
};
|
||||
if (!searchOptions.strategy) {
|
||||
searchOptions.strategy = ENHANCED_ES_SEARCH_STRATEGY;
|
||||
}
|
||||
|
||||
const { sessionId, abortSignal } = searchOptions;
|
||||
|
||||
return this.createRequestHash$(request, searchOptions).pipe(
|
||||
|
|
|
@ -392,6 +392,10 @@ export const stackManagementSchema: MakeSchemaFrom<UsageStats> = {
|
|||
type: 'boolean',
|
||||
_meta: { description: 'Non-default value of setting.' },
|
||||
},
|
||||
'bfetch:disable': {
|
||||
type: 'boolean',
|
||||
_meta: { description: 'Non-default value of setting.' },
|
||||
},
|
||||
'visualization:visualize:legacyPieChartsLibrary': {
|
||||
type: 'boolean',
|
||||
_meta: { description: 'Non-default value of setting.' },
|
||||
|
|
|
@ -23,6 +23,7 @@ export interface UsageStats {
|
|||
/**
|
||||
* non-sensitive settings
|
||||
*/
|
||||
'bfetch:disable': boolean;
|
||||
'bfetch:disableCompression': boolean;
|
||||
'autocomplete:useTimeRange': boolean;
|
||||
'autocomplete:valueSuggestionMethod': string;
|
||||
|
|
|
@ -7736,6 +7736,12 @@
|
|||
"description": "Non-default value of setting."
|
||||
}
|
||||
},
|
||||
"bfetch:disable": {
|
||||
"type": "boolean",
|
||||
"_meta": {
|
||||
"description": "Non-default value of setting."
|
||||
}
|
||||
},
|
||||
"visualization:visualize:legacyPieChartsLibrary": {
|
||||
"type": "boolean",
|
||||
"_meta": {
|
||||
|
|
|
@ -17,62 +17,82 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
const toasts = getService('toasts');
|
||||
|
||||
describe('Search example', () => {
|
||||
describe('with bfetch', () => {
|
||||
testSearchExample();
|
||||
});
|
||||
|
||||
describe('no bfetch', () => {
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
before(async () => {
|
||||
await kibanaServer.uiSettings.replace({
|
||||
'bfetch:disable': true,
|
||||
});
|
||||
});
|
||||
after(async () => {
|
||||
await kibanaServer.uiSettings.unset('bfetch:disable');
|
||||
});
|
||||
|
||||
testSearchExample();
|
||||
});
|
||||
|
||||
const appId = 'searchExamples';
|
||||
|
||||
before(async function () {
|
||||
await PageObjects.common.navigateToApp(appId, { insertTimestamp: false });
|
||||
await comboBox.setCustom('dataViewSelector', 'logstash-*');
|
||||
await comboBox.set('searchBucketField', 'geo.src');
|
||||
await comboBox.set('searchMetricField', 'memory');
|
||||
await PageObjects.timePicker.setAbsoluteRange(
|
||||
'Mar 1, 2015 @ 00:00:00.000',
|
||||
'Nov 1, 2015 @ 00:00:00.000'
|
||||
);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await toasts.dismissAllToasts();
|
||||
await retry.waitFor('toasts gone', async () => {
|
||||
return (await toasts.getToastCount()) === 0;
|
||||
});
|
||||
});
|
||||
|
||||
it('should have an other bucket', async () => {
|
||||
await testSubjects.click('searchSourceWithOther');
|
||||
await testSubjects.click('responseTab');
|
||||
const codeBlock = await testSubjects.find('responseCodeBlock');
|
||||
await retry.waitFor('get code block', async () => {
|
||||
const visibleText = await codeBlock.getVisibleText();
|
||||
const parsedResponse = JSON.parse(visibleText);
|
||||
const buckets = parsedResponse.aggregations[1].buckets;
|
||||
return (
|
||||
buckets.length === 3 && buckets[2].key === '__other__' && buckets[2].doc_count === 9039
|
||||
function testSearchExample() {
|
||||
before(async function () {
|
||||
await PageObjects.common.navigateToApp(appId, { insertTimestamp: false });
|
||||
await comboBox.setCustom('dataViewSelector', 'logstash-*');
|
||||
await comboBox.set('searchBucketField', 'geo.src');
|
||||
await comboBox.set('searchMetricField', 'memory');
|
||||
await PageObjects.timePicker.setAbsoluteRange(
|
||||
'Mar 1, 2015 @ 00:00:00.000',
|
||||
'Nov 1, 2015 @ 00:00:00.000'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('should not have an other bucket', async () => {
|
||||
await testSubjects.click('searchSourceWithoutOther');
|
||||
await testSubjects.click('responseTab');
|
||||
const codeBlock = await testSubjects.find('responseCodeBlock');
|
||||
await retry.waitFor('get code block', async () => {
|
||||
const visibleText = await codeBlock.getVisibleText();
|
||||
const parsedResponse = JSON.parse(visibleText);
|
||||
const buckets = parsedResponse.aggregations[1].buckets;
|
||||
return buckets.length === 2;
|
||||
beforeEach(async () => {
|
||||
await toasts.dismissAllToasts();
|
||||
await retry.waitFor('toasts gone', async () => {
|
||||
return (await toasts.getToastCount()) === 0;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle warnings', async () => {
|
||||
await testSubjects.click('searchWithWarning');
|
||||
await retry.waitFor('', async () => {
|
||||
const toastCount = await toasts.getToastCount();
|
||||
return toastCount > 1;
|
||||
it('should have an other bucket', async () => {
|
||||
await testSubjects.click('searchSourceWithOther');
|
||||
await testSubjects.click('responseTab');
|
||||
const codeBlock = await testSubjects.find('responseCodeBlock');
|
||||
await retry.waitFor('get code block', async () => {
|
||||
const visibleText = await codeBlock.getVisibleText();
|
||||
const parsedResponse = JSON.parse(visibleText);
|
||||
const buckets = parsedResponse.aggregations[1].buckets;
|
||||
return (
|
||||
buckets.length === 3 && buckets[2].key === '__other__' && buckets[2].doc_count === 9039
|
||||
);
|
||||
});
|
||||
});
|
||||
const warningToast = await toasts.getToastElement(2);
|
||||
const textEl = await warningToast.findByClassName('euiToastBody');
|
||||
const text: string = await textEl.getVisibleText();
|
||||
expect(text).to.contain('Watch out!');
|
||||
});
|
||||
|
||||
it('should not have an other bucket', async () => {
|
||||
await testSubjects.click('searchSourceWithoutOther');
|
||||
await testSubjects.click('responseTab');
|
||||
const codeBlock = await testSubjects.find('responseCodeBlock');
|
||||
await retry.waitFor('get code block', async () => {
|
||||
const visibleText = await codeBlock.getVisibleText();
|
||||
const parsedResponse = JSON.parse(visibleText);
|
||||
const buckets = parsedResponse.aggregations[1].buckets;
|
||||
return buckets.length === 2;
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle warnings', async () => {
|
||||
await testSubjects.click('searchWithWarning');
|
||||
await retry.waitFor('', async () => {
|
||||
const toastCount = await toasts.getToastCount();
|
||||
return toastCount > 1;
|
||||
});
|
||||
const warningToast = await toasts.getToastElement(2);
|
||||
const textEl = await warningToast.findByClassName('euiToastBody');
|
||||
const text: string = await textEl.getVisibleText();
|
||||
expect(text).to.contain('Watch out!');
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue