From 71ca5f01f06435ace61ab5bfa5a09b0438eef89d Mon Sep 17 00:00:00 2001 From: bohandley Date: Fri, 10 Mar 2023 11:27:17 -0500 Subject: [PATCH] correctly debounce fuzzy search thank you leon --- .../components/MetricEncyclopediaModal.tsx | 75 +++++++------------ 1 file changed, 28 insertions(+), 47 deletions(-) diff --git a/public/app/plugins/datasource/prometheus/querybuilder/components/MetricEncyclopediaModal.tsx b/public/app/plugins/datasource/prometheus/querybuilder/components/MetricEncyclopediaModal.tsx index a56244aaeb6..95f9ee0aa38 100644 --- a/public/app/plugins/datasource/prometheus/querybuilder/components/MetricEncyclopediaModal.tsx +++ b/public/app/plugins/datasource/prometheus/querybuilder/components/MetricEncyclopediaModal.tsx @@ -2,7 +2,7 @@ import { css } from '@emotion/css'; import uFuzzy from '@leeoniya/ufuzzy'; import debounce from 'debounce-promise'; import { debounce as debounceLodash } from 'lodash'; -import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { GrafanaTheme2, SelectableValue } from '@grafana/data'; import { reportInteraction } from '@grafana/runtime'; @@ -83,9 +83,22 @@ export const placeholders = { export const DEFAULT_RESULTS_PER_PAGE = 10; -export const MetricEncyclopediaModal = (props: Props) => { - const uf = UseUfuzzy(); +const uf = new uFuzzy({ + intraMode: 1, + intraIns: 1, + intraSub: 1, + intraTrn: 1, + intraDel: 1, +}); +function fuzzySearch(haystack: string[], query: string, setter: React.Dispatch>) { + const idxs = uf.filter(haystack, query); + idxs && setter(idxs); +} + +const debouncedFuzzySearch = debounceLodash(fuzzySearch, 300); + +export const MetricEncyclopediaModal = (props: Props) => { const { datasource, isOpen, onClose, onChange, query } = props; const [variables, setVariables] = useState>>([]); @@ -95,7 +108,7 @@ export const MetricEncyclopediaModal = (props: Props) => { // metric list const [metrics, setMetrics] = useState([]); const [hasMetadata, setHasMetadata] = useState(true); - const [haystack, setHaystack] = useState([]); + const [metaHaystack, setMetaHaystack] = useState([]); const [nameHaystack, setNameHaystack] = useState([]); const [openTabs, setOpenTabs] = useState([]); @@ -106,7 +119,7 @@ export const MetricEncyclopediaModal = (props: Props) => { // filters const [fuzzySearchQuery, setFuzzySearchQuery] = useState(''); const [fuzzyMetaSearchResults, setFuzzyMetaSearchResults] = useState([]); - const [fuzzyNameSearchResults, setNameFuzzySearchResults] = useState([]); + const [fuzzyNameSearchResults, setFuzzyNameSearchResults] = useState([]); const [fullMetaSearch, setFullMetaSearch] = useState(false); const [excludeNullMetadata, setExcludeNullMetadata] = useState(false); const [selectedTypes, setSelectedTypes] = useState>>([]); @@ -145,14 +158,14 @@ export const MetricEncyclopediaModal = (props: Props) => { metrics = (await datasource.languageProvider.getLabelValues('__name__')) ?? []; } - let haystackData: string[] = []; + let haystackMetaData: string[] = []; let haystackNameData: string[] = []; let metricsData: MetricsData = metrics.map((m) => { const type = getMetadataType(m, datasource.languageProvider.metricsMetadata!); const description = getMetadataHelp(m, datasource.languageProvider.metricsMetadata!); // string[] = name + type + description - haystackData.push(`${m} ${type} ${description}`); + haystackMetaData.push(`${m} ${type} ${description}`); haystackNameData.push(m); return { value: m, @@ -163,7 +176,7 @@ export const MetricEncyclopediaModal = (props: Props) => { // setting this by the backend if useBackend is true setMetrics(metricsData); - setHaystack(haystackData); + setMetaHaystack(haystackMetaData); setNameHaystack(haystackNameData); setVariables( @@ -217,27 +230,6 @@ export const MetricEncyclopediaModal = (props: Props) => { return selectedTypes.length > 0; } - function fuzzySearch(query: string) { - // search either the names or all metadata - // fuzzy search go! - - if (fullMetaSearch) { - // considered simply filtering indexes with reduce and includes - // Performance comparison with 13,000 metrics searching metadata - // Fuzzy 6326ms - // Reduce & Includes 5541ms - const metaIdxs = uf.filter(haystack, query.toLowerCase()); - setFuzzyMetaSearchResults(metaIdxs); - } else { - const nameIdxs = uf.filter(nameHaystack, query.toLowerCase()); - setNameFuzzySearchResults(nameIdxs); - } - } - - const debouncedFuzzySearch = debounceLodash((query: string) => { - fuzzySearch(query); - }, 300); - /** * Filter * @@ -379,8 +371,13 @@ export const MetricEncyclopediaModal = (props: Props) => { } else if (useBackend) { debouncedBackendSearch(value); } else { - // do the search on the frontend - debouncedFuzzySearch(value); + // search either the names or all metadata + // fuzzy search go! + if (fullMetaSearch) { + debouncedFuzzySearch(metaHaystack, value, setFuzzyMetaSearchResults); + } else { + debouncedFuzzySearch(nameHaystack, value, setFuzzyNameSearchResults); + } } setPageNum(1); @@ -668,22 +665,6 @@ function alphabetically(ascending: boolean, metadataFilters: boolean) { }; } -function UseUfuzzy(): uFuzzy { - const ref = useRef(); - - if (!ref.current) { - ref.current = new uFuzzy({ - intraMode: 1, - intraIns: 1, - intraSub: 1, - intraTrn: 1, - intraDel: 1, - }); - } - - return ref.current; -} - const getStyles = (theme: GrafanaTheme2) => { return { cardsContainer: css`