Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[Autocomplete] Support useTimeFilter option #81515

Merged
merged 23 commits into from
Nov 10, 2020
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
a8831cd
pass timefilter to autocomplete
Oct 22, 2020
3362863
Merge branch 'master' of github.com:elastic/kibana into fix/timefilte…
Oct 29, 2020
f8b1be9
ignoreTimeRange advanced setting
Oct 29, 2020
d870eac
Merge branch 'master' of github.com:elastic/kibana into fix/timefilte…
Oct 29, 2020
0e674b7
Show all results in filter bar autocomplete
Oct 30, 2020
07e3d6a
Merge branch 'master' of github.com:elastic/kibana into fix/timefilte…
Nov 3, 2020
17084b4
Round timerange to minute for autocomplete memoization
Nov 3, 2020
895c6cc
Change useTimeFilter param name
Nov 4, 2020
87f0357
Fix maps test
Nov 5, 2020
c1af5ad
Merge branch 'master' of github.com:elastic/kibana into fix/timefilte…
Nov 5, 2020
de3941b
docs
Nov 5, 2020
519a4af
useTimeRange in apm
Nov 6, 2020
23a0ad2
remove date validation
Nov 6, 2020
812e22b
Merge branch 'master' of github.com:elastic/kibana into fix/timefilte…
Nov 6, 2020
d38c5bd
Merge branch 'master' into fix/timefilter-in-autocomplete
kibanamachine Nov 9, 2020
e28ae05
Merge branch 'master' of github.com:elastic/kibana into fix/timefilte…
Nov 9, 2020
302329d
Merge branch 'fix/timefilter-in-autocomplete' of github.com:lizozom/k…
Nov 9, 2020
f702bfd
Merge branch 'master' of github.com:elastic/kibana into fix/timefilte…
Nov 9, 2020
775632c
Update src/plugins/data/common/constants.ts
lizozom Nov 10, 2020
582f512
Merge branch 'master' into fix/timefilter-in-autocomplete
kibanamachine Nov 10, 2020
c512b19
Merge branch 'master' of github.com:elastic/kibana into fix/timefilte…
Nov 10, 2020
9af6054
Merge branch 'fix/timefilter-in-autocomplete' of github.com:lizozom/k…
Nov 10, 2020
08058f0
docs
Nov 10, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ export interface QuerySuggestionGetFnArgs
| [selectionEnd](./kibana-plugin-plugins-data-public.querysuggestiongetfnargs.selectionend.md) | <code>number</code> | |
| [selectionStart](./kibana-plugin-plugins-data-public.querysuggestiongetfnargs.selectionstart.md) | <code>number</code> | |
| [signal](./kibana-plugin-plugins-data-public.querysuggestiongetfnargs.signal.md) | <code>AbortSignal</code> | |
| [useTimeRange](./kibana-plugin-plugins-data-public.querysuggestiongetfnargs.usetimerange.md) | <code>boolean</code> | |

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [QuerySuggestionGetFnArgs](./kibana-plugin-plugins-data-public.querysuggestiongetfnargs.md) &gt; [useTimeRange](./kibana-plugin-plugins-data-public.querysuggestiongetfnargs.usetimerange.md)

## QuerySuggestionGetFnArgs.useTimeRange property

<b>Signature:</b>

