TSVB field list performance issue on using annotations (#84407)

* TSVB field list performance issue on using annotations

* Add AbortController to fetchFields and change translation id in annotations_editor

* Rename fetchFields to debouncedFetchFields

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Diana Derevyankina 2020-11-30 14:08:50 +03:00 committed by GitHub
parent 454635228e
commit 06da0e77b5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 54 additions and 22 deletions

View file

@ -22,4 +22,5 @@ export const INDEXES_SEPARATOR = ',';
export const AUTO_INTERVAL = 'auto';
export const ROUTES = {
VIS_DATA: '/api/metrics/vis/data',
FIELDS: '/api/metrics/fields',
};

View file

@ -91,7 +91,7 @@ function FieldSelectUi({
}
FieldSelectUi.defaultProps = {
indexPattern: '*',
indexPattern: '',
disabled: false,
restrict: [],
placeholder: i18n.translate('visTypeTimeseries.fieldSelect.selectFieldPlaceholder', {

View file

@ -43,13 +43,14 @@ import {
EuiCode,
EuiText,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
function newAnnotation() {
return {
id: uuid.v1(),
color: '#F00',
index_pattern: '*',
index_pattern: '',
time_field: '@timestamp',
icon: 'fa-tag',
ignore_global_filters: 1,
@ -84,7 +85,7 @@ export class AnnotationsEditor extends Component {
const defaults = {
fields: '',
template: '',
index_pattern: '*',
index_pattern: '',
query_string: { query: '', language: getDefaultQueryLanguage() },
};
const model = { ...defaults, ...row };
@ -100,6 +101,8 @@ export class AnnotationsEditor extends Component {
const htmlId = htmlIdGenerator(model.id);
const handleAdd = collectionActions.handleAdd.bind(null, this.props, newAnnotation);
const handleDelete = collectionActions.handleDelete.bind(null, this.props, model);
const defaultIndexPattern = this.props.model.default_index_pattern;
return (
<div className="tvbAnnotationsEditor" key={model.id}>
<EuiFlexGroup responsive={false}>
@ -120,14 +123,22 @@ export class AnnotationsEditor extends Component {
label={
<FormattedMessage
id="visTypeTimeseries.annotationsEditor.indexPatternLabel"
defaultMessage="Index pattern (required)"
defaultMessage="Index pattern"
/>
}
helpText={
defaultIndexPattern &&
!model.index_pattern &&
i18n.translate('visTypeTimeseries.annotationsEditor.searchByDefaultIndex', {
defaultMessage: 'Default index pattern is used. To query all indexes use *',
})
}
fullWidth
>
<EuiFieldText
onChange={this.handleChange(model, 'index_pattern')}
value={model.index_pattern}
placeholder={defaultIndexPattern}
fullWidth
/>
</EuiFormRow>

View file

@ -76,6 +76,19 @@ export class VisEditor extends Component {
});
}, VIS_STATE_DEBOUNCE_DELAY);
debouncedFetchFields = debounce(
(extractedIndexPatterns) => {
if (this.abortControllerFetchFields) {
this.abortControllerFetchFields.abort();
}
this.abortControllerFetchFields = new AbortController();
return fetchFields(extractedIndexPatterns, this.abortControllerFetchFields.signal);
},
VIS_STATE_DEBOUNCE_DELAY,
{ leading: true }
);
handleChange = (partialModel) => {
if (isEmpty(partialModel)) {
return;
@ -94,7 +107,7 @@ export class VisEditor extends Component {
const extractedIndexPatterns = extractIndexPatterns(nextModel);
if (!isEqual(this.state.extractedIndexPatterns, extractedIndexPatterns)) {
fetchFields(extractedIndexPatterns).then((visFields) =>
this.debouncedFetchFields(extractedIndexPatterns).then((visFields) =>
this.setState({
visFields,
extractedIndexPatterns,

View file

@ -19,34 +19,40 @@
import { i18n } from '@kbn/i18n';
import { extractIndexPatterns } from '../../../common/extract_index_patterns';
import { getCoreStart } from '../../services';
import { ROUTES } from '../../../common/constants';
export async function fetchFields(indexPatterns = ['*']) {
export async function fetchFields(indexPatterns = [], signal) {
const patterns = Array.isArray(indexPatterns) ? indexPatterns : [indexPatterns];
try {
const indexFields = await Promise.all(
patterns.map((pattern) => {
return getCoreStart().http.get('/api/metrics/fields', {
patterns.map((pattern) =>
getCoreStart().http.get(ROUTES.FIELDS, {
query: {
index: pattern,
},
});
})
signal,
})
)
);
const fields = patterns.reduce((cumulatedFields, currentPattern, index) => {
return {
return patterns.reduce(
(cumulatedFields, currentPattern, index) => ({
...cumulatedFields,
[currentPattern]: indexFields[index],
};
}, {});
return fields;
} catch (error) {
getCoreStart().notifications.toasts.addDanger({
title: i18n.translate('visTypeTimeseries.fetchFields.loadIndexPatternFieldsErrorMessage', {
defaultMessage: 'Unable to load index_pattern fields',
}),
text: error.message,
});
{}
);
} catch (error) {
if (error.name !== 'AbortError') {
getCoreStart().notifications.toasts.addDanger({
title: i18n.translate('visTypeTimeseries.fetchFields.loadIndexPatternFieldsErrorMessage', {
defaultMessage: 'Unable to load index_pattern fields',
}),
text: error.message,
});
}
}
return [];
}
export async function fetchIndexPatternFields({ params, fields = {} }) {

View file

@ -21,11 +21,12 @@ import { isBoom } from '@hapi/boom';
import { schema } from '@kbn/config-schema';
import { getFields } from '../lib/get_fields';
import { Framework } from '../plugin';
import { ROUTES } from '../../common/constants';
export const fieldsRoutes = (framework: Framework) => {
framework.router.get(
{
path: '/api/metrics/fields',
path: ROUTES.FIELDS,
validate: {
query: schema.object({ index: schema.string() }),
},