mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Prometheus: Fix label value suggestion (#21294)
* Prometheus: Fix label value suggestion - remove quotes from typeahead input to suggest correct label values - fix acceptance of partial label values * Disable mid-word suggestions * Fix test
This commit is contained in:
parent
649fa6789e
commit
334b89f3ee
@ -301,7 +301,7 @@ describe('Language completion provider', () => {
|
||||
instance.lookupsDisabled = false;
|
||||
const value = Plain.deserialize('{job!=}');
|
||||
const ed = new SlateEditor({ value });
|
||||
const valueWithSelection = ed.moveForward(8).value;
|
||||
const valueWithSelection = ed.moveForward(6).value;
|
||||
const result = await instance.provideCompletionItems({
|
||||
text: '!=',
|
||||
prefix: '',
|
||||
|
@ -88,7 +88,10 @@ export default class PromQlLanguageProvider extends LanguageProvider {
|
||||
cleanText(s: string) {
|
||||
const parts = s.split(PREFIX_DELIMITER_REGEX);
|
||||
const last = parts.pop();
|
||||
return last.trimLeft().replace(/"$/, '');
|
||||
return last
|
||||
.trimLeft()
|
||||
.replace(/"$/, '')
|
||||
.replace(/^"/, '');
|
||||
}
|
||||
|
||||
get syntax() {
|
||||
@ -297,8 +300,15 @@ export default class PromQlLanguageProvider extends LanguageProvider {
|
||||
labelKey,
|
||||
value,
|
||||
}: TypeaheadInput): Promise<TypeaheadOutput> => {
|
||||
const suggestions: CompletionItemGroup[] = [];
|
||||
const line = value.anchorBlock.getText();
|
||||
const cursorOffset = value.selection.anchor.offset;
|
||||
const nextChar = line[cursorOffset];
|
||||
const isValueContext = wrapperClasses.includes('attr-value');
|
||||
if (!nextChar.match(/["}]/)) {
|
||||
// Don't suggest anything inside a value
|
||||
return { suggestions };
|
||||
}
|
||||
|
||||
// Get normalized selector
|
||||
let selector;
|
||||
@ -313,7 +323,6 @@ export default class PromQlLanguageProvider extends LanguageProvider {
|
||||
const containsMetric = selector.includes('__name__=');
|
||||
const existingKeys = parsedSelector ? parsedSelector.labelKeys : [];
|
||||
|
||||
const suggestions: CompletionItemGroup[] = [];
|
||||
let labelValues;
|
||||
// Query labels for selector
|
||||
if (selector) {
|
||||
@ -326,7 +335,7 @@ export default class PromQlLanguageProvider extends LanguageProvider {
|
||||
}
|
||||
|
||||
let context: string;
|
||||
if ((text && text.match(/^!?=~?/)) || wrapperClasses.includes('attr-value')) {
|
||||
if ((text && text.match(/^!?=~?/)) || isValueContext) {
|
||||
// Label values
|
||||
if (labelKey && labelValues[labelKey]) {
|
||||
context = 'context-label-values';
|
||||
|
@ -31,6 +31,13 @@ describe('parseSelector()', () => {
|
||||
|
||||
parsed = parseSelector('{foo="bar",baz="}');
|
||||
expect(parsed.selector).toBe('{foo="bar"}');
|
||||
|
||||
// Cursor in value area counts as incomplete
|
||||
parsed = parseSelector('{foo="bar",baz=""}', 16);
|
||||
expect(parsed.selector).toBe('{foo="bar"}');
|
||||
|
||||
parsed = parseSelector('{foo="bar",baz="4"}', 17);
|
||||
expect(parsed.selector).toBe('{foo="bar"}');
|
||||
});
|
||||
|
||||
it('throws if not inside a selector', () => {
|
||||
@ -55,7 +62,7 @@ describe('parseSelector()', () => {
|
||||
parsed = parseSelector('bar{foo}', 4);
|
||||
expect(parsed.selector).toBe('{__name__="bar"}');
|
||||
|
||||
parsed = parseSelector('baz{foo="bar"}', 12);
|
||||
parsed = parseSelector('baz{foo="bar"}', 13);
|
||||
expect(parsed.selector).toBe('{__name__="baz",foo="bar"}');
|
||||
|
||||
parsed = parseSelector('bar:metric:1m{}', 14);
|
||||
|
@ -79,8 +79,14 @@ export function parseSelector(query: string, cursorOffset = 1): { labelKeys: any
|
||||
// Extract clean labels to form clean selector, incomplete labels are dropped
|
||||
const selector = query.slice(prefixOpen, suffixClose);
|
||||
const labels: { [key: string]: { value: string; operator: string } } = {};
|
||||
selector.replace(labelRegexp, (_, key, operator, value) => {
|
||||
labels[key] = { value, operator };
|
||||
selector.replace(labelRegexp, (label, key, operator, value) => {
|
||||
const labelOffset = query.indexOf(label);
|
||||
const valueStart = labelOffset + key.length + operator.length + 1;
|
||||
const valueEnd = labelOffset + key.length + operator.length + value.length - 1;
|
||||
// Skip label if cursor is in value
|
||||
if (cursorOffset < valueStart || cursorOffset > valueEnd) {
|
||||
labels[key] = { value, operator };
|
||||
}
|
||||
return '';
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user