```typescript
useTimeRange?: boolean;
```
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,6 @@ UI_SETTINGS: {
readonly INDEXPATTERN_PLACEHOLDER: "indexPattern:placeholder";
readonly FILTERS_PINNED_BY_DEFAULT: "filters:pinnedByDefault";
readonly FILTERS_EDITOR_SUGGEST_VALUES: "filterEditor:suggestValues";
readonly AUTOCOMPLETE_USE_TIMERANGE: "autocomplete:useTimerange";
}
```
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,6 @@ UI_SETTINGS: {
readonly INDEXPATTERN_PLACEHOLDER: "indexPattern:placeholder";
readonly FILTERS_PINNED_BY_DEFAULT: "filters:pinnedByDefault";
readonly FILTERS_EDITOR_SUGGEST_VALUES: "filterEditor:suggestValues";
readonly AUTOCOMPLETE_USE_TIMERANGE: "autocomplete:useTimerange";
}
```
1 change: 1 addition & 0 deletions src/plugins/data/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,5 @@ export const UI_SETTINGS = {
INDEXPATTERN_PLACEHOLDER: 'indexPattern:placeholder',
FILTERS_PINNED_BY_DEFAULT: 'filters:pinnedByDefault',
FILTERS_EDITOR_SUGGEST_VALUES: 'filterEditor:suggestValues',
AUTOCOMPLETE_USE_TIMERANGE: 'autocomplete:useTimerange',
lizozom marked this conversation as resolved.
Show resolved Hide resolved
} as const;
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export interface QuerySuggestionGetFnArgs {
selectionStart: number;
selectionEnd: number;
signal?: AbortSignal;
useTimeRange?: boolean;
boolFilter?: any;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,26 @@ import { stubIndexPattern, stubFields } from '../../stubs';
import { setupValueSuggestionProvider, ValueSuggestionsGetFn } from './value_suggestion_provider';
import { IUiSettingsClient, CoreSetup } from 'kibana/public';

jest.mock('../../services', () => ({
getQueryService: () => ({
timefilter: {
timefilter: {
createFilter: () => {
return {
time: 'fake',
};
},
getTime: () => {
return {
to: 'now',
from: 'now-15m',
};
},
},
},
}),
}));

describe('FieldSuggestions', () => {
let getValueSuggestions: ValueSuggestionsGetFn;
let http: any;
Expand Down Expand Up @@ -94,6 +114,7 @@ describe('FieldSuggestions', () => {
indexPattern: stubIndexPattern,
field,
query: '',
useTimeRange: false,
});

expect(http.fetch).toHaveBeenCalled();
Expand All @@ -107,6 +128,7 @@ describe('FieldSuggestions', () => {
indexPattern: stubIndexPattern,
field,
query: '',
useTimeRange: false,
};

await getValueSuggestions(args);
Expand All @@ -123,6 +145,7 @@ describe('FieldSuggestions', () => {
indexPattern: stubIndexPattern,
field,
query: '',
useTimeRange: false,
};

const { now } = Date;
Expand All @@ -146,50 +169,76 @@ describe('FieldSuggestions', () => {
indexPattern: stubIndexPattern,
field: fields[0],
query: '',
useTimeRange: false,
});
await getValueSuggestions({
indexPattern: stubIndexPattern,
field: fields[0],
query: 'query',
useTimeRange: false,
});
await getValueSuggestions({
indexPattern: stubIndexPattern,
field: fields[1],
query: '',
useTimeRange: false,
});
await getValueSuggestions({
indexPattern: stubIndexPattern,
field: fields[1],
query: 'query',
useTimeRange: false,
});

const customIndexPattern = {
...stubIndexPattern,
title: 'customIndexPattern',
useTimeRange: false,
};

await getValueSuggestions({
indexPattern: customIndexPattern,
field: fields[0],
query: '',
useTimeRange: false,
});
await getValueSuggestions({
indexPattern: customIndexPattern,
field: fields[0],
query: 'query',
useTimeRange: false,
});
await getValueSuggestions({
indexPattern: customIndexPattern,
field: fields[1],
query: '',
useTimeRange: false,
});
await getValueSuggestions({
indexPattern: customIndexPattern,
field: fields[1],
query: 'query',
useTimeRange: false,
});

expect(http.fetch).toHaveBeenCalledTimes(8);
});

it('should apply timefilter', async () => {
const [field] = stubFields.filter(
({ type, aggregatable }) => type === 'string' && aggregatable
);

await getValueSuggestions({
indexPattern: stubIndexPattern,
field,
query: '',
useTimeRange: true,
});
const callParams = http.fetch.mock.calls[0][1];

expect(JSON.parse(callParams.body).filters).toHaveLength(1);
expect(http.fetch).toHaveBeenCalled();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,16 @@
* under the License.
*/

import dateMath from '@elastic/datemath';
import { memoize } from 'lodash';
import { CoreSetup } from 'src/core/public';
import { IIndexPattern, IFieldType, UI_SETTINGS } from '../../../common';
import { IIndexPattern, IFieldType, UI_SETTINGS, buildQueryFromFilters } from '../../../common';
import { getQueryService } from '../../services';

function resolver(title: string, field: IFieldType, query: string, boolFilter: any) {
function resolver(title: string, field: IFieldType, query: string, filters: any[]) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be filters: Filter[] in this whole file?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are not filters of type Filter, but an array of whatever type BoolQuery.filter is ( src/plugins/data/server/search/es_search/elasticsearch.ts).

We could fix that, but I wouldn't want to do it in this PR.

// Only cache results for a minute
const ttl = Math.floor(Date.now() / 1000 / 60);

return [ttl, query, title, field.name, JSON.stringify(boolFilter)].join('|');
return [ttl, query, title, field.name, JSON.stringify(filters)].join('|');
}

export type ValueSuggestionsGetFn = (args: ValueSuggestionsGetFnArgs) => Promise<any[]>;
Expand All @@ -34,18 +35,31 @@ interface ValueSuggestionsGetFnArgs {
indexPattern: IIndexPattern;
field: IFieldType;
query: string;
useTimeRange?: boolean;
boolFilter?: any[];
signal?: AbortSignal;
}

const getAutocompleteTimefilter = (indexPattern: IIndexPattern) => {
const { timefilter } = getQueryService().timefilter;
const timeRange = timefilter.getTime();

// Use a rounded timerange so that memoizing works properly
const roundedTimerange = {
from: dateMath.parse(timeRange.from)!.startOf('minute').toISOString(),
to: dateMath.parse(timeRange.to)!.endOf('minute').toISOString(),
};
return timefilter.createFilter(indexPattern, roundedTimerange);
};

export const getEmptyValueSuggestions = (() => Promise.resolve([])) as ValueSuggestionsGetFn;

export const setupValueSuggestionProvider = (core: CoreSetup): ValueSuggestionsGetFn => {
const requestSuggestions = memoize(
(index: string, field: IFieldType, query: string, boolFilter: any = [], signal?: AbortSignal) =>
(index: string, field: IFieldType, query: string, filters: any = [], signal?: AbortSignal) =>
core.http.fetch(`/api/kibana/suggestions/values/${index}`, {
method: 'POST',
body: JSON.stringify({ query, field: field.name, boolFilter }),
body: JSON.stringify({ query, field: field.name, filters }),
signal,
}),
resolver
Expand All @@ -55,12 +69,15 @@ export const setupValueSuggestionProvider = (core: CoreSetup): ValueSuggestionsG
indexPattern,
field,
query,
useTimeRange,
boolFilter,
signal,
}: ValueSuggestionsGetFnArgs): Promise<any[]> => {
const shouldSuggestValues = core!.uiSettings.get<boolean>(
UI_SETTINGS.FILTERS_EDITOR_SUGGEST_VALUES
);
useTimeRange =
useTimeRange ?? core!.uiSettings.get<boolean>(UI_SETTINGS.AUTOCOMPLETE_USE_TIMERANGE);
const { title } = indexPattern;

if (field.type === 'boolean') {
Expand All @@ -69,6 +86,9 @@ export const setupValueSuggestionProvider = (core: CoreSetup): ValueSuggestionsG
return [];
}

return await requestSuggestions(title, field, query, boolFilter, signal);
const timeFilter = useTimeRange ? getAutocompleteTimefilter(indexPattern) : undefined;
const filterQuery = timeFilter ? buildQueryFromFilters([timeFilter], indexPattern).filter : [];
const filters = [...(boolFilter ? boolFilter : []), ...filterQuery];
lizozom marked this conversation as resolved.
Show resolved Hide resolved
return await requestSuggestions(title, field, query, filters, signal);
};
};
3 changes: 3 additions & 0 deletions src/plugins/data/public/public.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1806,6 +1806,8 @@ export interface QuerySuggestionGetFnArgs {
selectionStart: number;
// (undocumented)
signal?: AbortSignal;
// (undocumented)
useTimeRange?: boolean;
}

// Warning: (ae-missing-release-tag) "QuerySuggestionTypes" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
Expand Down Expand Up @@ -2275,6 +2277,7 @@ export const UI_SETTINGS: {
readonly INDEXPATTERN_PLACEHOLDER: "indexPattern:placeholder";
readonly FILTERS_PINNED_BY_DEFAULT: "filters:pinnedByDefault";
readonly FILTERS_EDITOR_SUGGEST_VALUES: "filterEditor:suggestValues";
readonly AUTOCOMPLETE_USE_TIMERANGE: "autocomplete:useTimerange";
};


Expand Down
11 changes: 8 additions & 3 deletions src/plugins/data/public/query/timefilter/timefilter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,14 @@ import { PublicMethodsOf } from '@kbn/utility-types';
import { areRefreshIntervalsDifferent, areTimeRangesDifferent } from './lib/diff_time_picker_vals';
import { getForceNow } from './lib/get_force_now';
import { TimefilterConfig, InputTimeRange, TimeRangeBounds } from './types';
import { calculateBounds, getTime, RefreshInterval, TimeRange } from '../../../common';
import {
calculateBounds,
getTime,
IIndexPattern,
RefreshInterval,
TimeRange,
} from '../../../common';
import { TimeHistoryContract } from './time_history';
import { IndexPattern } from '../../index_patterns';

// TODO: remove!

Expand Down Expand Up @@ -170,7 +175,7 @@ export class Timefilter {
}
};

public createFilter = (indexPattern: IndexPattern, timeRange?: TimeRange) => {
public createFilter = (indexPattern: IIndexPattern, timeRange?: TimeRange) => {
return getTime(indexPattern, timeRange ? timeRange : this._time, {
forceNow: this.getForceNow(),
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ export class PhraseSuggestorUI<T extends PhraseSuggestorProps> extends React.Com
field,
query,
signal: this.abortController.signal,
// Show all results in filter bar autocomplete
useTimeRange: false,
});

this.setState({ suggestions, isLoading: false });
Expand Down
10 changes: 5 additions & 5 deletions src/plugins/data/server/autocomplete/value_suggestions_route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,15 @@ export function registerValueSuggestionsRoute(
{
field: schema.string(),
query: schema.string(),
boolFilter: schema.maybe(schema.any()),
filters: schema.maybe(schema.any()),
},
{ unknowns: 'allow' }
),
},
},
async (context, request, response) => {
const config = await config$.pipe(first()).toPromise();
const { field: fieldName, query, boolFilter } = request.body;
const { field: fieldName, query, filters } = request.body;
const { index } = request.params;
const { client } = context.core.elasticsearch.legacy;
const signal = getRequestAbortedSignal(request.events.aborted$);
Expand All @@ -66,7 +66,7 @@ export function registerValueSuggestionsRoute(
const indexPattern = await findIndexPatternById(context.core.savedObjects.client, index);

const field = indexPattern && getFieldByName(fieldName, indexPattern);
const body = await getBody(autocompleteSearchOptions, field || fieldName, query, boolFilter);
const body = await getBody(autocompleteSearchOptions, field || fieldName, query, filters);

try {
const result = await client.callAsCurrentUser('search', { index, body }, { signal });
Expand All @@ -88,7 +88,7 @@ async function getBody(
{ timeout, terminate_after }: Record<string, any>,
field: IFieldType | string,
query: string,
boolFilter: Filter[] = []
filters: Filter[] = []
) {
const isFieldObject = (f: any): f is IFieldType => Boolean(f && f.name);

Expand All @@ -108,7 +108,7 @@ async function getBody(
terminate_after,
query: {
bool: {
filter: boolFilter,
filter: filters,
},
},
aggs: {
Expand Down
1 change: 1 addition & 0 deletions src/plugins/data/server/server.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1127,6 +1127,7 @@ export const UI_SETTINGS: {
readonly INDEXPATTERN_PLACEHOLDER: "indexPattern:placeholder";
readonly FILTERS_PINNED_BY_DEFAULT: "filters:pinnedByDefault";
readonly FILTERS_EDITOR_SUGGEST_VALUES: "filterEditor:suggestValues";
readonly AUTOCOMPLETE_USE_TIMERANGE: "autocomplete:useTimerange";
};

// Warning: (ae-missing-release-tag) "usageProvider" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
Expand Down
12 changes: 12 additions & 0 deletions src/plugins/data/server/ui_settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -684,5 +684,17 @@ export function getUiSettings(): Record<string, UiSettingsParams<unknown>> {
}),
schema: schema.boolean(),
},
[UI_SETTINGS.AUTOCOMPLETE_USE_TIMERANGE]: {
name: i18n.translate('data.advancedSettings.autocompleteIgnoreTimerange', {
defaultMessage: 'Use time range',
description: 'Restrict autocomplete results to the current time range',
}),
value: true,
description: i18n.translate('data.advancedSettings.autocompleteIgnoreTimerangeText', {
defaultMessage:
'Disable this property to get autocomplete suggestions from your full dataset, rather than from the current time range.',
}),
schema: schema.boolean(),
},
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const wrapAsSuggestions = (start: number, end: number, query: string, values: st

export const setupGetValueSuggestions: KqlQuerySuggestionProvider = () => {
return async (
{ indexPatterns, boolFilter, signal },
{ indexPatterns, boolFilter, useTimeRange, signal },
{ start, end, prefix, suffix, fieldName, nestedPath }
): Promise<QuerySuggestion[]> => {
const fullFieldName = nestedPath ? `${nestedPath}.${fieldName}` : fieldName;
Expand All @@ -49,6 +49,7 @@ export const setupGetValueSuggestions: KqlQuerySuggestionProvider = () => {
field,
query,
boolFilter,
useTimeRange,
signal,
}).then((valueSuggestions) => {
const quotedValues = valueSuggestions.map((value) =>
Expand Down
Loading