mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
feat(loki-monaco-editor): improve line filter suggestions (#57103)
This commit is contained in:
parent
4d0dd0647e
commit
d2abcbe4a5
@ -69,37 +69,37 @@ const afterSelectorCompletions = [
|
|||||||
type: 'OPPOSITE_PARSER_PLACEHOLDER',
|
type: 'OPPOSITE_PARSER_PLACEHOLDER',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
insertText: 'pattern',
|
insertText: '| pattern',
|
||||||
label: 'pattern',
|
label: 'pattern',
|
||||||
type: 'PARSER',
|
type: 'PARSER',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
insertText: 'regexp',
|
insertText: '| regexp',
|
||||||
label: 'regexp',
|
label: 'regexp',
|
||||||
type: 'PARSER',
|
type: 'PARSER',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
insertText: 'unpack',
|
insertText: '| unpack',
|
||||||
label: 'unpack',
|
label: 'unpack',
|
||||||
type: 'PARSER',
|
type: 'PARSER',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
insertText: 'unwrap extracted',
|
insertText: '| unwrap extracted',
|
||||||
label: 'unwrap extracted (detected)',
|
label: 'unwrap extracted (detected)',
|
||||||
type: 'LINE_FILTER',
|
type: 'LINE_FILTER',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
insertText: 'unwrap label',
|
insertText: '| unwrap label',
|
||||||
label: 'unwrap label (detected)',
|
label: 'unwrap label (detected)',
|
||||||
type: 'LINE_FILTER',
|
type: 'LINE_FILTER',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
insertText: 'unwrap',
|
insertText: '| unwrap',
|
||||||
label: 'unwrap',
|
label: 'unwrap',
|
||||||
type: 'LINE_FILTER',
|
type: 'LINE_FILTER',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
insertText: 'line_format "{{.$0}}"',
|
insertText: '| line_format "{{.$0}}"',
|
||||||
isSnippet: true,
|
isSnippet: true,
|
||||||
label: 'line_format',
|
label: 'line_format',
|
||||||
type: 'LINE_FORMAT',
|
type: 'LINE_FORMAT',
|
||||||
@ -110,27 +110,43 @@ function buildAfterSelectorCompletions(
|
|||||||
detectedParser: string,
|
detectedParser: string,
|
||||||
detectedParserType: string,
|
detectedParserType: string,
|
||||||
otherParser: string,
|
otherParser: string,
|
||||||
explanation = '(detected)'
|
afterPipe: boolean
|
||||||
) {
|
) {
|
||||||
return afterSelectorCompletions.map((completion) => {
|
const explanation = '(detected)';
|
||||||
|
const expectedCompletions = afterSelectorCompletions.map((completion) => {
|
||||||
if (completion.type === 'DETECTED_PARSER_PLACEHOLDER') {
|
if (completion.type === 'DETECTED_PARSER_PLACEHOLDER') {
|
||||||
return {
|
return {
|
||||||
...completion,
|
...completion,
|
||||||
type: detectedParserType,
|
type: detectedParserType,
|
||||||
label: `${detectedParser} ${explanation}`,
|
label: `${detectedParser} ${explanation}`,
|
||||||
insertText: detectedParser,
|
insertText: `| ${detectedParser}`,
|
||||||
};
|
};
|
||||||
} else if (completion.type === 'OPPOSITE_PARSER_PLACEHOLDER') {
|
} else if (completion.type === 'OPPOSITE_PARSER_PLACEHOLDER') {
|
||||||
return {
|
return {
|
||||||
...completion,
|
...completion,
|
||||||
type: 'PARSER',
|
type: 'PARSER',
|
||||||
label: otherParser,
|
label: otherParser,
|
||||||
insertText: otherParser,
|
insertText: `| ${otherParser}`,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return { ...completion };
|
return { ...completion };
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (afterPipe) {
|
||||||
|
// Remove pipe
|
||||||
|
return (
|
||||||
|
expectedCompletions
|
||||||
|
.map((completion) => {
|
||||||
|
completion.insertText = completion.insertText.replace('|', '');
|
||||||
|
return completion;
|
||||||
|
})
|
||||||
|
// Remove != and !~
|
||||||
|
.filter((completion) => !completion.insertText.startsWith('!'))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return expectedCompletions;
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('getCompletions', () => {
|
describe('getCompletions', () => {
|
||||||
@ -272,31 +288,37 @@ describe('getCompletions', () => {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Returns completion options when the situation is AFTER_SELECTOR and JSON parser', async () => {
|
test.each([true, false])(
|
||||||
jest.spyOn(completionProvider, 'getParserAndLabelKeys').mockResolvedValue({
|
'Returns completion options when the situation is AFTER_SELECTOR, JSON parser, and afterPipe %s',
|
||||||
extractedLabelKeys,
|
async (afterPipe: boolean) => {
|
||||||
hasJSON: true,
|
jest.spyOn(completionProvider, 'getParserAndLabelKeys').mockResolvedValue({
|
||||||
hasLogfmt: false,
|
extractedLabelKeys,
|
||||||
});
|
hasJSON: true,
|
||||||
const situation: Situation = { type: 'AFTER_SELECTOR', labels: [], afterPipe: true };
|
hasLogfmt: false,
|
||||||
const completions = await getCompletions(situation, completionProvider);
|
});
|
||||||
|
const situation: Situation = { type: 'AFTER_SELECTOR', labels: [], afterPipe };
|
||||||
|
const completions = await getCompletions(situation, completionProvider);
|
||||||
|
|
||||||
const expected = buildAfterSelectorCompletions('json', 'PARSER', 'logfmt');
|
const expected = buildAfterSelectorCompletions('json', 'PARSER', 'logfmt', afterPipe);
|
||||||
expect(completions).toEqual(expected);
|
expect(completions).toEqual(expected);
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
test('Returns completion options when the situation is AFTER_SELECTOR and Logfmt parser', async () => {
|
test.each([true, false])(
|
||||||
jest.spyOn(completionProvider, 'getParserAndLabelKeys').mockResolvedValue({
|
'Returns completion options when the situation is AFTER_SELECTOR, Logfmt parser, and afterPipe %s',
|
||||||
extractedLabelKeys,
|
async (afterPipe: boolean) => {
|
||||||
hasJSON: false,
|
jest.spyOn(completionProvider, 'getParserAndLabelKeys').mockResolvedValue({
|
||||||
hasLogfmt: true,
|
extractedLabelKeys,
|
||||||
});
|
hasJSON: false,
|
||||||
const situation: Situation = { type: 'AFTER_SELECTOR', labels: [], afterPipe: true };
|
hasLogfmt: true,
|
||||||
const completions = await getCompletions(situation, completionProvider);
|
});
|
||||||
|
const situation: Situation = { type: 'AFTER_SELECTOR', labels: [], afterPipe };
|
||||||
|
const completions = await getCompletions(situation, completionProvider);
|
||||||
|
|
||||||
const expected = buildAfterSelectorCompletions('logfmt', 'DURATION', 'json');
|
const expected = buildAfterSelectorCompletions('logfmt', 'DURATION', 'json', afterPipe);
|
||||||
expect(completions).toEqual(expected);
|
expect(completions).toEqual(expected);
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
test('Returns completion options when the situation is IN_AGGREGATION', async () => {
|
test('Returns completion options when the situation is IN_AGGREGATION', async () => {
|
||||||
const situation: Situation = { type: 'IN_AGGREGATION' };
|
const situation: Situation = { type: 'IN_AGGREGATION' };
|
||||||
|
@ -64,12 +64,17 @@ const DURATION_COMPLETIONS: Completion[] = ['$__interval', '$__range', '1m', '5m
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const LINE_FILTER_COMPLETIONS: Completion[] = ['|=', '!=', '|~', '!~'].map((item) => ({
|
function getLineFilterCompletions(afterPipe: boolean): Completion[] {
|
||||||
type: 'LINE_FILTER',
|
const lineFilters = afterPipe ? ['=', '~'] : ['|=', '!=', '|~', '!~'];
|
||||||
label: `${item} ""`,
|
const prefix = afterPipe ? '|' : '';
|
||||||
insertText: `${item} "$0"`,
|
|
||||||
isSnippet: true,
|
return lineFilters.map((operator) => ({
|
||||||
}));
|
type: 'LINE_FILTER',
|
||||||
|
label: `${prefix}${operator} ""`,
|
||||||
|
insertText: `${operator} "$0"`,
|
||||||
|
isSnippet: true,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
async function getAllHistoryCompletions(dataProvider: CompletionDataProvider): Promise<Completion[]> {
|
async function getAllHistoryCompletions(dataProvider: CompletionDataProvider): Promise<Completion[]> {
|
||||||
const history = await dataProvider.getHistory();
|
const history = await dataProvider.getHistory();
|
||||||
@ -133,7 +138,7 @@ async function getAfterSelectorCompletions(
|
|||||||
const { extractedLabelKeys, hasJSON, hasLogfmt } = await dataProvider.getParserAndLabelKeys(labels);
|
const { extractedLabelKeys, hasJSON, hasLogfmt } = await dataProvider.getParserAndLabelKeys(labels);
|
||||||
const allParsers = new Set(['json', 'logfmt', 'pattern', 'regexp', 'unpack']);
|
const allParsers = new Set(['json', 'logfmt', 'pattern', 'regexp', 'unpack']);
|
||||||
const completions: Completion[] = [];
|
const completions: Completion[] = [];
|
||||||
const prefix = afterPipe ? '' : '| ';
|
const prefix = afterPipe ? ' ' : '| ';
|
||||||
const hasLevelInExtractedLabels = extractedLabelKeys.some((key) => key === 'level');
|
const hasLevelInExtractedLabels = extractedLabelKeys.some((key) => key === 'level');
|
||||||
if (hasJSON) {
|
if (hasJSON) {
|
||||||
allParsers.delete('json');
|
allParsers.delete('json');
|
||||||
@ -185,7 +190,7 @@ async function getAfterSelectorCompletions(
|
|||||||
isSnippet: true,
|
isSnippet: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
return [...LINE_FILTER_COMPLETIONS, ...completions];
|
return [...getLineFilterCompletions(afterPipe), ...completions];
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getLabelValuesForMetricCompletions(
|
async function getLabelValuesForMetricCompletions(
|
||||||
|
Loading…
Reference in New Issue
Block a user