Skip to content

Commit

Permalink
Merge branch 'main' of github.com:elastic/kibana into prefer-throughp…
Browse files Browse the repository at this point in the history
…ut-as-tiebreaker
  • Loading branch information
dgieselaar committed Mar 24, 2022
2 parents 29927a8 + a743498 commit b32a80c
Show file tree
Hide file tree
Showing 205 changed files with 5,224 additions and 706 deletions.
9 changes: 9 additions & 0 deletions examples/search_examples/public/application.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,17 @@ import { SearchExamplePage, ExampleLink } from './common/example_page';
import { SearchExamplesApp } from './search/app';
import { SearchSessionsExampleApp } from './search_sessions/app';
import { RedirectAppLinks } from '../../../src/plugins/kibana_react/public';
import { SqlSearchExampleApp } from './sql_search/app';

const LINKS: ExampleLink[] = [
{
path: '/search',
title: 'Search',
},
{
path: '/sql-search',
title: 'SQL Search',
},
{
path: '/search-sessions',
title: 'Search Sessions',
Expand Down Expand Up @@ -51,12 +56,16 @@ export const renderApp = (
/>
</Route>
<Route path={LINKS[1].path}>
<SqlSearchExampleApp notifications={notifications} data={data} />
</Route>
<Route path={LINKS[2].path}>
<SearchSessionsExampleApp
navigation={navigation}
notifications={notifications}
data={data}
/>
</Route>

<Route path="/" exact={true}>
<Redirect to={LINKS[0].path} />
</Route>
Expand Down
164 changes: 164 additions & 0 deletions examples/search_examples/public/sql_search/app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import React, { useState } from 'react';

import {
EuiCodeBlock,
EuiFlexGroup,
EuiFlexItem,
EuiForm,
EuiPageBody,
EuiPageContent,
EuiPageContentBody,
EuiPageHeader,
EuiPanel,
EuiSuperUpdateButton,
EuiText,
EuiTextArea,
EuiTitle,
} from '@elastic/eui';

import { CoreStart } from '../../../../src/core/public';

import {
DataPublicPluginStart,
IKibanaSearchResponse,
isCompleteResponse,
isErrorResponse,
} from '../../../../src/plugins/data/public';
import {
SQL_SEARCH_STRATEGY,
SqlSearchStrategyRequest,
SqlSearchStrategyResponse,
} from '../../../../src/plugins/data/common';

interface SearchExamplesAppDeps {
notifications: CoreStart['notifications'];
data: DataPublicPluginStart;
}

export const SqlSearchExampleApp = ({ notifications, data }: SearchExamplesAppDeps) => {
const [sqlQuery, setSqlQuery] = useState<string>('');
const [request, setRequest] = useState<Record<string, any>>({});
const [isLoading, setIsLoading] = useState<boolean>(false);
const [rawResponse, setRawResponse] = useState<Record<string, any>>({});

function setResponse(response: IKibanaSearchResponse) {
setRawResponse(response.rawResponse);
}

const doSearch = async () => {
const req: SqlSearchStrategyRequest = {
params: {
query: sqlQuery,
},
};

// Submit the search request using the `data.search` service.
setRequest(req.params!);
setIsLoading(true);

data.search
.search<SqlSearchStrategyRequest, SqlSearchStrategyResponse>(req, {
strategy: SQL_SEARCH_STRATEGY,
})
.subscribe({
next: (res) => {
if (isCompleteResponse(res)) {
setIsLoading(false);
setResponse(res);
} else if (isErrorResponse(res)) {
setIsLoading(false);
setResponse(res);
notifications.toasts.addDanger('An error has occurred');
}
},
error: (e) => {
setIsLoading(false);
data.search.showError(e);
},
});
};

return (
<EuiPageBody>
<EuiPageHeader>
<EuiTitle size="l">
<h1>SQL search example</h1>
</EuiTitle>
</EuiPageHeader>
<EuiPageContent>
<EuiPageContentBody>
<EuiForm>
<EuiFlexGroup>
<EuiFlexItem grow>
<EuiTextArea
placeholder="SELECT * FROM library ORDER BY page_count DESC"
aria-label="SQL query to run"
value={sqlQuery}
onChange={(e) => setSqlQuery(e.target.value)}
fullWidth
data-test-subj="sqlQueryInput"
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiSuperUpdateButton
isLoading={isLoading}
isDisabled={sqlQuery.length === 0}
onClick={doSearch}
fill={true}
data-test-subj="querySubmitButton"
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiForm>

<EuiFlexGroup gutterSize="l">
<EuiFlexItem grow style={{ minWidth: 0 }}>
<EuiPanel grow>
<EuiText>
<h3>Request</h3>
</EuiText>
<EuiCodeBlock
language="json"
fontSize="s"
paddingSize="s"
overflowHeight={720}
isCopyable
data-test-subj="requestCodeBlock"
isVirtualized
>
{JSON.stringify(request, null, 2)}
</EuiCodeBlock>
</EuiPanel>
</EuiFlexItem>
<EuiFlexItem grow style={{ minWidth: 0 }}>
<EuiPanel grow>
<EuiText>
<h3>Response</h3>
</EuiText>
<EuiCodeBlock
language="json"
fontSize="s"
paddingSize="s"
isCopyable
data-test-subj="responseCodeBlock"
overflowHeight={720}
isVirtualized
>
{JSON.stringify(rawResponse, null, 2)}
</EuiCodeBlock>
</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPageContentBody>
</EuiPageContent>
</EuiPageBody>
);
};
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@
"deep-freeze-strict": "^1.1.1",
"deepmerge": "^4.2.2",
"del": "^5.1.0",
"elastic-apm-node": "^3.30.0",
"elastic-apm-node": "^3.31.0",
"execa": "^4.0.2",
"exit-hook": "^2.2.0",
"expiry-js": "0.1.7",
Expand Down
1 change: 1 addition & 0 deletions src/plugins/data/common/search/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ export * from './poll_search';
export * from './strategies/es_search';
export * from './strategies/eql_search';
export * from './strategies/ese_search';
export * from './strategies/sql_search';
9 changes: 9 additions & 0 deletions src/plugins/data/common/search/strategies/sql_search/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

export * from './types';
23 changes: 23 additions & 0 deletions src/plugins/data/common/search/strategies/sql_search/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import type {
SqlGetAsyncRequest,
SqlQueryRequest,
SqlQueryResponse,
} from '@elastic/elasticsearch/lib/api/types';
import { IKibanaSearchRequest, IKibanaSearchResponse } from '../../types';

export const SQL_SEARCH_STRATEGY = 'sql';

export type SqlRequestParams =
| Omit<SqlQueryRequest, 'keep_alive' | 'keep_on_completion'>
| Omit<SqlGetAsyncRequest, 'id' | 'keep_alive' | 'keep_on_completion'>;
export type SqlSearchStrategyRequest = IKibanaSearchRequest<SqlRequestParams>;

export type SqlSearchStrategyResponse = IKibanaSearchResponse<SqlQueryResponse>;
1 change: 1 addition & 0 deletions src/plugins/data/server/search/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ The `search` plugin includes:
- ES_SEARCH_STRATEGY - hitting regular es `_search` endpoint using query DSL
- (default) ESE_SEARCH_STRATEGY (Enhanced ES) - hitting `_async_search` endpoint and works with search sessions
- EQL_SEARCH_STRATEGY
- SQL_SEARCH_STRATEGY
3 changes: 3 additions & 0 deletions src/plugins/data/server/search/search_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ import {
eqlRawResponse,
ENHANCED_ES_SEARCH_STRATEGY,
EQL_SEARCH_STRATEGY,
SQL_SEARCH_STRATEGY,
} from '../../common/search';
import { getEsaggs, getEsdsl, getEql } from './expressions';
import {
Expand All @@ -93,6 +94,7 @@ import { enhancedEsSearchStrategyProvider } from './strategies/ese_search';
import { eqlSearchStrategyProvider } from './strategies/eql_search';
import { NoSearchIdInSessionError } from './errors/no_search_id_in_session';
import { CachedUiSettingsClient } from './services';
import { sqlSearchStrategyProvider } from './strategies/sql_search';

type StrategyMap = Record<string, ISearchStrategy<any, any>>;

Expand Down Expand Up @@ -176,6 +178,7 @@ export class SearchService implements Plugin<ISearchSetup, ISearchStart> {
);

this.registerSearchStrategy(EQL_SEARCH_STRATEGY, eqlSearchStrategyProvider(this.logger));
this.registerSearchStrategy(SQL_SEARCH_STRATEGY, sqlSearchStrategyProvider(this.logger));

registerBsearchRoute(
bfetch,
Expand Down
9 changes: 9 additions & 0 deletions src/plugins/data/server/search/strategies/sql_search/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

export { sqlSearchStrategyProvider } from './sql_search_strategy';
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import { getDefaultAsyncSubmitParams, getDefaultAsyncGetParams } from './request_utils';
import moment from 'moment';
import { SearchSessionsConfigSchema } from '../../../../config';

const getMockSearchSessionsConfig = ({
enabled = true,
defaultExpiration = moment.duration(7, 'd'),
} = {}) =>
({
enabled,
defaultExpiration,
} as SearchSessionsConfigSchema);

describe('request utils', () => {
describe('getDefaultAsyncSubmitParams', () => {
test('Uses `keep_alive` from default params if no `sessionId` is provided', async () => {
const mockConfig = getMockSearchSessionsConfig({
defaultExpiration: moment.duration(3, 'd'),
});
const params = getDefaultAsyncSubmitParams(mockConfig, {});
expect(params).toHaveProperty('keep_alive', '1m');
});

test('Uses `keep_alive` from config if enabled', async () => {
const mockConfig = getMockSearchSessionsConfig({
defaultExpiration: moment.duration(3, 'd'),
});
const params = getDefaultAsyncSubmitParams(mockConfig, {
sessionId: 'foo',
});
expect(params).toHaveProperty('keep_alive', '259200000ms');
});

test('Uses `keepAlive` of `1m` if disabled', async () => {
const mockConfig = getMockSearchSessionsConfig({
defaultExpiration: moment.duration(3, 'd'),
enabled: false,
});
const params = getDefaultAsyncSubmitParams(mockConfig, {
sessionId: 'foo',
});
expect(params).toHaveProperty('keep_alive', '1m');
});

test('Uses `keep_on_completion` if enabled', async () => {
const mockConfig = getMockSearchSessionsConfig({});
const params = getDefaultAsyncSubmitParams(mockConfig, {
sessionId: 'foo',
});
expect(params).toHaveProperty('keep_on_completion', true);
});

test('Does not use `keep_on_completion` if disabled', async () => {
const mockConfig = getMockSearchSessionsConfig({
defaultExpiration: moment.duration(3, 'd'),
enabled: false,
});
const params = getDefaultAsyncSubmitParams(mockConfig, {
sessionId: 'foo',
});
expect(params).toHaveProperty('keep_on_completion', false);
});
});

describe('getDefaultAsyncGetParams', () => {
test('Uses `wait_for_completion_timeout`', async () => {
const mockConfig = getMockSearchSessionsConfig({
defaultExpiration: moment.duration(3, 'd'),
enabled: true,
});
const params = getDefaultAsyncGetParams(mockConfig, {});
expect(params).toHaveProperty('wait_for_completion_timeout');
});

test('Uses `keep_alive` if `sessionId` is not provided', async () => {
const mockConfig = getMockSearchSessionsConfig({
defaultExpiration: moment.duration(3, 'd'),
enabled: true,
});
const params = getDefaultAsyncGetParams(mockConfig, {});
expect(params).toHaveProperty('keep_alive', '1m');
});

test('Has no `keep_alive` if `sessionId` is provided', async () => {
const mockConfig = getMockSearchSessionsConfig({
defaultExpiration: moment.duration(3, 'd'),
enabled: true,
});
const params = getDefaultAsyncGetParams(mockConfig, { sessionId: 'foo' });
expect(params).not.toHaveProperty('keep_alive');
});

test('Uses `keep_alive` if `sessionId` is provided but sessions disabled', async () => {
const mockConfig = getMockSearchSessionsConfig({
defaultExpiration: moment.duration(3, 'd'),
enabled: false,
});
const params = getDefaultAsyncGetParams(mockConfig, { sessionId: 'foo' });
expect(params).toHaveProperty('keep_alive', '1m');
});
});
});
Loading

0 comments on commit b32a80c

Please sign in to comment.