Prometheus: Use fuzzy string matching to autocomplete metric names and label (#32207)

* Fuzzy search prototype

* Aggregate filter and sorting functions for auto-complete suggestions

* Add a test for fuzzy search

* Simplify setting fuzzy search information

* Rename SimpleHighlighter

* Test PartialHighlighter

* Add PartialHighlighter snapshot

* Simplify PartialHighlighter

* Revert env change

* Clean up the code

* Add fuzzy search for labels

* Bring back backwards compatiblity

* Expose search function type only

* Update docs

* Covert snapshot test to assertions

* Fix docs

* Fix language provider test

* Add a test for autocomplete logic

* Clean up

* Mock Editor functions

* Add fuzzy search to Prometheus labels

* Add docs about backwards compatibility

* Simplify main fuzzy search loop
This commit is contained in:
Piotr Jamróz
2021-04-16 17:06:33 +02:00
committed by GitHub
parent 2c862678ab
commit dd095642e2
15 changed files with 614 additions and 56 deletions

View File

@@ -3,16 +3,16 @@ import LRU from 'lru-cache';
import { Value } from 'slate';
import { dateTime, HistoryItem, LanguageProvider } from '@grafana/data';
import { CompletionItem, CompletionItemGroup, TypeaheadInput, TypeaheadOutput } from '@grafana/ui';
import { CompletionItem, CompletionItemGroup, SearchFunctionType, TypeaheadInput, TypeaheadOutput } from '@grafana/ui';
import {
addLimitInfo,
fixSummariesMetadata,
limitSuggestions,
parseSelector,
processHistogramLabels,
processLabels,
roundSecToMin,
addLimitInfo,
limitSuggestions,
} from './language_utils';
import PromqlSyntax, { FUNCTIONS, RATE_RANGES } from './promql';
@@ -201,7 +201,7 @@ export default class PromQlLanguageProvider extends LanguageProvider {
getEmptyCompletionItems = (context: { history: Array<HistoryItem<PromQuery>> }): TypeaheadOutput => {
const { history } = context;
const suggestions = [];
const suggestions: CompletionItemGroup[] = [];
if (history && history.length) {
const historyItems = _.chain(history)
@@ -214,7 +214,7 @@ export default class PromQlLanguageProvider extends LanguageProvider {
.value();
suggestions.push({
prefixMatch: true,
searchFunctionType: SearchFunctionType.Prefix,
skipSort: true,
label: 'History',
items: historyItems,
@@ -226,10 +226,10 @@ export default class PromQlLanguageProvider extends LanguageProvider {
getTermCompletionItems = (): TypeaheadOutput => {
const { metrics, metricsMetadata } = this;
const suggestions = [];
const suggestions: CompletionItemGroup[] = [];
suggestions.push({
prefixMatch: true,
searchFunctionType: SearchFunctionType.Prefix,
label: 'Functions',
items: FUNCTIONS.map(setFunctionKind),
});
@@ -239,6 +239,7 @@ export default class PromQlLanguageProvider extends LanguageProvider {
suggestions.push({
label: `Metrics${limitInfo}`,
items: limitSuggestions(metrics).map((m) => addMetricsMetadata(m, metricsMetadata)),
searchFunctionType: SearchFunctionType.Fuzzy,
});
}
@@ -313,6 +314,7 @@ export default class PromQlLanguageProvider extends LanguageProvider {
suggestions.push({
label: `Labels${limitInfo}`,
items: Object.keys(labelValues).map(wrapLabel),
searchFunctionType: SearchFunctionType.Fuzzy,
});
}
return result;
@@ -379,6 +381,7 @@ export default class PromQlLanguageProvider extends LanguageProvider {
suggestions.push({
label: `Label values for "${labelKey}"${limitInfo}`,
items: labelValues[labelKey].map(wrapLabel),
searchFunctionType: SearchFunctionType.Fuzzy,
});
}
} else {
@@ -391,7 +394,11 @@ export default class PromQlLanguageProvider extends LanguageProvider {
context = 'context-labels';
const newItems = possibleKeys.map((key) => ({ label: key }));
const limitInfo = addLimitInfo(newItems);
const newSuggestion: CompletionItemGroup = { label: `Labels${limitInfo}`, items: newItems };
const newSuggestion: CompletionItemGroup = {
label: `Labels${limitInfo}`,
items: newItems,
searchFunctionType: SearchFunctionType.Fuzzy,
};
suggestions.push(newSuggestion);
}
}