CloudWatch: Add syntax highlighting and autocomplete for logs diff command (#111207)
This commit is contained in:
+18
-1
@@ -4,6 +4,8 @@ import { CustomVariableModel } from '@grafana/data';
|
||||
import { monacoTypes } from '@grafana/ui';
|
||||
|
||||
import { setupMockedTemplateService, logGroupNamesVariable } from '../../../mocks/CloudWatchDataSource';
|
||||
import { logsTestDataDiffModifierQuery } from '../../../mocks/cloudwatch-logs-test-data/diffModifierQuery';
|
||||
import { logsTestDataDiffQuery } from '../../../mocks/cloudwatch-logs-test-data/diffQuery';
|
||||
import { logsTestDataEmptyQuery } from '../../../mocks/cloudwatch-logs-test-data/empty';
|
||||
import { logsTestDataFilterQuery } from '../../../mocks/cloudwatch-logs-test-data/filterQuery';
|
||||
import { logsTestDataNewCommandQuery } from '../../../mocks/cloudwatch-logs-test-data/newCommandQuery';
|
||||
@@ -12,7 +14,7 @@ import { ResourcesAPI } from '../../../resources/ResourcesAPI';
|
||||
import { ResourceResponse } from '../../../resources/types';
|
||||
import { LogGroup, LogGroupField } from '../../../types';
|
||||
import cloudWatchLogsLanguageDefinition, { CLOUDWATCH_LOGS_LANGUAGE_DEFINITION_ID } from '../definition';
|
||||
import { LOGS_COMMANDS, LOGS_FUNCTION_OPERATORS, SORT_DIRECTION_KEYWORDS, language } from '../language';
|
||||
import { DIFF_MODIFIERS, LOGS_COMMANDS, LOGS_FUNCTION_OPERATORS, SORT_DIRECTION_KEYWORDS, language } from '../language';
|
||||
|
||||
import { LogsCompletionItemProvider } from './CompletionItemProvider';
|
||||
|
||||
@@ -81,6 +83,21 @@ describe('LogsCompletionItemProvider', () => {
|
||||
expect(suggestionLabels).toEqual(expect.arrayContaining(LOGS_FUNCTION_OPERATORS));
|
||||
});
|
||||
|
||||
it('returns diff modifiers after the diff keyword', async () => {
|
||||
const suggestions = await getSuggestions(logsTestDataDiffQuery.query, logsTestDataDiffQuery.position);
|
||||
const suggestionLabels = suggestions.map((s) => s.label);
|
||||
expect(suggestionLabels).toEqual(expect.arrayContaining(DIFF_MODIFIERS));
|
||||
});
|
||||
|
||||
it('returns diff modifiers when partially typed', async () => {
|
||||
const suggestions = await getSuggestions(
|
||||
logsTestDataDiffModifierQuery.query,
|
||||
logsTestDataDiffModifierQuery.position
|
||||
);
|
||||
const suggestionLabels = suggestions.map((s) => s.label);
|
||||
expect(suggestionLabels).toEqual(expect.arrayContaining(DIFF_MODIFIERS));
|
||||
});
|
||||
|
||||
it('returns `in []` snippet for the `in` keyword', async () => {
|
||||
const suggestions = await getSuggestions(logsTestDataFilterQuery.query, logsTestDataFilterQuery.position);
|
||||
const suggestionLabels = suggestions.map((s) => s.label);
|
||||
|
||||
+9
-1
@@ -8,7 +8,7 @@ import { LinkedToken } from '../../monarch/LinkedToken';
|
||||
import { TRIGGER_SUGGEST } from '../../monarch/commands';
|
||||
import { CompletionItem, CompletionItemPriority, StatementPosition, SuggestionKind } from '../../monarch/types';
|
||||
import { fetchLogGroupFields } from '../../utils';
|
||||
import { LOGS_COMMANDS, LOGS_FUNCTION_OPERATORS, SORT_DIRECTION_KEYWORDS } from '../language';
|
||||
import { LOGS_COMMANDS, LOGS_FUNCTION_OPERATORS, SORT_DIRECTION_KEYWORDS, DIFF_MODIFIERS } from '../language';
|
||||
|
||||
import { getStatementPosition } from './statementPosition';
|
||||
import { getSuggestionKinds } from './suggestionKinds';
|
||||
@@ -115,6 +115,14 @@ export class LogsCompletionItemProvider extends CompletionItemProvider {
|
||||
});
|
||||
});
|
||||
break;
|
||||
case SuggestionKind.DiffModifier:
|
||||
DIFF_MODIFIERS.forEach((modifier) => {
|
||||
addSuggestion(modifier, {
|
||||
sortText: CompletionItemPriority.High,
|
||||
kind: monaco.languages.CompletionItemKind.Keyword,
|
||||
});
|
||||
});
|
||||
break;
|
||||
case SuggestionKind.InKeyword:
|
||||
addSuggestion('in []', {
|
||||
insertText: 'in ["$0"]',
|
||||
|
||||
+20
@@ -3,6 +3,8 @@ import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
|
||||
import { monacoTypes } from '@grafana/ui';
|
||||
|
||||
import { logsTestDataCommentOnlyQuery } from '../../../mocks/cloudwatch-logs-test-data/commentOnlyQuery';
|
||||
import { logsTestDataDiffModifierQuery } from '../../../mocks/cloudwatch-logs-test-data/diffModifierQuery';
|
||||
import { logsTestDataDiffQuery } from '../../../mocks/cloudwatch-logs-test-data/diffQuery';
|
||||
import { logsTestDataEmptyQuery } from '../../../mocks/cloudwatch-logs-test-data/empty';
|
||||
import { logsTestDataMultiLineFullQuery } from '../../../mocks/cloudwatch-logs-test-data/multiLineFullQuery';
|
||||
import { logsTestDataSingleLineFullQuery } from '../../../mocks/cloudwatch-logs-test-data/singleLineFullQuery';
|
||||
@@ -164,4 +166,22 @@ describe('getStatementPosition', () => {
|
||||
getStatementPosition(generateToken(logsTestDataMultiLineFullQuery.query, { lineNumber: 5, column: 3 }))
|
||||
).toEqual(StatementPosition.Comment);
|
||||
});
|
||||
|
||||
it('should return StatementPosition.DiffKeyword inside the `diff` keyword', () => {
|
||||
expect(getStatementPosition(generateToken(logsTestDataDiffQuery.query, { lineNumber: 1, column: 22 }))).toEqual(
|
||||
StatementPosition.DiffKeyword
|
||||
);
|
||||
});
|
||||
|
||||
it('should return StatementPosition.AfterDiffKeyword after the `diff` keyword', () => {
|
||||
expect(getStatementPosition(generateToken(logsTestDataDiffQuery.query, { lineNumber: 1, column: 25 }))).toEqual(
|
||||
StatementPosition.AfterDiffKeyword
|
||||
);
|
||||
});
|
||||
|
||||
it('should return StatementPosition.DiffModifierArg when typing a diff modifier', () => {
|
||||
expect(
|
||||
getStatementPosition(generateToken(logsTestDataDiffModifierQuery.query, { lineNumber: 1, column: 28 }))
|
||||
).toEqual(StatementPosition.DiffModifierArg);
|
||||
});
|
||||
});
|
||||
|
||||
+11
@@ -9,6 +9,7 @@ import {
|
||||
LIMIT,
|
||||
PARSE,
|
||||
DEDUP,
|
||||
DIFF,
|
||||
LOGS_COMMANDS,
|
||||
LOGS_FUNCTION_OPERATORS,
|
||||
LOGS_LOGIC_OPERATORS,
|
||||
@@ -66,6 +67,8 @@ export const getStatementPosition = (currentToken: LinkedToken | null): Statemen
|
||||
switch (normalizedCurrentToken) {
|
||||
case DEDUP:
|
||||
return StatementPosition.DedupKeyword;
|
||||
case DIFF:
|
||||
return StatementPosition.DiffKeyword;
|
||||
case DISPLAY:
|
||||
return StatementPosition.DisplayKeyword;
|
||||
case FIELDS:
|
||||
@@ -95,6 +98,8 @@ export const getStatementPosition = (currentToken: LinkedToken | null): Statemen
|
||||
switch (normalizedPreviousNonWhiteSpace) {
|
||||
case DEDUP:
|
||||
return StatementPosition.AfterDedupKeyword;
|
||||
case DIFF:
|
||||
return StatementPosition.AfterDiffKeyword;
|
||||
case DISPLAY:
|
||||
return StatementPosition.AfterDisplayKeyword;
|
||||
case FIELDS:
|
||||
@@ -171,6 +176,9 @@ export const getStatementPosition = (currentToken: LinkedToken | null): Statemen
|
||||
if (nearestKeyword.value === FILTER) {
|
||||
return StatementPosition.FilterArg;
|
||||
}
|
||||
if (nearestKeyword.value === DIFF) {
|
||||
return StatementPosition.DiffModifierArg;
|
||||
}
|
||||
return StatementPosition.CommandArg;
|
||||
}
|
||||
|
||||
@@ -189,6 +197,9 @@ export const getStatementPosition = (currentToken: LinkedToken | null): Statemen
|
||||
if (nearestKeyword.value === FILTER) {
|
||||
return StatementPosition.FilterArg;
|
||||
}
|
||||
if (nearestKeyword.value === DIFF) {
|
||||
return StatementPosition.DiffModifierArg;
|
||||
}
|
||||
return StatementPosition.CommandArg;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,9 @@ export function getSuggestionKinds(statementPosition: StatementPosition): Sugges
|
||||
case StatementPosition.AfterSortKeyword:
|
||||
case StatementPosition.SortArg:
|
||||
return [SuggestionKind.SortOrderDirectionKeyword, SuggestionKind.Function];
|
||||
case StatementPosition.AfterDiffKeyword:
|
||||
case StatementPosition.DiffModifierArg:
|
||||
return [SuggestionKind.DiffModifier];
|
||||
case StatementPosition.AfterDisplayKeyword:
|
||||
case StatementPosition.AfterFieldsKeyword:
|
||||
case StatementPosition.AfterFilterKeyword:
|
||||
|
||||
@@ -7,6 +7,7 @@ interface CloudWatchLogsLanguage extends monacoType.languages.IMonarchLanguage {
|
||||
builtinFunctions: string[];
|
||||
}
|
||||
|
||||
export const DIFF = 'diff';
|
||||
export const DISPLAY = 'display';
|
||||
export const FIELDS = 'fields';
|
||||
export const FILTER = 'filter';
|
||||
@@ -16,7 +17,7 @@ export const SORT = 'sort';
|
||||
export const LIMIT = 'limit';
|
||||
export const PARSE = 'parse';
|
||||
export const DEDUP = 'dedup';
|
||||
export const LOGS_COMMANDS = [DISPLAY, FIELDS, FILTER, PATTERN, STATS, SORT, LIMIT, PARSE, DEDUP];
|
||||
export const LOGS_COMMANDS = [DISPLAY, FIELDS, FILTER, PATTERN, STATS, SORT, LIMIT, PARSE, DEDUP, DIFF];
|
||||
|
||||
export const LOGS_LOGIC_OPERATORS = ['and', 'or', 'not'];
|
||||
|
||||
@@ -77,7 +78,8 @@ export const LOGS_FUNCTION_OPERATORS = [
|
||||
];
|
||||
|
||||
export const SORT_DIRECTION_KEYWORDS = ['asc', 'desc'];
|
||||
export const LOGS_KEYWORDS = ['like', 'by', 'in', 'as', ...SORT_DIRECTION_KEYWORDS];
|
||||
export const DIFF_MODIFIERS = ['previousDay', 'previousWeek', 'previousMonth'];
|
||||
export const LOGS_KEYWORDS = ['like', 'by', 'in', 'as', ...SORT_DIRECTION_KEYWORDS, ...DIFF_MODIFIERS];
|
||||
|
||||
export const language: CloudWatchLogsLanguage = {
|
||||
defaultToken: 'invalid',
|
||||
|
||||
@@ -103,6 +103,10 @@ export enum StatementPosition {
|
||||
LikeKeyword,
|
||||
AfterLikeKeyword,
|
||||
|
||||
DiffKeyword,
|
||||
AfterDiffKeyword,
|
||||
DiffModifierArg,
|
||||
|
||||
Function,
|
||||
FunctionArg,
|
||||
CommandArg,
|
||||
@@ -171,6 +175,7 @@ export enum SuggestionKind {
|
||||
Command,
|
||||
Function,
|
||||
InKeyword,
|
||||
DiffModifier,
|
||||
|
||||
// PPL
|
||||
BooleanFunction,
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
export const logsTestDataDiffModifierQuery = {
|
||||
query: `pattern @message | diff previous`,
|
||||
position: { lineNumber: 1, column: 32 },
|
||||
};
|
||||
@@ -0,0 +1,4 @@
|
||||
export const logsTestDataDiffQuery = {
|
||||
query: `pattern @message | diff `,
|
||||
position: { lineNumber: 1, column: 24 },
|
||||
};
|
||||
Reference in New Issue
Block a user