Tempo: Allow quotes in tag names and attributes (#77864)

This commit is contained in:
Fabrizio 2023-11-24 17:24:40 +01:00 committed by GitHub
parent 53e6182257
commit 6c7beb1ec3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 38 additions and 17 deletions

View File

@ -251,7 +251,7 @@
"@grafana/flamegraph": "workspace:*",
"@grafana/google-sdk": "0.1.1",
"@grafana/lezer-logql": "0.2.1",
"@grafana/lezer-traceql": "0.0.10",
"@grafana/lezer-traceql": "0.0.11",
"@grafana/monaco-logql": "^0.0.7",
"@grafana/runtime": "workspace:*",
"@grafana/scenes": "1.24.1",

View File

@ -3,9 +3,9 @@ import { computeErrorMessage, getErrorNodes } from './errorHighlighting';
describe('Check for syntax errors in query', () => {
it.each([
['{span.http.status_code = }', 'Invalid value after comparison or aritmetic operator.'],
['{span.http.status_code 200}', 'Invalid comparison operator after field expression.'],
['{span.http.status_code ""}', 'Invalid comparison operator after field expression.'],
['{span.http.status_code @ 200}', 'Invalid comparison operator after field expression.'],
['{span.http.status_code 200}', 'Invalid operator after field expression.'],
['{span.http.status_code ""}', 'Invalid operator after field expression.'],
['{span.http.status_code @ 200}', 'Invalid operator after field expression.'],
['{span.http.status_code span.http.status_code}', 'Invalid operator after field expression.'],
[
'{span.http.status_code = 200} {span.http.status_code = 200}',
@ -28,8 +28,8 @@ describe('Check for syntax errors in query', () => {
['{ .a && }', 'Invalid value after logical operator.'],
['{ .a || }', 'Invalid value after logical operator.'],
['{ .a + }', 'Invalid value after comparison or aritmetic operator.'],
['{ 200 = 200 200 }', 'Invalid comparison operator after field expression.'],
['{.foo 300}', 'Invalid comparison operator after field expression.'],
['{ 200 = 200 200 }', 'Invalid operator after field expression.'],
['{.foo 300}', 'Invalid operator after field expression.'],
['{.foo 300 && .bar = 200}', 'Invalid operator after field expression.'],
['{.foo 300 && .bar 200}', 'Invalid operator after field expression.'],
['{.foo=1} {.bar=2}', 'Invalid spanset combining operator after spanset expression.'],
@ -59,6 +59,7 @@ describe('Check for syntax errors in query', () => {
['{.foo=300} && {.foo=300} | avg(.value) =', 'Invalid value after comparison operator.'],
['{.foo=300} | max(duration) > 1hs', 'Invalid value after comparison operator.'],
['{ span.http.status_code', 'Invalid comparison operator after field expression.'],
['{ .foo = "bar"', 'Invalid comparison operator after field expression.'],
['abcxyz', 'Invalid query.'],
])('error message for invalid query - %s, %s', (query: string, expectedErrorMessage: string) => {
const errorNode = getErrorNodes(query)[0];
@ -80,6 +81,9 @@ describe('Check for syntax errors in query', () => {
`{ true } /* && { false } && */ && { true } // && { false }
&& { true }`,
],
['{span.s"t\\"at"us}'],
['{span.s"t\\\\at"us}'],
['{ span.s"tat"us" = "GET123 }'], // weird query, but technically valid
])('valid query - %s', (query: string) => {
expect(getErrorNodes(query)).toStrictEqual([]);
});

View File

@ -73,15 +73,32 @@ export const language: languages.IMonarchLanguage = {
// trace ID
[/^\s*[0-9A-Fa-f]+\s*$/, 'tag'],
// functions, keywords, predefined values
// keywords
[
/[a-zA-Z_.]\w*/,
// match only predefined keywords
`(?:${keywords.join('|')})`,
{
cases: {
'@keywords': 'keyword',
'@default': 'tag', // fallback, but should never happen
},
},
],
// functions and predefined values
[
// If not inside quotes, namely outside of open and closed `"`,
// allow only word characters (those matching `\w`) and full stop (`.`).
//
// If inside quotes, e.g. `"here"`, allow for any character, except for `"` and `\` which must be
// escaped with a backslash (`\"` and `\\` respectively).
// Quotes can be used to support special tag names, such as those with spaces (e.g., `my tag`).
/(?:\w|[.]|"(?:\\"|\\\\|[^\\"])*")+/,
{
cases: {
'@functions': 'predefined',
'@keywords': 'keyword',
'@statusValues': 'type',
'@default': 'tag',
'@default': 'tag', // fallback, used for tag names
},
},
],
@ -89,8 +106,8 @@ export const language: languages.IMonarchLanguage = {
// strings
[/"([^"\\]|\\.)*$/, 'string.invalid'], // non-teminated string
[/'([^'\\]|\\.)*$/, 'string.invalid'], // non-teminated string
[/"/, 'string', '@string_double'],
[/'/, 'string', '@string_single'],
[/([^\w])(")/, [{ token: '' }, { token: 'string', next: '@string_double' }]],
[/([^\w])(')/, [{ token: '' }, { token: 'string', next: '@string_single' }]],
// delimiters and operators
[/[{}()\[\]]/, 'delimiter.bracket'],

View File

@ -3224,12 +3224,12 @@ __metadata:
languageName: node
linkType: hard
"@grafana/lezer-traceql@npm:0.0.10":
version: 0.0.10
resolution: "@grafana/lezer-traceql@npm:0.0.10"
"@grafana/lezer-traceql@npm:0.0.11":
version: 0.0.11
resolution: "@grafana/lezer-traceql@npm:0.0.11"
peerDependencies:
"@lezer/lr": ^1.3.0
checksum: 9335458543a5155a4ece6a0d526dd78d8dba087f197b19ca80546529a39a107d62d4d0faa3fabc3f4d5caefc173cb1a6b93650a471101d34a0ee1c8f7c348de0
checksum: cb312cf8f0cf70af6eb307aa0b6478cd8bde9233f281d6f4bb385f3c846a1e9fe0caf8addef5cbc0ccadb57b968fbd10e26ad5df6f898fb2b174536dca924926
languageName: node
linkType: hard
@ -17311,7 +17311,7 @@ __metadata:
"@grafana/flamegraph": "workspace:*"
"@grafana/google-sdk": "npm:0.1.1"
"@grafana/lezer-logql": "npm:0.2.1"
"@grafana/lezer-traceql": "npm:0.0.10"
"@grafana/lezer-traceql": "npm:0.0.11"
"@grafana/monaco-logql": "npm:^0.0.7"
"@grafana/runtime": "workspace:*"
"@grafana/scenes": "npm:1.24.1"