Commit ae1d2fb5 by Ivana Huckova Committed by GitHub

Prometheus: Fix autocomplete does not work on incomplete input (#29854)

* WIP, works but need to do more testing

* Update solution

* Fix autocomplete with metrics

* Update public/app/plugins/datasource/prometheus/language_provider.ts

* Update public/app/plugins/datasource/prometheus/language_provider.ts

* Change test for new functionality
parent 2221a8c5
...@@ -329,11 +329,11 @@ export default class PromQlLanguageProvider extends LanguageProvider { ...@@ -329,11 +329,11 @@ export default class PromQlLanguageProvider extends LanguageProvider {
const suffix = line.substr(cursorOffset); const suffix = line.substr(cursorOffset);
const prefix = line.substr(0, cursorOffset); const prefix = line.substr(0, cursorOffset);
const isValueStart = text.match(/^(=|=~|!=|!~)/); const isValueStart = text.match(/^(=|=~|!=|!~)/);
const isValueEnd = suffix.match(/^"?[,}]/); const isValueEnd = suffix.match(/^"?[,}]|$/);
// detect cursor in front of value, e.g., {key=|"} // Detect cursor in front of value, e.g., {key=|"}
const isPreValue = prefix.match(/(=|=~|!=|!~)$/) && suffix.match(/^"/); const isPreValue = prefix.match(/(=|=~|!=|!~)$/) && suffix.match(/^"/);
// Don't suggestq anything at the beginning or inside a value // Don't suggest anything at the beginning or inside a value
const isValueEmpty = isValueStart && isValueEnd; const isValueEmpty = isValueStart && isValueEnd;
const hasValuePrefix = isValueEnd && !isValueStart; const hasValuePrefix = isValueEnd && !isValueStart;
if ((!isValueEmpty && !hasValuePrefix) || isPreValue) { if ((!isValueEmpty && !hasValuePrefix) || isPreValue) {
......
...@@ -9,8 +9,9 @@ describe('parseSelector()', () => { ...@@ -9,8 +9,9 @@ describe('parseSelector()', () => {
expect(parsed.labelKeys).toEqual([]); expect(parsed.labelKeys).toEqual([]);
}); });
it('throws if selector is broken', () => { it('returns a clean selector from an unclosed selector', () => {
expect(() => parseSelector('{foo')).toThrow(); const parsed = parseSelector('{foo');
expect(parsed.selector).toBe('{}');
}); });
it('returns the selector sorted by label key', () => { it('returns the selector sorted by label key', () => {
......
...@@ -42,7 +42,7 @@ export function processLabels(labels: Array<{ [key: string]: string }>, withName ...@@ -42,7 +42,7 @@ export function processLabels(labels: Array<{ [key: string]: string }>, withName
} }
// const cleanSelectorRegexp = /\{(\w+="[^"\n]*?")(,\w+="[^"\n]*?")*\}/; // const cleanSelectorRegexp = /\{(\w+="[^"\n]*?")(,\w+="[^"\n]*?")*\}/;
export const selectorRegexp = /\{[^}]*?\}/; export const selectorRegexp = /\{[^}]*?(\}|$)/;
export const labelRegexp = /\b(\w+)(!?=~?)("[^"\n]*?")/g; export const labelRegexp = /\b(\w+)(!?=~?)("[^"\n]*?")/g;
export function parseSelector(query: string, cursorOffset = 1): { labelKeys: any[]; selector: string } { export function parseSelector(query: string, cursorOffset = 1): { labelKeys: any[]; selector: string } {
if (!query.match(selectorRegexp)) { if (!query.match(selectorRegexp)) {
......
...@@ -393,7 +393,7 @@ const tokenizer: Grammar = { ...@@ -393,7 +393,7 @@ const tokenizer: Grammar = {
}, },
}, },
'context-labels': { 'context-labels': {
pattern: /\{[^}]*(?=})/, pattern: /\{[^}]*(?=}?)/,
greedy: true, greedy: true,
inside: { inside: {
comment: { comment: {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment