Skip to content

Commit

Permalink
Merge pull request #138 from grafana/joey/improve-select-performance
Browse files Browse the repository at this point in the history
Improve select performance
  • Loading branch information
joey-grafana authored Aug 15, 2024
2 parents e5db8dd + 2995751 commit bd16b7e
Showing 1 changed file with 62 additions and 3 deletions.
65 changes: 62 additions & 3 deletions src/components/Explore/filters/FilterRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { css } from '@emotion/css';
import React, { useEffect, useMemo, useState } from 'react';

import { AdHocVariableFilter, GrafanaTheme2, SelectableValue, toOption } from '@grafana/data';
import { Button, Select, SelectBaseProps, useStyles2 } from '@grafana/ui';
import { Button, InputActionMeta, Select, SelectBaseProps, useStyles2 } from '@grafana/ui';

import { FilterByVariable } from './FilterByVariable';
import { ignoredAttributes, RESOURCE_ATTR, SPAN_ATTR } from 'utils/shared';
Expand All @@ -25,6 +25,11 @@ export function FilterRenderer({ filter, model, isWip }: Props) {
isValuesLoading?: boolean;
}>({});

// Limit maximum options in select dropdowns for performance reasons
const maxOptions = 10000;
const [keyQuery, setKeyQuery] = useState<string>('');
const [valueQuery, setValueQuery] = useState<string>('');

const key = filter.key !== '' ? state?.keys?.find((key) => key.value === filter.key) ?? toOption(filter.key) : null;
const value = filter.value !== '' ? toOption(filter.value) : null;
const exploration = getTraceExplorationScene(model);
Expand All @@ -46,6 +51,46 @@ export function FilterRenderer({ filter, model, isWip }: Props) {
updateKeys();
}
}, [filter, key, metric, model, state]);

const keyOptions = useMemo(() => {
if (!state.keys) {
return;
}

if (keyQuery.length === 0) {
return state.keys.slice(0, maxOptions);
}

const queryLowerCase = keyQuery.toLowerCase();
return state.keys
.filter((tag) => {
if (tag.value && tag.value.length > 0) {
return tag.value.toLowerCase().includes(queryLowerCase);
}
return false;
})
.slice(0, maxOptions);
}, [keyQuery, state.keys]);

const valueOptions = useMemo(() => {
if (!state.values) {
return;
}

if (valueQuery.length === 0) {
return state.values.slice(0, maxOptions);
}

const queryLowerCase = valueQuery.toLowerCase();
return state.values
.filter((tag) => {
if (tag.value && tag.value.length > 0) {
return tag.value.toLowerCase().includes(queryLowerCase);
}
return false;
})
.slice(0, maxOptions);
}, [valueQuery, state.values]);

const formatKeys = (keys: Array<SelectableValue<string>>, filters: AdHocVariableFilter[], metric: VariableValue) => {
// Ensure we always have the same order of keys
Expand Down Expand Up @@ -101,7 +146,7 @@ export function FilterRenderer({ filter, model, isWip }: Props) {
<BaseSelect
value={key}
placeholder={'Select attribute'}
options={state.keys}
options={keyOptions}
onChange={(v) => model._updateFilter(filter, 'key', v.value)}
isLoading={state.isKeysLoading}
autoFocus={keyAutoFocus}
Expand All @@ -111,6 +156,13 @@ export function FilterRenderer({ filter, model, isWip }: Props) {
const keys = formatKeys(await model._getKeys(filter.key), model.state.filters, metric);
setState({ ...state, isKeysLoading: false, keys });
}}
onInputChange={(value: string, { action }: InputActionMeta) => {
if (action === 'input-change') {
setKeyQuery(value);
}
}}
onCloseMenu={() => setKeyQuery('')}
virtualized
/>
);

Expand All @@ -119,7 +171,7 @@ export function FilterRenderer({ filter, model, isWip }: Props) {
<BaseSelect
value={value}
placeholder={'value'}
options={state.values}
options={valueOptions}
onChange={(v) => model._updateFilter(filter, 'value', v.value)}
isLoading={state.isValuesLoading}
autoFocus={valueAutoFocus}
Expand All @@ -129,6 +181,13 @@ export function FilterRenderer({ filter, model, isWip }: Props) {
const values = sortValues(await model._getValuesFor(filter));
setState({ ...state, isValuesLoading: false, values });
}}
onInputChange={(value: string, { action }: InputActionMeta) => {
if (action === 'input-change') {
setValueQuery(value);
}
}}
onCloseMenu={() => setValueQuery('')}
virtualized
/>
);

Expand Down

0 comments on commit bd16b7e

Please sign in to comment.