diff --git a/package.json b/package.json index 448494bac54..a696c38a518 100644 --- a/package.json +++ b/package.json @@ -271,7 +271,7 @@ "@grafana/schema": "workspace:*", "@grafana/ui": "workspace:*", "@kusto/monaco-kusto": "5.3.6", - "@leeoniya/ufuzzy": "1.0.2", + "@leeoniya/ufuzzy": "1.0.6", "@lezer/common": "1.0.2", "@lezer/highlight": "1.1.3", "@lezer/lr": "1.3.3", diff --git a/packages/grafana-ui/package.json b/packages/grafana-ui/package.json index 8c229cc0eae..2ad949e3324 100644 --- a/packages/grafana-ui/package.json +++ b/packages/grafana-ui/package.json @@ -52,7 +52,7 @@ "@grafana/data": "9.5.0-pre", "@grafana/e2e-selectors": "9.5.0-pre", "@grafana/schema": "9.5.0-pre", - "@leeoniya/ufuzzy": "1.0.2", + "@leeoniya/ufuzzy": "1.0.6", "@monaco-editor/react": "4.4.6", "@popperjs/core": "2.11.6", "@react-aria/button": "3.6.1", diff --git a/public/app/features/alerting/unified/hooks/useFilteredRules.ts b/public/app/features/alerting/unified/hooks/useFilteredRules.ts index f7b259706a6..75cc2226bee 100644 --- a/public/app/features/alerting/unified/hooks/useFilteredRules.ts +++ b/public/app/features/alerting/unified/hooks/useFilteredRules.ts @@ -108,7 +108,7 @@ export const filterRules = ( const [idxs, info, order] = ufuzzy.search(namespaceHaystack, namespaceFilter); if (info && order) { filteredNamespaces = order.map((idx) => filteredNamespaces[info.idx[idx]]); - } else { + } else if (idxs) { filteredNamespaces = idxs.map((idx) => filteredNamespaces[idx]); } } @@ -127,7 +127,7 @@ const reduceNamespaces = (filterState: RulesFilter) => { const [idxs, info, order] = ufuzzy.search(groupsHaystack, groupNameFilter); if (info && order) { filteredGroups = order.map((idx) => filteredGroups[info.idx[idx]]); - } else { + } else if (idxs) { filteredGroups = idxs.map((idx) => filteredGroups[idx]); } } @@ -157,7 +157,7 @@ const reduceGroups = (filterState: RulesFilter) => { const [idxs, info, order] = ufuzzy.search(rulesHaystack, ruleNameQuery); if (info && order) { filteredRules = order.map((idx) => filteredRules[info.idx[idx]]); - } else { + } else if (idxs) { filteredRules = idxs.map((idx) => filteredRules[idx]); } } diff --git a/public/app/features/search/service/frontend.ts b/public/app/features/search/service/frontend.ts index b11fe34d77d..51b5af4c657 100644 --- a/public/app/features/search/service/frontend.ts +++ b/public/app/features/search/service/frontend.ts @@ -130,7 +130,7 @@ class FullResultCache { } } // > 1000 matches (unranked) - else { + else if (idxs) { for (let i = 0; i < idxs.length; i++) { let haystackIdx = idxs[i]; dst.push(src[haystackIdx]); diff --git a/public/app/plugins/datasource/prometheus/querybuilder/components/MetricEncyclopediaModal.tsx b/public/app/plugins/datasource/prometheus/querybuilder/components/MetricEncyclopediaModal.tsx index 969a6135a4a..60e5a6dcb3a 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'; @@ -81,9 +81,24 @@ 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>) { + // console.log('fuzzySearch'); + + 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>>([]); @@ -93,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([]); @@ -104,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>>([]); @@ -141,14 +156,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, @@ -159,7 +174,7 @@ export const MetricEncyclopediaModal = (props: Props) => { // setting this by the backend if useBackend is true setMetrics(metricsData); - setHaystack(haystackData); + setMetaHaystack(haystackMetaData); setNameHaystack(haystackNameData); setVariables( @@ -211,27 +226,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 * @@ -367,8 +361,14 @@ export const MetricEncyclopediaModal = (props: Props) => { setIsLoading(true); 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); @@ -656,22 +656,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` diff --git a/public/app/plugins/panel/flamegraph/components/FlameGraph/FlameGraph.tsx b/public/app/plugins/panel/flamegraph/components/FlameGraph/FlameGraph.tsx index 22d150e2463..c72381de55a 100644 --- a/public/app/plugins/panel/flamegraph/components/FlameGraph/FlameGraph.tsx +++ b/public/app/plugins/panel/flamegraph/components/FlameGraph/FlameGraph.tsx @@ -92,8 +92,12 @@ const FlameGraph = ({ const foundLabels = new Set(); if (search) { - for (let idx of ufuzzy.filter(uniqueLabels, search)) { - foundLabels.add(uniqueLabels[idx]); + let idxs = ufuzzy.filter(uniqueLabels, search); + + if (idxs) { + for (let idx of idxs) { + foundLabels.add(uniqueLabels[idx]); + } } } diff --git a/yarn.lock b/yarn.lock index 97eb18e03a8..b72d883bfb7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5351,7 +5351,7 @@ __metadata: "@grafana/e2e-selectors": 9.5.0-pre "@grafana/schema": 9.5.0-pre "@grafana/tsconfig": ^1.2.0-rc1 - "@leeoniya/ufuzzy": 1.0.2 + "@leeoniya/ufuzzy": 1.0.6 "@mdx-js/react": 1.6.22 "@monaco-editor/react": 4.4.6 "@popperjs/core": 2.11.6 @@ -6330,10 +6330,10 @@ __metadata: languageName: node linkType: hard -"@leeoniya/ufuzzy@npm:1.0.2": - version: 1.0.2 - resolution: "@leeoniya/ufuzzy@npm:1.0.2" - checksum: 5460378a8c32d121b0bc7c8e95cde995316516655528e248051b1bf360cdca0311ef3275de14b802587748231333cee6183c931b3abba26f9e4236ecc4959aa3 +"@leeoniya/ufuzzy@npm:1.0.6": + version: 1.0.6 + resolution: "@leeoniya/ufuzzy@npm:1.0.6" + checksum: e09672848e094745726331feebe6744d42563ccf160b38796eed4d72105daa052838fdec1944d5b44a27e328fc74a00547d00b894710e2720aa692ed5d3d6e3b languageName: node linkType: hard @@ -22136,7 +22136,7 @@ __metadata: "@grafana/tsconfig": ^1.2.0-rc1 "@grafana/ui": "workspace:*" "@kusto/monaco-kusto": 5.3.6 - "@leeoniya/ufuzzy": 1.0.2 + "@leeoniya/ufuzzy": 1.0.6 "@lezer/common": 1.0.2 "@lezer/highlight": 1.1.3 "@lezer/lr": 1.3.3