mirror of
https://github.com/grafana/grafana.git
synced 2025-09-28 01:54:01 +08: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:
@ -301,7 +301,7 @@ describe('Language completion provider', () => {
|
|||||||
instance.lookupsDisabled = false;
|
instance.lookupsDisabled = false;
|
||||||
const value = Plain.deserialize('{job!=}');
|
const value = Plain.deserialize('{job!=}');
|
||||||
const ed = new SlateEditor({ value });
|
const ed = new SlateEditor({ value });
|
||||||
const valueWithSelection = ed.moveForward(8).value;
|
const valueWithSelection = ed.moveForward(6).value;
|
||||||
const result = await instance.provideCompletionItems({
|
const result = await instance.provideCompletionItems({
|
||||||
text: '!=',
|
text: '!=',
|
||||||
prefix: '',
|
prefix: '',
|
||||||
|
@ -88,7 +88,10 @@ export default class PromQlLanguageProvider extends LanguageProvider {
|
|||||||
cleanText(s: string) {
|
cleanText(s: string) {
|
||||||
const parts = s.split(PREFIX_DELIMITER_REGEX);
|
const parts = s.split(PREFIX_DELIMITER_REGEX);
|
||||||
const last = parts.pop();
|
const last = parts.pop();
|
||||||
return last.trimLeft().replace(/"$/, '');
|
return last
|
||||||
|
.trimLeft()
|
||||||
|
.replace(/"$/, '')
|
||||||
|
.replace(/^"/, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
get syntax() {
|
get syntax() {
|
||||||
@ -297,8 +300,15 @@ export default class PromQlLanguageProvider extends LanguageProvider {
|
|||||||
labelKey,
|
labelKey,
|
||||||
value,
|
value,
|
||||||
}: TypeaheadInput): Promise<TypeaheadOutput> => {
|
}: TypeaheadInput): Promise<TypeaheadOutput> => {
|
||||||
|
const suggestions: CompletionItemGroup[] = [];
|
||||||
const line = value.anchorBlock.getText();
|
const line = value.anchorBlock.getText();
|
||||||
const cursorOffset = value.selection.anchor.offset;
|
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
|
// Get normalized selector
|
||||||
let selector;
|
let selector;
|
||||||
@ -313,7 +323,6 @@ export default class PromQlLanguageProvider extends LanguageProvider {
|
|||||||
const containsMetric = selector.includes('__name__=');
|
const containsMetric = selector.includes('__name__=');
|
||||||
const existingKeys = parsedSelector ? parsedSelector.labelKeys : [];
|
const existingKeys = parsedSelector ? parsedSelector.labelKeys : [];
|
||||||
|
|
||||||
const suggestions: CompletionItemGroup[] = [];
|
|
||||||
let labelValues;
|
let labelValues;
|
||||||
// Query labels for selector
|
// Query labels for selector
|
||||||
if (selector) {
|
if (selector) {
|
||||||
@ -326,7 +335,7 @@ export default class PromQlLanguageProvider extends LanguageProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let context: string;
|
let context: string;
|
||||||
if ((text && text.match(/^!?=~?/)) || wrapperClasses.includes('attr-value')) {
|
if ((text && text.match(/^!?=~?/)) || isValueContext) {
|
||||||
// Label values
|
// Label values
|
||||||
if (labelKey && labelValues[labelKey]) {
|
if (labelKey && labelValues[labelKey]) {
|
||||||
context = 'context-label-values';
|
context = 'context-label-values';
|
||||||
|
@ -31,6 +31,13 @@ describe('parseSelector()', () => {
|
|||||||
|
|
||||||
parsed = parseSelector('{foo="bar",baz="}');
|
parsed = parseSelector('{foo="bar",baz="}');
|
||||||
expect(parsed.selector).toBe('{foo="bar"}');
|
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', () => {
|
it('throws if not inside a selector', () => {
|
||||||
@ -55,7 +62,7 @@ describe('parseSelector()', () => {
|
|||||||
parsed = parseSelector('bar{foo}', 4);
|
parsed = parseSelector('bar{foo}', 4);
|
||||||
expect(parsed.selector).toBe('{__name__="bar"}');
|
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"}');
|
expect(parsed.selector).toBe('{__name__="baz",foo="bar"}');
|
||||||
|
|
||||||
parsed = parseSelector('bar:metric:1m{}', 14);
|
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
|
// Extract clean labels to form clean selector, incomplete labels are dropped
|
||||||
const selector = query.slice(prefixOpen, suffixClose);
|
const selector = query.slice(prefixOpen, suffixClose);
|
||||||
const labels: { [key: string]: { value: string; operator: string } } = {};
|
const labels: { [key: string]: { value: string; operator: string } } = {};
|
||||||
selector.replace(labelRegexp, (_, key, operator, value) => {
|
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 };
|
labels[key] = { value, operator };
|
||||||
|
}
|
||||||
return '';
|
return '';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user