prometheus: monaco: better suggestions inside quotes (#41262)

* prometheus: monaco: better suggestions inside quotes

* add double-quote as trigger character

* moved comment to correct place
pull/41346/head
Gábor Farkas 4 years ago committed by GitHub
parent 345f0b658d
commit eec7b9d325
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      public/app/plugins/datasource/prometheus/components/monaco-query-field/monaco-completion-provider/completions.ts
  2. 2
      public/app/plugins/datasource/prometheus/components/monaco-query-field/monaco-completion-provider/index.ts
  3. 15
      public/app/plugins/datasource/prometheus/components/monaco-query-field/monaco-completion-provider/situation.test.ts
  4. 23
      public/app/plugins/datasource/prometheus/components/monaco-query-field/monaco-completion-provider/situation.ts

@ -162,6 +162,7 @@ async function getLabelValues(
async function getLabelValuesForMetricCompletions(
metric: string | undefined,
labelName: string,
betweenQuotes: boolean,
otherLabels: Label[],
dataProvider: DataProvider
): Promise<Completion[]> {
@ -169,7 +170,7 @@ async function getLabelValuesForMetricCompletions(
return values.map((text) => ({
type: 'LABEL_VALUE',
label: text,
insertText: `"${text}"`, // FIXME: escaping strange characters?
insertText: betweenQuotes ? text : `"${text}"`, // FIXME: escaping strange characters?
}));
}
@ -195,6 +196,7 @@ export async function getCompletions(situation: Situation, dataProvider: DataPro
return getLabelValuesForMetricCompletions(
situation.metricName,
situation.labelName,
situation.betweenQuotes,
situation.otherLabels,
dataProvider
);

@ -95,7 +95,7 @@ export function getCompletionProvider(
};
return {
triggerCharacters: ['{', ',', '[', '(', '=', '~', ' '],
triggerCharacters: ['{', ',', '[', '(', '=', '~', ' ', '"'],
provideCompletionItems,
};
}

@ -96,6 +96,7 @@ describe('situation', () => {
type: 'IN_LABEL_SELECTOR_WITH_LABEL_NAME',
metricName: 'something',
labelName: 'job',
betweenQuotes: false,
otherLabels: [],
});
@ -103,6 +104,7 @@ describe('situation', () => {
type: 'IN_LABEL_SELECTOR_WITH_LABEL_NAME',
metricName: 'something',
labelName: 'job',
betweenQuotes: false,
otherLabels: [],
});
@ -110,6 +112,7 @@ describe('situation', () => {
type: 'IN_LABEL_SELECTOR_WITH_LABEL_NAME',
metricName: 'something',
labelName: 'job',
betweenQuotes: false,
otherLabels: [],
});
@ -117,6 +120,7 @@ describe('situation', () => {
type: 'IN_LABEL_SELECTOR_WITH_LABEL_NAME',
metricName: 'something',
labelName: 'job',
betweenQuotes: false,
otherLabels: [],
});
@ -124,12 +128,22 @@ describe('situation', () => {
type: 'IN_LABEL_SELECTOR_WITH_LABEL_NAME',
metricName: 'something',
labelName: 'job',
betweenQuotes: false,
otherLabels: [{ name: 'host', value: 'h1', op: '=' }],
});
assertSituation('something{job="j1",host="^"}', {
type: 'IN_LABEL_SELECTOR_WITH_LABEL_NAME',
metricName: 'something',
labelName: 'host',
betweenQuotes: true,
otherLabels: [{ name: 'job', value: 'j1', op: '=' }],
});
assertSituation('{job=^,host="h1"}', {
type: 'IN_LABEL_SELECTOR_WITH_LABEL_NAME',
labelName: 'job',
betweenQuotes: false,
otherLabels: [{ name: 'host', value: 'h1', op: '=' }],
});
@ -137,6 +151,7 @@ describe('situation', () => {
type: 'IN_LABEL_SELECTOR_WITH_LABEL_NAME',
metricName: 'something',
labelName: 'three',
betweenQuotes: false,
otherLabels: [
{ name: 'one', value: 'val1', op: '=' },
{ name: 'two', value: 'val2', op: '!=' },

@ -111,6 +111,7 @@ export type Situation =
type: 'IN_LABEL_SELECTOR_WITH_LABEL_NAME';
metricName?: string;
labelName: string;
betweenQuotes: boolean;
otherLabels: Label[];
};
@ -138,9 +139,13 @@ const RESOLVERS: Resolver[] = [
path: ['FunctionCallBody'],
fun: resolveInFunction,
},
{
path: ['StringLiteral', 'LabelMatcher'],
fun: resolveLabelMatcher,
},
{
path: [ERROR_NODE_NAME, 'LabelMatcher'],
fun: resolveLabelMatcherError,
fun: resolveLabelMatcher,
},
{
path: [ERROR_NODE_NAME, 'MatrixSelector'],
@ -290,9 +295,12 @@ function resolveLabelsForGrouping(node: SyntaxNode, text: string, pos: number):
};
}
function resolveLabelMatcherError(node: SyntaxNode, text: string, pos: number): Situation | null {
// we are probably in the scenario where the user is before entering the
// label-value, like `{job=^}` (^ marks the cursor)
function resolveLabelMatcher(node: SyntaxNode, text: string, pos: number): Situation | null {
// we can arrive here in two situation. `node` is either:
// - a StringNode (like in `{job="^"}`)
// - or an error node (like in `{job=^}`)
const inStringNode = !node.type.isError;
const parent = walk(node, [['parent', 'LabelMatcher']]);
if (parent === null) {
return null;
@ -344,7 +352,10 @@ function resolveLabelMatcherError(node: SyntaxNode, text: string, pos: number):
}
// now we need to find the other names
const otherLabels = getLabels(labelMatchersNode, text);
const allLabels = getLabels(labelMatchersNode, text);
// we need to remove "our" label from all-labels, if it is in there
const otherLabels = allLabels.filter((label) => label.name !== labelName);
const metricNameNode = walk(labelMatchersNode, [
['parent', 'VectorSelector'],
@ -357,6 +368,7 @@ function resolveLabelMatcherError(node: SyntaxNode, text: string, pos: number):
return {
type: 'IN_LABEL_SELECTOR_WITH_LABEL_NAME',
labelName,
betweenQuotes: inStringNode,
otherLabels,
};
}
@ -367,6 +379,7 @@ function resolveLabelMatcherError(node: SyntaxNode, text: string, pos: number):
type: 'IN_LABEL_SELECTOR_WITH_LABEL_NAME',
metricName,
labelName,
betweenQuotes: inStringNode,
otherLabels,
};
}

Loading…
Cancel
Save