mirror of
https://github.com/SigNoz/signoz.git
synced 2026-09-30 07:10:42 +01:00
Compare commits
7 Commits
feat/ai-tr
...
feat/semco
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a46a7a50f | ||
|
|
39407aeb32 | ||
|
|
e28cf8aaaa | ||
|
|
a0e5c7c126 | ||
|
|
78c4f5a7e4 | ||
|
|
09bdda1280 | ||
|
|
7b9e9207ea |
4
.github/workflows/goci.yaml
vendored
4
.github/workflows/goci.yaml
vendored
@@ -66,8 +66,8 @@ jobs:
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.24"
|
||||
- name: check-semconv-generated-files
|
||||
run: go run ./scripts/semconv -check
|
||||
- name: check-semconv-generated-files-and-product-literals
|
||||
run: make semconv-check
|
||||
build:
|
||||
if: |
|
||||
github.event_name == 'merge_group' ||
|
||||
|
||||
23
Makefile
23
Makefile
@@ -220,6 +220,25 @@ py-test-teardown: ## Tear down the shared SigNoz backend
|
||||
py-test: ## Runs integration tests
|
||||
@cd tests && uv run pytest --basetemp=./tmp/ -vv --capture=no integration/tests/
|
||||
|
||||
.PHONY: py-test-semconv-phase1
|
||||
py-test-semconv-phase1: py-test-setup ## Rebuild the shared stack and run the semantic-convention Phase 1 matrix
|
||||
@cd tests && uv run pytest --basetemp=./tmp/ -vv --reuse --capture=no integration/tests/queriertraces/13_semconv_evolution.py
|
||||
|
||||
.PHONY: py-test-semconv-phase2
|
||||
py-test-semconv-phase2: py-test-setup ## Rebuild the shared stack and run the Phase 1-2 cross-signal matrices
|
||||
@cd tests && uv run pytest --basetemp=./tmp/ -vv --reuse --capture=no integration/tests/queriertraces/13_semconv_evolution.py integration/tests/queriersemconv/02_cross_signal.py
|
||||
|
||||
.PHONY: py-test-semconv-phase3
|
||||
py-test-semconv-phase3: py-test-setup ## Rebuild the shared stack and run the Phase 1-3 compatibility and migration-report matrices
|
||||
@cd tests && uv run pytest --basetemp=./tmp/ -vv --reuse --capture=no integration/tests/queriertraces/13_semconv_evolution.py integration/tests/queriersemconv/02_cross_signal.py
|
||||
|
||||
.PHONY: py-test-semconv-phase4
|
||||
py-test-semconv-phase4: py-test-setup ## Rebuild the shared stack and run all semantic-convention compatibility matrices
|
||||
@cd tests && uv run pytest --basetemp=./tmp/ -vv --reuse --capture=no integration/tests/queriertraces/13_semconv_evolution.py integration/tests/queriersemconv/02_cross_signal.py integration/tests/queriersemconv/04_phase4_families.py
|
||||
|
||||
.PHONY: py-test-semconv
|
||||
py-test-semconv: py-test-semconv-phase4 ## Run the complete semantic-convention evolution closure gate
|
||||
|
||||
.PHONY: py-clean
|
||||
py-clean: ## Clear all pycache and pytest cache from tests directory recursively
|
||||
@echo ">> cleaning python cache files from tests directory"
|
||||
@@ -237,6 +256,10 @@ py-clean: ## Clear all pycache and pytest cache from tests directory recursively
|
||||
semconv-generate: ## Regenerate semantic-convention families for Go and TypeScript
|
||||
@go run ./scripts/semconv
|
||||
|
||||
.PHONY: semconv-check
|
||||
semconv-check: ## Verify generated semantic-convention files and reject old-name product literals
|
||||
@go run ./scripts/semconv -check -lint
|
||||
|
||||
.PHONY: gen-mocks
|
||||
gen-mocks:
|
||||
@echo ">> Generating mocks"
|
||||
|
||||
@@ -6401,6 +6401,8 @@ components:
|
||||
$ref: '#/components/schemas/TelemetrytypesFieldContext'
|
||||
fieldDataType:
|
||||
$ref: '#/components/schemas/TelemetrytypesFieldDataType'
|
||||
fieldResolution:
|
||||
$ref: '#/components/schemas/TelemetrytypesFieldResolution'
|
||||
meta:
|
||||
properties:
|
||||
unit:
|
||||
@@ -6445,6 +6447,10 @@ components:
|
||||
rowsScanned:
|
||||
minimum: 0
|
||||
type: integer
|
||||
semconvResolutions:
|
||||
items:
|
||||
$ref: '#/components/schemas/Querybuildertypesv5SemconvResolution'
|
||||
type: array
|
||||
stepIntervals:
|
||||
additionalProperties:
|
||||
minimum: 0
|
||||
@@ -6511,6 +6517,8 @@ components:
|
||||
$ref: '#/components/schemas/TelemetrytypesFieldContext'
|
||||
fieldDataType:
|
||||
$ref: '#/components/schemas/TelemetrytypesFieldDataType'
|
||||
fieldResolution:
|
||||
$ref: '#/components/schemas/TelemetrytypesFieldResolution'
|
||||
name:
|
||||
type: string
|
||||
signal:
|
||||
@@ -6582,6 +6590,8 @@ components:
|
||||
$ref: '#/components/schemas/TelemetrytypesFieldContext'
|
||||
fieldDataType:
|
||||
$ref: '#/components/schemas/TelemetrytypesFieldDataType'
|
||||
fieldResolution:
|
||||
$ref: '#/components/schemas/TelemetrytypesFieldResolution'
|
||||
name:
|
||||
type: string
|
||||
signal:
|
||||
@@ -7149,6 +7159,20 @@ components:
|
||||
stepInterval:
|
||||
$ref: '#/components/schemas/Querybuildertypesv5Step'
|
||||
type: object
|
||||
Querybuildertypesv5SemconvResolution:
|
||||
properties:
|
||||
current:
|
||||
type: string
|
||||
kind:
|
||||
type: string
|
||||
members:
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
requested:
|
||||
type: string
|
||||
type: object
|
||||
Querybuildertypesv5Step:
|
||||
description: Step interval. Accepts a Go duration string (e.g., "60s", "1m",
|
||||
"1h") or a number representing seconds (e.g., 60).
|
||||
@@ -8660,6 +8684,11 @@ components:
|
||||
- number
|
||||
- ""
|
||||
type: string
|
||||
TelemetrytypesFieldResolution:
|
||||
enum:
|
||||
- exact
|
||||
- ""
|
||||
type: string
|
||||
TelemetrytypesGettableFieldKeys:
|
||||
properties:
|
||||
complete:
|
||||
@@ -8685,6 +8714,42 @@ components:
|
||||
- values
|
||||
- complete
|
||||
type: object
|
||||
TelemetrytypesGettableSemconvMigrationReport:
|
||||
properties:
|
||||
endUnixMilli:
|
||||
format: int64
|
||||
type: integer
|
||||
entries:
|
||||
items:
|
||||
$ref: '#/components/schemas/TelemetrytypesSemconvMigrationReportEntry'
|
||||
nullable: true
|
||||
type: array
|
||||
startUnixMilli:
|
||||
format: int64
|
||||
type: integer
|
||||
required:
|
||||
- entries
|
||||
type: object
|
||||
TelemetrytypesSemconvMigrationReportEntry:
|
||||
properties:
|
||||
current:
|
||||
type: string
|
||||
lastSeenUnixMilli:
|
||||
format: int64
|
||||
type: integer
|
||||
old:
|
||||
type: string
|
||||
resourceSets:
|
||||
minimum: 0
|
||||
type: integer
|
||||
services:
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
signal:
|
||||
type: string
|
||||
type: object
|
||||
TelemetrytypesSignal:
|
||||
enum:
|
||||
- traces
|
||||
@@ -8705,6 +8770,8 @@ components:
|
||||
$ref: '#/components/schemas/TelemetrytypesFieldContext'
|
||||
fieldDataType:
|
||||
$ref: '#/components/schemas/TelemetrytypesFieldDataType'
|
||||
fieldResolution:
|
||||
$ref: '#/components/schemas/TelemetrytypesFieldResolution'
|
||||
name:
|
||||
type: string
|
||||
signal:
|
||||
@@ -11201,6 +11268,64 @@ paths:
|
||||
summary: Get field keys
|
||||
tags:
|
||||
- fields
|
||||
/api/v1/fields/semconv-migration:
|
||||
get:
|
||||
deprecated: false
|
||||
description: Returns services that still emit old semantic-convention names
|
||||
without the current family name
|
||||
operationId: GetSemconvMigrationReport
|
||||
parameters:
|
||||
- in: query
|
||||
name: startUnixMilli
|
||||
schema:
|
||||
format: int64
|
||||
type: integer
|
||||
- in: query
|
||||
name: endUnixMilli
|
||||
schema:
|
||||
format: int64
|
||||
type: integer
|
||||
responses:
|
||||
"200":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/TelemetrytypesGettableSemconvMigrationReport'
|
||||
status:
|
||||
type: string
|
||||
required:
|
||||
- status
|
||||
- data
|
||||
type: object
|
||||
description: OK
|
||||
"401":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Unauthorized
|
||||
"403":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Forbidden
|
||||
"500":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/RenderErrorResponse'
|
||||
description: Internal Server Error
|
||||
security:
|
||||
- api_key:
|
||||
- VIEWER
|
||||
- tokenizer:
|
||||
- VIEWER
|
||||
summary: Get semantic-convention migration report
|
||||
tags:
|
||||
- fields
|
||||
/api/v1/fields/values:
|
||||
get:
|
||||
deprecated: false
|
||||
@@ -18786,8 +18911,8 @@ paths:
|
||||
alert: Payments-api error log rate above 1%
|
||||
alertType: LOGS_BASED_ALERT
|
||||
annotations:
|
||||
description: Error log rate in {{$deployment.environment}} is
|
||||
{{$value}}%
|
||||
description: Error log rate in {{$deployment.environment.name}}
|
||||
is {{$value}}%
|
||||
summary: Payments-api error rate above {{$threshold}}%
|
||||
condition:
|
||||
compositeQuery:
|
||||
@@ -18803,7 +18928,7 @@ paths:
|
||||
groupBy:
|
||||
- fieldContext: resource
|
||||
fieldDataType: string
|
||||
name: deployment.environment
|
||||
name: deployment.environment.name
|
||||
name: A
|
||||
signal: logs
|
||||
stepInterval: 60
|
||||
@@ -18817,14 +18942,14 @@ paths:
|
||||
groupBy:
|
||||
- fieldContext: resource
|
||||
fieldDataType: string
|
||||
name: deployment.environment
|
||||
name: deployment.environment.name
|
||||
name: B
|
||||
signal: logs
|
||||
stepInterval: 60
|
||||
type: builder_query
|
||||
- spec:
|
||||
expression: (A / B) * 100
|
||||
legend: '{{deployment.environment}}'
|
||||
legend: '{{deployment.environment.name}}'
|
||||
name: F1
|
||||
type: builder_formula
|
||||
queryType: builder
|
||||
@@ -18850,7 +18975,7 @@ paths:
|
||||
team: payments
|
||||
notificationSettings:
|
||||
groupBy:
|
||||
- deployment.environment
|
||||
- deployment.environment.name
|
||||
renotify:
|
||||
alertStates:
|
||||
- firing
|
||||
@@ -18869,7 +18994,7 @@ paths:
|
||||
alertType: LOGS_BASED_ALERT
|
||||
annotations:
|
||||
description: '{{$k8s.pod.name}} emitted {{$value}} panic log(s)
|
||||
in {{$deployment.environment}}.'
|
||||
in {{$deployment.environment.name}}.'
|
||||
summary: Payments service panic
|
||||
condition:
|
||||
compositeQuery:
|
||||
@@ -18887,8 +19012,8 @@ paths:
|
||||
name: k8s.pod.name
|
||||
- fieldContext: resource
|
||||
fieldDataType: string
|
||||
name: deployment.environment
|
||||
legend: '{{k8s.pod.name}} ({{deployment.environment}})'
|
||||
name: deployment.environment.name
|
||||
legend: '{{k8s.pod.name}} ({{deployment.environment.name}})'
|
||||
name: A
|
||||
signal: logs
|
||||
stepInterval: 60
|
||||
@@ -18917,7 +19042,7 @@ paths:
|
||||
notificationSettings:
|
||||
groupBy:
|
||||
- k8s.pod.name
|
||||
- deployment.environment
|
||||
- deployment.environment.name
|
||||
renotify:
|
||||
alertStates:
|
||||
- firing
|
||||
@@ -18987,8 +19112,9 @@ paths:
|
||||
version: v5
|
||||
metric_promql:
|
||||
description: PromQL expression instead of the builder. Dotted OTEL
|
||||
resource attributes are quoted ("deployment.environment"). Useful
|
||||
for queries that combine series with group_right or other Prom operators.
|
||||
resource attributes are quoted ("deployment.environment.name").
|
||||
Useful for queries that combine series with group_right or other
|
||||
Prom operators.
|
||||
summary: Metric threshold PromQL rule
|
||||
value:
|
||||
alert: Kafka consumer group lag above 1000
|
||||
@@ -19004,9 +19130,9 @@ paths:
|
||||
- spec:
|
||||
legend: '{{topic}}/{{partition}} ({{group}})'
|
||||
name: A
|
||||
query: (max by(topic, partition, "deployment.environment")(kafka_log_end_offset)
|
||||
- on(topic, partition, "deployment.environment") group_right
|
||||
max by(group, topic, partition, "deployment.environment")(kafka_consumer_committed_offset))
|
||||
query: (max by(topic, partition, "deployment.environment.name")(kafka_log_end_offset)
|
||||
- on(topic, partition, "deployment.environment.name")
|
||||
group_right max by(group, topic, partition, "deployment.environment.name")(kafka_consumer_committed_offset))
|
||||
> 0
|
||||
type: promql
|
||||
queryType: promql
|
||||
@@ -19142,7 +19268,7 @@ paths:
|
||||
alertType: METRIC_BASED_ALERT
|
||||
annotations:
|
||||
description: Pod {{$k8s.pod.name}} CPU is at {{$value}} of request
|
||||
in {{$deployment.environment}}.
|
||||
in {{$deployment.environment.name}}.
|
||||
summary: Pod CPU above {{$threshold}} of request
|
||||
condition:
|
||||
compositeQuery:
|
||||
@@ -19161,8 +19287,8 @@ paths:
|
||||
name: k8s.pod.name
|
||||
- fieldContext: resource
|
||||
fieldDataType: string
|
||||
name: deployment.environment
|
||||
legend: '{{k8s.pod.name}} ({{deployment.environment}})'
|
||||
name: deployment.environment.name
|
||||
legend: '{{k8s.pod.name}} ({{deployment.environment.name}})'
|
||||
name: A
|
||||
signal: metrics
|
||||
stepInterval: 60
|
||||
@@ -19193,7 +19319,7 @@ paths:
|
||||
notificationSettings:
|
||||
groupBy:
|
||||
- k8s.pod.name
|
||||
- deployment.environment
|
||||
- deployment.environment.name
|
||||
renotify:
|
||||
alertStates:
|
||||
- firing
|
||||
@@ -19217,7 +19343,7 @@ paths:
|
||||
alert: API 5xx error rate above 1%
|
||||
alertType: TRACES_BASED_ALERT
|
||||
annotations:
|
||||
description: '{{$service.name}} 5xx rate in {{$deployment.environment}}
|
||||
description: '{{$service.name}} 5xx rate in {{$deployment.environment.name}}
|
||||
is {{$value}}%.'
|
||||
summary: API service error rate elevated
|
||||
condition:
|
||||
@@ -19229,7 +19355,7 @@ paths:
|
||||
- expression: count()
|
||||
disabled: true
|
||||
filter:
|
||||
expression: service.name CONTAINS 'api' AND http.status_code
|
||||
expression: service.name CONTAINS 'api' AND http.response.status_code
|
||||
>= 500
|
||||
groupBy:
|
||||
- fieldContext: resource
|
||||
@@ -19237,7 +19363,7 @@ paths:
|
||||
name: service.name
|
||||
- fieldContext: resource
|
||||
fieldDataType: string
|
||||
name: deployment.environment
|
||||
name: deployment.environment.name
|
||||
name: A
|
||||
signal: traces
|
||||
stepInterval: 60
|
||||
@@ -19254,14 +19380,14 @@ paths:
|
||||
name: service.name
|
||||
- fieldContext: resource
|
||||
fieldDataType: string
|
||||
name: deployment.environment
|
||||
name: deployment.environment.name
|
||||
name: B
|
||||
signal: traces
|
||||
stepInterval: 60
|
||||
type: builder_query
|
||||
- spec:
|
||||
expression: (A / B) * 100
|
||||
legend: '{{service.name}} ({{deployment.environment}})'
|
||||
legend: '{{service.name}} ({{deployment.environment.name}})'
|
||||
name: F1
|
||||
type: builder_formula
|
||||
queryType: builder
|
||||
@@ -19289,7 +19415,7 @@ paths:
|
||||
notificationSettings:
|
||||
groupBy:
|
||||
- service.name
|
||||
- deployment.environment
|
||||
- deployment.environment.name
|
||||
newGroupEvalDelay: 2m
|
||||
renotify:
|
||||
alertStates:
|
||||
@@ -19735,8 +19861,8 @@ paths:
|
||||
alert: Payments-api error log rate above 1%
|
||||
alertType: LOGS_BASED_ALERT
|
||||
annotations:
|
||||
description: Error log rate in {{$deployment.environment}} is
|
||||
{{$value}}%
|
||||
description: Error log rate in {{$deployment.environment.name}}
|
||||
is {{$value}}%
|
||||
summary: Payments-api error rate above {{$threshold}}%
|
||||
condition:
|
||||
compositeQuery:
|
||||
@@ -19752,7 +19878,7 @@ paths:
|
||||
groupBy:
|
||||
- fieldContext: resource
|
||||
fieldDataType: string
|
||||
name: deployment.environment
|
||||
name: deployment.environment.name
|
||||
name: A
|
||||
signal: logs
|
||||
stepInterval: 60
|
||||
@@ -19766,14 +19892,14 @@ paths:
|
||||
groupBy:
|
||||
- fieldContext: resource
|
||||
fieldDataType: string
|
||||
name: deployment.environment
|
||||
name: deployment.environment.name
|
||||
name: B
|
||||
signal: logs
|
||||
stepInterval: 60
|
||||
type: builder_query
|
||||
- spec:
|
||||
expression: (A / B) * 100
|
||||
legend: '{{deployment.environment}}'
|
||||
legend: '{{deployment.environment.name}}'
|
||||
name: F1
|
||||
type: builder_formula
|
||||
queryType: builder
|
||||
@@ -19799,7 +19925,7 @@ paths:
|
||||
team: payments
|
||||
notificationSettings:
|
||||
groupBy:
|
||||
- deployment.environment
|
||||
- deployment.environment.name
|
||||
renotify:
|
||||
alertStates:
|
||||
- firing
|
||||
@@ -19818,7 +19944,7 @@ paths:
|
||||
alertType: LOGS_BASED_ALERT
|
||||
annotations:
|
||||
description: '{{$k8s.pod.name}} emitted {{$value}} panic log(s)
|
||||
in {{$deployment.environment}}.'
|
||||
in {{$deployment.environment.name}}.'
|
||||
summary: Payments service panic
|
||||
condition:
|
||||
compositeQuery:
|
||||
@@ -19836,8 +19962,8 @@ paths:
|
||||
name: k8s.pod.name
|
||||
- fieldContext: resource
|
||||
fieldDataType: string
|
||||
name: deployment.environment
|
||||
legend: '{{k8s.pod.name}} ({{deployment.environment}})'
|
||||
name: deployment.environment.name
|
||||
legend: '{{k8s.pod.name}} ({{deployment.environment.name}})'
|
||||
name: A
|
||||
signal: logs
|
||||
stepInterval: 60
|
||||
@@ -19866,7 +19992,7 @@ paths:
|
||||
notificationSettings:
|
||||
groupBy:
|
||||
- k8s.pod.name
|
||||
- deployment.environment
|
||||
- deployment.environment.name
|
||||
renotify:
|
||||
alertStates:
|
||||
- firing
|
||||
@@ -19936,8 +20062,9 @@ paths:
|
||||
version: v5
|
||||
metric_promql:
|
||||
description: PromQL expression instead of the builder. Dotted OTEL
|
||||
resource attributes are quoted ("deployment.environment"). Useful
|
||||
for queries that combine series with group_right or other Prom operators.
|
||||
resource attributes are quoted ("deployment.environment.name").
|
||||
Useful for queries that combine series with group_right or other
|
||||
Prom operators.
|
||||
summary: Metric threshold PromQL rule
|
||||
value:
|
||||
alert: Kafka consumer group lag above 1000
|
||||
@@ -19953,9 +20080,9 @@ paths:
|
||||
- spec:
|
||||
legend: '{{topic}}/{{partition}} ({{group}})'
|
||||
name: A
|
||||
query: (max by(topic, partition, "deployment.environment")(kafka_log_end_offset)
|
||||
- on(topic, partition, "deployment.environment") group_right
|
||||
max by(group, topic, partition, "deployment.environment")(kafka_consumer_committed_offset))
|
||||
query: (max by(topic, partition, "deployment.environment.name")(kafka_log_end_offset)
|
||||
- on(topic, partition, "deployment.environment.name")
|
||||
group_right max by(group, topic, partition, "deployment.environment.name")(kafka_consumer_committed_offset))
|
||||
> 0
|
||||
type: promql
|
||||
queryType: promql
|
||||
@@ -20091,7 +20218,7 @@ paths:
|
||||
alertType: METRIC_BASED_ALERT
|
||||
annotations:
|
||||
description: Pod {{$k8s.pod.name}} CPU is at {{$value}} of request
|
||||
in {{$deployment.environment}}.
|
||||
in {{$deployment.environment.name}}.
|
||||
summary: Pod CPU above {{$threshold}} of request
|
||||
condition:
|
||||
compositeQuery:
|
||||
@@ -20110,8 +20237,8 @@ paths:
|
||||
name: k8s.pod.name
|
||||
- fieldContext: resource
|
||||
fieldDataType: string
|
||||
name: deployment.environment
|
||||
legend: '{{k8s.pod.name}} ({{deployment.environment}})'
|
||||
name: deployment.environment.name
|
||||
legend: '{{k8s.pod.name}} ({{deployment.environment.name}})'
|
||||
name: A
|
||||
signal: metrics
|
||||
stepInterval: 60
|
||||
@@ -20142,7 +20269,7 @@ paths:
|
||||
notificationSettings:
|
||||
groupBy:
|
||||
- k8s.pod.name
|
||||
- deployment.environment
|
||||
- deployment.environment.name
|
||||
renotify:
|
||||
alertStates:
|
||||
- firing
|
||||
@@ -20166,7 +20293,7 @@ paths:
|
||||
alert: API 5xx error rate above 1%
|
||||
alertType: TRACES_BASED_ALERT
|
||||
annotations:
|
||||
description: '{{$service.name}} 5xx rate in {{$deployment.environment}}
|
||||
description: '{{$service.name}} 5xx rate in {{$deployment.environment.name}}
|
||||
is {{$value}}%.'
|
||||
summary: API service error rate elevated
|
||||
condition:
|
||||
@@ -20178,7 +20305,7 @@ paths:
|
||||
- expression: count()
|
||||
disabled: true
|
||||
filter:
|
||||
expression: service.name CONTAINS 'api' AND http.status_code
|
||||
expression: service.name CONTAINS 'api' AND http.response.status_code
|
||||
>= 500
|
||||
groupBy:
|
||||
- fieldContext: resource
|
||||
@@ -20186,7 +20313,7 @@ paths:
|
||||
name: service.name
|
||||
- fieldContext: resource
|
||||
fieldDataType: string
|
||||
name: deployment.environment
|
||||
name: deployment.environment.name
|
||||
name: A
|
||||
signal: traces
|
||||
stepInterval: 60
|
||||
@@ -20203,14 +20330,14 @@ paths:
|
||||
name: service.name
|
||||
- fieldContext: resource
|
||||
fieldDataType: string
|
||||
name: deployment.environment
|
||||
name: deployment.environment.name
|
||||
name: B
|
||||
signal: traces
|
||||
stepInterval: 60
|
||||
type: builder_query
|
||||
- spec:
|
||||
expression: (A / B) * 100
|
||||
legend: '{{service.name}} ({{deployment.environment}})'
|
||||
legend: '{{service.name}} ({{deployment.environment.name}})'
|
||||
name: F1
|
||||
type: builder_formula
|
||||
queryType: builder
|
||||
@@ -20238,7 +20365,7 @@ paths:
|
||||
notificationSettings:
|
||||
groupBy:
|
||||
- service.name
|
||||
- deployment.environment
|
||||
- deployment.environment.name
|
||||
newGroupEvalDelay: 2m
|
||||
renotify:
|
||||
alertStates:
|
||||
@@ -20587,8 +20714,8 @@ paths:
|
||||
alert: Payments-api error log rate above 1%
|
||||
alertType: LOGS_BASED_ALERT
|
||||
annotations:
|
||||
description: Error log rate in {{$deployment.environment}} is
|
||||
{{$value}}%
|
||||
description: Error log rate in {{$deployment.environment.name}}
|
||||
is {{$value}}%
|
||||
summary: Payments-api error rate above {{$threshold}}%
|
||||
condition:
|
||||
compositeQuery:
|
||||
@@ -20604,7 +20731,7 @@ paths:
|
||||
groupBy:
|
||||
- fieldContext: resource
|
||||
fieldDataType: string
|
||||
name: deployment.environment
|
||||
name: deployment.environment.name
|
||||
name: A
|
||||
signal: logs
|
||||
stepInterval: 60
|
||||
@@ -20618,14 +20745,14 @@ paths:
|
||||
groupBy:
|
||||
- fieldContext: resource
|
||||
fieldDataType: string
|
||||
name: deployment.environment
|
||||
name: deployment.environment.name
|
||||
name: B
|
||||
signal: logs
|
||||
stepInterval: 60
|
||||
type: builder_query
|
||||
- spec:
|
||||
expression: (A / B) * 100
|
||||
legend: '{{deployment.environment}}'
|
||||
legend: '{{deployment.environment.name}}'
|
||||
name: F1
|
||||
type: builder_formula
|
||||
queryType: builder
|
||||
@@ -20651,7 +20778,7 @@ paths:
|
||||
team: payments
|
||||
notificationSettings:
|
||||
groupBy:
|
||||
- deployment.environment
|
||||
- deployment.environment.name
|
||||
renotify:
|
||||
alertStates:
|
||||
- firing
|
||||
@@ -20670,7 +20797,7 @@ paths:
|
||||
alertType: LOGS_BASED_ALERT
|
||||
annotations:
|
||||
description: '{{$k8s.pod.name}} emitted {{$value}} panic log(s)
|
||||
in {{$deployment.environment}}.'
|
||||
in {{$deployment.environment.name}}.'
|
||||
summary: Payments service panic
|
||||
condition:
|
||||
compositeQuery:
|
||||
@@ -20688,8 +20815,8 @@ paths:
|
||||
name: k8s.pod.name
|
||||
- fieldContext: resource
|
||||
fieldDataType: string
|
||||
name: deployment.environment
|
||||
legend: '{{k8s.pod.name}} ({{deployment.environment}})'
|
||||
name: deployment.environment.name
|
||||
legend: '{{k8s.pod.name}} ({{deployment.environment.name}})'
|
||||
name: A
|
||||
signal: logs
|
||||
stepInterval: 60
|
||||
@@ -20718,7 +20845,7 @@ paths:
|
||||
notificationSettings:
|
||||
groupBy:
|
||||
- k8s.pod.name
|
||||
- deployment.environment
|
||||
- deployment.environment.name
|
||||
renotify:
|
||||
alertStates:
|
||||
- firing
|
||||
@@ -20788,8 +20915,9 @@ paths:
|
||||
version: v5
|
||||
metric_promql:
|
||||
description: PromQL expression instead of the builder. Dotted OTEL
|
||||
resource attributes are quoted ("deployment.environment"). Useful
|
||||
for queries that combine series with group_right or other Prom operators.
|
||||
resource attributes are quoted ("deployment.environment.name").
|
||||
Useful for queries that combine series with group_right or other
|
||||
Prom operators.
|
||||
summary: Metric threshold PromQL rule
|
||||
value:
|
||||
alert: Kafka consumer group lag above 1000
|
||||
@@ -20805,9 +20933,9 @@ paths:
|
||||
- spec:
|
||||
legend: '{{topic}}/{{partition}} ({{group}})'
|
||||
name: A
|
||||
query: (max by(topic, partition, "deployment.environment")(kafka_log_end_offset)
|
||||
- on(topic, partition, "deployment.environment") group_right
|
||||
max by(group, topic, partition, "deployment.environment")(kafka_consumer_committed_offset))
|
||||
query: (max by(topic, partition, "deployment.environment.name")(kafka_log_end_offset)
|
||||
- on(topic, partition, "deployment.environment.name")
|
||||
group_right max by(group, topic, partition, "deployment.environment.name")(kafka_consumer_committed_offset))
|
||||
> 0
|
||||
type: promql
|
||||
queryType: promql
|
||||
@@ -20943,7 +21071,7 @@ paths:
|
||||
alertType: METRIC_BASED_ALERT
|
||||
annotations:
|
||||
description: Pod {{$k8s.pod.name}} CPU is at {{$value}} of request
|
||||
in {{$deployment.environment}}.
|
||||
in {{$deployment.environment.name}}.
|
||||
summary: Pod CPU above {{$threshold}} of request
|
||||
condition:
|
||||
compositeQuery:
|
||||
@@ -20962,8 +21090,8 @@ paths:
|
||||
name: k8s.pod.name
|
||||
- fieldContext: resource
|
||||
fieldDataType: string
|
||||
name: deployment.environment
|
||||
legend: '{{k8s.pod.name}} ({{deployment.environment}})'
|
||||
name: deployment.environment.name
|
||||
legend: '{{k8s.pod.name}} ({{deployment.environment.name}})'
|
||||
name: A
|
||||
signal: metrics
|
||||
stepInterval: 60
|
||||
@@ -20994,7 +21122,7 @@ paths:
|
||||
notificationSettings:
|
||||
groupBy:
|
||||
- k8s.pod.name
|
||||
- deployment.environment
|
||||
- deployment.environment.name
|
||||
renotify:
|
||||
alertStates:
|
||||
- firing
|
||||
@@ -21018,7 +21146,7 @@ paths:
|
||||
alert: API 5xx error rate above 1%
|
||||
alertType: TRACES_BASED_ALERT
|
||||
annotations:
|
||||
description: '{{$service.name}} 5xx rate in {{$deployment.environment}}
|
||||
description: '{{$service.name}} 5xx rate in {{$deployment.environment.name}}
|
||||
is {{$value}}%.'
|
||||
summary: API service error rate elevated
|
||||
condition:
|
||||
@@ -21030,7 +21158,7 @@ paths:
|
||||
- expression: count()
|
||||
disabled: true
|
||||
filter:
|
||||
expression: service.name CONTAINS 'api' AND http.status_code
|
||||
expression: service.name CONTAINS 'api' AND http.response.status_code
|
||||
>= 500
|
||||
groupBy:
|
||||
- fieldContext: resource
|
||||
@@ -21038,7 +21166,7 @@ paths:
|
||||
name: service.name
|
||||
- fieldContext: resource
|
||||
fieldDataType: string
|
||||
name: deployment.environment
|
||||
name: deployment.environment.name
|
||||
name: A
|
||||
signal: traces
|
||||
stepInterval: 60
|
||||
@@ -21055,14 +21183,14 @@ paths:
|
||||
name: service.name
|
||||
- fieldContext: resource
|
||||
fieldDataType: string
|
||||
name: deployment.environment
|
||||
name: deployment.environment.name
|
||||
name: B
|
||||
signal: traces
|
||||
stepInterval: 60
|
||||
type: builder_query
|
||||
- spec:
|
||||
expression: (A / B) * 100
|
||||
legend: '{{service.name}} ({{deployment.environment}})'
|
||||
legend: '{{service.name}} ({{deployment.environment.name}})'
|
||||
name: F1
|
||||
type: builder_formula
|
||||
queryType: builder
|
||||
@@ -21090,7 +21218,7 @@ paths:
|
||||
notificationSettings:
|
||||
groupBy:
|
||||
- service.name
|
||||
- deployment.environment
|
||||
- deployment.environment.name
|
||||
newGroupEvalDelay: 2m
|
||||
renotify:
|
||||
alertStates:
|
||||
@@ -21942,8 +22070,8 @@ paths:
|
||||
alert: Payments-api error log rate above 1%
|
||||
alertType: LOGS_BASED_ALERT
|
||||
annotations:
|
||||
description: Error log rate in {{$deployment.environment}} is
|
||||
{{$value}}%
|
||||
description: Error log rate in {{$deployment.environment.name}}
|
||||
is {{$value}}%
|
||||
summary: Payments-api error rate above {{$threshold}}%
|
||||
condition:
|
||||
compositeQuery:
|
||||
@@ -21959,7 +22087,7 @@ paths:
|
||||
groupBy:
|
||||
- fieldContext: resource
|
||||
fieldDataType: string
|
||||
name: deployment.environment
|
||||
name: deployment.environment.name
|
||||
name: A
|
||||
signal: logs
|
||||
stepInterval: 60
|
||||
@@ -21973,14 +22101,14 @@ paths:
|
||||
groupBy:
|
||||
- fieldContext: resource
|
||||
fieldDataType: string
|
||||
name: deployment.environment
|
||||
name: deployment.environment.name
|
||||
name: B
|
||||
signal: logs
|
||||
stepInterval: 60
|
||||
type: builder_query
|
||||
- spec:
|
||||
expression: (A / B) * 100
|
||||
legend: '{{deployment.environment}}'
|
||||
legend: '{{deployment.environment.name}}'
|
||||
name: F1
|
||||
type: builder_formula
|
||||
queryType: builder
|
||||
@@ -22006,7 +22134,7 @@ paths:
|
||||
team: payments
|
||||
notificationSettings:
|
||||
groupBy:
|
||||
- deployment.environment
|
||||
- deployment.environment.name
|
||||
renotify:
|
||||
alertStates:
|
||||
- firing
|
||||
@@ -22025,7 +22153,7 @@ paths:
|
||||
alertType: LOGS_BASED_ALERT
|
||||
annotations:
|
||||
description: '{{$k8s.pod.name}} emitted {{$value}} panic log(s)
|
||||
in {{$deployment.environment}}.'
|
||||
in {{$deployment.environment.name}}.'
|
||||
summary: Payments service panic
|
||||
condition:
|
||||
compositeQuery:
|
||||
@@ -22043,8 +22171,8 @@ paths:
|
||||
name: k8s.pod.name
|
||||
- fieldContext: resource
|
||||
fieldDataType: string
|
||||
name: deployment.environment
|
||||
legend: '{{k8s.pod.name}} ({{deployment.environment}})'
|
||||
name: deployment.environment.name
|
||||
legend: '{{k8s.pod.name}} ({{deployment.environment.name}})'
|
||||
name: A
|
||||
signal: logs
|
||||
stepInterval: 60
|
||||
@@ -22073,7 +22201,7 @@ paths:
|
||||
notificationSettings:
|
||||
groupBy:
|
||||
- k8s.pod.name
|
||||
- deployment.environment
|
||||
- deployment.environment.name
|
||||
renotify:
|
||||
alertStates:
|
||||
- firing
|
||||
@@ -22143,8 +22271,9 @@ paths:
|
||||
version: v5
|
||||
metric_promql:
|
||||
description: PromQL expression instead of the builder. Dotted OTEL
|
||||
resource attributes are quoted ("deployment.environment"). Useful
|
||||
for queries that combine series with group_right or other Prom operators.
|
||||
resource attributes are quoted ("deployment.environment.name").
|
||||
Useful for queries that combine series with group_right or other
|
||||
Prom operators.
|
||||
summary: Metric threshold PromQL rule
|
||||
value:
|
||||
alert: Kafka consumer group lag above 1000
|
||||
@@ -22160,9 +22289,9 @@ paths:
|
||||
- spec:
|
||||
legend: '{{topic}}/{{partition}} ({{group}})'
|
||||
name: A
|
||||
query: (max by(topic, partition, "deployment.environment")(kafka_log_end_offset)
|
||||
- on(topic, partition, "deployment.environment") group_right
|
||||
max by(group, topic, partition, "deployment.environment")(kafka_consumer_committed_offset))
|
||||
query: (max by(topic, partition, "deployment.environment.name")(kafka_log_end_offset)
|
||||
- on(topic, partition, "deployment.environment.name")
|
||||
group_right max by(group, topic, partition, "deployment.environment.name")(kafka_consumer_committed_offset))
|
||||
> 0
|
||||
type: promql
|
||||
queryType: promql
|
||||
@@ -22298,7 +22427,7 @@ paths:
|
||||
alertType: METRIC_BASED_ALERT
|
||||
annotations:
|
||||
description: Pod {{$k8s.pod.name}} CPU is at {{$value}} of request
|
||||
in {{$deployment.environment}}.
|
||||
in {{$deployment.environment.name}}.
|
||||
summary: Pod CPU above {{$threshold}} of request
|
||||
condition:
|
||||
compositeQuery:
|
||||
@@ -22317,8 +22446,8 @@ paths:
|
||||
name: k8s.pod.name
|
||||
- fieldContext: resource
|
||||
fieldDataType: string
|
||||
name: deployment.environment
|
||||
legend: '{{k8s.pod.name}} ({{deployment.environment}})'
|
||||
name: deployment.environment.name
|
||||
legend: '{{k8s.pod.name}} ({{deployment.environment.name}})'
|
||||
name: A
|
||||
signal: metrics
|
||||
stepInterval: 60
|
||||
@@ -22349,7 +22478,7 @@ paths:
|
||||
notificationSettings:
|
||||
groupBy:
|
||||
- k8s.pod.name
|
||||
- deployment.environment
|
||||
- deployment.environment.name
|
||||
renotify:
|
||||
alertStates:
|
||||
- firing
|
||||
@@ -22373,7 +22502,7 @@ paths:
|
||||
alert: API 5xx error rate above 1%
|
||||
alertType: TRACES_BASED_ALERT
|
||||
annotations:
|
||||
description: '{{$service.name}} 5xx rate in {{$deployment.environment}}
|
||||
description: '{{$service.name}} 5xx rate in {{$deployment.environment.name}}
|
||||
is {{$value}}%.'
|
||||
summary: API service error rate elevated
|
||||
condition:
|
||||
@@ -22385,7 +22514,7 @@ paths:
|
||||
- expression: count()
|
||||
disabled: true
|
||||
filter:
|
||||
expression: service.name CONTAINS 'api' AND http.status_code
|
||||
expression: service.name CONTAINS 'api' AND http.response.status_code
|
||||
>= 500
|
||||
groupBy:
|
||||
- fieldContext: resource
|
||||
@@ -22393,7 +22522,7 @@ paths:
|
||||
name: service.name
|
||||
- fieldContext: resource
|
||||
fieldDataType: string
|
||||
name: deployment.environment
|
||||
name: deployment.environment.name
|
||||
name: A
|
||||
signal: traces
|
||||
stepInterval: 60
|
||||
@@ -22410,14 +22539,14 @@ paths:
|
||||
name: service.name
|
||||
- fieldContext: resource
|
||||
fieldDataType: string
|
||||
name: deployment.environment
|
||||
name: deployment.environment.name
|
||||
name: B
|
||||
signal: traces
|
||||
stepInterval: 60
|
||||
type: builder_query
|
||||
- spec:
|
||||
expression: (A / B) * 100
|
||||
legend: '{{service.name}} ({{deployment.environment}})'
|
||||
legend: '{{service.name}} ({{deployment.environment.name}})'
|
||||
name: F1
|
||||
type: builder_formula
|
||||
queryType: builder
|
||||
@@ -22445,7 +22574,7 @@ paths:
|
||||
notificationSettings:
|
||||
groupBy:
|
||||
- service.name
|
||||
- deployment.environment
|
||||
- deployment.environment.name
|
||||
newGroupEvalDelay: 2m
|
||||
renotify:
|
||||
alertStates:
|
||||
|
||||
@@ -176,7 +176,7 @@ func (m *module) Create(ctx context.Context, orgID valuer.UUID, userEmail string
|
||||
if err := m.checkAccess(ctx, orgID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := req.Validate(); err != nil {
|
||||
if err := metricreductionrule.ValidatePostableReductionRule(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := m.validateMetricForReduction(ctx, orgID, req.MetricName); err != nil {
|
||||
@@ -218,7 +218,7 @@ func (m *module) UpdateByID(ctx context.Context, orgID valuer.UUID, userEmail st
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := req.Validate(); err != nil {
|
||||
if err := metricreductionrule.ValidateUpdatableReductionRule(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -543,7 +543,7 @@ func resolveDroppedKept(matchType metricreductionruletypes.MatchType, ruleLabels
|
||||
}
|
||||
|
||||
for _, k := range keys {
|
||||
if metricreductionruletypes.IsProtectedLabel(k) {
|
||||
if metricreductionrule.IsProtectedLabel(k) {
|
||||
kept = append(kept, k)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ import type {
|
||||
GetFieldsKeysParams,
|
||||
GetFieldsValues200,
|
||||
GetFieldsValuesParams,
|
||||
GetSemconvMigrationReport200,
|
||||
GetSemconvMigrationReportParams,
|
||||
RenderErrorResponseDTO,
|
||||
} from '../sigNoz.schemas';
|
||||
|
||||
@@ -120,6 +122,108 @@ export const invalidateGetFieldsKeys = async (
|
||||
return queryClient;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns services that still emit old semantic-convention names without the current family name
|
||||
* @summary Get semantic-convention migration report
|
||||
*/
|
||||
export const getSemconvMigrationReport = (
|
||||
params?: GetSemconvMigrationReportParams,
|
||||
signal?: AbortSignal,
|
||||
) => {
|
||||
return GeneratedAPIInstance<GetSemconvMigrationReport200>({
|
||||
url: `/api/v1/fields/semconv-migration`,
|
||||
method: 'GET',
|
||||
params,
|
||||
signal,
|
||||
});
|
||||
};
|
||||
|
||||
export const getGetSemconvMigrationReportQueryKey = (
|
||||
params?: GetSemconvMigrationReportParams,
|
||||
) => {
|
||||
return [
|
||||
`/api/v1/fields/semconv-migration`,
|
||||
...(params ? [params] : []),
|
||||
] as const;
|
||||
};
|
||||
|
||||
export const getGetSemconvMigrationReportQueryOptions = <
|
||||
TData = Awaited<ReturnType<typeof getSemconvMigrationReport>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
>(
|
||||
params?: GetSemconvMigrationReportParams,
|
||||
options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getSemconvMigrationReport>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
},
|
||||
) => {
|
||||
const { query: queryOptions } = options ?? {};
|
||||
|
||||
const queryKey =
|
||||
queryOptions?.queryKey ?? getGetSemconvMigrationReportQueryKey(params);
|
||||
|
||||
const queryFn: QueryFunction<
|
||||
Awaited<ReturnType<typeof getSemconvMigrationReport>>
|
||||
> = ({ signal }) => getSemconvMigrationReport(params, signal);
|
||||
|
||||
return { queryKey, queryFn, ...queryOptions } as UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getSemconvMigrationReport>>,
|
||||
TError,
|
||||
TData
|
||||
> & { queryKey: QueryKey };
|
||||
};
|
||||
|
||||
export type GetSemconvMigrationReportQueryResult = NonNullable<
|
||||
Awaited<ReturnType<typeof getSemconvMigrationReport>>
|
||||
>;
|
||||
export type GetSemconvMigrationReportQueryError =
|
||||
ErrorType<RenderErrorResponseDTO>;
|
||||
|
||||
/**
|
||||
* @summary Get semantic-convention migration report
|
||||
*/
|
||||
|
||||
export function useGetSemconvMigrationReport<
|
||||
TData = Awaited<ReturnType<typeof getSemconvMigrationReport>>,
|
||||
TError = ErrorType<RenderErrorResponseDTO>,
|
||||
>(
|
||||
params?: GetSemconvMigrationReportParams,
|
||||
options?: {
|
||||
query?: UseQueryOptions<
|
||||
Awaited<ReturnType<typeof getSemconvMigrationReport>>,
|
||||
TError,
|
||||
TData
|
||||
>;
|
||||
},
|
||||
): UseQueryResult<TData, TError> & { queryKey: QueryKey } {
|
||||
const queryOptions = getGetSemconvMigrationReportQueryOptions(params, options);
|
||||
|
||||
const query = useQuery(queryOptions) as UseQueryResult<TData, TError> & {
|
||||
queryKey: QueryKey;
|
||||
};
|
||||
|
||||
return { ...query, queryKey: queryOptions.queryKey };
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Get semantic-convention migration report
|
||||
*/
|
||||
export const invalidateGetSemconvMigrationReport = async (
|
||||
queryClient: QueryClient,
|
||||
params?: GetSemconvMigrationReportParams,
|
||||
options?: InvalidateOptions,
|
||||
): Promise<QueryClient> => {
|
||||
await queryClient.invalidateQueries(
|
||||
{ queryKey: getGetSemconvMigrationReportQueryKey(params) },
|
||||
options,
|
||||
);
|
||||
|
||||
return queryClient;
|
||||
};
|
||||
|
||||
/**
|
||||
* This endpoint returns field values
|
||||
* @summary Get field values
|
||||
|
||||
@@ -3482,6 +3482,10 @@ export enum TelemetrytypesFieldDataTypeDTO {
|
||||
number = 'number',
|
||||
'' = '',
|
||||
}
|
||||
export enum TelemetrytypesFieldResolutionDTO {
|
||||
exact = 'exact',
|
||||
'' = '',
|
||||
}
|
||||
export enum TelemetrytypesSignalDTO {
|
||||
traces = 'traces',
|
||||
logs = 'logs',
|
||||
@@ -3495,6 +3499,7 @@ export interface Querybuildertypesv5GroupByKeyDTO {
|
||||
description?: string;
|
||||
fieldContext?: TelemetrytypesFieldContextDTO;
|
||||
fieldDataType?: TelemetrytypesFieldDataTypeDTO;
|
||||
fieldResolution?: TelemetrytypesFieldResolutionDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -3535,6 +3540,7 @@ export interface Querybuildertypesv5OrderByKeyDTO {
|
||||
description?: string;
|
||||
fieldContext?: TelemetrytypesFieldContextDTO;
|
||||
fieldDataType?: TelemetrytypesFieldDataTypeDTO;
|
||||
fieldResolution?: TelemetrytypesFieldResolutionDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -3588,6 +3594,7 @@ export interface TelemetrytypesTelemetryFieldKeyDTO {
|
||||
description?: string;
|
||||
fieldContext?: TelemetrytypesFieldContextDTO;
|
||||
fieldDataType?: TelemetrytypesFieldDataTypeDTO;
|
||||
fieldResolution?: TelemetrytypesFieldResolutionDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
@@ -7936,6 +7943,7 @@ export interface Querybuildertypesv5ColumnDescriptorDTO {
|
||||
description?: string;
|
||||
fieldContext?: TelemetrytypesFieldContextDTO;
|
||||
fieldDataType?: TelemetrytypesFieldDataTypeDTO;
|
||||
fieldResolution?: TelemetrytypesFieldResolutionDTO;
|
||||
/**
|
||||
* @type object
|
||||
*/
|
||||
@@ -7959,6 +7967,25 @@ export type Querybuildertypesv5ExecStatsDTOStepIntervals = {
|
||||
[key: string]: number;
|
||||
};
|
||||
|
||||
export interface Querybuildertypesv5SemconvResolutionDTO {
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
current?: string;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
kind?: string;
|
||||
/**
|
||||
* @type array,null
|
||||
*/
|
||||
members?: string[] | null;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
requested?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execution statistics for the query, including rows scanned, bytes scanned, and duration.
|
||||
*/
|
||||
@@ -7978,6 +8005,10 @@ export interface Querybuildertypesv5ExecStatsDTO {
|
||||
* @minimum 0
|
||||
*/
|
||||
rowsScanned?: number;
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
semconvResolutions?: Querybuildertypesv5SemconvResolutionDTO[];
|
||||
/**
|
||||
* @type object
|
||||
*/
|
||||
@@ -9816,6 +9847,52 @@ export interface TelemetrytypesGettableFieldValuesDTO {
|
||||
values: TelemetrytypesTelemetryFieldValuesDTO;
|
||||
}
|
||||
|
||||
export interface TelemetrytypesSemconvMigrationReportEntryDTO {
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
current?: string;
|
||||
/**
|
||||
* @type integer
|
||||
* @format int64
|
||||
*/
|
||||
lastSeenUnixMilli?: number;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
old?: string;
|
||||
/**
|
||||
* @type integer
|
||||
* @minimum 0
|
||||
*/
|
||||
resourceSets?: number;
|
||||
/**
|
||||
* @type array,null
|
||||
*/
|
||||
services?: string[] | null;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
signal?: string;
|
||||
}
|
||||
|
||||
export interface TelemetrytypesGettableSemconvMigrationReportDTO {
|
||||
/**
|
||||
* @type integer
|
||||
* @format int64
|
||||
*/
|
||||
endUnixMilli?: number;
|
||||
/**
|
||||
* @type array,null
|
||||
*/
|
||||
entries: TelemetrytypesSemconvMigrationReportEntryDTO[] | null;
|
||||
/**
|
||||
* @type integer
|
||||
* @format int64
|
||||
*/
|
||||
startUnixMilli?: number;
|
||||
}
|
||||
|
||||
export interface TypesChangePasswordRequestDTO {
|
||||
/**
|
||||
* @type string
|
||||
@@ -10582,6 +10659,29 @@ export type GetFieldsKeys200 = {
|
||||
status: string;
|
||||
};
|
||||
|
||||
export type GetSemconvMigrationReportParams = {
|
||||
/**
|
||||
* @type integer
|
||||
* @format int64
|
||||
* @description undefined
|
||||
*/
|
||||
startUnixMilli?: number;
|
||||
/**
|
||||
* @type integer
|
||||
* @format int64
|
||||
* @description undefined
|
||||
*/
|
||||
endUnixMilli?: number;
|
||||
};
|
||||
|
||||
export type GetSemconvMigrationReport200 = {
|
||||
data: TelemetrytypesGettableSemconvMigrationReportDTO;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
status: string;
|
||||
};
|
||||
|
||||
export type GetFieldsValuesParams = {
|
||||
/**
|
||||
* @description undefined
|
||||
|
||||
9
frontend/src/api/semconv/getMigrationReport.ts
Normal file
9
frontend/src/api/semconv/getMigrationReport.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import axios from 'api';
|
||||
import { SemconvMigrationReport } from 'types/api/semconvMigration';
|
||||
|
||||
async function getSemconvMigrationReport(): Promise<SemconvMigrationReport> {
|
||||
const response = await axios.get('/fields/semconv-migration');
|
||||
return response.data.data;
|
||||
}
|
||||
|
||||
export default getSemconvMigrationReport;
|
||||
@@ -64,12 +64,12 @@ export const COMMON_FILTERS = {
|
||||
SERVER_SPANS: "kind_string = 'Server'",
|
||||
CLIENT_SPANS: "kind_string = 'Client'",
|
||||
INTERNAL_SPANS: "kind_string = 'Internal'",
|
||||
ERROR_SPANS: 'http.status_code >= 400',
|
||||
SUCCESS_SPANS: 'http.status_code < 400',
|
||||
ERROR_SPANS: 'http.response.status_code >= 400',
|
||||
SUCCESS_SPANS: 'http.response.status_code < 400',
|
||||
|
||||
// Common service filters
|
||||
EXCLUDE_HEALTH_CHECKS: "http.route != '/health' AND http.route != '/ping'",
|
||||
HTTP_REQUESTS: "http.method != ''",
|
||||
HTTP_REQUESTS: "http.request.method != ''",
|
||||
|
||||
// Log filters
|
||||
ERROR_LOGS: "severity_text = 'ERROR'",
|
||||
@@ -87,7 +87,7 @@ export const COMMON_GROUP_BY_FIELDS = {
|
||||
fieldContext: 'resource' as const,
|
||||
},
|
||||
HTTP_METHOD: {
|
||||
name: 'http.method',
|
||||
name: 'http.request.method',
|
||||
fieldDataType: 'string' as const,
|
||||
fieldContext: 'attribute' as const,
|
||||
},
|
||||
@@ -97,7 +97,7 @@ export const COMMON_GROUP_BY_FIELDS = {
|
||||
fieldContext: 'attribute' as const,
|
||||
},
|
||||
HTTP_STATUS_CODE: {
|
||||
name: 'http.status_code',
|
||||
name: 'http.response.status_code',
|
||||
fieldDataType: 'int64' as const,
|
||||
fieldContext: 'attribute' as const,
|
||||
},
|
||||
|
||||
@@ -145,7 +145,7 @@ function CeleryOverviewConfigOptions(): JSX.Element {
|
||||
{
|
||||
placeholder: 'Destination',
|
||||
queryParam: QueryParams.destination,
|
||||
filterType: ['messaging.destination.name', 'messaging.destination'],
|
||||
filterType: ['messaging.destination.name'],
|
||||
},
|
||||
{
|
||||
placeholder: 'Kind',
|
||||
|
||||
@@ -1746,7 +1746,7 @@ QuerySearch.defaultProps = {
|
||||
signalSource: '',
|
||||
hardcodedAttributeKeys: undefined,
|
||||
placeholder:
|
||||
"Enter your filter query (e.g., http.status_code >= 500 AND service.name = 'frontend')",
|
||||
"Enter your filter query (e.g., http.response.status_code >= 500 AND service.name = 'frontend')",
|
||||
showFilterSuggestionsWithoutMetric: false,
|
||||
initialExpression: undefined,
|
||||
};
|
||||
|
||||
@@ -152,15 +152,18 @@ describe('QuerySearch (Integration with Real CodeMirror)', () => {
|
||||
/>,
|
||||
);
|
||||
|
||||
// Wait for debounced API call (300ms debounce + some buffer)
|
||||
await waitFor(() => expect(mockedGetKeysOnMount).toHaveBeenCalled(), {
|
||||
timeout: 2000,
|
||||
});
|
||||
|
||||
const lastArgs = mockedGetKeysOnMount.mock.calls[
|
||||
mockedGetKeysOnMount.mock.calls.length - 1
|
||||
]?.[0] as { signal: unknown; searchText: string };
|
||||
expect(lastArgs).toMatchObject({ signal: DataSource.LOGS, searchText: '' });
|
||||
// Wait for this mount's debounced call. A debounce from the preceding
|
||||
// real-CodeMirror test can finish after mockClear(), so do not assume the
|
||||
// first or last recorded call belongs to this render.
|
||||
await waitFor(
|
||||
() =>
|
||||
expect(
|
||||
mockedGetKeysOnMount.mock.calls.some(
|
||||
([args]) => args.signal === DataSource.LOGS && args.searchText === '',
|
||||
),
|
||||
).toBe(true),
|
||||
{ timeout: 2000 },
|
||||
);
|
||||
});
|
||||
|
||||
it('calls provided onRun on Mod-Enter', async () => {
|
||||
|
||||
@@ -995,6 +995,16 @@ describe('removeKeysFromExpression', () => {
|
||||
expect(result).toBe("status = 'success'");
|
||||
});
|
||||
|
||||
it('should remove a comparison that uses the exact field wrapper', () => {
|
||||
const expression =
|
||||
"exact(resource.deployment.environment) EXISTS AND service.name = 'api-gateway'";
|
||||
const result = removeKeysFromExpression(expression, [
|
||||
'resource.deployment.environment',
|
||||
]);
|
||||
|
||||
expect(result).toBe("service.name = 'api-gateway'");
|
||||
});
|
||||
|
||||
it('should remove multiple keys from expression', () => {
|
||||
const expression =
|
||||
"service.name = 'api-gateway' AND status = 'success' AND region = 'us-east-1'";
|
||||
|
||||
@@ -652,7 +652,16 @@ export const removeKeysFromExpression = (
|
||||
}
|
||||
|
||||
function visitComparison(ctx: ComparisonContext): string | null {
|
||||
const keyText = ctx.key().getText().trim().toLowerCase();
|
||||
const field = ctx.field();
|
||||
// The runtime returns null for the inactive field alternative even though
|
||||
// the generated TypeScript signature is non-nullable.
|
||||
const exactCall = field.exactCall() as unknown as ReturnType<
|
||||
typeof field.exactCall
|
||||
> | null;
|
||||
const keyText = (exactCall ? exactCall.key() : field.key())
|
||||
.getText()
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
|
||||
if (!keysSet.has(keyText)) {
|
||||
return src(ctx);
|
||||
|
||||
@@ -5,7 +5,7 @@ import { ArrowUpRight } from '@signozhq/icons';
|
||||
|
||||
const QUICK_FILTER_DOC_PATHS: Record<string, string> = {
|
||||
severity_text: 'severity-text',
|
||||
'deployment.environment': 'environment',
|
||||
'deployment.environment.name': 'environment',
|
||||
'service.name': 'service-name',
|
||||
'host.name': 'hostname',
|
||||
'k8s.cluster.name': 'k8s-cluster-name',
|
||||
|
||||
32
frontend/src/components/Semconv/SemconvEditorWarning.tsx
Normal file
32
frontend/src/components/Semconv/SemconvEditorWarning.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import { Alert } from 'antd';
|
||||
import { findOldSemconvNames } from 'utils/semconv';
|
||||
|
||||
interface SemconvEditorWarningProps {
|
||||
value: unknown;
|
||||
editor: string;
|
||||
}
|
||||
|
||||
function SemconvEditorWarning({
|
||||
value,
|
||||
editor,
|
||||
}: SemconvEditorWarningProps): JSX.Element | null {
|
||||
const text = typeof value === 'string' ? value : JSON.stringify(value ?? '');
|
||||
const renames = findOldSemconvNames(text);
|
||||
if (renames.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Alert
|
||||
type="warning"
|
||||
showIcon
|
||||
data-testid="semconv-editor-warning"
|
||||
message={`${editor} contains renamed OpenTelemetry fields`}
|
||||
description={renames
|
||||
.map(({ old, current }) => `${old} → ${current}`)
|
||||
.join(', ')}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default SemconvEditorWarning;
|
||||
23
frontend/src/components/Semconv/SemconvOldNameBadge.tsx
Normal file
23
frontend/src/components/Semconv/SemconvOldNameBadge.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import { Badge } from '@signozhq/ui/badge';
|
||||
import { getSemconvRename } from 'utils/semconv';
|
||||
|
||||
interface SemconvOldNameBadgeProps {
|
||||
name: string;
|
||||
}
|
||||
|
||||
function SemconvOldNameBadge({
|
||||
name,
|
||||
}: SemconvOldNameBadgeProps): JSX.Element | null {
|
||||
const rename = getSemconvRename(name);
|
||||
if (!rename || rename.family.kind !== 'attribute') {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Badge color="amber" variant="outline" data-testid="semconv-old-name-badge">
|
||||
old name, renamed to {rename.current}
|
||||
</Badge>
|
||||
);
|
||||
}
|
||||
|
||||
export default SemconvOldNameBadge;
|
||||
39
frontend/src/components/Semconv/__tests__/Semconv.test.tsx
Normal file
39
frontend/src/components/Semconv/__tests__/Semconv.test.tsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
|
||||
import SemconvEditorWarning from '../SemconvEditorWarning';
|
||||
import SemconvOldNameBadge from '../SemconvOldNameBadge';
|
||||
|
||||
describe('semantic convention product hints', () => {
|
||||
it('badges an old raw attribute with its current name', () => {
|
||||
render(<SemconvOldNameBadge name="deployment.environment" />);
|
||||
|
||||
expect(screen.getByTestId('semconv-old-name-badge')).toHaveTextContent(
|
||||
'old name, renamed to deployment.environment.name',
|
||||
);
|
||||
});
|
||||
|
||||
it('does not badge a current raw attribute', () => {
|
||||
render(<SemconvOldNameBadge name="deployment.environment.name" />);
|
||||
|
||||
expect(
|
||||
screen.queryByTestId('semconv-old-name-badge'),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows an informational editor warning without disabling the editor', () => {
|
||||
render(
|
||||
<>
|
||||
<input aria-label="query" defaultValue="db.system = 'postgresql'" />
|
||||
<SemconvEditorWarning
|
||||
value="db.system = 'postgresql'"
|
||||
editor="ClickHouse SQL"
|
||||
/>
|
||||
</>,
|
||||
);
|
||||
|
||||
expect(screen.getByLabelText('query')).not.toBeDisabled();
|
||||
expect(screen.getByTestId('semconv-editor-warning')).toHaveTextContent(
|
||||
'db.system → db.system.name',
|
||||
);
|
||||
});
|
||||
});
|
||||
2
frontend/src/components/Semconv/index.ts
Normal file
2
frontend/src/components/Semconv/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export { default as SemconvEditorWarning } from './SemconvEditorWarning';
|
||||
export { default as SemconvOldNameBadge } from './SemconvOldNameBadge';
|
||||
@@ -12,8 +12,8 @@ export type SemconvFamily = {
|
||||
|
||||
export const SEMCONV_FAMILIES: readonly SemconvFamily[] = [
|
||||
{
|
||||
current: 'db.system.name',
|
||||
old: ['db.system'],
|
||||
current: 'code.file.path',
|
||||
old: ['code.filepath'],
|
||||
kind: 'attribute',
|
||||
contexts: [],
|
||||
signals: [],
|
||||
@@ -21,12 +21,215 @@ export const SEMCONV_FAMILIES: readonly SemconvFamily[] = [
|
||||
valueMap: {},
|
||||
},
|
||||
{
|
||||
current: 'deployment.environment.name',
|
||||
old: ['deployment.environment'],
|
||||
current: 'code.function.name',
|
||||
old: ['code.function'],
|
||||
kind: 'attribute',
|
||||
contexts: [],
|
||||
signals: [],
|
||||
applyToMetrics: [],
|
||||
valueMap: {},
|
||||
},
|
||||
{
|
||||
current: 'code.line.number',
|
||||
old: ['code.lineno'],
|
||||
kind: 'attribute',
|
||||
contexts: [],
|
||||
signals: [],
|
||||
applyToMetrics: [],
|
||||
valueMap: {},
|
||||
},
|
||||
{
|
||||
current: 'container.cpu.usage',
|
||||
old: ['container.cpu.utilization'],
|
||||
kind: 'metric',
|
||||
contexts: ['metric'],
|
||||
signals: ['metrics'],
|
||||
applyToMetrics: [],
|
||||
valueMap: {},
|
||||
},
|
||||
{
|
||||
current: 'container.runtime.name',
|
||||
old: ['container.runtime'],
|
||||
kind: 'attribute',
|
||||
contexts: [],
|
||||
signals: [],
|
||||
applyToMetrics: [],
|
||||
valueMap: {},
|
||||
},
|
||||
{
|
||||
current: 'db.namespace',
|
||||
old: [
|
||||
'db.elasticsearch.cluster.name',
|
||||
'db.name',
|
||||
'db.cassandra.keyspace',
|
||||
'db.hbase.namespace',
|
||||
],
|
||||
kind: 'attribute',
|
||||
contexts: ['attribute'],
|
||||
signals: ['traces'],
|
||||
applyToMetrics: [],
|
||||
valueMap: {},
|
||||
},
|
||||
{
|
||||
current: 'db.operation.name',
|
||||
old: ['db.operation'],
|
||||
kind: 'attribute',
|
||||
contexts: ['attribute'],
|
||||
signals: ['traces'],
|
||||
applyToMetrics: [],
|
||||
valueMap: {},
|
||||
},
|
||||
{
|
||||
current: 'db.query.text',
|
||||
old: ['db.statement'],
|
||||
kind: 'attribute',
|
||||
contexts: ['attribute'],
|
||||
signals: ['traces'],
|
||||
applyToMetrics: [],
|
||||
valueMap: {},
|
||||
},
|
||||
{
|
||||
current: 'db.system.name',
|
||||
old: ['db.system'],
|
||||
kind: 'attribute',
|
||||
contexts: ['attribute', 'resource'],
|
||||
signals: ['logs', 'metrics', 'traces'],
|
||||
applyToMetrics: [],
|
||||
valueMap: {},
|
||||
},
|
||||
{
|
||||
current: 'deployment.environment.name',
|
||||
old: ['deployment.environment'],
|
||||
kind: 'attribute',
|
||||
contexts: ['attribute', 'resource'],
|
||||
signals: ['logs', 'metrics', 'traces'],
|
||||
applyToMetrics: [],
|
||||
valueMap: {},
|
||||
},
|
||||
{
|
||||
current: 'http.request.method',
|
||||
old: ['http.method'],
|
||||
kind: 'attribute',
|
||||
contexts: ['attribute'],
|
||||
signals: ['logs', 'traces'],
|
||||
applyToMetrics: [],
|
||||
valueMap: {},
|
||||
},
|
||||
{
|
||||
current: 'http.response.status_code',
|
||||
old: ['http.status_code'],
|
||||
kind: 'attribute',
|
||||
contexts: ['attribute'],
|
||||
signals: ['logs', 'traces'],
|
||||
applyToMetrics: [],
|
||||
valueMap: {},
|
||||
},
|
||||
{
|
||||
current: 'k8s.node.cpu.usage',
|
||||
old: ['k8s.node.cpu.utilization'],
|
||||
kind: 'metric',
|
||||
contexts: ['metric'],
|
||||
signals: ['metrics'],
|
||||
applyToMetrics: [],
|
||||
valueMap: {},
|
||||
},
|
||||
{
|
||||
current: 'k8s.pod.cpu.usage',
|
||||
old: ['k8s.pod.cpu.utilization'],
|
||||
kind: 'metric',
|
||||
contexts: ['metric'],
|
||||
signals: ['metrics'],
|
||||
applyToMetrics: [],
|
||||
valueMap: {},
|
||||
},
|
||||
{
|
||||
current: 'messaging.client.id',
|
||||
old: [
|
||||
'messaging.client_id',
|
||||
'messaging.kafka.client_id',
|
||||
'messaging.rocketmq.client_id',
|
||||
],
|
||||
kind: 'attribute',
|
||||
contexts: ['attribute'],
|
||||
signals: ['metrics', 'traces'],
|
||||
applyToMetrics: [],
|
||||
valueMap: {},
|
||||
},
|
||||
{
|
||||
current: 'messaging.consumer.group.name',
|
||||
old: [
|
||||
'messaging.eventhubs.consumer.group',
|
||||
'messaging.kafka.consumer.group',
|
||||
'messaging.rocketmq.client_group',
|
||||
'messaging.kafka.consumer_group',
|
||||
],
|
||||
kind: 'attribute',
|
||||
contexts: [],
|
||||
signals: [],
|
||||
applyToMetrics: [],
|
||||
valueMap: {},
|
||||
},
|
||||
{
|
||||
current: 'messaging.destination.name',
|
||||
old: ['messaging.destination'],
|
||||
kind: 'attribute',
|
||||
contexts: ['attribute'],
|
||||
signals: ['traces'],
|
||||
applyToMetrics: [],
|
||||
valueMap: {},
|
||||
},
|
||||
{
|
||||
current: 'messaging.operation.type',
|
||||
old: ['messaging.operation'],
|
||||
kind: 'attribute',
|
||||
contexts: ['attribute'],
|
||||
signals: ['traces'],
|
||||
applyToMetrics: [],
|
||||
valueMap: {},
|
||||
},
|
||||
{
|
||||
current: 'rpc.system.name',
|
||||
old: ['rpc.system'],
|
||||
kind: 'attribute',
|
||||
contexts: [],
|
||||
signals: [],
|
||||
applyToMetrics: [],
|
||||
valueMap: {},
|
||||
},
|
||||
{
|
||||
current: 'service.peer.name',
|
||||
old: ['peer.service'],
|
||||
kind: 'attribute',
|
||||
contexts: [],
|
||||
signals: [],
|
||||
applyToMetrics: [],
|
||||
valueMap: {},
|
||||
},
|
||||
{
|
||||
current: 'url.full',
|
||||
old: ['http.url'],
|
||||
kind: 'attribute',
|
||||
contexts: ['attribute'],
|
||||
signals: ['logs', 'traces'],
|
||||
applyToMetrics: [],
|
||||
valueMap: {},
|
||||
},
|
||||
{
|
||||
current: 'url.scheme',
|
||||
old: ['http.scheme'],
|
||||
kind: 'attribute',
|
||||
contexts: ['attribute'],
|
||||
signals: ['logs', 'traces'],
|
||||
applyToMetrics: [],
|
||||
valueMap: {},
|
||||
},
|
||||
{
|
||||
current: 'user_agent.original',
|
||||
old: ['browser.user_agent', 'http.user_agent'],
|
||||
kind: 'attribute',
|
||||
contexts: ['attribute'],
|
||||
signals: ['logs', 'traces'],
|
||||
applyToMetrics: [],
|
||||
valueMap: {},
|
||||
},
|
||||
] as const;
|
||||
|
||||
@@ -155,7 +155,7 @@ function DomainList(): JSX.Element {
|
||||
dataSource={DataSource.TRACES}
|
||||
queryData={query}
|
||||
onChange={handleSearchChange}
|
||||
placeholder="Enter your filter query (e.g., deployment.environment = 'otel-demo' AND service.name = 'frontend')"
|
||||
placeholder="Enter your filter query (e.g., deployment.environment.name = 'otel-demo' AND service.name = 'frontend')"
|
||||
hardcodedAttributeKeys={ApiMonitoringHardcodedAttributeKeys}
|
||||
/>
|
||||
</div>
|
||||
@@ -180,9 +180,8 @@ function DomainList(): JSX.Element {
|
||||
</div>
|
||||
<div className="no-domain-subtitle">
|
||||
Ensure all HTTP client spans are being sent with kind as{' '}
|
||||
<span className="attribute">Client</span> and url set in{' '}
|
||||
<span className="attribute">url.full</span> or{' '}
|
||||
<span className="attribute">http.url</span> attribute.
|
||||
<span className="attribute">Client</span> and the URL set in the{' '}
|
||||
<span className="attribute">url.full</span> attribute.
|
||||
</div>
|
||||
<a
|
||||
href={DOCLINKS.EXTERNAL_API_MONITORING}
|
||||
|
||||
@@ -6,9 +6,9 @@ import { SPAN_ATTRIBUTES } from './Explorer/Domains/DomainDetails/constants';
|
||||
export const ApiMonitoringHardcodedAttributeKeys: QueryKeyDataSuggestionsProps[] =
|
||||
[
|
||||
{
|
||||
label: 'deployment.environment',
|
||||
label: 'deployment.environment.name',
|
||||
type: 'resource',
|
||||
name: 'deployment.environment',
|
||||
name: 'deployment.environment.name',
|
||||
signal: 'traces',
|
||||
fieldDataType: QUERY_BUILDER_KEY_TYPES.STRING,
|
||||
},
|
||||
|
||||
@@ -87,7 +87,7 @@ export const ApiMonitoringQuickFiltersConfig: IQuickFiltersConfig[] = [
|
||||
title: 'Environment',
|
||||
|
||||
attributeKey: {
|
||||
key: 'deployment.environment',
|
||||
key: 'deployment.environment.name',
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
import { RowData } from 'lib/query/createTableColumnsFromQuery';
|
||||
import { BaseAutocompleteData } from 'types/api/queryBuilder/queryAutocompleteResponse';
|
||||
import { FormatTimezoneAdjustedTimestamp } from 'hooks/useTimezoneFormatter/useTimezoneFormatter';
|
||||
import { getSemconvMembers } from 'utils/semconv';
|
||||
import styles from './traceListColumns.module.scss';
|
||||
|
||||
const keyToLabelMap: Record<string, string> = {
|
||||
@@ -27,7 +28,12 @@ const keyToLabelMap: Record<string, string> = {
|
||||
const keyAliases: Record<string, string[]> = {
|
||||
serviceName: ['serviceName', 'service.name', 'service_name'],
|
||||
durationNano: ['durationNano', 'duration.nano', 'duration_nano'],
|
||||
httpMethod: ['httpMethod', 'http.method', 'http_method'],
|
||||
httpMethod: [
|
||||
'httpMethod',
|
||||
...getSemconvMembers('http.request.method'),
|
||||
'http_request_method',
|
||||
'http_method',
|
||||
],
|
||||
responseStatusCode: [
|
||||
'response_status_code',
|
||||
'response.status.code',
|
||||
|
||||
@@ -112,7 +112,7 @@ export const INFRA_MONITORING_ATTR_KEYS = {
|
||||
K8S_OBJECT_NAME: 'k8s.object.name',
|
||||
|
||||
// Environment
|
||||
DEPLOYMENT_ENVIRONMENT: 'deployment.environment',
|
||||
DEPLOYMENT_ENVIRONMENT: 'deployment.environment.name',
|
||||
|
||||
// Host System
|
||||
OS_TYPE: 'os.type',
|
||||
@@ -733,7 +733,7 @@ export const ENTITY_FILTER_PLACEHOLDERS: Record<InfraMonitoringEntity, string> =
|
||||
[InfraMonitoringEntity.NAMESPACES]:
|
||||
"Enter your filter query (e.g., k8s.namespace.name = 'production' AND k8s.cluster.name = 'prod-cluster')",
|
||||
[InfraMonitoringEntity.CLUSTERS]:
|
||||
"Enter your filter query (e.g., k8s.cluster.name = 'prod-cluster' AND deployment.environment = 'production')",
|
||||
"Enter your filter query (e.g., k8s.cluster.name = 'prod-cluster' AND deployment.environment.name = 'production')",
|
||||
[InfraMonitoringEntity.DEPLOYMENTS]:
|
||||
"Enter your filter query (e.g., k8s.deployment.name = 'api-server' AND k8s.namespace.name = 'production')",
|
||||
[InfraMonitoringEntity.STATEFULSETS]:
|
||||
|
||||
@@ -2,6 +2,17 @@
|
||||
color: white;
|
||||
}
|
||||
|
||||
.semconv-migration-report {
|
||||
margin-top: 32px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
|
||||
.ant-table-wrapper {
|
||||
margin-top: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.ingestion-key-container {
|
||||
margin-top: 24px;
|
||||
display: flex;
|
||||
|
||||
@@ -5,6 +5,8 @@ import getIngestionData from 'api/settings/getIngestionData';
|
||||
import { useAppContext } from 'providers/App/App';
|
||||
import { IngestionDataType } from 'types/api/settings/ingestion';
|
||||
|
||||
import SemconvMigrationReport from './SemconvMigrationReport';
|
||||
|
||||
import './IngestionSettings.styles.scss';
|
||||
|
||||
export default function IngestionSettings(): JSX.Element {
|
||||
@@ -84,6 +86,7 @@ export default function IngestionSettings(): JSX.Element {
|
||||
dataSource={data}
|
||||
bordered
|
||||
/>
|
||||
<SemconvMigrationReport />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -83,6 +83,8 @@ import { MeterAggregateOperator } from 'types/common/queryBuilder';
|
||||
import { USER_ROLES } from 'types/roles';
|
||||
import { getDaysUntilExpiry } from 'utils/timeUtils';
|
||||
|
||||
import SemconvMigrationReport from './SemconvMigrationReport';
|
||||
|
||||
import './IngestionSettings.styles.scss';
|
||||
|
||||
const { Option } = Select;
|
||||
@@ -1705,6 +1707,7 @@ function MultiIngestionSettings(): JSX.Element {
|
||||
}}
|
||||
className="ingestion-keys-table"
|
||||
/>
|
||||
<SemconvMigrationReport />
|
||||
</div>
|
||||
|
||||
{/* Delete Key Modal */}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
import { useQuery } from 'react-query';
|
||||
import { Alert, Table, TableColumnsType } from 'antd';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import getSemconvMigrationReport from 'api/semconv/getMigrationReport';
|
||||
import dayjs from 'dayjs';
|
||||
import { SemconvMigrationReportEntry } from 'types/api/semconvMigration';
|
||||
|
||||
function SemconvMigrationReport(): JSX.Element {
|
||||
const { data, isLoading, isError } = useQuery({
|
||||
queryKey: ['semconv-migration-report'],
|
||||
queryFn: getSemconvMigrationReport,
|
||||
});
|
||||
|
||||
const columns: TableColumnsType<SemconvMigrationReportEntry> = [
|
||||
{
|
||||
title: 'Old name',
|
||||
dataIndex: 'old',
|
||||
key: 'old',
|
||||
},
|
||||
{
|
||||
title: 'Current name',
|
||||
dataIndex: 'current',
|
||||
key: 'current',
|
||||
},
|
||||
{
|
||||
title: 'Signal',
|
||||
dataIndex: 'signal',
|
||||
key: 'signal',
|
||||
},
|
||||
{
|
||||
title: 'Services still sending only the old name',
|
||||
dataIndex: 'services',
|
||||
key: 'services',
|
||||
render: (services: string[]): string => services.join(', '),
|
||||
},
|
||||
{
|
||||
title: 'Last seen',
|
||||
dataIndex: 'lastSeenUnixMilli',
|
||||
key: 'lastSeenUnixMilli',
|
||||
render: (value: number): string =>
|
||||
dayjs(value).format('YYYY-MM-DD HH:mm:ss'),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<section className="semconv-migration-report">
|
||||
<Typography.Title level={4}>Semantic convention migration</Typography.Title>
|
||||
<Typography.Text>
|
||||
Services in this report sent an old OpenTelemetry field during the last 24
|
||||
hours without sending its current replacement. Update their SDK or
|
||||
instrumentation when practical; SigNoz queries remain backward compatible.
|
||||
</Typography.Text>
|
||||
{isError && (
|
||||
<Alert
|
||||
type="error"
|
||||
showIcon
|
||||
message="Could not load the semantic convention migration report"
|
||||
/>
|
||||
)}
|
||||
<Table
|
||||
loading={isLoading}
|
||||
columns={columns}
|
||||
dataSource={data?.entries ?? []}
|
||||
rowKey={(entry): string => `${entry.current}-${entry.old}-${entry.signal}`}
|
||||
pagination={false}
|
||||
locale={{ emptyText: 'No old-only services found in the last 24 hours' }}
|
||||
/>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
export default SemconvMigrationReport;
|
||||
@@ -15,7 +15,7 @@ export const SAMPLE_SPAN_JSON = `{
|
||||
},
|
||||
"resource": {
|
||||
"service.name": "llm-gateway",
|
||||
"deployment.environment": "production"
|
||||
"deployment.environment.name": "production"
|
||||
}
|
||||
}`;
|
||||
|
||||
|
||||
@@ -1120,7 +1120,7 @@
|
||||
"plugin": {
|
||||
"kind": "signoz/QueryVariable",
|
||||
"spec": {
|
||||
"queryValue": "SELECT DISTINCT resources_string['deployment.environment'] AS environment FROM signoz_traces.distributed_signoz_index_v3 WHERE mapContains(resources_string, 'deployment.environment') AND timestamp >= now() - INTERVAL 1 DAY"
|
||||
"queryValue": "SELECT DISTINCT resources_string['deployment.environment.name'] AS environment FROM signoz_traces.distributed_signoz_index_v3 WHERE mapContains(resources_string, 'deployment.environment.name') AND timestamp >= now() - INTERVAL 1 DAY"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Divider } from '@signozhq/ui/divider';
|
||||
import { TooltipSimple } from '@signozhq/ui/tooltip';
|
||||
import { Typography } from '@signozhq/ui/typography';
|
||||
import { SemconvOldNameBadge } from 'components/Semconv';
|
||||
|
||||
import { TagContainer, TagLabel, TagValue } from './FieldRenderer.styles';
|
||||
import { FieldRendererProps } from './LogDetailedView.types';
|
||||
@@ -28,6 +29,7 @@ function FieldRenderer({ field }: FieldRendererProps): JSX.Element {
|
||||
<Typography.Text truncate={1} className="label">
|
||||
{newField}{' '}
|
||||
</Typography.Text>
|
||||
<SemconvOldNameBadge name={newField} />
|
||||
</TooltipSimple>
|
||||
|
||||
<div className="tags">
|
||||
@@ -47,7 +49,10 @@ function FieldRenderer({ field }: FieldRendererProps): JSX.Element {
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<span className="label">{field}</span>
|
||||
<>
|
||||
<span className="label">{field}</span>
|
||||
<SemconvOldNameBadge name={field} />
|
||||
</>
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
|
||||
@@ -164,7 +164,9 @@ describe('useInitialQuery - Priority-Based Resource Filtering', () => {
|
||||
value: 'frontend-service',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
key: expect.objectContaining({ key: 'deployment.environment' }),
|
||||
key: expect.objectContaining({
|
||||
key: 'deployment.environment.name',
|
||||
}),
|
||||
value: 'production',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
@@ -286,7 +288,9 @@ describe('useInitialQuery - Priority-Based Resource Filtering', () => {
|
||||
value: 'legacy-app',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
key: expect.objectContaining({ key: 'deployment.environment' }),
|
||||
key: expect.objectContaining({
|
||||
key: 'deployment.environment.name',
|
||||
}),
|
||||
value: 'production',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
|
||||
@@ -6,13 +6,14 @@ import {
|
||||
TagFilterItem,
|
||||
} from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { getSemconvRename } from 'utils/semconv';
|
||||
|
||||
const FALLBACK_STARTS_WITH_REGEX = /^(k8s|cloud|host|deployment)/; // regex to filter out resources that start with the specified keywords
|
||||
const FALLBACK_CONTAINS_REGEX = /(env|service|file|container|tenant)/; // regex to filter out resources that contains the specified keywords
|
||||
|
||||
// Priority categories for filter selection
|
||||
// Strategy:
|
||||
// - Always include: service.name, deployment.environment, env, environment
|
||||
// - Always include: service.name, deployment.environment.name, env, environment
|
||||
// - Select ONE category only: stops at the first category with a matching attribute
|
||||
// - Within category: picks the first available attribute by order
|
||||
// - Order (highest to lowest priority): Kubernetes > Cloud > Host > Container
|
||||
@@ -26,27 +27,36 @@ const PRIORITY_CATEGORIES = [
|
||||
|
||||
const SERVICE_AND_ENVIRONMENT_KEYS = [
|
||||
'service.name',
|
||||
'deployment.environment',
|
||||
'deployment.environment.name',
|
||||
'env',
|
||||
'environment',
|
||||
];
|
||||
|
||||
export const getFiltersFromResources = (
|
||||
resources: ILog['resources_string'],
|
||||
): TagFilterItem[] =>
|
||||
Object.keys(resources).map((key: string) => {
|
||||
): TagFilterItem[] => {
|
||||
const items = new Map<string, TagFilterItem>();
|
||||
Object.keys(resources).forEach((key: string) => {
|
||||
const currentKey = getSemconvRename(key)?.current ?? key;
|
||||
const resourceValue = resources[key] as string;
|
||||
return {
|
||||
const item = {
|
||||
id: uuid(),
|
||||
key: {
|
||||
key,
|
||||
key: currentKey,
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
op: OPERATORS['='],
|
||||
value: resourceValue,
|
||||
};
|
||||
// If raw data contains both names, retain the current value just like the
|
||||
// backend's current-first resolver.
|
||||
if (!items.has(currentKey) || key === currentKey) {
|
||||
items.set(currentKey, item);
|
||||
}
|
||||
});
|
||||
return Array.from(items.values());
|
||||
};
|
||||
|
||||
export const isServiceOrEnvironmentAttribute = (key: string): boolean =>
|
||||
SERVICE_AND_ENVIRONMENT_KEYS.includes(key);
|
||||
|
||||
@@ -94,7 +94,7 @@ function DBCall(): JSX.Element {
|
||||
featureFlags?.find((flag) => flag.name === FeatureKeys.DOT_METRICS_ENABLED)
|
||||
?.active || false;
|
||||
|
||||
const legend = dotMetricsEnabled ? '{{db.system}}' : '{{db_system}}';
|
||||
const legend = dotMetricsEnabled ? '{{db.system.name}}' : '{{db_system_name}}';
|
||||
|
||||
const databaseCallsRPSWidget = useMemo(
|
||||
() =>
|
||||
|
||||
@@ -28,7 +28,7 @@ import { v4 as uuid } from 'uuid';
|
||||
|
||||
export const dbSystemTags: Tags[] = [
|
||||
{
|
||||
Key: 'db.system.(string)',
|
||||
Key: 'db.system.name.(string)',
|
||||
StringValues: [''],
|
||||
NumberValues: [],
|
||||
BoolValues: [],
|
||||
|
||||
@@ -103,7 +103,7 @@ export enum WidgetKeys {
|
||||
SignozExternalCallLatencySum = 'signoz_external_call_latency_sum',
|
||||
Signoz_latency_bucket_norm = 'signoz_latency_bucket',
|
||||
Signoz_latency_bucket = 'signoz_latency.bucket',
|
||||
Db_system = 'db.system',
|
||||
Db_system = 'db.system.name',
|
||||
Db_system_norm = 'db_system',
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import { ChangeEvent, useCallback } from 'react';
|
||||
import MEditor, { Monaco } from '@monaco-editor/react';
|
||||
import { Color } from '@signozhq/design-tokens';
|
||||
import { Input } from 'antd';
|
||||
import { SemconvEditorWarning } from 'components/Semconv';
|
||||
import { LEGEND } from 'constants/global';
|
||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||
import { useIsDarkMode } from 'hooks/useDarkMode';
|
||||
@@ -118,6 +119,7 @@ function ClickHouseQueryBuilder({
|
||||
theme={isDarkMode ? 'my-theme' : 'light'}
|
||||
beforeMount={setEditorTheme}
|
||||
/>
|
||||
<SemconvEditorWarning value={queryData?.query} editor="ClickHouse SQL" />
|
||||
<Input
|
||||
onChange={handleUpdateInput}
|
||||
name="legend"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ChangeEvent, useCallback } from 'react';
|
||||
import { Input } from 'antd';
|
||||
import { LEGEND } from 'constants/global';
|
||||
import { SemconvEditorWarning } from 'components/Semconv';
|
||||
import { useQueryBuilder } from 'hooks/queryBuilder/useQueryBuilder';
|
||||
import { IPromQLQuery } from 'types/api/queryBuilder/queryBuilderData';
|
||||
import { EQueryType } from 'types/common/dashboard';
|
||||
@@ -66,6 +67,7 @@ function PromQLQueryBuilder({
|
||||
style={{ marginBottom: '0.5rem' }}
|
||||
data-testid="promql-query-input"
|
||||
/>
|
||||
<SemconvEditorWarning value={queryData?.query} editor="PromQL" />
|
||||
|
||||
<Input
|
||||
onChange={handleUpdateQuery}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Form } from 'antd';
|
||||
import { initialQueryBuilderFormValuesMap } from 'constants/queryBuilder';
|
||||
import { SemconvEditorWarning } from 'components/Semconv';
|
||||
import QueryBuilderSearchV2 from 'container/QueryBuilder/filters/QueryBuilderSearchV2/QueryBuilderSearchV2';
|
||||
import isEqual from 'lodash-es/isEqual';
|
||||
import { TagFilter } from 'types/api/queryBuilder/queryBuilderData';
|
||||
@@ -55,6 +56,7 @@ function TagFilterInputWithLogsResultPreview({
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
/>
|
||||
<SemconvEditorWarning value={value} editor="Pipeline filter" />
|
||||
<div className="pipeline-filter-input-preview-container">
|
||||
<LogsFilterPreview filter={value} />
|
||||
</div>
|
||||
|
||||
@@ -424,7 +424,7 @@ describe('ResourceProvider', () => {
|
||||
await waitFor(() => {
|
||||
expect(result.current.queries).toHaveLength(1);
|
||||
expect(result.current.queries[0]).toMatchObject({
|
||||
tagKey: 'resource_deployment_environment',
|
||||
tagKey: 'resource_deployment_environment_name',
|
||||
operator: 'IN',
|
||||
tagValue: ['production'],
|
||||
});
|
||||
@@ -435,7 +435,7 @@ describe('ResourceProvider', () => {
|
||||
const seeded = [
|
||||
{
|
||||
id: 'env',
|
||||
tagKey: 'resource_deployment_environment',
|
||||
tagKey: 'resource_deployment_environment_name',
|
||||
operator: 'IN',
|
||||
tagValue: ['production'],
|
||||
},
|
||||
@@ -459,7 +459,7 @@ describe('ResourceProvider', () => {
|
||||
|
||||
await waitFor(() => {
|
||||
const tagKeys = result.current.queries.map((q) => q.tagKey);
|
||||
expect(tagKeys).not.toContain('resource_deployment_environment');
|
||||
expect(tagKeys).not.toContain('resource_deployment_environment_name');
|
||||
expect(tagKeys).toContain('resource_service_name');
|
||||
});
|
||||
});
|
||||
@@ -468,7 +468,7 @@ describe('ResourceProvider', () => {
|
||||
const seeded = [
|
||||
{
|
||||
id: 'env',
|
||||
tagKey: 'resource_deployment_environment',
|
||||
tagKey: 'resource_deployment_environment_name',
|
||||
operator: 'IN',
|
||||
tagValue: ['production'],
|
||||
},
|
||||
@@ -486,7 +486,7 @@ describe('ResourceProvider', () => {
|
||||
|
||||
await waitFor(() => {
|
||||
const envQueries = result.current.queries.filter(
|
||||
(q) => q.tagKey === 'resource_deployment_environment',
|
||||
(q) => q.tagKey === 'resource_deployment_environment_name',
|
||||
);
|
||||
expect(envQueries).toHaveLength(1);
|
||||
expect(envQueries[0].tagValue).toStrictEqual(['staging']);
|
||||
@@ -518,7 +518,7 @@ describe('ResourceProvider', () => {
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.queries[0].tagKey).toBe(
|
||||
'resource_deployment.environment',
|
||||
'resource_deployment.environment.name',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,13 +6,13 @@ import { mappingWithRoutesAndKeys } from '../utils';
|
||||
describe('useResourceAttribute config', () => {
|
||||
describe('whilelistedKeys', () => {
|
||||
it('should include underscore-notation keys (DOT_METRICS_ENABLED=false)', () => {
|
||||
expect(whilelistedKeys).toContain('resource_deployment_environment');
|
||||
expect(whilelistedKeys).toContain('resource_deployment_environment_name');
|
||||
expect(whilelistedKeys).toContain('resource_k8s_cluster_name');
|
||||
expect(whilelistedKeys).toContain('resource_k8s_cluster_namespace');
|
||||
});
|
||||
|
||||
it('should include dot-notation keys (DOT_METRICS_ENABLED=true)', () => {
|
||||
expect(whilelistedKeys).toContain('resource_deployment.environment');
|
||||
expect(whilelistedKeys).toContain('resource_deployment.environment.name');
|
||||
expect(whilelistedKeys).toContain('resource_k8s.cluster.name');
|
||||
expect(whilelistedKeys).toContain('resource_k8s.cluster.namespace');
|
||||
});
|
||||
@@ -21,8 +21,8 @@ describe('useResourceAttribute config', () => {
|
||||
describe('mappingWithRoutesAndKeys', () => {
|
||||
const dotNotationFilters = [
|
||||
{
|
||||
label: 'deployment.environment',
|
||||
value: 'resource_deployment.environment',
|
||||
label: 'deployment.environment.name',
|
||||
value: 'resource_deployment.environment.name',
|
||||
},
|
||||
{ label: 'k8s.cluster.name', value: 'resource_k8s.cluster.name' },
|
||||
{ label: 'k8s.cluster.namespace', value: 'resource_k8s.cluster.namespace' },
|
||||
@@ -30,8 +30,8 @@ describe('useResourceAttribute config', () => {
|
||||
|
||||
const underscoreNotationFilters = [
|
||||
{
|
||||
label: 'deployment.environment',
|
||||
value: 'resource_deployment_environment',
|
||||
label: 'deployment.environment.name',
|
||||
value: 'resource_deployment_environment_name',
|
||||
},
|
||||
{ label: 'k8s.cluster.name', value: 'resource_k8s_cluster_name' },
|
||||
{ label: 'k8s.cluster.namespace', value: 'resource_k8s_cluster_namespace' },
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export const whilelistedKeys = [
|
||||
'resource_deployment_environment',
|
||||
'resource_deployment.environment',
|
||||
'resource_deployment_environment_name',
|
||||
'resource_deployment.environment.name',
|
||||
'resource_k8s_cluster_name',
|
||||
'resource_k8s.cluster.name',
|
||||
'resource_k8s_cluster_namespace',
|
||||
|
||||
@@ -148,9 +148,9 @@ export const getResourceDeploymentKeys = (
|
||||
dotMetricsEnabled: boolean,
|
||||
): string => {
|
||||
if (dotMetricsEnabled) {
|
||||
return 'resource_deployment.environment';
|
||||
return 'resource_deployment.environment.name';
|
||||
}
|
||||
return 'resource_deployment_environment';
|
||||
return 'resource_deployment_environment_name';
|
||||
};
|
||||
|
||||
export const GetTagKeys = async (
|
||||
|
||||
@@ -35,13 +35,7 @@ export default function CeleryOverviewDetails({
|
||||
? undefined
|
||||
: getFiltersFromKeyValue('messaging.system', value, 'tag');
|
||||
case 'destination':
|
||||
return getFiltersFromKeyValue(
|
||||
details.messaging_system === 'celery'
|
||||
? 'messaging.destination'
|
||||
: 'messaging.destination.name',
|
||||
value,
|
||||
'tag',
|
||||
);
|
||||
return getFiltersFromKeyValue('messaging.destination.name', value, 'tag');
|
||||
case 'kind_string':
|
||||
return getFiltersFromKeyValue('kind_string', value, '');
|
||||
default:
|
||||
|
||||
@@ -233,7 +233,7 @@ describe('Logs Explorer Tests', () => {
|
||||
);
|
||||
|
||||
const queries = queryAllByText(
|
||||
"Enter your filter query (e.g., http.status_code >= 500 AND service.name = 'frontend')",
|
||||
"Enter your filter query (e.g., http.response.status_code >= 500 AND service.name = 'frontend')",
|
||||
);
|
||||
expect(queries).toHaveLength(1);
|
||||
});
|
||||
|
||||
@@ -40,7 +40,7 @@ export const LogsQuickFiltersConfig: IQuickFiltersConfig[] = [
|
||||
type: FiltersType.CHECKBOX,
|
||||
title: 'Environment',
|
||||
attributeKey: {
|
||||
key: 'deployment.environment',
|
||||
key: 'deployment.environment.name',
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
},
|
||||
|
||||
@@ -11,6 +11,7 @@ import { Skeleton } from 'antd';
|
||||
import { DetailsHeader, DetailsPanelDrawer } from 'components/DetailsPanel';
|
||||
import { HeaderAction } from 'components/DetailsPanel/DetailsHeader/DetailsHeader';
|
||||
import { DetailsPanelState } from 'components/DetailsPanel/types';
|
||||
import { SemconvOldNameBadge } from 'components/Semconv';
|
||||
import { QueryParams } from 'constants/query';
|
||||
import {
|
||||
initialQueryBuilderFormValuesMap,
|
||||
@@ -108,6 +109,12 @@ function SpanDetailsContent({
|
||||
() => getSpanDisplayData(selectedSpan),
|
||||
[selectedSpan],
|
||||
);
|
||||
const semconvLabelSuffix = useCallback(
|
||||
(fieldKey: string): React.ReactNode => (
|
||||
<SemconvOldNameBadge name={fieldKey} />
|
||||
),
|
||||
[],
|
||||
);
|
||||
|
||||
// Map span attribute actions to PrettyView actions format.
|
||||
// Use the last key in fieldKeyPath (the actual attribute key), not the full display path.
|
||||
@@ -329,6 +336,7 @@ function SpanDetailsContent({
|
||||
visibleActions: VISIBLE_ACTIONS,
|
||||
pinnedFieldsValue,
|
||||
onPinnedFieldsChange,
|
||||
labelSuffixRenderer: semconvLabelSuffix,
|
||||
}}
|
||||
/>
|
||||
</TabsContent>
|
||||
|
||||
@@ -29,7 +29,7 @@ export const KEY_ATTRIBUTE_KEYS: Record<string, string[]> = {
|
||||
traces: [
|
||||
'service.name',
|
||||
'service.namespace',
|
||||
'deployment.environment',
|
||||
'deployment.environment.name',
|
||||
'timestamp',
|
||||
'duration_nano',
|
||||
'kind_string',
|
||||
|
||||
@@ -359,7 +359,7 @@ function Filters({
|
||||
onChange={handleExpressionChange}
|
||||
onRun={handleRunQuery}
|
||||
dataSource={DataSource.TRACES}
|
||||
placeholder="Enter your filter query (e.g., http.status_code >= 500 AND service.name = 'frontend')"
|
||||
placeholder="Enter your filter query (e.g., http.response.status_code >= 500 AND service.name = 'frontend')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -22,8 +22,8 @@ export const SPAN_CATEGORIES: readonly SpanCategory[] = [
|
||||
|
||||
// Map each category to the attribute key it filters on
|
||||
const CATEGORY_KEYS: Record<Exclude<SpanCategory, 'All'>, string> = {
|
||||
Database: 'db.system',
|
||||
HTTP: 'http.method',
|
||||
Database: 'db.system.name',
|
||||
HTTP: 'http.request.method',
|
||||
Functions: 'kind_string',
|
||||
Jobs: 'messaging.system',
|
||||
LLM: 'gen_ai.request.model',
|
||||
@@ -34,8 +34,8 @@ const ALL_CATEGORY_KEYS = Object.values(CATEGORY_KEYS);
|
||||
|
||||
// The expression clause to add for each category
|
||||
const CATEGORY_EXPRESSIONS: Record<Exclude<SpanCategory, 'All'>, string> = {
|
||||
Database: 'db.system exists',
|
||||
HTTP: 'http.method exists',
|
||||
Database: 'db.system.name exists',
|
||||
HTTP: 'http.request.method exists',
|
||||
Functions: "kind_string = 'Internal'",
|
||||
Jobs: 'messaging.system exists',
|
||||
LLM: 'gen_ai.request.model exists',
|
||||
|
||||
@@ -38,7 +38,7 @@ export function Section(props: SectionProps): JSX.Element {
|
||||
'hasError',
|
||||
'durationNano',
|
||||
'serviceName',
|
||||
'deployment.environment',
|
||||
'deployment.environment.name',
|
||||
]),
|
||||
),
|
||||
[selectedFilters],
|
||||
|
||||
@@ -14,7 +14,7 @@ export const AllTraceFilterKeyValue: Record<string, string> = {
|
||||
durationNano: 'Duration',
|
||||
duration_nano: 'Duration',
|
||||
durationNanoMax: 'Duration',
|
||||
'deployment.environment': 'Environment',
|
||||
'deployment.environment.name': 'Environment',
|
||||
hasError: 'Status',
|
||||
has_error: 'Status',
|
||||
serviceName: 'Service Name',
|
||||
@@ -208,11 +208,11 @@ export const traceFilterKeys: Record<AllTraceFilterKeys, BaseAutocompleteData> =
|
||||
id: 'serviceName--string--tag--true',
|
||||
},
|
||||
|
||||
'deployment.environment': {
|
||||
key: 'deployment.environment',
|
||||
'deployment.environment.name': {
|
||||
key: 'deployment.environment.name',
|
||||
dataType: DataTypes.String,
|
||||
type: 'resource',
|
||||
id: 'deployment.environment--string--resource--false',
|
||||
id: 'deployment.environment.name--string--resource--false',
|
||||
},
|
||||
name: {
|
||||
key: 'name',
|
||||
|
||||
@@ -74,7 +74,8 @@ export function tracesRunQueryAction(
|
||||
properties: {
|
||||
key: {
|
||||
type: 'string',
|
||||
description: 'Attribute key, e.g. service.name, http.status_code',
|
||||
description:
|
||||
'Attribute key, e.g. service.name, http.response.status_code',
|
||||
},
|
||||
op: {
|
||||
type: 'string',
|
||||
@@ -143,7 +144,7 @@ export function tracesAddFilterAction(
|
||||
properties: {
|
||||
key: {
|
||||
type: 'string',
|
||||
description: 'Attribute key, e.g. service.name, http.status_code',
|
||||
description: 'Attribute key, e.g. service.name, http.response.status_code',
|
||||
},
|
||||
op: {
|
||||
type: 'string',
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -24,12 +24,14 @@ HASTOKEN=23
|
||||
HAS=24
|
||||
HASANY=25
|
||||
HASALL=26
|
||||
BOOL=27
|
||||
NUMBER=28
|
||||
QUOTED_TEXT=29
|
||||
KEY=30
|
||||
WS=31
|
||||
FREETEXT=32
|
||||
SEARCH=27
|
||||
EXACT=28
|
||||
BOOL=29
|
||||
NUMBER=30
|
||||
QUOTED_TEXT=31
|
||||
KEY=32
|
||||
WS=33
|
||||
FREETEXT=34
|
||||
'('=1
|
||||
')'=2
|
||||
'['=3
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -24,12 +24,14 @@ HASTOKEN=23
|
||||
HAS=24
|
||||
HASANY=25
|
||||
HASALL=26
|
||||
BOOL=27
|
||||
NUMBER=28
|
||||
QUOTED_TEXT=29
|
||||
KEY=30
|
||||
WS=31
|
||||
FREETEXT=32
|
||||
SEARCH=27
|
||||
EXACT=28
|
||||
BOOL=29
|
||||
NUMBER=30
|
||||
QUOTED_TEXT=31
|
||||
KEY=32
|
||||
WS=33
|
||||
FREETEXT=34
|
||||
'('=1
|
||||
')'=2
|
||||
'['=3
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated from FilterQuery.g4 by ANTLR 4.13.1
|
||||
// Generated from grammar/FilterQuery.g4 by ANTLR 4.13.2
|
||||
// noinspection ES6UnusedImports,JSUnusedGlobalSymbols,JSUnusedLocalSymbols
|
||||
import {
|
||||
ATN,
|
||||
@@ -38,12 +38,14 @@ export default class FilterQueryLexer extends Lexer {
|
||||
public static readonly HAS = 24;
|
||||
public static readonly HASANY = 25;
|
||||
public static readonly HASALL = 26;
|
||||
public static readonly BOOL = 27;
|
||||
public static readonly NUMBER = 28;
|
||||
public static readonly QUOTED_TEXT = 29;
|
||||
public static readonly KEY = 30;
|
||||
public static readonly WS = 31;
|
||||
public static readonly FREETEXT = 32;
|
||||
public static readonly SEARCH = 27;
|
||||
public static readonly EXACT = 28;
|
||||
public static readonly BOOL = 29;
|
||||
public static readonly NUMBER = 30;
|
||||
public static readonly QUOTED_TEXT = 31;
|
||||
public static readonly KEY = 32;
|
||||
public static readonly WS = 33;
|
||||
public static readonly FREETEXT = 34;
|
||||
public static readonly EOF = Token.EOF;
|
||||
|
||||
public static readonly channelNames: string[] = [ "DEFAULT_TOKEN_CHANNEL", "HIDDEN" ];
|
||||
@@ -68,7 +70,8 @@ export default class FilterQueryLexer extends Lexer {
|
||||
"AND", "OR",
|
||||
"HASTOKEN",
|
||||
"HAS", "HASANY",
|
||||
"HASALL", "BOOL",
|
||||
"HASALL", "SEARCH",
|
||||
"EXACT", "BOOL",
|
||||
"NUMBER", "QUOTED_TEXT",
|
||||
"KEY", "WS",
|
||||
"FREETEXT" ];
|
||||
@@ -78,8 +81,8 @@ export default class FilterQueryLexer extends Lexer {
|
||||
"LPAREN", "RPAREN", "LBRACK", "RBRACK", "COMMA", "EQUALS", "NOT_EQUALS",
|
||||
"NEQ", "LT", "LE", "GT", "GE", "LIKE", "ILIKE", "BETWEEN", "EXISTS", "REGEXP",
|
||||
"CONTAINS", "IN", "NOT", "AND", "OR", "HASTOKEN", "HAS", "HASANY", "HASALL",
|
||||
"BOOL", "SIGN", "NUMBER", "QUOTED_TEXT", "SEGMENT", "EMPTY_BRACKS", "OLD_JSON_BRACKS",
|
||||
"KEY", "WS", "DIGIT", "FREETEXT",
|
||||
"SEARCH", "EXACT", "BOOL", "SIGN", "NUMBER", "QUOTED_TEXT", "SEGMENT",
|
||||
"EMPTY_BRACKS", "OLD_JSON_BRACKS", "KEY", "WS", "DIGIT", "FREETEXT",
|
||||
];
|
||||
|
||||
|
||||
@@ -100,119 +103,124 @@ export default class FilterQueryLexer extends Lexer {
|
||||
|
||||
public get modeNames(): string[] { return FilterQueryLexer.modeNames; }
|
||||
|
||||
public static readonly _serializedATN: number[] = [4,0,32,320,6,-1,2,0,
|
||||
public static readonly _serializedATN: number[] = [4,0,34,337,6,-1,2,0,
|
||||
7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7,6,2,7,7,7,2,8,7,8,2,9,
|
||||
7,9,2,10,7,10,2,11,7,11,2,12,7,12,2,13,7,13,2,14,7,14,2,15,7,15,2,16,7,
|
||||
16,2,17,7,17,2,18,7,18,2,19,7,19,2,20,7,20,2,21,7,21,2,22,7,22,2,23,7,23,
|
||||
2,24,7,24,2,25,7,25,2,26,7,26,2,27,7,27,2,28,7,28,2,29,7,29,2,30,7,30,2,
|
||||
31,7,31,2,32,7,32,2,33,7,33,2,34,7,34,2,35,7,35,2,36,7,36,1,0,1,0,1,1,1,
|
||||
1,1,2,1,2,1,3,1,3,1,4,1,4,1,5,1,5,1,5,3,5,89,8,5,1,6,1,6,1,6,1,7,1,7,1,
|
||||
7,1,8,1,8,1,9,1,9,1,9,1,10,1,10,1,11,1,11,1,11,1,12,1,12,1,12,1,12,1,12,
|
||||
1,13,1,13,1,13,1,13,1,13,1,13,1,14,1,14,1,14,1,14,1,14,1,14,1,14,1,14,1,
|
||||
15,1,15,1,15,1,15,1,15,1,15,3,15,132,8,15,1,16,1,16,1,16,1,16,1,16,1,16,
|
||||
1,16,1,17,1,17,1,17,1,17,1,17,1,17,1,17,1,17,3,17,149,8,17,1,18,1,18,1,
|
||||
18,1,19,1,19,1,19,1,19,1,20,1,20,1,20,1,20,1,21,1,21,1,21,1,22,1,22,1,22,
|
||||
1,22,1,22,1,22,1,22,1,22,1,22,1,23,1,23,1,23,1,23,1,24,1,24,1,24,1,24,1,
|
||||
24,1,24,1,24,1,25,1,25,1,25,1,25,1,25,1,25,1,25,1,26,1,26,1,26,1,26,1,26,
|
||||
1,26,1,26,1,26,1,26,3,26,201,8,26,1,27,1,27,1,28,3,28,206,8,28,1,28,4,28,
|
||||
209,8,28,11,28,12,28,210,1,28,1,28,5,28,215,8,28,10,28,12,28,218,9,28,3,
|
||||
28,220,8,28,1,28,1,28,3,28,224,8,28,1,28,4,28,227,8,28,11,28,12,28,228,
|
||||
3,28,231,8,28,1,28,3,28,234,8,28,1,28,1,28,4,28,238,8,28,11,28,12,28,239,
|
||||
1,28,1,28,3,28,244,8,28,1,28,4,28,247,8,28,11,28,12,28,248,3,28,251,8,28,
|
||||
3,28,253,8,28,1,29,1,29,1,29,1,29,5,29,259,8,29,10,29,12,29,262,9,29,1,
|
||||
29,1,29,1,29,1,29,1,29,5,29,269,8,29,10,29,12,29,272,9,29,1,29,3,29,275,
|
||||
8,29,1,30,1,30,5,30,279,8,30,10,30,12,30,282,9,30,1,31,1,31,1,31,1,32,1,
|
||||
32,1,32,1,32,1,33,1,33,1,33,1,33,1,33,1,33,1,33,4,33,298,8,33,11,33,12,
|
||||
33,299,5,33,302,8,33,10,33,12,33,305,9,33,1,34,4,34,308,8,34,11,34,12,34,
|
||||
309,1,34,1,34,1,35,1,35,1,36,4,36,317,8,36,11,36,12,36,318,0,0,37,1,1,3,
|
||||
2,5,3,7,4,9,5,11,6,13,7,15,8,17,9,19,10,21,11,23,12,25,13,27,14,29,15,31,
|
||||
16,33,17,35,18,37,19,39,20,41,21,43,22,45,23,47,24,49,25,51,26,53,27,55,
|
||||
0,57,28,59,29,61,0,63,0,65,0,67,30,69,31,71,0,73,32,1,0,29,2,0,76,76,108,
|
||||
108,2,0,73,73,105,105,2,0,75,75,107,107,2,0,69,69,101,101,2,0,66,66,98,
|
||||
98,2,0,84,84,116,116,2,0,87,87,119,119,2,0,78,78,110,110,2,0,88,88,120,
|
||||
120,2,0,83,83,115,115,2,0,82,82,114,114,2,0,71,71,103,103,2,0,80,80,112,
|
||||
112,2,0,67,67,99,99,2,0,79,79,111,111,2,0,65,65,97,97,2,0,68,68,100,100,
|
||||
2,0,72,72,104,104,2,0,89,89,121,121,2,0,85,85,117,117,2,0,70,70,102,102,
|
||||
2,0,43,43,45,45,2,0,34,34,92,92,2,0,39,39,92,92,4,0,35,36,64,90,95,95,97,
|
||||
123,7,0,35,36,45,45,47,58,64,90,95,95,97,123,125,125,3,0,9,10,13,13,32,
|
||||
32,1,0,48,57,8,0,9,10,13,13,32,34,39,41,44,44,60,62,91,91,93,93,344,0,1,
|
||||
1,0,0,0,0,3,1,0,0,0,0,5,1,0,0,0,0,7,1,0,0,0,0,9,1,0,0,0,0,11,1,0,0,0,0,
|
||||
13,1,0,0,0,0,15,1,0,0,0,0,17,1,0,0,0,0,19,1,0,0,0,0,21,1,0,0,0,0,23,1,0,
|
||||
0,0,0,25,1,0,0,0,0,27,1,0,0,0,0,29,1,0,0,0,0,31,1,0,0,0,0,33,1,0,0,0,0,
|
||||
35,1,0,0,0,0,37,1,0,0,0,0,39,1,0,0,0,0,41,1,0,0,0,0,43,1,0,0,0,0,45,1,0,
|
||||
0,0,0,47,1,0,0,0,0,49,1,0,0,0,0,51,1,0,0,0,0,53,1,0,0,0,0,57,1,0,0,0,0,
|
||||
59,1,0,0,0,0,67,1,0,0,0,0,69,1,0,0,0,0,73,1,0,0,0,1,75,1,0,0,0,3,77,1,0,
|
||||
0,0,5,79,1,0,0,0,7,81,1,0,0,0,9,83,1,0,0,0,11,88,1,0,0,0,13,90,1,0,0,0,
|
||||
15,93,1,0,0,0,17,96,1,0,0,0,19,98,1,0,0,0,21,101,1,0,0,0,23,103,1,0,0,0,
|
||||
25,106,1,0,0,0,27,111,1,0,0,0,29,117,1,0,0,0,31,125,1,0,0,0,33,133,1,0,
|
||||
0,0,35,140,1,0,0,0,37,150,1,0,0,0,39,153,1,0,0,0,41,157,1,0,0,0,43,161,
|
||||
1,0,0,0,45,164,1,0,0,0,47,173,1,0,0,0,49,177,1,0,0,0,51,184,1,0,0,0,53,
|
||||
200,1,0,0,0,55,202,1,0,0,0,57,252,1,0,0,0,59,274,1,0,0,0,61,276,1,0,0,0,
|
||||
63,283,1,0,0,0,65,286,1,0,0,0,67,290,1,0,0,0,69,307,1,0,0,0,71,313,1,0,
|
||||
0,0,73,316,1,0,0,0,75,76,5,40,0,0,76,2,1,0,0,0,77,78,5,41,0,0,78,4,1,0,
|
||||
0,0,79,80,5,91,0,0,80,6,1,0,0,0,81,82,5,93,0,0,82,8,1,0,0,0,83,84,5,44,
|
||||
0,0,84,10,1,0,0,0,85,89,5,61,0,0,86,87,5,61,0,0,87,89,5,61,0,0,88,85,1,
|
||||
0,0,0,88,86,1,0,0,0,89,12,1,0,0,0,90,91,5,33,0,0,91,92,5,61,0,0,92,14,1,
|
||||
0,0,0,93,94,5,60,0,0,94,95,5,62,0,0,95,16,1,0,0,0,96,97,5,60,0,0,97,18,
|
||||
1,0,0,0,98,99,5,60,0,0,99,100,5,61,0,0,100,20,1,0,0,0,101,102,5,62,0,0,
|
||||
102,22,1,0,0,0,103,104,5,62,0,0,104,105,5,61,0,0,105,24,1,0,0,0,106,107,
|
||||
7,0,0,0,107,108,7,1,0,0,108,109,7,2,0,0,109,110,7,3,0,0,110,26,1,0,0,0,
|
||||
111,112,7,1,0,0,112,113,7,0,0,0,113,114,7,1,0,0,114,115,7,2,0,0,115,116,
|
||||
7,3,0,0,116,28,1,0,0,0,117,118,7,4,0,0,118,119,7,3,0,0,119,120,7,5,0,0,
|
||||
120,121,7,6,0,0,121,122,7,3,0,0,122,123,7,3,0,0,123,124,7,7,0,0,124,30,
|
||||
1,0,0,0,125,126,7,3,0,0,126,127,7,8,0,0,127,128,7,1,0,0,128,129,7,9,0,0,
|
||||
129,131,7,5,0,0,130,132,7,9,0,0,131,130,1,0,0,0,131,132,1,0,0,0,132,32,
|
||||
1,0,0,0,133,134,7,10,0,0,134,135,7,3,0,0,135,136,7,11,0,0,136,137,7,3,0,
|
||||
0,137,138,7,8,0,0,138,139,7,12,0,0,139,34,1,0,0,0,140,141,7,13,0,0,141,
|
||||
142,7,14,0,0,142,143,7,7,0,0,143,144,7,5,0,0,144,145,7,15,0,0,145,146,7,
|
||||
1,0,0,146,148,7,7,0,0,147,149,7,9,0,0,148,147,1,0,0,0,148,149,1,0,0,0,149,
|
||||
36,1,0,0,0,150,151,7,1,0,0,151,152,7,7,0,0,152,38,1,0,0,0,153,154,7,7,0,
|
||||
0,154,155,7,14,0,0,155,156,7,5,0,0,156,40,1,0,0,0,157,158,7,15,0,0,158,
|
||||
159,7,7,0,0,159,160,7,16,0,0,160,42,1,0,0,0,161,162,7,14,0,0,162,163,7,
|
||||
10,0,0,163,44,1,0,0,0,164,165,7,17,0,0,165,166,7,15,0,0,166,167,7,9,0,0,
|
||||
167,168,7,5,0,0,168,169,7,14,0,0,169,170,7,2,0,0,170,171,7,3,0,0,171,172,
|
||||
7,7,0,0,172,46,1,0,0,0,173,174,7,17,0,0,174,175,7,15,0,0,175,176,7,9,0,
|
||||
0,176,48,1,0,0,0,177,178,7,17,0,0,178,179,7,15,0,0,179,180,7,9,0,0,180,
|
||||
181,7,15,0,0,181,182,7,7,0,0,182,183,7,18,0,0,183,50,1,0,0,0,184,185,7,
|
||||
17,0,0,185,186,7,15,0,0,186,187,7,9,0,0,187,188,7,15,0,0,188,189,7,0,0,
|
||||
0,189,190,7,0,0,0,190,52,1,0,0,0,191,192,7,5,0,0,192,193,7,10,0,0,193,194,
|
||||
7,19,0,0,194,201,7,3,0,0,195,196,7,20,0,0,196,197,7,15,0,0,197,198,7,0,
|
||||
0,0,198,199,7,9,0,0,199,201,7,3,0,0,200,191,1,0,0,0,200,195,1,0,0,0,201,
|
||||
54,1,0,0,0,202,203,7,21,0,0,203,56,1,0,0,0,204,206,3,55,27,0,205,204,1,
|
||||
0,0,0,205,206,1,0,0,0,206,208,1,0,0,0,207,209,3,71,35,0,208,207,1,0,0,0,
|
||||
209,210,1,0,0,0,210,208,1,0,0,0,210,211,1,0,0,0,211,219,1,0,0,0,212,216,
|
||||
5,46,0,0,213,215,3,71,35,0,214,213,1,0,0,0,215,218,1,0,0,0,216,214,1,0,
|
||||
0,0,216,217,1,0,0,0,217,220,1,0,0,0,218,216,1,0,0,0,219,212,1,0,0,0,219,
|
||||
220,1,0,0,0,220,230,1,0,0,0,221,223,7,3,0,0,222,224,3,55,27,0,223,222,1,
|
||||
0,0,0,223,224,1,0,0,0,224,226,1,0,0,0,225,227,3,71,35,0,226,225,1,0,0,0,
|
||||
227,228,1,0,0,0,228,226,1,0,0,0,228,229,1,0,0,0,229,231,1,0,0,0,230,221,
|
||||
1,0,0,0,230,231,1,0,0,0,231,253,1,0,0,0,232,234,3,55,27,0,233,232,1,0,0,
|
||||
0,233,234,1,0,0,0,234,235,1,0,0,0,235,237,5,46,0,0,236,238,3,71,35,0,237,
|
||||
236,1,0,0,0,238,239,1,0,0,0,239,237,1,0,0,0,239,240,1,0,0,0,240,250,1,0,
|
||||
0,0,241,243,7,3,0,0,242,244,3,55,27,0,243,242,1,0,0,0,243,244,1,0,0,0,244,
|
||||
246,1,0,0,0,245,247,3,71,35,0,246,245,1,0,0,0,247,248,1,0,0,0,248,246,1,
|
||||
0,0,0,248,249,1,0,0,0,249,251,1,0,0,0,250,241,1,0,0,0,250,251,1,0,0,0,251,
|
||||
253,1,0,0,0,252,205,1,0,0,0,252,233,1,0,0,0,253,58,1,0,0,0,254,260,5,34,
|
||||
0,0,255,259,8,22,0,0,256,257,5,92,0,0,257,259,9,0,0,0,258,255,1,0,0,0,258,
|
||||
256,1,0,0,0,259,262,1,0,0,0,260,258,1,0,0,0,260,261,1,0,0,0,261,263,1,0,
|
||||
0,0,262,260,1,0,0,0,263,275,5,34,0,0,264,270,5,39,0,0,265,269,8,23,0,0,
|
||||
266,267,5,92,0,0,267,269,9,0,0,0,268,265,1,0,0,0,268,266,1,0,0,0,269,272,
|
||||
1,0,0,0,270,268,1,0,0,0,270,271,1,0,0,0,271,273,1,0,0,0,272,270,1,0,0,0,
|
||||
273,275,5,39,0,0,274,254,1,0,0,0,274,264,1,0,0,0,275,60,1,0,0,0,276,280,
|
||||
7,24,0,0,277,279,7,25,0,0,278,277,1,0,0,0,279,282,1,0,0,0,280,278,1,0,0,
|
||||
0,280,281,1,0,0,0,281,62,1,0,0,0,282,280,1,0,0,0,283,284,5,91,0,0,284,285,
|
||||
5,93,0,0,285,64,1,0,0,0,286,287,5,91,0,0,287,288,5,42,0,0,288,289,5,93,
|
||||
0,0,289,66,1,0,0,0,290,303,3,61,30,0,291,292,5,46,0,0,292,302,3,61,30,0,
|
||||
293,302,3,63,31,0,294,302,3,65,32,0,295,297,5,46,0,0,296,298,3,71,35,0,
|
||||
297,296,1,0,0,0,298,299,1,0,0,0,299,297,1,0,0,0,299,300,1,0,0,0,300,302,
|
||||
1,0,0,0,301,291,1,0,0,0,301,293,1,0,0,0,301,294,1,0,0,0,301,295,1,0,0,0,
|
||||
302,305,1,0,0,0,303,301,1,0,0,0,303,304,1,0,0,0,304,68,1,0,0,0,305,303,
|
||||
1,0,0,0,306,308,7,26,0,0,307,306,1,0,0,0,308,309,1,0,0,0,309,307,1,0,0,
|
||||
0,309,310,1,0,0,0,310,311,1,0,0,0,311,312,6,34,0,0,312,70,1,0,0,0,313,314,
|
||||
7,27,0,0,314,72,1,0,0,0,315,317,8,28,0,0,316,315,1,0,0,0,317,318,1,0,0,
|
||||
0,318,316,1,0,0,0,318,319,1,0,0,0,319,74,1,0,0,0,29,0,88,131,148,200,205,
|
||||
210,216,219,223,228,230,233,239,243,248,250,252,258,260,268,270,274,280,
|
||||
299,301,303,309,318,1,6,0,0];
|
||||
31,7,31,2,32,7,32,2,33,7,33,2,34,7,34,2,35,7,35,2,36,7,36,2,37,7,37,2,38,
|
||||
7,38,1,0,1,0,1,1,1,1,1,2,1,2,1,3,1,3,1,4,1,4,1,5,1,5,1,5,3,5,93,8,5,1,6,
|
||||
1,6,1,6,1,7,1,7,1,7,1,8,1,8,1,9,1,9,1,9,1,10,1,10,1,11,1,11,1,11,1,12,1,
|
||||
12,1,12,1,12,1,12,1,13,1,13,1,13,1,13,1,13,1,13,1,14,1,14,1,14,1,14,1,14,
|
||||
1,14,1,14,1,14,1,15,1,15,1,15,1,15,1,15,1,15,3,15,136,8,15,1,16,1,16,1,
|
||||
16,1,16,1,16,1,16,1,16,1,17,1,17,1,17,1,17,1,17,1,17,1,17,1,17,3,17,153,
|
||||
8,17,1,18,1,18,1,18,1,19,1,19,1,19,1,19,1,20,1,20,1,20,1,20,1,21,1,21,1,
|
||||
21,1,22,1,22,1,22,1,22,1,22,1,22,1,22,1,22,1,22,1,23,1,23,1,23,1,23,1,24,
|
||||
1,24,1,24,1,24,1,24,1,24,1,24,1,25,1,25,1,25,1,25,1,25,1,25,1,25,1,26,1,
|
||||
26,1,26,1,26,1,26,1,26,1,26,1,27,1,27,1,27,1,27,1,27,1,27,1,28,1,28,1,28,
|
||||
1,28,1,28,1,28,1,28,1,28,1,28,3,28,218,8,28,1,29,1,29,1,30,3,30,223,8,30,
|
||||
1,30,4,30,226,8,30,11,30,12,30,227,1,30,1,30,5,30,232,8,30,10,30,12,30,
|
||||
235,9,30,3,30,237,8,30,1,30,1,30,3,30,241,8,30,1,30,4,30,244,8,30,11,30,
|
||||
12,30,245,3,30,248,8,30,1,30,3,30,251,8,30,1,30,1,30,4,30,255,8,30,11,30,
|
||||
12,30,256,1,30,1,30,3,30,261,8,30,1,30,4,30,264,8,30,11,30,12,30,265,3,
|
||||
30,268,8,30,3,30,270,8,30,1,31,1,31,1,31,1,31,5,31,276,8,31,10,31,12,31,
|
||||
279,9,31,1,31,1,31,1,31,1,31,1,31,5,31,286,8,31,10,31,12,31,289,9,31,1,
|
||||
31,3,31,292,8,31,1,32,1,32,5,32,296,8,32,10,32,12,32,299,9,32,1,33,1,33,
|
||||
1,33,1,34,1,34,1,34,1,34,1,35,1,35,1,35,1,35,1,35,1,35,1,35,4,35,315,8,
|
||||
35,11,35,12,35,316,5,35,319,8,35,10,35,12,35,322,9,35,1,36,4,36,325,8,36,
|
||||
11,36,12,36,326,1,36,1,36,1,37,1,37,1,38,4,38,334,8,38,11,38,12,38,335,
|
||||
0,0,39,1,1,3,2,5,3,7,4,9,5,11,6,13,7,15,8,17,9,19,10,21,11,23,12,25,13,
|
||||
27,14,29,15,31,16,33,17,35,18,37,19,39,20,41,21,43,22,45,23,47,24,49,25,
|
||||
51,26,53,27,55,28,57,29,59,0,61,30,63,31,65,0,67,0,69,0,71,32,73,33,75,
|
||||
0,77,34,1,0,29,2,0,76,76,108,108,2,0,73,73,105,105,2,0,75,75,107,107,2,
|
||||
0,69,69,101,101,2,0,66,66,98,98,2,0,84,84,116,116,2,0,87,87,119,119,2,0,
|
||||
78,78,110,110,2,0,88,88,120,120,2,0,83,83,115,115,2,0,82,82,114,114,2,0,
|
||||
71,71,103,103,2,0,80,80,112,112,2,0,67,67,99,99,2,0,79,79,111,111,2,0,65,
|
||||
65,97,97,2,0,68,68,100,100,2,0,72,72,104,104,2,0,89,89,121,121,2,0,85,85,
|
||||
117,117,2,0,70,70,102,102,2,0,43,43,45,45,2,0,34,34,92,92,2,0,39,39,92,
|
||||
92,4,0,35,36,64,90,95,95,97,123,7,0,35,36,45,45,47,58,64,90,95,95,97,123,
|
||||
125,125,3,0,9,10,13,13,32,32,1,0,48,57,8,0,9,10,13,13,32,34,39,41,44,44,
|
||||
60,62,91,91,93,93,361,0,1,1,0,0,0,0,3,1,0,0,0,0,5,1,0,0,0,0,7,1,0,0,0,0,
|
||||
9,1,0,0,0,0,11,1,0,0,0,0,13,1,0,0,0,0,15,1,0,0,0,0,17,1,0,0,0,0,19,1,0,
|
||||
0,0,0,21,1,0,0,0,0,23,1,0,0,0,0,25,1,0,0,0,0,27,1,0,0,0,0,29,1,0,0,0,0,
|
||||
31,1,0,0,0,0,33,1,0,0,0,0,35,1,0,0,0,0,37,1,0,0,0,0,39,1,0,0,0,0,41,1,0,
|
||||
0,0,0,43,1,0,0,0,0,45,1,0,0,0,0,47,1,0,0,0,0,49,1,0,0,0,0,51,1,0,0,0,0,
|
||||
53,1,0,0,0,0,55,1,0,0,0,0,57,1,0,0,0,0,61,1,0,0,0,0,63,1,0,0,0,0,71,1,0,
|
||||
0,0,0,73,1,0,0,0,0,77,1,0,0,0,1,79,1,0,0,0,3,81,1,0,0,0,5,83,1,0,0,0,7,
|
||||
85,1,0,0,0,9,87,1,0,0,0,11,92,1,0,0,0,13,94,1,0,0,0,15,97,1,0,0,0,17,100,
|
||||
1,0,0,0,19,102,1,0,0,0,21,105,1,0,0,0,23,107,1,0,0,0,25,110,1,0,0,0,27,
|
||||
115,1,0,0,0,29,121,1,0,0,0,31,129,1,0,0,0,33,137,1,0,0,0,35,144,1,0,0,0,
|
||||
37,154,1,0,0,0,39,157,1,0,0,0,41,161,1,0,0,0,43,165,1,0,0,0,45,168,1,0,
|
||||
0,0,47,177,1,0,0,0,49,181,1,0,0,0,51,188,1,0,0,0,53,195,1,0,0,0,55,202,
|
||||
1,0,0,0,57,217,1,0,0,0,59,219,1,0,0,0,61,269,1,0,0,0,63,291,1,0,0,0,65,
|
||||
293,1,0,0,0,67,300,1,0,0,0,69,303,1,0,0,0,71,307,1,0,0,0,73,324,1,0,0,0,
|
||||
75,330,1,0,0,0,77,333,1,0,0,0,79,80,5,40,0,0,80,2,1,0,0,0,81,82,5,41,0,
|
||||
0,82,4,1,0,0,0,83,84,5,91,0,0,84,6,1,0,0,0,85,86,5,93,0,0,86,8,1,0,0,0,
|
||||
87,88,5,44,0,0,88,10,1,0,0,0,89,93,5,61,0,0,90,91,5,61,0,0,91,93,5,61,0,
|
||||
0,92,89,1,0,0,0,92,90,1,0,0,0,93,12,1,0,0,0,94,95,5,33,0,0,95,96,5,61,0,
|
||||
0,96,14,1,0,0,0,97,98,5,60,0,0,98,99,5,62,0,0,99,16,1,0,0,0,100,101,5,60,
|
||||
0,0,101,18,1,0,0,0,102,103,5,60,0,0,103,104,5,61,0,0,104,20,1,0,0,0,105,
|
||||
106,5,62,0,0,106,22,1,0,0,0,107,108,5,62,0,0,108,109,5,61,0,0,109,24,1,
|
||||
0,0,0,110,111,7,0,0,0,111,112,7,1,0,0,112,113,7,2,0,0,113,114,7,3,0,0,114,
|
||||
26,1,0,0,0,115,116,7,1,0,0,116,117,7,0,0,0,117,118,7,1,0,0,118,119,7,2,
|
||||
0,0,119,120,7,3,0,0,120,28,1,0,0,0,121,122,7,4,0,0,122,123,7,3,0,0,123,
|
||||
124,7,5,0,0,124,125,7,6,0,0,125,126,7,3,0,0,126,127,7,3,0,0,127,128,7,7,
|
||||
0,0,128,30,1,0,0,0,129,130,7,3,0,0,130,131,7,8,0,0,131,132,7,1,0,0,132,
|
||||
133,7,9,0,0,133,135,7,5,0,0,134,136,7,9,0,0,135,134,1,0,0,0,135,136,1,0,
|
||||
0,0,136,32,1,0,0,0,137,138,7,10,0,0,138,139,7,3,0,0,139,140,7,11,0,0,140,
|
||||
141,7,3,0,0,141,142,7,8,0,0,142,143,7,12,0,0,143,34,1,0,0,0,144,145,7,13,
|
||||
0,0,145,146,7,14,0,0,146,147,7,7,0,0,147,148,7,5,0,0,148,149,7,15,0,0,149,
|
||||
150,7,1,0,0,150,152,7,7,0,0,151,153,7,9,0,0,152,151,1,0,0,0,152,153,1,0,
|
||||
0,0,153,36,1,0,0,0,154,155,7,1,0,0,155,156,7,7,0,0,156,38,1,0,0,0,157,158,
|
||||
7,7,0,0,158,159,7,14,0,0,159,160,7,5,0,0,160,40,1,0,0,0,161,162,7,15,0,
|
||||
0,162,163,7,7,0,0,163,164,7,16,0,0,164,42,1,0,0,0,165,166,7,14,0,0,166,
|
||||
167,7,10,0,0,167,44,1,0,0,0,168,169,7,17,0,0,169,170,7,15,0,0,170,171,7,
|
||||
9,0,0,171,172,7,5,0,0,172,173,7,14,0,0,173,174,7,2,0,0,174,175,7,3,0,0,
|
||||
175,176,7,7,0,0,176,46,1,0,0,0,177,178,7,17,0,0,178,179,7,15,0,0,179,180,
|
||||
7,9,0,0,180,48,1,0,0,0,181,182,7,17,0,0,182,183,7,15,0,0,183,184,7,9,0,
|
||||
0,184,185,7,15,0,0,185,186,7,7,0,0,186,187,7,18,0,0,187,50,1,0,0,0,188,
|
||||
189,7,17,0,0,189,190,7,15,0,0,190,191,7,9,0,0,191,192,7,15,0,0,192,193,
|
||||
7,0,0,0,193,194,7,0,0,0,194,52,1,0,0,0,195,196,7,9,0,0,196,197,7,3,0,0,
|
||||
197,198,7,15,0,0,198,199,7,10,0,0,199,200,7,13,0,0,200,201,7,17,0,0,201,
|
||||
54,1,0,0,0,202,203,7,3,0,0,203,204,7,8,0,0,204,205,7,15,0,0,205,206,7,13,
|
||||
0,0,206,207,7,5,0,0,207,56,1,0,0,0,208,209,7,5,0,0,209,210,7,10,0,0,210,
|
||||
211,7,19,0,0,211,218,7,3,0,0,212,213,7,20,0,0,213,214,7,15,0,0,214,215,
|
||||
7,0,0,0,215,216,7,9,0,0,216,218,7,3,0,0,217,208,1,0,0,0,217,212,1,0,0,0,
|
||||
218,58,1,0,0,0,219,220,7,21,0,0,220,60,1,0,0,0,221,223,3,59,29,0,222,221,
|
||||
1,0,0,0,222,223,1,0,0,0,223,225,1,0,0,0,224,226,3,75,37,0,225,224,1,0,0,
|
||||
0,226,227,1,0,0,0,227,225,1,0,0,0,227,228,1,0,0,0,228,236,1,0,0,0,229,233,
|
||||
5,46,0,0,230,232,3,75,37,0,231,230,1,0,0,0,232,235,1,0,0,0,233,231,1,0,
|
||||
0,0,233,234,1,0,0,0,234,237,1,0,0,0,235,233,1,0,0,0,236,229,1,0,0,0,236,
|
||||
237,1,0,0,0,237,247,1,0,0,0,238,240,7,3,0,0,239,241,3,59,29,0,240,239,1,
|
||||
0,0,0,240,241,1,0,0,0,241,243,1,0,0,0,242,244,3,75,37,0,243,242,1,0,0,0,
|
||||
244,245,1,0,0,0,245,243,1,0,0,0,245,246,1,0,0,0,246,248,1,0,0,0,247,238,
|
||||
1,0,0,0,247,248,1,0,0,0,248,270,1,0,0,0,249,251,3,59,29,0,250,249,1,0,0,
|
||||
0,250,251,1,0,0,0,251,252,1,0,0,0,252,254,5,46,0,0,253,255,3,75,37,0,254,
|
||||
253,1,0,0,0,255,256,1,0,0,0,256,254,1,0,0,0,256,257,1,0,0,0,257,267,1,0,
|
||||
0,0,258,260,7,3,0,0,259,261,3,59,29,0,260,259,1,0,0,0,260,261,1,0,0,0,261,
|
||||
263,1,0,0,0,262,264,3,75,37,0,263,262,1,0,0,0,264,265,1,0,0,0,265,263,1,
|
||||
0,0,0,265,266,1,0,0,0,266,268,1,0,0,0,267,258,1,0,0,0,267,268,1,0,0,0,268,
|
||||
270,1,0,0,0,269,222,1,0,0,0,269,250,1,0,0,0,270,62,1,0,0,0,271,277,5,34,
|
||||
0,0,272,276,8,22,0,0,273,274,5,92,0,0,274,276,9,0,0,0,275,272,1,0,0,0,275,
|
||||
273,1,0,0,0,276,279,1,0,0,0,277,275,1,0,0,0,277,278,1,0,0,0,278,280,1,0,
|
||||
0,0,279,277,1,0,0,0,280,292,5,34,0,0,281,287,5,39,0,0,282,286,8,23,0,0,
|
||||
283,284,5,92,0,0,284,286,9,0,0,0,285,282,1,0,0,0,285,283,1,0,0,0,286,289,
|
||||
1,0,0,0,287,285,1,0,0,0,287,288,1,0,0,0,288,290,1,0,0,0,289,287,1,0,0,0,
|
||||
290,292,5,39,0,0,291,271,1,0,0,0,291,281,1,0,0,0,292,64,1,0,0,0,293,297,
|
||||
7,24,0,0,294,296,7,25,0,0,295,294,1,0,0,0,296,299,1,0,0,0,297,295,1,0,0,
|
||||
0,297,298,1,0,0,0,298,66,1,0,0,0,299,297,1,0,0,0,300,301,5,91,0,0,301,302,
|
||||
5,93,0,0,302,68,1,0,0,0,303,304,5,91,0,0,304,305,5,42,0,0,305,306,5,93,
|
||||
0,0,306,70,1,0,0,0,307,320,3,65,32,0,308,309,5,46,0,0,309,319,3,65,32,0,
|
||||
310,319,3,67,33,0,311,319,3,69,34,0,312,314,5,46,0,0,313,315,3,75,37,0,
|
||||
314,313,1,0,0,0,315,316,1,0,0,0,316,314,1,0,0,0,316,317,1,0,0,0,317,319,
|
||||
1,0,0,0,318,308,1,0,0,0,318,310,1,0,0,0,318,311,1,0,0,0,318,312,1,0,0,0,
|
||||
319,322,1,0,0,0,320,318,1,0,0,0,320,321,1,0,0,0,321,72,1,0,0,0,322,320,
|
||||
1,0,0,0,323,325,7,26,0,0,324,323,1,0,0,0,325,326,1,0,0,0,326,324,1,0,0,
|
||||
0,326,327,1,0,0,0,327,328,1,0,0,0,328,329,6,36,0,0,329,74,1,0,0,0,330,331,
|
||||
7,27,0,0,331,76,1,0,0,0,332,334,8,28,0,0,333,332,1,0,0,0,334,335,1,0,0,
|
||||
0,335,333,1,0,0,0,335,336,1,0,0,0,336,78,1,0,0,0,29,0,92,135,152,217,222,
|
||||
227,233,236,240,245,247,250,256,260,265,267,269,275,277,285,287,291,297,
|
||||
316,318,320,326,335,1,6,0,0];
|
||||
|
||||
private static __ATN: ATN;
|
||||
public static get _ATN(): ATN {
|
||||
@@ -225,4 +233,4 @@ export default class FilterQueryLexer extends Lexer {
|
||||
|
||||
|
||||
static DecisionsToDFA = FilterQueryLexer._ATN.decisionToState.map( (ds: DecisionState, index: number) => new DFA(ds, index) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,28 @@
|
||||
// Generated from FilterQuery.g4 by ANTLR 4.13.1
|
||||
// Generated from grammar/FilterQuery.g4 by ANTLR 4.13.2
|
||||
|
||||
import {ParseTreeListener} from "antlr4";
|
||||
|
||||
|
||||
import { QueryContext } from "./FilterQueryParser";
|
||||
import { ExpressionContext } from "./FilterQueryParser";
|
||||
import { OrExpressionContext } from "./FilterQueryParser";
|
||||
import { AndExpressionContext } from "./FilterQueryParser";
|
||||
import { UnaryExpressionContext } from "./FilterQueryParser";
|
||||
import { PrimaryContext } from "./FilterQueryParser";
|
||||
import { ComparisonContext } from "./FilterQueryParser";
|
||||
import { InClauseContext } from "./FilterQueryParser";
|
||||
import { NotInClauseContext } from "./FilterQueryParser";
|
||||
import { ValueListContext } from "./FilterQueryParser";
|
||||
import { FullTextContext } from "./FilterQueryParser";
|
||||
import { FunctionCallContext } from "./FilterQueryParser";
|
||||
import { FunctionParamListContext } from "./FilterQueryParser";
|
||||
import { FunctionParamContext } from "./FilterQueryParser";
|
||||
import { ArrayContext } from "./FilterQueryParser";
|
||||
import { ValueContext } from "./FilterQueryParser";
|
||||
import { KeyContext } from "./FilterQueryParser";
|
||||
import { QueryContext } from "./FilterQueryParser.js";
|
||||
import { ExpressionContext } from "./FilterQueryParser.js";
|
||||
import { OrExpressionContext } from "./FilterQueryParser.js";
|
||||
import { AndExpressionContext } from "./FilterQueryParser.js";
|
||||
import { UnaryExpressionContext } from "./FilterQueryParser.js";
|
||||
import { PrimaryContext } from "./FilterQueryParser.js";
|
||||
import { ComparisonContext } from "./FilterQueryParser.js";
|
||||
import { InClauseContext } from "./FilterQueryParser.js";
|
||||
import { NotInClauseContext } from "./FilterQueryParser.js";
|
||||
import { ValueListContext } from "./FilterQueryParser.js";
|
||||
import { FullTextContext } from "./FilterQueryParser.js";
|
||||
import { FunctionCallContext } from "./FilterQueryParser.js";
|
||||
import { SearchCallContext } from "./FilterQueryParser.js";
|
||||
import { FunctionParamListContext } from "./FilterQueryParser.js";
|
||||
import { FunctionParamContext } from "./FilterQueryParser.js";
|
||||
import { ArrayContext } from "./FilterQueryParser.js";
|
||||
import { ValueContext } from "./FilterQueryParser.js";
|
||||
import { KeyContext } from "./FilterQueryParser.js";
|
||||
import { FieldContext } from "./FilterQueryParser.js";
|
||||
import { ExactCallContext } from "./FilterQueryParser.js";
|
||||
|
||||
|
||||
/**
|
||||
@@ -147,6 +150,16 @@ export default class FilterQueryListener extends ParseTreeListener {
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitFunctionCall?: (ctx: FunctionCallContext) => void;
|
||||
/**
|
||||
* Enter a parse tree produced by `FilterQueryParser.searchCall`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterSearchCall?: (ctx: SearchCallContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `FilterQueryParser.searchCall`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitSearchCall?: (ctx: SearchCallContext) => void;
|
||||
/**
|
||||
* Enter a parse tree produced by `FilterQueryParser.functionParamList`.
|
||||
* @param ctx the parse tree
|
||||
@@ -197,5 +210,25 @@ export default class FilterQueryListener extends ParseTreeListener {
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitKey?: (ctx: KeyContext) => void;
|
||||
/**
|
||||
* Enter a parse tree produced by `FilterQueryParser.field`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterField?: (ctx: FieldContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `FilterQueryParser.field`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitField?: (ctx: FieldContext) => void;
|
||||
/**
|
||||
* Enter a parse tree produced by `FilterQueryParser.exactCall`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
enterExactCall?: (ctx: ExactCallContext) => void;
|
||||
/**
|
||||
* Exit a parse tree produced by `FilterQueryParser.exactCall`.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
exitExactCall?: (ctx: ExactCallContext) => void;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,25 +1,28 @@
|
||||
// Generated from FilterQuery.g4 by ANTLR 4.13.1
|
||||
// Generated from grammar/FilterQuery.g4 by ANTLR 4.13.2
|
||||
|
||||
import {ParseTreeVisitor} from 'antlr4';
|
||||
|
||||
|
||||
import { QueryContext } from "./FilterQueryParser";
|
||||
import { ExpressionContext } from "./FilterQueryParser";
|
||||
import { OrExpressionContext } from "./FilterQueryParser";
|
||||
import { AndExpressionContext } from "./FilterQueryParser";
|
||||
import { UnaryExpressionContext } from "./FilterQueryParser";
|
||||
import { PrimaryContext } from "./FilterQueryParser";
|
||||
import { ComparisonContext } from "./FilterQueryParser";
|
||||
import { InClauseContext } from "./FilterQueryParser";
|
||||
import { NotInClauseContext } from "./FilterQueryParser";
|
||||
import { ValueListContext } from "./FilterQueryParser";
|
||||
import { FullTextContext } from "./FilterQueryParser";
|
||||
import { FunctionCallContext } from "./FilterQueryParser";
|
||||
import { FunctionParamListContext } from "./FilterQueryParser";
|
||||
import { FunctionParamContext } from "./FilterQueryParser";
|
||||
import { ArrayContext } from "./FilterQueryParser";
|
||||
import { ValueContext } from "./FilterQueryParser";
|
||||
import { KeyContext } from "./FilterQueryParser";
|
||||
import { QueryContext } from "./FilterQueryParser.js";
|
||||
import { ExpressionContext } from "./FilterQueryParser.js";
|
||||
import { OrExpressionContext } from "./FilterQueryParser.js";
|
||||
import { AndExpressionContext } from "./FilterQueryParser.js";
|
||||
import { UnaryExpressionContext } from "./FilterQueryParser.js";
|
||||
import { PrimaryContext } from "./FilterQueryParser.js";
|
||||
import { ComparisonContext } from "./FilterQueryParser.js";
|
||||
import { InClauseContext } from "./FilterQueryParser.js";
|
||||
import { NotInClauseContext } from "./FilterQueryParser.js";
|
||||
import { ValueListContext } from "./FilterQueryParser.js";
|
||||
import { FullTextContext } from "./FilterQueryParser.js";
|
||||
import { FunctionCallContext } from "./FilterQueryParser.js";
|
||||
import { SearchCallContext } from "./FilterQueryParser.js";
|
||||
import { FunctionParamListContext } from "./FilterQueryParser.js";
|
||||
import { FunctionParamContext } from "./FilterQueryParser.js";
|
||||
import { ArrayContext } from "./FilterQueryParser.js";
|
||||
import { ValueContext } from "./FilterQueryParser.js";
|
||||
import { KeyContext } from "./FilterQueryParser.js";
|
||||
import { FieldContext } from "./FilterQueryParser.js";
|
||||
import { ExactCallContext } from "./FilterQueryParser.js";
|
||||
|
||||
|
||||
/**
|
||||
@@ -102,6 +105,12 @@ export default class FilterQueryVisitor<Result> extends ParseTreeVisitor<Result>
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitFunctionCall?: (ctx: FunctionCallContext) => Result;
|
||||
/**
|
||||
* Visit a parse tree produced by `FilterQueryParser.searchCall`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitSearchCall?: (ctx: SearchCallContext) => Result;
|
||||
/**
|
||||
* Visit a parse tree produced by `FilterQueryParser.functionParamList`.
|
||||
* @param ctx the parse tree
|
||||
@@ -132,5 +141,17 @@ export default class FilterQueryVisitor<Result> extends ParseTreeVisitor<Result>
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitKey?: (ctx: KeyContext) => Result;
|
||||
/**
|
||||
* Visit a parse tree produced by `FilterQueryParser.field`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitField?: (ctx: FieldContext) => Result;
|
||||
/**
|
||||
* Visit a parse tree produced by `FilterQueryParser.exactCall`.
|
||||
* @param ctx the parse tree
|
||||
* @return the visitor result
|
||||
*/
|
||||
visitExactCall?: (ctx: ExactCallContext) => Result;
|
||||
}
|
||||
|
||||
|
||||
@@ -223,6 +223,12 @@
|
||||
padding-left: 6px !important;
|
||||
}
|
||||
|
||||
&__label {
|
||||
display: inline-flex;
|
||||
align-items: baseline;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
&__pinned-icon {
|
||||
flex-shrink: 0;
|
||||
color: var(--text-robin-400);
|
||||
|
||||
@@ -67,6 +67,7 @@ export interface PrettyViewProps {
|
||||
*/
|
||||
pinnedFieldsValue?: string[];
|
||||
onPinnedFieldsChange?: (next: string[]) => void;
|
||||
labelSuffixRenderer?: (fieldKey: string) => React.ReactNode;
|
||||
}
|
||||
|
||||
function PrettyView({
|
||||
@@ -78,6 +79,7 @@ function PrettyView({
|
||||
drawerKey = 'default',
|
||||
pinnedFieldsValue,
|
||||
onPinnedFieldsChange,
|
||||
labelSuffixRenderer,
|
||||
}: PrettyViewProps): JSX.Element {
|
||||
const isDarkMode = useIsDarkMode();
|
||||
const [, setCopy] = useCopyToClipboard();
|
||||
@@ -305,10 +307,24 @@ function PrettyView({
|
||||
}}
|
||||
/>
|
||||
<span>{displayKey}</span>
|
||||
{labelSuffixRenderer?.(displayKey)}
|
||||
</span>
|
||||
);
|
||||
},
|
||||
[togglePin, pinnedEntries],
|
||||
[togglePin, pinnedEntries, labelSuffixRenderer],
|
||||
);
|
||||
|
||||
const labelRenderer = useCallback(
|
||||
(keyPath: KeyPath): React.ReactNode => {
|
||||
const displayKey = String(keyPath[0]);
|
||||
return (
|
||||
<span className="pretty-view__label">
|
||||
<span>{displayKey}</span>
|
||||
{labelSuffixRenderer?.(displayKey)}
|
||||
</span>
|
||||
);
|
||||
},
|
||||
[labelSuffixRenderer],
|
||||
);
|
||||
|
||||
return (
|
||||
@@ -351,6 +367,7 @@ function PrettyView({
|
||||
shouldExpandNodeInitially={shouldExpandNodeInitially}
|
||||
valueRenderer={valueRenderer}
|
||||
getItemString={getItemString}
|
||||
labelRenderer={labelRenderer}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
14
frontend/src/types/api/semconvMigration.ts
Normal file
14
frontend/src/types/api/semconvMigration.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
export interface SemconvMigrationReportEntry {
|
||||
current: string;
|
||||
old: string;
|
||||
signal: string;
|
||||
services: string[];
|
||||
resourceSets: number;
|
||||
lastSeenUnixMilli: number;
|
||||
}
|
||||
|
||||
export interface SemconvMigrationReport {
|
||||
startUnixMilli: number;
|
||||
endUnixMilli: number;
|
||||
entries: SemconvMigrationReportEntry[];
|
||||
}
|
||||
@@ -117,6 +117,8 @@ export type SpaceAggregation =
|
||||
|
||||
export type ColumnType = 'group' | 'aggregation';
|
||||
|
||||
export type FieldResolution = 'exact';
|
||||
|
||||
// ===================== Variable Types =====================
|
||||
|
||||
export type VariableType = 'query' | 'dynamic' | 'custom' | 'text';
|
||||
@@ -136,6 +138,7 @@ export interface TelemetryFieldKey {
|
||||
signal?: SignalType;
|
||||
fieldContext?: FieldContext;
|
||||
fieldDataType?: FieldDataType;
|
||||
fieldResolution?: FieldResolution;
|
||||
materialized?: boolean;
|
||||
isIndexed?: boolean;
|
||||
}
|
||||
|
||||
40
frontend/src/utils/__tests__/semconv.test.ts
Normal file
40
frontend/src/utils/__tests__/semconv.test.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import {
|
||||
findOldSemconvNames,
|
||||
getSemconvMembers,
|
||||
getSemconvRename,
|
||||
} from 'utils/semconv';
|
||||
|
||||
describe('semantic convention helpers', () => {
|
||||
it('returns the current name for an old attribute', () => {
|
||||
expect(getSemconvRename('deployment.environment')).toMatchObject({
|
||||
old: 'deployment.environment',
|
||||
current: 'deployment.environment.name',
|
||||
});
|
||||
});
|
||||
|
||||
it('finds old names in editor text without matching larger custom names', () => {
|
||||
expect(
|
||||
findOldSemconvNames(
|
||||
"deployment.environment = 'prod' AND custom.db.system.value = 'x'",
|
||||
),
|
||||
).toStrictEqual([
|
||||
expect.objectContaining({
|
||||
old: 'deployment.environment',
|
||||
current: 'deployment.environment.name',
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
it('does not warn for current names', () => {
|
||||
expect(
|
||||
findOldSemconvNames('deployment.environment.name = prod'),
|
||||
).toStrictEqual([]);
|
||||
});
|
||||
|
||||
it('returns current-first members for compatibility readers', () => {
|
||||
expect(getSemconvMembers('http.request.method')).toStrictEqual([
|
||||
'http.request.method',
|
||||
'http.method',
|
||||
]);
|
||||
});
|
||||
});
|
||||
61
frontend/src/utils/semconv.ts
Normal file
61
frontend/src/utils/semconv.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import {
|
||||
SEMCONV_FAMILIES,
|
||||
SemconvFamily,
|
||||
} from 'constants/generated/semconvFamilies.gen';
|
||||
|
||||
export type SemconvRename = {
|
||||
old: string;
|
||||
current: string;
|
||||
family: SemconvFamily;
|
||||
};
|
||||
|
||||
const OLD_NAMES = SEMCONV_FAMILIES.flatMap((family) =>
|
||||
family.old.map((old) => ({ old, current: family.current, family })),
|
||||
);
|
||||
|
||||
const OLD_NAME_INDEX = new Map(OLD_NAMES.map((rename) => [rename.old, rename]));
|
||||
const FAMILY_BY_NAME = new Map(
|
||||
SEMCONV_FAMILIES.flatMap((family) =>
|
||||
[family.current, ...family.old].map((name) => [name, family] as const),
|
||||
),
|
||||
);
|
||||
|
||||
export function getSemconvRename(name: string): SemconvRename | undefined {
|
||||
return OLD_NAME_INDEX.get(name);
|
||||
}
|
||||
|
||||
/** Returns the current name first, followed by every historical spelling. */
|
||||
export function getSemconvMembers(name: string): readonly string[] {
|
||||
const family = FAMILY_BY_NAME.get(name);
|
||||
return family ? [family.current, ...family.old] : [name];
|
||||
}
|
||||
|
||||
export function findOldSemconvNames(text: string): SemconvRename[] {
|
||||
if (!text) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return OLD_NAMES.filter(({ old }) => containsSemconvName(text, old));
|
||||
}
|
||||
|
||||
function containsSemconvName(text: string, name: string): boolean {
|
||||
let offset = 0;
|
||||
while (offset < text.length) {
|
||||
const index = text.indexOf(name, offset);
|
||||
if (index === -1) {
|
||||
return false;
|
||||
}
|
||||
const before = index === 0 ? '' : text[index - 1];
|
||||
const afterIndex = index + name.length;
|
||||
const after = afterIndex === text.length ? '' : text[afterIndex];
|
||||
if (!isSemconvNameCharacter(before) && !isSemconvNameCharacter(after)) {
|
||||
return true;
|
||||
}
|
||||
offset = index + 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isSemconvNameCharacter(value: string): boolean {
|
||||
return /[A-Za-z0-9_.-]/.test(value);
|
||||
}
|
||||
@@ -50,30 +50,30 @@ primary
|
||||
* [NOT] BETWEEN, [NOT] IN, [NOT] EXISTS, [NOT] REGEXP, [NOT] CONTAINS, etc.
|
||||
*/
|
||||
comparison
|
||||
: key EQUALS value
|
||||
| key (NOT_EQUALS | NEQ) value
|
||||
| key LT value
|
||||
| key LE value
|
||||
| key GT value
|
||||
| key GE value
|
||||
: field EQUALS value
|
||||
| field (NOT_EQUALS | NEQ) value
|
||||
| field LT value
|
||||
| field LE value
|
||||
| field GT value
|
||||
| field GE value
|
||||
|
||||
| key (LIKE | ILIKE) value
|
||||
| key NOT (LIKE | ILIKE) value
|
||||
| field (LIKE | ILIKE) value
|
||||
| field NOT (LIKE | ILIKE) value
|
||||
|
||||
| key BETWEEN value AND value
|
||||
| key NOT BETWEEN value AND value
|
||||
| field BETWEEN value AND value
|
||||
| field NOT BETWEEN value AND value
|
||||
|
||||
| key inClause
|
||||
| key notInClause
|
||||
| field inClause
|
||||
| field notInClause
|
||||
|
||||
| key EXISTS
|
||||
| key NOT EXISTS
|
||||
| field EXISTS
|
||||
| field NOT EXISTS
|
||||
|
||||
| key REGEXP value
|
||||
| key NOT REGEXP value
|
||||
| field REGEXP value
|
||||
| field NOT REGEXP value
|
||||
|
||||
| key CONTAINS value
|
||||
| key NOT CONTAINS value
|
||||
| field CONTAINS value
|
||||
| field NOT CONTAINS value
|
||||
;
|
||||
|
||||
// in(...) or in[...]
|
||||
@@ -126,7 +126,7 @@ functionParamList
|
||||
;
|
||||
|
||||
functionParam
|
||||
: key
|
||||
: field
|
||||
| value
|
||||
| array
|
||||
;
|
||||
@@ -155,6 +155,17 @@ key
|
||||
: KEY
|
||||
;
|
||||
|
||||
// exact(key) disables semantic-convention family resolution for this field.
|
||||
// It is deliberately a field wrapper rather than a general function.
|
||||
field
|
||||
: key
|
||||
| exactCall
|
||||
;
|
||||
|
||||
exactCall
|
||||
: EXACT LPAREN key RPAREN
|
||||
;
|
||||
|
||||
|
||||
/*
|
||||
* Lexer Rules
|
||||
@@ -195,6 +206,7 @@ HAS : [Hh][Aa][Ss] ;
|
||||
HASANY : [Hh][Aa][Ss][Aa][Nn][Yy] ;
|
||||
HASALL : [Hh][Aa][Ss][Aa][Ll][Ll] ;
|
||||
SEARCH : [Ss][Ee][Aa][Rr][Cc][Hh] ;
|
||||
EXACT : [Ee][Xx][Aa][Cc][Tt] ;
|
||||
|
||||
// Potential boolean constants
|
||||
BOOL
|
||||
|
||||
@@ -46,5 +46,23 @@ func (provider *provider) addFieldsRoutes(router *mux.Router) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := router.Handle("/api/v1/fields/semconv-migration", handler.New(provider.authzMiddleware.ViewAccess(provider.fieldsHandler.GetSemconvMigrationReport), handler.OpenAPIDef{
|
||||
ID: "GetSemconvMigrationReport",
|
||||
Tags: []string{"fields"},
|
||||
Summary: "Get semantic-convention migration report",
|
||||
Description: "Returns services that still emit old semantic-convention names without the current family name",
|
||||
Request: nil,
|
||||
RequestQuery: new(telemetrytypes.PostableSemconvMigrationReportParams),
|
||||
RequestContentType: "",
|
||||
Response: new(telemetrytypes.GettableSemconvMigrationReport),
|
||||
ResponseContentType: "application/json",
|
||||
SuccessStatusCode: http.StatusOK,
|
||||
ErrorStatusCodes: []int{},
|
||||
Deprecated: false,
|
||||
SecuritySchemes: newSecuritySchemes(types.RoleViewer),
|
||||
})).Methods(http.MethodGet).GetError(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -51,9 +51,9 @@ func postableRuleExamples() []handler.OpenAPIExample {
|
||||
"filter": map[string]any{"expression": "k8s.deployment.name = 'api-service'"},
|
||||
"groupBy": []any{
|
||||
map[string]any{"name": "k8s.pod.name", "fieldContext": "resource", "fieldDataType": "string"},
|
||||
map[string]any{"name": "deployment.environment", "fieldContext": "resource", "fieldDataType": "string"},
|
||||
map[string]any{"name": "deployment.environment.name", "fieldContext": "resource", "fieldDataType": "string"},
|
||||
},
|
||||
"legend": "{{k8s.pod.name}} ({{deployment.environment}})",
|
||||
"legend": "{{k8s.pod.name}} ({{deployment.environment.name}})",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -74,12 +74,12 @@ func postableRuleExamples() []handler.OpenAPIExample {
|
||||
},
|
||||
"evaluation": rolling("15m", "1m"),
|
||||
"notificationSettings": map[string]any{
|
||||
"groupBy": []any{"k8s.pod.name", "deployment.environment"},
|
||||
"groupBy": []any{"k8s.pod.name", "deployment.environment.name"},
|
||||
"renotify": renotify("4h", "firing"),
|
||||
},
|
||||
"labels": map[string]any{"severity": "critical", "team": "platform"},
|
||||
"annotations": map[string]any{
|
||||
"description": "Pod {{$k8s.pod.name}} CPU is at {{$value}} of request in {{$deployment.environment}}.",
|
||||
"description": "Pod {{$k8s.pod.name}} CPU is at {{$value}} of request in {{$deployment.environment.name}}.",
|
||||
"summary": "Pod CPU above {{$threshold}} of request",
|
||||
},
|
||||
},
|
||||
@@ -170,7 +170,7 @@ func postableRuleExamples() []handler.OpenAPIExample {
|
||||
{
|
||||
Name: "metric_promql",
|
||||
Summary: "Metric threshold PromQL rule",
|
||||
Description: "PromQL expression instead of the builder. Dotted OTEL resource attributes are quoted (\"deployment.environment\"). Useful for queries that combine series with group_right or other Prom operators.",
|
||||
Description: "PromQL expression instead of the builder. Dotted OTEL resource attributes are quoted (\"deployment.environment.name\"). Useful for queries that combine series with group_right or other Prom operators.",
|
||||
Value: map[string]any{
|
||||
"alert": "Kafka consumer group lag above 1000",
|
||||
"alertType": "METRIC_BASED_ALERT",
|
||||
@@ -187,7 +187,7 @@ func postableRuleExamples() []handler.OpenAPIExample {
|
||||
"type": "promql",
|
||||
"spec": map[string]any{
|
||||
"name": "A",
|
||||
"query": "(max by(topic, partition, \"deployment.environment\")(kafka_log_end_offset) - on(topic, partition, \"deployment.environment\") group_right max by(group, topic, partition, \"deployment.environment\")(kafka_consumer_committed_offset)) > 0",
|
||||
"query": "(max by(topic, partition, \"deployment.environment.name\")(kafka_log_end_offset) - on(topic, partition, \"deployment.environment.name\") group_right max by(group, topic, partition, \"deployment.environment.name\")(kafka_consumer_committed_offset)) > 0",
|
||||
"legend": "{{topic}}/{{partition}} ({{group}})",
|
||||
},
|
||||
},
|
||||
@@ -299,9 +299,9 @@ func postableRuleExamples() []handler.OpenAPIExample {
|
||||
"filter": map[string]any{"expression": "service.name = 'payments-api' AND severity_text = 'ERROR' AND body CONTAINS 'panic'"},
|
||||
"groupBy": []any{
|
||||
map[string]any{"name": "k8s.pod.name", "fieldContext": "resource", "fieldDataType": "string"},
|
||||
map[string]any{"name": "deployment.environment", "fieldContext": "resource", "fieldDataType": "string"},
|
||||
map[string]any{"name": "deployment.environment.name", "fieldContext": "resource", "fieldDataType": "string"},
|
||||
},
|
||||
"legend": "{{k8s.pod.name}} ({{deployment.environment}})",
|
||||
"legend": "{{k8s.pod.name}} ({{deployment.environment.name}})",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -322,12 +322,12 @@ func postableRuleExamples() []handler.OpenAPIExample {
|
||||
},
|
||||
"evaluation": rolling("5m", "1m"),
|
||||
"notificationSettings": map[string]any{
|
||||
"groupBy": []any{"k8s.pod.name", "deployment.environment"},
|
||||
"groupBy": []any{"k8s.pod.name", "deployment.environment.name"},
|
||||
"renotify": renotify("15m", "firing"),
|
||||
},
|
||||
"labels": map[string]any{"severity": "critical", "team": "payments"},
|
||||
"annotations": map[string]any{
|
||||
"description": "{{$k8s.pod.name}} emitted {{$value}} panic log(s) in {{$deployment.environment}}.",
|
||||
"description": "{{$k8s.pod.name}} emitted {{$value}} panic log(s) in {{$deployment.environment.name}}.",
|
||||
"summary": "Payments service panic",
|
||||
},
|
||||
},
|
||||
@@ -358,7 +358,7 @@ func postableRuleExamples() []handler.OpenAPIExample {
|
||||
"disabled": true,
|
||||
"aggregations": []any{map[string]any{"expression": "count()"}},
|
||||
"filter": map[string]any{"expression": "service.name = 'payments-api' AND severity_text IN ['ERROR', 'FATAL']"},
|
||||
"groupBy": []any{map[string]any{"name": "deployment.environment", "fieldContext": "resource", "fieldDataType": "string"}},
|
||||
"groupBy": []any{map[string]any{"name": "deployment.environment.name", "fieldContext": "resource", "fieldDataType": "string"}},
|
||||
},
|
||||
},
|
||||
map[string]any{
|
||||
@@ -370,7 +370,7 @@ func postableRuleExamples() []handler.OpenAPIExample {
|
||||
"disabled": true,
|
||||
"aggregations": []any{map[string]any{"expression": "count()"}},
|
||||
"filter": map[string]any{"expression": "service.name = 'payments-api'"},
|
||||
"groupBy": []any{map[string]any{"name": "deployment.environment", "fieldContext": "resource", "fieldDataType": "string"}},
|
||||
"groupBy": []any{map[string]any{"name": "deployment.environment.name", "fieldContext": "resource", "fieldDataType": "string"}},
|
||||
},
|
||||
},
|
||||
map[string]any{
|
||||
@@ -378,7 +378,7 @@ func postableRuleExamples() []handler.OpenAPIExample {
|
||||
"spec": map[string]any{
|
||||
"name": "F1",
|
||||
"expression": "(A / B) * 100",
|
||||
"legend": "{{deployment.environment}}",
|
||||
"legend": "{{deployment.environment.name}}",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -399,12 +399,12 @@ func postableRuleExamples() []handler.OpenAPIExample {
|
||||
},
|
||||
"evaluation": rolling("5m", "1m"),
|
||||
"notificationSettings": map[string]any{
|
||||
"groupBy": []any{"deployment.environment"},
|
||||
"groupBy": []any{"deployment.environment.name"},
|
||||
"renotify": renotify("30m", "firing"),
|
||||
},
|
||||
"labels": map[string]any{"severity": "critical", "team": "payments"},
|
||||
"annotations": map[string]any{
|
||||
"description": "Error log rate in {{$deployment.environment}} is {{$value}}%",
|
||||
"description": "Error log rate in {{$deployment.environment.name}} is {{$value}}%",
|
||||
"summary": "Payments-api error rate above {{$threshold}}%",
|
||||
},
|
||||
},
|
||||
@@ -669,10 +669,10 @@ func postableRuleExamples() []handler.OpenAPIExample {
|
||||
"stepInterval": 60,
|
||||
"disabled": true,
|
||||
"aggregations": []any{map[string]any{"expression": "count()"}},
|
||||
"filter": map[string]any{"expression": "service.name CONTAINS 'api' AND http.status_code >= 500"},
|
||||
"filter": map[string]any{"expression": "service.name CONTAINS 'api' AND http.response.status_code >= 500"},
|
||||
"groupBy": []any{
|
||||
map[string]any{"name": "service.name", "fieldContext": "resource", "fieldDataType": "string"},
|
||||
map[string]any{"name": "deployment.environment", "fieldContext": "resource", "fieldDataType": "string"},
|
||||
map[string]any{"name": "deployment.environment.name", "fieldContext": "resource", "fieldDataType": "string"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -687,7 +687,7 @@ func postableRuleExamples() []handler.OpenAPIExample {
|
||||
"filter": map[string]any{"expression": "service.name CONTAINS 'api'"},
|
||||
"groupBy": []any{
|
||||
map[string]any{"name": "service.name", "fieldContext": "resource", "fieldDataType": "string"},
|
||||
map[string]any{"name": "deployment.environment", "fieldContext": "resource", "fieldDataType": "string"},
|
||||
map[string]any{"name": "deployment.environment.name", "fieldContext": "resource", "fieldDataType": "string"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -696,7 +696,7 @@ func postableRuleExamples() []handler.OpenAPIExample {
|
||||
"spec": map[string]any{
|
||||
"name": "F1",
|
||||
"expression": "(A / B) * 100",
|
||||
"legend": "{{service.name}} ({{deployment.environment}})",
|
||||
"legend": "{{service.name}} ({{deployment.environment.name}})",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -717,14 +717,14 @@ func postableRuleExamples() []handler.OpenAPIExample {
|
||||
},
|
||||
"evaluation": rolling("5m", "1m"),
|
||||
"notificationSettings": map[string]any{
|
||||
"groupBy": []any{"service.name", "deployment.environment"},
|
||||
"groupBy": []any{"service.name", "deployment.environment.name"},
|
||||
"newGroupEvalDelay": "2m",
|
||||
"usePolicy": false,
|
||||
"renotify": renotify("30m", "firing", "nodata"),
|
||||
},
|
||||
"labels": map[string]any{"team": "platform"},
|
||||
"annotations": map[string]any{
|
||||
"description": "{{$service.name}} 5xx rate in {{$deployment.environment}} is {{$value}}%.",
|
||||
"description": "{{$service.name}} 5xx rate in {{$deployment.environment.name}} is {{$value}}%.",
|
||||
"summary": "API service error rate elevated",
|
||||
},
|
||||
},
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"strings"
|
||||
|
||||
parser "github.com/SigNoz/signoz/pkg/parser/filterquery/grammar"
|
||||
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
|
||||
"github.com/antlr4-go/antlr/v4"
|
||||
"golang.org/x/exp/maps"
|
||||
|
||||
@@ -187,25 +188,35 @@ func (r *WhereClauseRewriter) VisitPrimary(ctx *parser.PrimaryContext) any {
|
||||
|
||||
// VisitComparison visits comparison expressions.
|
||||
func (r *WhereClauseRewriter) VisitComparison(ctx *parser.ComparisonContext) any {
|
||||
if ctx.Key() == nil {
|
||||
if ctx.Field() == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
key := ctx.Key().GetText()
|
||||
field := ctx.Field().GetText()
|
||||
key := field
|
||||
if exactCall := ctx.Field().ExactCall(); exactCall != nil {
|
||||
key = exactCall.Key().GetText()
|
||||
}
|
||||
r.keysSeen[key] = struct{}{}
|
||||
parsedKey := telemetrytypes.GetFieldKeyFromKeyText(key)
|
||||
r.keysSeen[parsedKey.Name] = struct{}{}
|
||||
labelKey := key
|
||||
if _, exists := r.labels[labelKey]; !exists {
|
||||
labelKey = parsedKey.Name
|
||||
}
|
||||
|
||||
// Check if this key is in the labels and was part of group by
|
||||
if value, exists := r.labels[key]; exists {
|
||||
if _, partOfGroup := r.groupBySet[key]; partOfGroup {
|
||||
if value, exists := r.labels[labelKey]; exists {
|
||||
if _, partOfGroup := r.groupBySet[labelKey]; partOfGroup {
|
||||
// Case 1: Replace with actual value
|
||||
escapedValue := escapeValueIfNeeded(value)
|
||||
fmt.Fprintf(&r.rewritten, "%s=%s", key, escapedValue)
|
||||
fmt.Fprintf(&r.rewritten, "%s=%s", field, escapedValue)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, keep the original comparison
|
||||
r.rewritten.WriteString(key)
|
||||
r.rewritten.WriteString(field)
|
||||
|
||||
if ctx.EQUALS() != nil {
|
||||
r.rewritten.WriteString("=")
|
||||
@@ -408,8 +419,8 @@ func (r *WhereClauseRewriter) VisitFunctionParamList(ctx *parser.FunctionParamLi
|
||||
|
||||
// VisitFunctionParam visits function parameters.
|
||||
func (r *WhereClauseRewriter) VisitFunctionParam(ctx *parser.FunctionParamContext) any {
|
||||
if ctx.Key() != nil {
|
||||
ctx.Key().Accept(r)
|
||||
if ctx.Field() != nil {
|
||||
r.rewritten.WriteString(ctx.Field().GetText())
|
||||
} else if ctx.Value() != nil {
|
||||
ctx.Value().Accept(r)
|
||||
} else if ctx.Array() != nil {
|
||||
|
||||
@@ -234,6 +234,18 @@ func TestPrepareFiltersV5(t *testing.T) {
|
||||
expected: "(error_details EXISTS) AND service.name='serviceA'",
|
||||
description: "Should preserve EXISTS operator",
|
||||
},
|
||||
{
|
||||
name: "exact_field_label_replacement",
|
||||
labels: map[string]string{
|
||||
"deployment.environment": "production",
|
||||
},
|
||||
whereClause: "exact(resource.deployment.environment) = 'staging'",
|
||||
groupByItems: []qbtypes.GroupByKey{
|
||||
{TelemetryFieldKey: telemetrytypes.TelemetryFieldKey{Name: "deployment.environment"}},
|
||||
},
|
||||
expected: "exact(resource.deployment.environment)='production'",
|
||||
description: "Should keep the exact wrapper when replacing a grouped label",
|
||||
},
|
||||
|
||||
{
|
||||
name: "empty_where_clause_with_labels",
|
||||
|
||||
@@ -23,13 +23,13 @@ func TestSource(t *testing.T) {
|
||||
err := json.Unmarshal(buf.Bytes(), &m)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Contains(t, m, "code.filepath")
|
||||
assert.Contains(t, m, "code.function")
|
||||
assert.Contains(t, m, "code.lineno")
|
||||
assert.Contains(t, m, "code.file.path")
|
||||
assert.Contains(t, m, "code.function.name")
|
||||
assert.Contains(t, m, "code.line.number")
|
||||
|
||||
assert.Contains(t, m["code.filepath"], "source_test.go")
|
||||
assert.Contains(t, m["code.function"], "TestSource")
|
||||
assert.NotZero(t, m["code.lineno"])
|
||||
assert.Contains(t, m["code.file.path"], "source_test.go")
|
||||
assert.Contains(t, m["code.function.name"], "TestSource")
|
||||
assert.NotZero(t, m["code.line.number"])
|
||||
|
||||
// Ensure the nested "source" key is not present.
|
||||
assert.NotContains(t, m, "source")
|
||||
|
||||
@@ -136,7 +136,12 @@ func (v *visitor) VisitPrimary(ctx *grammar.PrimaryContext) any {
|
||||
// predicate; any other identifier is treated as a tag key — the operator
|
||||
// applies to the tag's value, with a case-insensitive match on the tag's key.
|
||||
func (v *visitor) VisitComparison(ctx *grammar.ComparisonContext) any {
|
||||
key := strings.ToLower(strings.TrimSpace(ctx.Key().GetText()))
|
||||
field := ctx.Field()
|
||||
keyText := field.GetText()
|
||||
if exactCall := field.ExactCall(); exactCall != nil {
|
||||
keyText = exactCall.Key().GetText()
|
||||
}
|
||||
key := strings.ToLower(strings.TrimSpace(keyText))
|
||||
|
||||
operation, ok := v.extractOperation(ctx)
|
||||
if !ok {
|
||||
@@ -427,7 +432,7 @@ func (v *visitor) buildFreeTextTerm(value string) string {
|
||||
}
|
||||
|
||||
// buildFreeTextContains emits a case-insensitive contains as
|
||||
// LOWER(COALESCE(col, '')) LIKE LOWER(?), identical on SQLite and Postgres.
|
||||
// LOWER(COALESCE(col, ”)) LIKE LOWER(?), identical on SQLite and Postgres.
|
||||
// COALESCE keeps a NULL column (an absent description) false rather than NULL —
|
||||
// otherwise `NOT (…)` goes NULL and drops every description-less dashboard. The
|
||||
// value's % and _ are escaped, and ESCAPE pins backslash as the escape char.
|
||||
|
||||
@@ -8,4 +8,7 @@ type Handler interface {
|
||||
|
||||
// Gets the fields values for the given field value selector
|
||||
GetFieldsValues(http.ResponseWriter, *http.Request)
|
||||
|
||||
// Gets services that still emit only historical semantic-convention names.
|
||||
GetSemconvMigrationReport(http.ResponseWriter, *http.Request)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package implfields
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/factory"
|
||||
"github.com/SigNoz/signoz/pkg/http/binding"
|
||||
@@ -16,6 +17,43 @@ type handler struct {
|
||||
telemetryMetadataStore telemetrytypes.MetadataStore
|
||||
}
|
||||
|
||||
func (handler *handler) GetSemconvMigrationReport(rw http.ResponseWriter, req *http.Request) {
|
||||
ctx := req.Context()
|
||||
|
||||
var params telemetrytypes.PostableSemconvMigrationReportParams
|
||||
if err := binding.Query.BindQuery(req.URL.Query(), ¶ms); err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
if params.EndUnixMilli == 0 {
|
||||
params.EndUnixMilli = now.UnixMilli()
|
||||
}
|
||||
if params.StartUnixMilli == 0 {
|
||||
params.StartUnixMilli = now.Add(-24 * time.Hour).UnixMilli()
|
||||
}
|
||||
|
||||
claims, err := authtypes.ClaimsFromContext(ctx)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
report, err := handler.telemetryMetadataStore.GetSemconvMigrationReport(
|
||||
ctx,
|
||||
valuer.MustNewUUID(claims.OrgID),
|
||||
params.StartUnixMilli,
|
||||
params.EndUnixMilli,
|
||||
)
|
||||
if err != nil {
|
||||
render.Error(rw, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.Success(rw, http.StatusOK, report)
|
||||
}
|
||||
|
||||
func NewHandler(settings factory.ProviderSettings, telemetryMetadataStore telemetrytypes.MetadataStore) fields.Handler {
|
||||
return &handler{
|
||||
telemetryMetadataStore: telemetryMetadataStore,
|
||||
|
||||
65
pkg/modules/metricreductionrule/validation.go
Normal file
65
pkg/modules/metricreductionrule/validation.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package metricreductionrule
|
||||
|
||||
import (
|
||||
"github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/semconv"
|
||||
"github.com/SigNoz/signoz/pkg/types/metricreductionruletypes"
|
||||
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
|
||||
)
|
||||
|
||||
var protectedLabels = buildProtectedLabels()
|
||||
|
||||
// ValidatePostableReductionRule validates request structure and protected-label
|
||||
// policy before a rule reaches storage.
|
||||
func ValidatePostableReductionRule(req *metricreductionruletypes.PostableReductionRule) error {
|
||||
if err := req.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
return validateProtectedLabels(req.MatchType, req.Labels)
|
||||
}
|
||||
|
||||
// ValidateUpdatableReductionRule validates request structure and
|
||||
// protected-label policy before a rule reaches storage.
|
||||
func ValidateUpdatableReductionRule(req *metricreductionruletypes.UpdatableReductionRule) error {
|
||||
if err := req.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
return validateProtectedLabels(req.MatchType, req.Labels)
|
||||
}
|
||||
|
||||
// IsProtectedLabel reports whether metric reduction must always retain label.
|
||||
func IsProtectedLabel(label string) bool {
|
||||
_, ok := protectedLabels[label]
|
||||
return ok
|
||||
}
|
||||
|
||||
func buildProtectedLabels() map[string]struct{} {
|
||||
labels := map[string]struct{}{
|
||||
"le": {},
|
||||
"quantile": {},
|
||||
"__name__": {},
|
||||
"__temporality__": {},
|
||||
}
|
||||
selector := telemetrytypes.FieldKeySelector{
|
||||
Name: "deployment.environment.name",
|
||||
Signal: telemetrytypes.SignalMetrics,
|
||||
FieldContext: telemetrytypes.FieldContextResource,
|
||||
}
|
||||
for _, member := range semconv.Members(semconv.KindAttribute, selector) {
|
||||
labels[member] = struct{}{}
|
||||
}
|
||||
return labels
|
||||
}
|
||||
|
||||
func validateProtectedLabels(matchType metricreductionruletypes.MatchType, labels []string) error {
|
||||
if matchType != metricreductionruletypes.MatchTypeDrop {
|
||||
return nil
|
||||
}
|
||||
for _, label := range labels {
|
||||
if IsProtectedLabel(label) {
|
||||
return errors.Newf(errors.TypeInvalidInput, metricreductionruletypes.ErrCodeMetricReductionRuleProtectedLabel,
|
||||
"label %q is protected and cannot be dropped", label)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
64
pkg/modules/metricreductionrule/validation_test.go
Normal file
64
pkg/modules/metricreductionrule/validation_test.go
Normal file
@@ -0,0 +1,64 @@
|
||||
package metricreductionrule_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/modules/metricreductionrule"
|
||||
"github.com/SigNoz/signoz/pkg/types/metricreductionruletypes"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestDropRuleRejectsBuiltInProtectedLabel(t *testing.T) {
|
||||
req := &metricreductionruletypes.UpdatableReductionRule{
|
||||
MatchType: metricreductionruletypes.MatchTypeDrop,
|
||||
Labels: []string{"le"},
|
||||
}
|
||||
|
||||
err := metricreductionrule.ValidateUpdatableReductionRule(req)
|
||||
|
||||
assert.Error(t, err, "histogram boundary label must remain protected")
|
||||
}
|
||||
|
||||
func TestDropRuleRejectsCurrentEnvironmentLabel(t *testing.T) {
|
||||
req := &metricreductionruletypes.UpdatableReductionRule{
|
||||
MatchType: metricreductionruletypes.MatchTypeDrop,
|
||||
Labels: []string{"deployment.environment.name"},
|
||||
}
|
||||
|
||||
err := metricreductionrule.ValidateUpdatableReductionRule(req)
|
||||
|
||||
assert.Error(t, err, "current deployment environment label must remain protected")
|
||||
}
|
||||
|
||||
func TestDropRuleRejectsHistoricalEnvironmentLabel(t *testing.T) {
|
||||
req := &metricreductionruletypes.UpdatableReductionRule{
|
||||
MatchType: metricreductionruletypes.MatchTypeDrop,
|
||||
Labels: []string{"deployment.environment"},
|
||||
}
|
||||
|
||||
err := metricreductionrule.ValidateUpdatableReductionRule(req)
|
||||
|
||||
assert.Error(t, err, "historical deployment environment label must remain protected")
|
||||
}
|
||||
|
||||
func TestKeepRuleAllowsProtectedLabel(t *testing.T) {
|
||||
req := &metricreductionruletypes.UpdatableReductionRule{
|
||||
MatchType: metricreductionruletypes.MatchTypeKeep,
|
||||
Labels: []string{"le"},
|
||||
}
|
||||
|
||||
err := metricreductionrule.ValidateUpdatableReductionRule(req)
|
||||
|
||||
assert.NoError(t, err, "a keep rule may retain a protected label")
|
||||
}
|
||||
|
||||
func TestDropRuleAllowsUnprotectedLabel(t *testing.T) {
|
||||
req := &metricreductionruletypes.UpdatableReductionRule{
|
||||
MatchType: metricreductionruletypes.MatchTypeDrop,
|
||||
Labels: []string{"host.name"},
|
||||
}
|
||||
|
||||
err := metricreductionrule.ValidateUpdatableReductionRule(req)
|
||||
|
||||
assert.NoError(t, err, "an ordinary label may be dropped")
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -25,12 +25,13 @@ HAS=24
|
||||
HASANY=25
|
||||
HASALL=26
|
||||
SEARCH=27
|
||||
BOOL=28
|
||||
NUMBER=29
|
||||
QUOTED_TEXT=30
|
||||
KEY=31
|
||||
WS=32
|
||||
FREETEXT=33
|
||||
EXACT=28
|
||||
BOOL=29
|
||||
NUMBER=30
|
||||
QUOTED_TEXT=31
|
||||
KEY=32
|
||||
WS=33
|
||||
FREETEXT=34
|
||||
'('=1
|
||||
')'=2
|
||||
'['=3
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -25,12 +25,13 @@ HAS=24
|
||||
HASANY=25
|
||||
HASALL=26
|
||||
SEARCH=27
|
||||
BOOL=28
|
||||
NUMBER=29
|
||||
QUOTED_TEXT=30
|
||||
KEY=31
|
||||
WS=32
|
||||
FREETEXT=33
|
||||
EXACT=28
|
||||
BOOL=29
|
||||
NUMBER=30
|
||||
QUOTED_TEXT=31
|
||||
KEY=32
|
||||
WS=33
|
||||
FREETEXT=34
|
||||
'('=1
|
||||
')'=2
|
||||
'['=3
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated from FilterQuery.g4 by ANTLR 4.13.2. DO NOT EDIT.
|
||||
// Code generated from grammar/FilterQuery.g4 by ANTLR 4.13.2. DO NOT EDIT.
|
||||
|
||||
package parser // FilterQuery
|
||||
|
||||
@@ -128,3 +128,15 @@ func (s *BaseFilterQueryListener) EnterKey(ctx *KeyContext) {}
|
||||
|
||||
// ExitKey is called when production key is exited.
|
||||
func (s *BaseFilterQueryListener) ExitKey(ctx *KeyContext) {}
|
||||
|
||||
// EnterField is called when production field is entered.
|
||||
func (s *BaseFilterQueryListener) EnterField(ctx *FieldContext) {}
|
||||
|
||||
// ExitField is called when production field is exited.
|
||||
func (s *BaseFilterQueryListener) ExitField(ctx *FieldContext) {}
|
||||
|
||||
// EnterExactCall is called when production exactCall is entered.
|
||||
func (s *BaseFilterQueryListener) EnterExactCall(ctx *ExactCallContext) {}
|
||||
|
||||
// ExitExactCall is called when production exactCall is exited.
|
||||
func (s *BaseFilterQueryListener) ExitExactCall(ctx *ExactCallContext) {}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated from FilterQuery.g4 by ANTLR 4.13.2. DO NOT EDIT.
|
||||
// Code generated from grammar/FilterQuery.g4 by ANTLR 4.13.2. DO NOT EDIT.
|
||||
|
||||
package parser // FilterQuery
|
||||
|
||||
@@ -79,3 +79,11 @@ func (v *BaseFilterQueryVisitor) VisitValue(ctx *ValueContext) interface{} {
|
||||
func (v *BaseFilterQueryVisitor) VisitKey(ctx *KeyContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseFilterQueryVisitor) VisitField(ctx *FieldContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
func (v *BaseFilterQueryVisitor) VisitExactCall(ctx *ExactCallContext) interface{} {
|
||||
return v.VisitChildren(ctx)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated from FilterQuery.g4 by ANTLR 4.13.2. DO NOT EDIT.
|
||||
// Code generated from grammar/FilterQuery.g4 by ANTLR 4.13.2. DO NOT EDIT.
|
||||
|
||||
package parser
|
||||
|
||||
@@ -50,66 +50,69 @@ func filterquerylexerLexerInit() {
|
||||
"", "LPAREN", "RPAREN", "LBRACK", "RBRACK", "COMMA", "EQUALS", "NOT_EQUALS",
|
||||
"NEQ", "LT", "LE", "GT", "GE", "LIKE", "ILIKE", "BETWEEN", "EXISTS",
|
||||
"REGEXP", "CONTAINS", "IN", "NOT", "AND", "OR", "HASTOKEN", "HAS", "HASANY",
|
||||
"HASALL", "SEARCH", "BOOL", "NUMBER", "QUOTED_TEXT", "KEY", "WS", "FREETEXT",
|
||||
"HASALL", "SEARCH", "EXACT", "BOOL", "NUMBER", "QUOTED_TEXT", "KEY",
|
||||
"WS", "FREETEXT",
|
||||
}
|
||||
staticData.RuleNames = []string{
|
||||
"LPAREN", "RPAREN", "LBRACK", "RBRACK", "COMMA", "EQUALS", "NOT_EQUALS",
|
||||
"NEQ", "LT", "LE", "GT", "GE", "LIKE", "ILIKE", "BETWEEN", "EXISTS",
|
||||
"REGEXP", "CONTAINS", "IN", "NOT", "AND", "OR", "HASTOKEN", "HAS", "HASANY",
|
||||
"HASALL", "SEARCH", "BOOL", "SIGN", "NUMBER", "QUOTED_TEXT", "SEGMENT",
|
||||
"EMPTY_BRACKS", "OLD_JSON_BRACKS", "KEY", "WS", "DIGIT", "FREETEXT",
|
||||
"HASALL", "SEARCH", "EXACT", "BOOL", "SIGN", "NUMBER", "QUOTED_TEXT",
|
||||
"SEGMENT", "EMPTY_BRACKS", "OLD_JSON_BRACKS", "KEY", "WS", "DIGIT",
|
||||
"FREETEXT",
|
||||
}
|
||||
staticData.PredictionContextCache = antlr.NewPredictionContextCache()
|
||||
staticData.serializedATN = []int32{
|
||||
4, 0, 33, 329, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2,
|
||||
4, 0, 34, 337, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2,
|
||||
4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2,
|
||||
10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15,
|
||||
7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7,
|
||||
20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25,
|
||||
2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2,
|
||||
31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36,
|
||||
7, 36, 2, 37, 7, 37, 1, 0, 1, 0, 1, 1, 1, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1,
|
||||
4, 1, 4, 1, 5, 1, 5, 1, 5, 3, 5, 91, 8, 5, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7,
|
||||
1, 7, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11,
|
||||
1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1,
|
||||
13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15,
|
||||
1, 15, 1, 15, 1, 15, 1, 15, 3, 15, 134, 8, 15, 1, 16, 1, 16, 1, 16, 1,
|
||||
16, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17,
|
||||
1, 17, 3, 17, 151, 8, 17, 1, 18, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1,
|
||||
19, 1, 20, 1, 20, 1, 20, 1, 20, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22,
|
||||
1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 1, 23, 1, 23, 1,
|
||||
24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 1, 25,
|
||||
1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1,
|
||||
27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 3, 27, 210,
|
||||
8, 27, 1, 28, 1, 28, 1, 29, 3, 29, 215, 8, 29, 1, 29, 4, 29, 218, 8, 29,
|
||||
11, 29, 12, 29, 219, 1, 29, 1, 29, 5, 29, 224, 8, 29, 10, 29, 12, 29, 227,
|
||||
9, 29, 3, 29, 229, 8, 29, 1, 29, 1, 29, 3, 29, 233, 8, 29, 1, 29, 4, 29,
|
||||
236, 8, 29, 11, 29, 12, 29, 237, 3, 29, 240, 8, 29, 1, 29, 3, 29, 243,
|
||||
8, 29, 1, 29, 1, 29, 4, 29, 247, 8, 29, 11, 29, 12, 29, 248, 1, 29, 1,
|
||||
29, 3, 29, 253, 8, 29, 1, 29, 4, 29, 256, 8, 29, 11, 29, 12, 29, 257, 3,
|
||||
29, 260, 8, 29, 3, 29, 262, 8, 29, 1, 30, 1, 30, 1, 30, 1, 30, 5, 30, 268,
|
||||
8, 30, 10, 30, 12, 30, 271, 9, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 5,
|
||||
30, 278, 8, 30, 10, 30, 12, 30, 281, 9, 30, 1, 30, 3, 30, 284, 8, 30, 1,
|
||||
31, 1, 31, 5, 31, 288, 8, 31, 10, 31, 12, 31, 291, 9, 31, 1, 32, 1, 32,
|
||||
1, 32, 1, 33, 1, 33, 1, 33, 1, 33, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 1,
|
||||
34, 1, 34, 4, 34, 307, 8, 34, 11, 34, 12, 34, 308, 5, 34, 311, 8, 34, 10,
|
||||
34, 12, 34, 314, 9, 34, 1, 35, 4, 35, 317, 8, 35, 11, 35, 12, 35, 318,
|
||||
1, 35, 1, 35, 1, 36, 1, 36, 1, 37, 4, 37, 326, 8, 37, 11, 37, 12, 37, 327,
|
||||
0, 0, 38, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19,
|
||||
10, 21, 11, 23, 12, 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37,
|
||||
19, 39, 20, 41, 21, 43, 22, 45, 23, 47, 24, 49, 25, 51, 26, 53, 27, 55,
|
||||
28, 57, 0, 59, 29, 61, 30, 63, 0, 65, 0, 67, 0, 69, 31, 71, 32, 73, 0,
|
||||
75, 33, 1, 0, 29, 2, 0, 76, 76, 108, 108, 2, 0, 73, 73, 105, 105, 2, 0,
|
||||
75, 75, 107, 107, 2, 0, 69, 69, 101, 101, 2, 0, 66, 66, 98, 98, 2, 0, 84,
|
||||
84, 116, 116, 2, 0, 87, 87, 119, 119, 2, 0, 78, 78, 110, 110, 2, 0, 88,
|
||||
88, 120, 120, 2, 0, 83, 83, 115, 115, 2, 0, 82, 82, 114, 114, 2, 0, 71,
|
||||
71, 103, 103, 2, 0, 80, 80, 112, 112, 2, 0, 67, 67, 99, 99, 2, 0, 79, 79,
|
||||
111, 111, 2, 0, 65, 65, 97, 97, 2, 0, 68, 68, 100, 100, 2, 0, 72, 72, 104,
|
||||
104, 2, 0, 89, 89, 121, 121, 2, 0, 85, 85, 117, 117, 2, 0, 70, 70, 102,
|
||||
102, 2, 0, 43, 43, 45, 45, 2, 0, 34, 34, 92, 92, 2, 0, 39, 39, 92, 92,
|
||||
4, 0, 35, 36, 64, 90, 95, 95, 97, 123, 7, 0, 35, 36, 45, 45, 47, 58, 64,
|
||||
90, 95, 95, 97, 123, 125, 125, 3, 0, 9, 10, 13, 13, 32, 32, 1, 0, 48, 57,
|
||||
8, 0, 9, 10, 13, 13, 32, 34, 39, 41, 44, 44, 60, 62, 91, 91, 93, 93, 353,
|
||||
7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 1, 0, 1, 0, 1, 1, 1, 1, 1, 2, 1, 2,
|
||||
1, 3, 1, 3, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 3, 5, 93, 8, 5, 1, 6, 1, 6, 1,
|
||||
6, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 11,
|
||||
1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1,
|
||||
13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14,
|
||||
1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 3, 15, 136, 8, 15, 1, 16, 1,
|
||||
16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17,
|
||||
1, 17, 1, 17, 1, 17, 3, 17, 153, 8, 17, 1, 18, 1, 18, 1, 18, 1, 19, 1,
|
||||
19, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 1, 20, 1, 21, 1, 21, 1, 21, 1, 22,
|
||||
1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 1,
|
||||
23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25,
|
||||
1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1,
|
||||
26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28,
|
||||
1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 3, 28, 218, 8, 28, 1, 29, 1,
|
||||
29, 1, 30, 3, 30, 223, 8, 30, 1, 30, 4, 30, 226, 8, 30, 11, 30, 12, 30,
|
||||
227, 1, 30, 1, 30, 5, 30, 232, 8, 30, 10, 30, 12, 30, 235, 9, 30, 3, 30,
|
||||
237, 8, 30, 1, 30, 1, 30, 3, 30, 241, 8, 30, 1, 30, 4, 30, 244, 8, 30,
|
||||
11, 30, 12, 30, 245, 3, 30, 248, 8, 30, 1, 30, 3, 30, 251, 8, 30, 1, 30,
|
||||
1, 30, 4, 30, 255, 8, 30, 11, 30, 12, 30, 256, 1, 30, 1, 30, 3, 30, 261,
|
||||
8, 30, 1, 30, 4, 30, 264, 8, 30, 11, 30, 12, 30, 265, 3, 30, 268, 8, 30,
|
||||
3, 30, 270, 8, 30, 1, 31, 1, 31, 1, 31, 1, 31, 5, 31, 276, 8, 31, 10, 31,
|
||||
12, 31, 279, 9, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 5, 31, 286, 8, 31,
|
||||
10, 31, 12, 31, 289, 9, 31, 1, 31, 3, 31, 292, 8, 31, 1, 32, 1, 32, 5,
|
||||
32, 296, 8, 32, 10, 32, 12, 32, 299, 9, 32, 1, 33, 1, 33, 1, 33, 1, 34,
|
||||
1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 4,
|
||||
35, 315, 8, 35, 11, 35, 12, 35, 316, 5, 35, 319, 8, 35, 10, 35, 12, 35,
|
||||
322, 9, 35, 1, 36, 4, 36, 325, 8, 36, 11, 36, 12, 36, 326, 1, 36, 1, 36,
|
||||
1, 37, 1, 37, 1, 38, 4, 38, 334, 8, 38, 11, 38, 12, 38, 335, 0, 0, 39,
|
||||
1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11,
|
||||
23, 12, 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20,
|
||||
41, 21, 43, 22, 45, 23, 47, 24, 49, 25, 51, 26, 53, 27, 55, 28, 57, 29,
|
||||
59, 0, 61, 30, 63, 31, 65, 0, 67, 0, 69, 0, 71, 32, 73, 33, 75, 0, 77,
|
||||
34, 1, 0, 29, 2, 0, 76, 76, 108, 108, 2, 0, 73, 73, 105, 105, 2, 0, 75,
|
||||
75, 107, 107, 2, 0, 69, 69, 101, 101, 2, 0, 66, 66, 98, 98, 2, 0, 84, 84,
|
||||
116, 116, 2, 0, 87, 87, 119, 119, 2, 0, 78, 78, 110, 110, 2, 0, 88, 88,
|
||||
120, 120, 2, 0, 83, 83, 115, 115, 2, 0, 82, 82, 114, 114, 2, 0, 71, 71,
|
||||
103, 103, 2, 0, 80, 80, 112, 112, 2, 0, 67, 67, 99, 99, 2, 0, 79, 79, 111,
|
||||
111, 2, 0, 65, 65, 97, 97, 2, 0, 68, 68, 100, 100, 2, 0, 72, 72, 104, 104,
|
||||
2, 0, 89, 89, 121, 121, 2, 0, 85, 85, 117, 117, 2, 0, 70, 70, 102, 102,
|
||||
2, 0, 43, 43, 45, 45, 2, 0, 34, 34, 92, 92, 2, 0, 39, 39, 92, 92, 4, 0,
|
||||
35, 36, 64, 90, 95, 95, 97, 123, 7, 0, 35, 36, 45, 45, 47, 58, 64, 90,
|
||||
95, 95, 97, 123, 125, 125, 3, 0, 9, 10, 13, 13, 32, 32, 1, 0, 48, 57, 8,
|
||||
0, 9, 10, 13, 13, 32, 34, 39, 41, 44, 44, 60, 62, 91, 91, 93, 93, 361,
|
||||
0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0,
|
||||
0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0,
|
||||
0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0,
|
||||
@@ -117,107 +120,110 @@ func filterquerylexerLexerInit() {
|
||||
0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39,
|
||||
1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0,
|
||||
47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0,
|
||||
0, 55, 1, 0, 0, 0, 0, 59, 1, 0, 0, 0, 0, 61, 1, 0, 0, 0, 0, 69, 1, 0, 0,
|
||||
0, 0, 71, 1, 0, 0, 0, 0, 75, 1, 0, 0, 0, 1, 77, 1, 0, 0, 0, 3, 79, 1, 0,
|
||||
0, 0, 5, 81, 1, 0, 0, 0, 7, 83, 1, 0, 0, 0, 9, 85, 1, 0, 0, 0, 11, 90,
|
||||
1, 0, 0, 0, 13, 92, 1, 0, 0, 0, 15, 95, 1, 0, 0, 0, 17, 98, 1, 0, 0, 0,
|
||||
19, 100, 1, 0, 0, 0, 21, 103, 1, 0, 0, 0, 23, 105, 1, 0, 0, 0, 25, 108,
|
||||
1, 0, 0, 0, 27, 113, 1, 0, 0, 0, 29, 119, 1, 0, 0, 0, 31, 127, 1, 0, 0,
|
||||
0, 33, 135, 1, 0, 0, 0, 35, 142, 1, 0, 0, 0, 37, 152, 1, 0, 0, 0, 39, 155,
|
||||
1, 0, 0, 0, 41, 159, 1, 0, 0, 0, 43, 163, 1, 0, 0, 0, 45, 166, 1, 0, 0,
|
||||
0, 47, 175, 1, 0, 0, 0, 49, 179, 1, 0, 0, 0, 51, 186, 1, 0, 0, 0, 53, 193,
|
||||
1, 0, 0, 0, 55, 209, 1, 0, 0, 0, 57, 211, 1, 0, 0, 0, 59, 261, 1, 0, 0,
|
||||
0, 61, 283, 1, 0, 0, 0, 63, 285, 1, 0, 0, 0, 65, 292, 1, 0, 0, 0, 67, 295,
|
||||
1, 0, 0, 0, 69, 299, 1, 0, 0, 0, 71, 316, 1, 0, 0, 0, 73, 322, 1, 0, 0,
|
||||
0, 75, 325, 1, 0, 0, 0, 77, 78, 5, 40, 0, 0, 78, 2, 1, 0, 0, 0, 79, 80,
|
||||
5, 41, 0, 0, 80, 4, 1, 0, 0, 0, 81, 82, 5, 91, 0, 0, 82, 6, 1, 0, 0, 0,
|
||||
83, 84, 5, 93, 0, 0, 84, 8, 1, 0, 0, 0, 85, 86, 5, 44, 0, 0, 86, 10, 1,
|
||||
0, 0, 0, 87, 91, 5, 61, 0, 0, 88, 89, 5, 61, 0, 0, 89, 91, 5, 61, 0, 0,
|
||||
90, 87, 1, 0, 0, 0, 90, 88, 1, 0, 0, 0, 91, 12, 1, 0, 0, 0, 92, 93, 5,
|
||||
33, 0, 0, 93, 94, 5, 61, 0, 0, 94, 14, 1, 0, 0, 0, 95, 96, 5, 60, 0, 0,
|
||||
96, 97, 5, 62, 0, 0, 97, 16, 1, 0, 0, 0, 98, 99, 5, 60, 0, 0, 99, 18, 1,
|
||||
0, 0, 0, 100, 101, 5, 60, 0, 0, 101, 102, 5, 61, 0, 0, 102, 20, 1, 0, 0,
|
||||
0, 103, 104, 5, 62, 0, 0, 104, 22, 1, 0, 0, 0, 105, 106, 5, 62, 0, 0, 106,
|
||||
107, 5, 61, 0, 0, 107, 24, 1, 0, 0, 0, 108, 109, 7, 0, 0, 0, 109, 110,
|
||||
7, 1, 0, 0, 110, 111, 7, 2, 0, 0, 111, 112, 7, 3, 0, 0, 112, 26, 1, 0,
|
||||
0, 0, 113, 114, 7, 1, 0, 0, 114, 115, 7, 0, 0, 0, 115, 116, 7, 1, 0, 0,
|
||||
116, 117, 7, 2, 0, 0, 117, 118, 7, 3, 0, 0, 118, 28, 1, 0, 0, 0, 119, 120,
|
||||
7, 4, 0, 0, 120, 121, 7, 3, 0, 0, 121, 122, 7, 5, 0, 0, 122, 123, 7, 6,
|
||||
0, 0, 123, 124, 7, 3, 0, 0, 124, 125, 7, 3, 0, 0, 125, 126, 7, 7, 0, 0,
|
||||
126, 30, 1, 0, 0, 0, 127, 128, 7, 3, 0, 0, 128, 129, 7, 8, 0, 0, 129, 130,
|
||||
7, 1, 0, 0, 130, 131, 7, 9, 0, 0, 131, 133, 7, 5, 0, 0, 132, 134, 7, 9,
|
||||
0, 0, 133, 132, 1, 0, 0, 0, 133, 134, 1, 0, 0, 0, 134, 32, 1, 0, 0, 0,
|
||||
135, 136, 7, 10, 0, 0, 136, 137, 7, 3, 0, 0, 137, 138, 7, 11, 0, 0, 138,
|
||||
139, 7, 3, 0, 0, 139, 140, 7, 8, 0, 0, 140, 141, 7, 12, 0, 0, 141, 34,
|
||||
1, 0, 0, 0, 142, 143, 7, 13, 0, 0, 143, 144, 7, 14, 0, 0, 144, 145, 7,
|
||||
7, 0, 0, 145, 146, 7, 5, 0, 0, 146, 147, 7, 15, 0, 0, 147, 148, 7, 1, 0,
|
||||
0, 148, 150, 7, 7, 0, 0, 149, 151, 7, 9, 0, 0, 150, 149, 1, 0, 0, 0, 150,
|
||||
151, 1, 0, 0, 0, 151, 36, 1, 0, 0, 0, 152, 153, 7, 1, 0, 0, 153, 154, 7,
|
||||
7, 0, 0, 154, 38, 1, 0, 0, 0, 155, 156, 7, 7, 0, 0, 156, 157, 7, 14, 0,
|
||||
0, 157, 158, 7, 5, 0, 0, 158, 40, 1, 0, 0, 0, 159, 160, 7, 15, 0, 0, 160,
|
||||
161, 7, 7, 0, 0, 161, 162, 7, 16, 0, 0, 162, 42, 1, 0, 0, 0, 163, 164,
|
||||
7, 14, 0, 0, 164, 165, 7, 10, 0, 0, 165, 44, 1, 0, 0, 0, 166, 167, 7, 17,
|
||||
0, 0, 167, 168, 7, 15, 0, 0, 168, 169, 7, 9, 0, 0, 169, 170, 7, 5, 0, 0,
|
||||
170, 171, 7, 14, 0, 0, 171, 172, 7, 2, 0, 0, 172, 173, 7, 3, 0, 0, 173,
|
||||
174, 7, 7, 0, 0, 174, 46, 1, 0, 0, 0, 175, 176, 7, 17, 0, 0, 176, 177,
|
||||
7, 15, 0, 0, 177, 178, 7, 9, 0, 0, 178, 48, 1, 0, 0, 0, 179, 180, 7, 17,
|
||||
0, 0, 180, 181, 7, 15, 0, 0, 181, 182, 7, 9, 0, 0, 182, 183, 7, 15, 0,
|
||||
0, 183, 184, 7, 7, 0, 0, 184, 185, 7, 18, 0, 0, 185, 50, 1, 0, 0, 0, 186,
|
||||
187, 7, 17, 0, 0, 187, 188, 7, 15, 0, 0, 188, 189, 7, 9, 0, 0, 189, 190,
|
||||
7, 15, 0, 0, 190, 191, 7, 0, 0, 0, 191, 192, 7, 0, 0, 0, 192, 52, 1, 0,
|
||||
0, 0, 193, 194, 7, 9, 0, 0, 194, 195, 7, 3, 0, 0, 195, 196, 7, 15, 0, 0,
|
||||
196, 197, 7, 10, 0, 0, 197, 198, 7, 13, 0, 0, 198, 199, 7, 17, 0, 0, 199,
|
||||
54, 1, 0, 0, 0, 200, 201, 7, 5, 0, 0, 201, 202, 7, 10, 0, 0, 202, 203,
|
||||
7, 19, 0, 0, 203, 210, 7, 3, 0, 0, 204, 205, 7, 20, 0, 0, 205, 206, 7,
|
||||
15, 0, 0, 206, 207, 7, 0, 0, 0, 207, 208, 7, 9, 0, 0, 208, 210, 7, 3, 0,
|
||||
0, 209, 200, 1, 0, 0, 0, 209, 204, 1, 0, 0, 0, 210, 56, 1, 0, 0, 0, 211,
|
||||
212, 7, 21, 0, 0, 212, 58, 1, 0, 0, 0, 213, 215, 3, 57, 28, 0, 214, 213,
|
||||
1, 0, 0, 0, 214, 215, 1, 0, 0, 0, 215, 217, 1, 0, 0, 0, 216, 218, 3, 73,
|
||||
36, 0, 217, 216, 1, 0, 0, 0, 218, 219, 1, 0, 0, 0, 219, 217, 1, 0, 0, 0,
|
||||
219, 220, 1, 0, 0, 0, 220, 228, 1, 0, 0, 0, 221, 225, 5, 46, 0, 0, 222,
|
||||
224, 3, 73, 36, 0, 223, 222, 1, 0, 0, 0, 224, 227, 1, 0, 0, 0, 225, 223,
|
||||
1, 0, 0, 0, 225, 226, 1, 0, 0, 0, 226, 229, 1, 0, 0, 0, 227, 225, 1, 0,
|
||||
0, 0, 228, 221, 1, 0, 0, 0, 228, 229, 1, 0, 0, 0, 229, 239, 1, 0, 0, 0,
|
||||
230, 232, 7, 3, 0, 0, 231, 233, 3, 57, 28, 0, 232, 231, 1, 0, 0, 0, 232,
|
||||
233, 1, 0, 0, 0, 233, 235, 1, 0, 0, 0, 234, 236, 3, 73, 36, 0, 235, 234,
|
||||
1, 0, 0, 0, 236, 237, 1, 0, 0, 0, 237, 235, 1, 0, 0, 0, 237, 238, 1, 0,
|
||||
0, 0, 238, 240, 1, 0, 0, 0, 239, 230, 1, 0, 0, 0, 239, 240, 1, 0, 0, 0,
|
||||
240, 262, 1, 0, 0, 0, 241, 243, 3, 57, 28, 0, 242, 241, 1, 0, 0, 0, 242,
|
||||
243, 1, 0, 0, 0, 243, 244, 1, 0, 0, 0, 244, 246, 5, 46, 0, 0, 245, 247,
|
||||
3, 73, 36, 0, 246, 245, 1, 0, 0, 0, 247, 248, 1, 0, 0, 0, 248, 246, 1,
|
||||
0, 0, 0, 248, 249, 1, 0, 0, 0, 249, 259, 1, 0, 0, 0, 250, 252, 7, 3, 0,
|
||||
0, 251, 253, 3, 57, 28, 0, 252, 251, 1, 0, 0, 0, 252, 253, 1, 0, 0, 0,
|
||||
253, 255, 1, 0, 0, 0, 254, 256, 3, 73, 36, 0, 255, 254, 1, 0, 0, 0, 256,
|
||||
257, 1, 0, 0, 0, 257, 255, 1, 0, 0, 0, 257, 258, 1, 0, 0, 0, 258, 260,
|
||||
1, 0, 0, 0, 259, 250, 1, 0, 0, 0, 259, 260, 1, 0, 0, 0, 260, 262, 1, 0,
|
||||
0, 0, 261, 214, 1, 0, 0, 0, 261, 242, 1, 0, 0, 0, 262, 60, 1, 0, 0, 0,
|
||||
263, 269, 5, 34, 0, 0, 264, 268, 8, 22, 0, 0, 265, 266, 5, 92, 0, 0, 266,
|
||||
268, 9, 0, 0, 0, 267, 264, 1, 0, 0, 0, 267, 265, 1, 0, 0, 0, 268, 271,
|
||||
1, 0, 0, 0, 269, 267, 1, 0, 0, 0, 269, 270, 1, 0, 0, 0, 270, 272, 1, 0,
|
||||
0, 0, 271, 269, 1, 0, 0, 0, 272, 284, 5, 34, 0, 0, 273, 279, 5, 39, 0,
|
||||
0, 274, 278, 8, 23, 0, 0, 275, 276, 5, 92, 0, 0, 276, 278, 9, 0, 0, 0,
|
||||
277, 274, 1, 0, 0, 0, 277, 275, 1, 0, 0, 0, 278, 281, 1, 0, 0, 0, 279,
|
||||
277, 1, 0, 0, 0, 279, 280, 1, 0, 0, 0, 280, 282, 1, 0, 0, 0, 281, 279,
|
||||
1, 0, 0, 0, 282, 284, 5, 39, 0, 0, 283, 263, 1, 0, 0, 0, 283, 273, 1, 0,
|
||||
0, 0, 284, 62, 1, 0, 0, 0, 285, 289, 7, 24, 0, 0, 286, 288, 7, 25, 0, 0,
|
||||
287, 286, 1, 0, 0, 0, 288, 291, 1, 0, 0, 0, 289, 287, 1, 0, 0, 0, 289,
|
||||
290, 1, 0, 0, 0, 290, 64, 1, 0, 0, 0, 291, 289, 1, 0, 0, 0, 292, 293, 5,
|
||||
91, 0, 0, 293, 294, 5, 93, 0, 0, 294, 66, 1, 0, 0, 0, 295, 296, 5, 91,
|
||||
0, 0, 296, 297, 5, 42, 0, 0, 297, 298, 5, 93, 0, 0, 298, 68, 1, 0, 0, 0,
|
||||
299, 312, 3, 63, 31, 0, 300, 301, 5, 46, 0, 0, 301, 311, 3, 63, 31, 0,
|
||||
302, 311, 3, 65, 32, 0, 303, 311, 3, 67, 33, 0, 304, 306, 5, 46, 0, 0,
|
||||
305, 307, 3, 73, 36, 0, 306, 305, 1, 0, 0, 0, 307, 308, 1, 0, 0, 0, 308,
|
||||
306, 1, 0, 0, 0, 308, 309, 1, 0, 0, 0, 309, 311, 1, 0, 0, 0, 310, 300,
|
||||
1, 0, 0, 0, 310, 302, 1, 0, 0, 0, 310, 303, 1, 0, 0, 0, 310, 304, 1, 0,
|
||||
0, 0, 311, 314, 1, 0, 0, 0, 312, 310, 1, 0, 0, 0, 312, 313, 1, 0, 0, 0,
|
||||
313, 70, 1, 0, 0, 0, 314, 312, 1, 0, 0, 0, 315, 317, 7, 26, 0, 0, 316,
|
||||
315, 1, 0, 0, 0, 317, 318, 1, 0, 0, 0, 318, 316, 1, 0, 0, 0, 318, 319,
|
||||
1, 0, 0, 0, 319, 320, 1, 0, 0, 0, 320, 321, 6, 35, 0, 0, 321, 72, 1, 0,
|
||||
0, 0, 322, 323, 7, 27, 0, 0, 323, 74, 1, 0, 0, 0, 324, 326, 8, 28, 0, 0,
|
||||
325, 324, 1, 0, 0, 0, 326, 327, 1, 0, 0, 0, 327, 325, 1, 0, 0, 0, 327,
|
||||
328, 1, 0, 0, 0, 328, 76, 1, 0, 0, 0, 29, 0, 90, 133, 150, 209, 214, 219,
|
||||
225, 228, 232, 237, 239, 242, 248, 252, 257, 259, 261, 267, 269, 277, 279,
|
||||
283, 289, 308, 310, 312, 318, 327, 1, 6, 0, 0,
|
||||
0, 55, 1, 0, 0, 0, 0, 57, 1, 0, 0, 0, 0, 61, 1, 0, 0, 0, 0, 63, 1, 0, 0,
|
||||
0, 0, 71, 1, 0, 0, 0, 0, 73, 1, 0, 0, 0, 0, 77, 1, 0, 0, 0, 1, 79, 1, 0,
|
||||
0, 0, 3, 81, 1, 0, 0, 0, 5, 83, 1, 0, 0, 0, 7, 85, 1, 0, 0, 0, 9, 87, 1,
|
||||
0, 0, 0, 11, 92, 1, 0, 0, 0, 13, 94, 1, 0, 0, 0, 15, 97, 1, 0, 0, 0, 17,
|
||||
100, 1, 0, 0, 0, 19, 102, 1, 0, 0, 0, 21, 105, 1, 0, 0, 0, 23, 107, 1,
|
||||
0, 0, 0, 25, 110, 1, 0, 0, 0, 27, 115, 1, 0, 0, 0, 29, 121, 1, 0, 0, 0,
|
||||
31, 129, 1, 0, 0, 0, 33, 137, 1, 0, 0, 0, 35, 144, 1, 0, 0, 0, 37, 154,
|
||||
1, 0, 0, 0, 39, 157, 1, 0, 0, 0, 41, 161, 1, 0, 0, 0, 43, 165, 1, 0, 0,
|
||||
0, 45, 168, 1, 0, 0, 0, 47, 177, 1, 0, 0, 0, 49, 181, 1, 0, 0, 0, 51, 188,
|
||||
1, 0, 0, 0, 53, 195, 1, 0, 0, 0, 55, 202, 1, 0, 0, 0, 57, 217, 1, 0, 0,
|
||||
0, 59, 219, 1, 0, 0, 0, 61, 269, 1, 0, 0, 0, 63, 291, 1, 0, 0, 0, 65, 293,
|
||||
1, 0, 0, 0, 67, 300, 1, 0, 0, 0, 69, 303, 1, 0, 0, 0, 71, 307, 1, 0, 0,
|
||||
0, 73, 324, 1, 0, 0, 0, 75, 330, 1, 0, 0, 0, 77, 333, 1, 0, 0, 0, 79, 80,
|
||||
5, 40, 0, 0, 80, 2, 1, 0, 0, 0, 81, 82, 5, 41, 0, 0, 82, 4, 1, 0, 0, 0,
|
||||
83, 84, 5, 91, 0, 0, 84, 6, 1, 0, 0, 0, 85, 86, 5, 93, 0, 0, 86, 8, 1,
|
||||
0, 0, 0, 87, 88, 5, 44, 0, 0, 88, 10, 1, 0, 0, 0, 89, 93, 5, 61, 0, 0,
|
||||
90, 91, 5, 61, 0, 0, 91, 93, 5, 61, 0, 0, 92, 89, 1, 0, 0, 0, 92, 90, 1,
|
||||
0, 0, 0, 93, 12, 1, 0, 0, 0, 94, 95, 5, 33, 0, 0, 95, 96, 5, 61, 0, 0,
|
||||
96, 14, 1, 0, 0, 0, 97, 98, 5, 60, 0, 0, 98, 99, 5, 62, 0, 0, 99, 16, 1,
|
||||
0, 0, 0, 100, 101, 5, 60, 0, 0, 101, 18, 1, 0, 0, 0, 102, 103, 5, 60, 0,
|
||||
0, 103, 104, 5, 61, 0, 0, 104, 20, 1, 0, 0, 0, 105, 106, 5, 62, 0, 0, 106,
|
||||
22, 1, 0, 0, 0, 107, 108, 5, 62, 0, 0, 108, 109, 5, 61, 0, 0, 109, 24,
|
||||
1, 0, 0, 0, 110, 111, 7, 0, 0, 0, 111, 112, 7, 1, 0, 0, 112, 113, 7, 2,
|
||||
0, 0, 113, 114, 7, 3, 0, 0, 114, 26, 1, 0, 0, 0, 115, 116, 7, 1, 0, 0,
|
||||
116, 117, 7, 0, 0, 0, 117, 118, 7, 1, 0, 0, 118, 119, 7, 2, 0, 0, 119,
|
||||
120, 7, 3, 0, 0, 120, 28, 1, 0, 0, 0, 121, 122, 7, 4, 0, 0, 122, 123, 7,
|
||||
3, 0, 0, 123, 124, 7, 5, 0, 0, 124, 125, 7, 6, 0, 0, 125, 126, 7, 3, 0,
|
||||
0, 126, 127, 7, 3, 0, 0, 127, 128, 7, 7, 0, 0, 128, 30, 1, 0, 0, 0, 129,
|
||||
130, 7, 3, 0, 0, 130, 131, 7, 8, 0, 0, 131, 132, 7, 1, 0, 0, 132, 133,
|
||||
7, 9, 0, 0, 133, 135, 7, 5, 0, 0, 134, 136, 7, 9, 0, 0, 135, 134, 1, 0,
|
||||
0, 0, 135, 136, 1, 0, 0, 0, 136, 32, 1, 0, 0, 0, 137, 138, 7, 10, 0, 0,
|
||||
138, 139, 7, 3, 0, 0, 139, 140, 7, 11, 0, 0, 140, 141, 7, 3, 0, 0, 141,
|
||||
142, 7, 8, 0, 0, 142, 143, 7, 12, 0, 0, 143, 34, 1, 0, 0, 0, 144, 145,
|
||||
7, 13, 0, 0, 145, 146, 7, 14, 0, 0, 146, 147, 7, 7, 0, 0, 147, 148, 7,
|
||||
5, 0, 0, 148, 149, 7, 15, 0, 0, 149, 150, 7, 1, 0, 0, 150, 152, 7, 7, 0,
|
||||
0, 151, 153, 7, 9, 0, 0, 152, 151, 1, 0, 0, 0, 152, 153, 1, 0, 0, 0, 153,
|
||||
36, 1, 0, 0, 0, 154, 155, 7, 1, 0, 0, 155, 156, 7, 7, 0, 0, 156, 38, 1,
|
||||
0, 0, 0, 157, 158, 7, 7, 0, 0, 158, 159, 7, 14, 0, 0, 159, 160, 7, 5, 0,
|
||||
0, 160, 40, 1, 0, 0, 0, 161, 162, 7, 15, 0, 0, 162, 163, 7, 7, 0, 0, 163,
|
||||
164, 7, 16, 0, 0, 164, 42, 1, 0, 0, 0, 165, 166, 7, 14, 0, 0, 166, 167,
|
||||
7, 10, 0, 0, 167, 44, 1, 0, 0, 0, 168, 169, 7, 17, 0, 0, 169, 170, 7, 15,
|
||||
0, 0, 170, 171, 7, 9, 0, 0, 171, 172, 7, 5, 0, 0, 172, 173, 7, 14, 0, 0,
|
||||
173, 174, 7, 2, 0, 0, 174, 175, 7, 3, 0, 0, 175, 176, 7, 7, 0, 0, 176,
|
||||
46, 1, 0, 0, 0, 177, 178, 7, 17, 0, 0, 178, 179, 7, 15, 0, 0, 179, 180,
|
||||
7, 9, 0, 0, 180, 48, 1, 0, 0, 0, 181, 182, 7, 17, 0, 0, 182, 183, 7, 15,
|
||||
0, 0, 183, 184, 7, 9, 0, 0, 184, 185, 7, 15, 0, 0, 185, 186, 7, 7, 0, 0,
|
||||
186, 187, 7, 18, 0, 0, 187, 50, 1, 0, 0, 0, 188, 189, 7, 17, 0, 0, 189,
|
||||
190, 7, 15, 0, 0, 190, 191, 7, 9, 0, 0, 191, 192, 7, 15, 0, 0, 192, 193,
|
||||
7, 0, 0, 0, 193, 194, 7, 0, 0, 0, 194, 52, 1, 0, 0, 0, 195, 196, 7, 9,
|
||||
0, 0, 196, 197, 7, 3, 0, 0, 197, 198, 7, 15, 0, 0, 198, 199, 7, 10, 0,
|
||||
0, 199, 200, 7, 13, 0, 0, 200, 201, 7, 17, 0, 0, 201, 54, 1, 0, 0, 0, 202,
|
||||
203, 7, 3, 0, 0, 203, 204, 7, 8, 0, 0, 204, 205, 7, 15, 0, 0, 205, 206,
|
||||
7, 13, 0, 0, 206, 207, 7, 5, 0, 0, 207, 56, 1, 0, 0, 0, 208, 209, 7, 5,
|
||||
0, 0, 209, 210, 7, 10, 0, 0, 210, 211, 7, 19, 0, 0, 211, 218, 7, 3, 0,
|
||||
0, 212, 213, 7, 20, 0, 0, 213, 214, 7, 15, 0, 0, 214, 215, 7, 0, 0, 0,
|
||||
215, 216, 7, 9, 0, 0, 216, 218, 7, 3, 0, 0, 217, 208, 1, 0, 0, 0, 217,
|
||||
212, 1, 0, 0, 0, 218, 58, 1, 0, 0, 0, 219, 220, 7, 21, 0, 0, 220, 60, 1,
|
||||
0, 0, 0, 221, 223, 3, 59, 29, 0, 222, 221, 1, 0, 0, 0, 222, 223, 1, 0,
|
||||
0, 0, 223, 225, 1, 0, 0, 0, 224, 226, 3, 75, 37, 0, 225, 224, 1, 0, 0,
|
||||
0, 226, 227, 1, 0, 0, 0, 227, 225, 1, 0, 0, 0, 227, 228, 1, 0, 0, 0, 228,
|
||||
236, 1, 0, 0, 0, 229, 233, 5, 46, 0, 0, 230, 232, 3, 75, 37, 0, 231, 230,
|
||||
1, 0, 0, 0, 232, 235, 1, 0, 0, 0, 233, 231, 1, 0, 0, 0, 233, 234, 1, 0,
|
||||
0, 0, 234, 237, 1, 0, 0, 0, 235, 233, 1, 0, 0, 0, 236, 229, 1, 0, 0, 0,
|
||||
236, 237, 1, 0, 0, 0, 237, 247, 1, 0, 0, 0, 238, 240, 7, 3, 0, 0, 239,
|
||||
241, 3, 59, 29, 0, 240, 239, 1, 0, 0, 0, 240, 241, 1, 0, 0, 0, 241, 243,
|
||||
1, 0, 0, 0, 242, 244, 3, 75, 37, 0, 243, 242, 1, 0, 0, 0, 244, 245, 1,
|
||||
0, 0, 0, 245, 243, 1, 0, 0, 0, 245, 246, 1, 0, 0, 0, 246, 248, 1, 0, 0,
|
||||
0, 247, 238, 1, 0, 0, 0, 247, 248, 1, 0, 0, 0, 248, 270, 1, 0, 0, 0, 249,
|
||||
251, 3, 59, 29, 0, 250, 249, 1, 0, 0, 0, 250, 251, 1, 0, 0, 0, 251, 252,
|
||||
1, 0, 0, 0, 252, 254, 5, 46, 0, 0, 253, 255, 3, 75, 37, 0, 254, 253, 1,
|
||||
0, 0, 0, 255, 256, 1, 0, 0, 0, 256, 254, 1, 0, 0, 0, 256, 257, 1, 0, 0,
|
||||
0, 257, 267, 1, 0, 0, 0, 258, 260, 7, 3, 0, 0, 259, 261, 3, 59, 29, 0,
|
||||
260, 259, 1, 0, 0, 0, 260, 261, 1, 0, 0, 0, 261, 263, 1, 0, 0, 0, 262,
|
||||
264, 3, 75, 37, 0, 263, 262, 1, 0, 0, 0, 264, 265, 1, 0, 0, 0, 265, 263,
|
||||
1, 0, 0, 0, 265, 266, 1, 0, 0, 0, 266, 268, 1, 0, 0, 0, 267, 258, 1, 0,
|
||||
0, 0, 267, 268, 1, 0, 0, 0, 268, 270, 1, 0, 0, 0, 269, 222, 1, 0, 0, 0,
|
||||
269, 250, 1, 0, 0, 0, 270, 62, 1, 0, 0, 0, 271, 277, 5, 34, 0, 0, 272,
|
||||
276, 8, 22, 0, 0, 273, 274, 5, 92, 0, 0, 274, 276, 9, 0, 0, 0, 275, 272,
|
||||
1, 0, 0, 0, 275, 273, 1, 0, 0, 0, 276, 279, 1, 0, 0, 0, 277, 275, 1, 0,
|
||||
0, 0, 277, 278, 1, 0, 0, 0, 278, 280, 1, 0, 0, 0, 279, 277, 1, 0, 0, 0,
|
||||
280, 292, 5, 34, 0, 0, 281, 287, 5, 39, 0, 0, 282, 286, 8, 23, 0, 0, 283,
|
||||
284, 5, 92, 0, 0, 284, 286, 9, 0, 0, 0, 285, 282, 1, 0, 0, 0, 285, 283,
|
||||
1, 0, 0, 0, 286, 289, 1, 0, 0, 0, 287, 285, 1, 0, 0, 0, 287, 288, 1, 0,
|
||||
0, 0, 288, 290, 1, 0, 0, 0, 289, 287, 1, 0, 0, 0, 290, 292, 5, 39, 0, 0,
|
||||
291, 271, 1, 0, 0, 0, 291, 281, 1, 0, 0, 0, 292, 64, 1, 0, 0, 0, 293, 297,
|
||||
7, 24, 0, 0, 294, 296, 7, 25, 0, 0, 295, 294, 1, 0, 0, 0, 296, 299, 1,
|
||||
0, 0, 0, 297, 295, 1, 0, 0, 0, 297, 298, 1, 0, 0, 0, 298, 66, 1, 0, 0,
|
||||
0, 299, 297, 1, 0, 0, 0, 300, 301, 5, 91, 0, 0, 301, 302, 5, 93, 0, 0,
|
||||
302, 68, 1, 0, 0, 0, 303, 304, 5, 91, 0, 0, 304, 305, 5, 42, 0, 0, 305,
|
||||
306, 5, 93, 0, 0, 306, 70, 1, 0, 0, 0, 307, 320, 3, 65, 32, 0, 308, 309,
|
||||
5, 46, 0, 0, 309, 319, 3, 65, 32, 0, 310, 319, 3, 67, 33, 0, 311, 319,
|
||||
3, 69, 34, 0, 312, 314, 5, 46, 0, 0, 313, 315, 3, 75, 37, 0, 314, 313,
|
||||
1, 0, 0, 0, 315, 316, 1, 0, 0, 0, 316, 314, 1, 0, 0, 0, 316, 317, 1, 0,
|
||||
0, 0, 317, 319, 1, 0, 0, 0, 318, 308, 1, 0, 0, 0, 318, 310, 1, 0, 0, 0,
|
||||
318, 311, 1, 0, 0, 0, 318, 312, 1, 0, 0, 0, 319, 322, 1, 0, 0, 0, 320,
|
||||
318, 1, 0, 0, 0, 320, 321, 1, 0, 0, 0, 321, 72, 1, 0, 0, 0, 322, 320, 1,
|
||||
0, 0, 0, 323, 325, 7, 26, 0, 0, 324, 323, 1, 0, 0, 0, 325, 326, 1, 0, 0,
|
||||
0, 326, 324, 1, 0, 0, 0, 326, 327, 1, 0, 0, 0, 327, 328, 1, 0, 0, 0, 328,
|
||||
329, 6, 36, 0, 0, 329, 74, 1, 0, 0, 0, 330, 331, 7, 27, 0, 0, 331, 76,
|
||||
1, 0, 0, 0, 332, 334, 8, 28, 0, 0, 333, 332, 1, 0, 0, 0, 334, 335, 1, 0,
|
||||
0, 0, 335, 333, 1, 0, 0, 0, 335, 336, 1, 0, 0, 0, 336, 78, 1, 0, 0, 0,
|
||||
29, 0, 92, 135, 152, 217, 222, 227, 233, 236, 240, 245, 247, 250, 256,
|
||||
260, 265, 267, 269, 275, 277, 285, 287, 291, 297, 316, 318, 320, 326, 335,
|
||||
1, 6, 0, 0,
|
||||
}
|
||||
deserializer := antlr.NewATNDeserializer(nil)
|
||||
staticData.atn = deserializer.Deserialize(staticData.serializedATN)
|
||||
@@ -285,10 +291,11 @@ const (
|
||||
FilterQueryLexerHASANY = 25
|
||||
FilterQueryLexerHASALL = 26
|
||||
FilterQueryLexerSEARCH = 27
|
||||
FilterQueryLexerBOOL = 28
|
||||
FilterQueryLexerNUMBER = 29
|
||||
FilterQueryLexerQUOTED_TEXT = 30
|
||||
FilterQueryLexerKEY = 31
|
||||
FilterQueryLexerWS = 32
|
||||
FilterQueryLexerFREETEXT = 33
|
||||
FilterQueryLexerEXACT = 28
|
||||
FilterQueryLexerBOOL = 29
|
||||
FilterQueryLexerNUMBER = 30
|
||||
FilterQueryLexerQUOTED_TEXT = 31
|
||||
FilterQueryLexerKEY = 32
|
||||
FilterQueryLexerWS = 33
|
||||
FilterQueryLexerFREETEXT = 34
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Code generated from FilterQuery.g4 by ANTLR 4.13.2. DO NOT EDIT.
|
||||
// Code generated from grammar/FilterQuery.g4 by ANTLR 4.13.2. DO NOT EDIT.
|
||||
|
||||
package parser // FilterQuery
|
||||
|
||||
@@ -62,6 +62,12 @@ type FilterQueryListener interface {
|
||||
// EnterKey is called when entering the key production.
|
||||
EnterKey(c *KeyContext)
|
||||
|
||||
// EnterField is called when entering the field production.
|
||||
EnterField(c *FieldContext)
|
||||
|
||||
// EnterExactCall is called when entering the exactCall production.
|
||||
EnterExactCall(c *ExactCallContext)
|
||||
|
||||
// ExitQuery is called when exiting the query production.
|
||||
ExitQuery(c *QueryContext)
|
||||
|
||||
@@ -115,4 +121,10 @@ type FilterQueryListener interface {
|
||||
|
||||
// ExitKey is called when exiting the key production.
|
||||
ExitKey(c *KeyContext)
|
||||
|
||||
// ExitField is called when exiting the field production.
|
||||
ExitField(c *FieldContext)
|
||||
|
||||
// ExitExactCall is called when exiting the exactCall production.
|
||||
ExitExactCall(c *ExactCallContext)
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
// Code generated from FilterQuery.g4 by ANTLR 4.13.2. DO NOT EDIT.
|
||||
// Code generated from grammar/FilterQuery.g4 by ANTLR 4.13.2. DO NOT EDIT.
|
||||
|
||||
package parser // FilterQuery
|
||||
|
||||
@@ -61,4 +61,10 @@ type FilterQueryVisitor interface {
|
||||
|
||||
// Visit a parse tree produced by FilterQueryParser#key.
|
||||
VisitKey(ctx *KeyContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by FilterQueryParser#field.
|
||||
VisitField(ctx *FieldContext) interface{}
|
||||
|
||||
// Visit a parse tree produced by FilterQueryParser#exactCall.
|
||||
VisitExactCall(ctx *ExactCallContext) interface{}
|
||||
}
|
||||
|
||||
@@ -136,6 +136,10 @@ func (q *querier) QueryRange(ctx context.Context, orgID valuer.UUID, req *qbtype
|
||||
// safely assume ms regardless of the resolution the caller sent.
|
||||
req.Start = querybuilder.ToMilliSecs(req.Start)
|
||||
req.End = querybuilder.ToMilliSecs(req.End)
|
||||
// Key resolution mutates parts of builder queries while compiling them.
|
||||
// Capture the caller's spelling before that happens so response metadata
|
||||
// can identify the exact old/current name supplied in the request.
|
||||
semconvResolutions := semconvResolutionsForRequest(req)
|
||||
|
||||
event := &qbtypes.QBEvent{
|
||||
Version: "v5",
|
||||
@@ -188,6 +192,7 @@ func (q *querier) QueryRange(ctx context.Context, orgID valuer.UUID, req *qbtype
|
||||
qbResp, qbErr := q.run(ctx, orgID, queries, req, steps, event, preseededResults)
|
||||
if qbResp != nil {
|
||||
qbResp.QBEvent = event
|
||||
qbResp.Meta.SemconvResolutions = semconvResolutions
|
||||
if len(intervalWarnings) != 0 && req.RequestType == qbtypes.RequestTypeTimeSeries {
|
||||
if qbResp.Warning == nil {
|
||||
qbResp.Warning = &qbtypes.QueryWarnData{
|
||||
|
||||
223
pkg/querier/semconv_resolutions.go
Normal file
223
pkg/querier/semconv_resolutions.go
Normal file
@@ -0,0 +1,223 @@
|
||||
package querier
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"slices"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
grammar "github.com/SigNoz/signoz/pkg/parser/filterquery/grammar"
|
||||
"github.com/SigNoz/signoz/pkg/semconv"
|
||||
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
|
||||
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
|
||||
"github.com/antlr4-go/antlr/v4"
|
||||
)
|
||||
|
||||
// semconvResolutionsForRequest reports only query-builder resolutions. Raw
|
||||
// ClickHouse SQL and PromQL are deliberately excluded: SigNoz does not rewrite
|
||||
// those languages and their editors surface non-blocking warnings instead.
|
||||
func semconvResolutionsForRequest(req *qbtypes.QueryRangeRequest) []qbtypes.SemconvResolution {
|
||||
if req == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
resolutions := make([]qbtypes.SemconvResolution, 0)
|
||||
seen := make(map[string]struct{})
|
||||
for _, envelope := range req.CompositeQuery.Queries {
|
||||
signal, applies := semconvResolutionSignal(envelope.Spec)
|
||||
if !applies {
|
||||
continue
|
||||
}
|
||||
|
||||
payload, err := semconvResolutionPayload(envelope.Spec)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
text := string(payload)
|
||||
|
||||
for _, family := range semconv.All() {
|
||||
if _, ok := semconv.Lookup(family.Kind, telemetrytypes.FieldKeySelector{
|
||||
Name: family.Current,
|
||||
Signal: signal,
|
||||
}); !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, requested := range semconvRequestSpellings(family, signal) {
|
||||
if !containsSemconvRequestName(text, requested) {
|
||||
continue
|
||||
}
|
||||
identity := family.Kind.StringValue() + "\x00" + requested + "\x00" + family.Current
|
||||
if _, ok := seen[identity]; ok {
|
||||
continue
|
||||
}
|
||||
seen[identity] = struct{}{}
|
||||
resolutions = append(resolutions, qbtypes.SemconvResolution{
|
||||
Requested: requested,
|
||||
Current: family.Current,
|
||||
Members: append([]string{family.Current}, family.Old...),
|
||||
Kind: family.Kind.StringValue(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(resolutions) == 0 {
|
||||
return nil
|
||||
}
|
||||
return resolutions
|
||||
}
|
||||
|
||||
// semconvResolutionPayload removes fields that explicitly selected exact
|
||||
// resolution before the generic family-name scan. This keeps response metadata
|
||||
// aligned with execution for both exact(key) filter syntax and structured
|
||||
// TelemetryFieldKey objects with fieldResolution:"exact".
|
||||
func semconvResolutionPayload(spec any) ([]byte, error) {
|
||||
payload, err := json.Marshal(spec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var document any
|
||||
if err := json.Unmarshal(payload, &document); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
scrubExactFields(document)
|
||||
return json.Marshal(document)
|
||||
}
|
||||
|
||||
func scrubExactFields(value any) {
|
||||
switch typed := value.(type) {
|
||||
case map[string]any:
|
||||
if resolution, ok := typed["fieldResolution"].(string); ok && strings.EqualFold(resolution, "exact") {
|
||||
delete(typed, "name")
|
||||
}
|
||||
for key, child := range typed {
|
||||
if text, ok := child.(string); ok {
|
||||
typed[key] = scrubExactCalls(text)
|
||||
continue
|
||||
}
|
||||
scrubExactFields(child)
|
||||
}
|
||||
case []any:
|
||||
for _, child := range typed {
|
||||
scrubExactFields(child)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func scrubExactCalls(input string) string {
|
||||
lexer := grammar.NewFilterQueryLexer(antlr.NewInputStream(input))
|
||||
tokens := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel)
|
||||
tokens.Fill()
|
||||
allTokens := tokens.GetAllTokens()
|
||||
result := []rune(input)
|
||||
for index := 0; index+3 < len(allTokens); index++ {
|
||||
if allTokens[index].GetTokenType() != grammar.FilterQueryLexerEXACT ||
|
||||
allTokens[index+1].GetTokenType() != grammar.FilterQueryLexerLPAREN ||
|
||||
allTokens[index+2].GetTokenType() != grammar.FilterQueryLexerKEY ||
|
||||
allTokens[index+3].GetTokenType() != grammar.FilterQueryLexerRPAREN {
|
||||
continue
|
||||
}
|
||||
start, stop := allTokens[index].GetStart(), allTokens[index+3].GetStop()
|
||||
if start < 0 || stop >= len(result) {
|
||||
continue
|
||||
}
|
||||
for position := start; position <= stop; position++ {
|
||||
result[position] = ' '
|
||||
}
|
||||
}
|
||||
return string(result)
|
||||
}
|
||||
|
||||
func semconvResolutionSignal(spec any) (telemetrytypes.Signal, bool) {
|
||||
switch spec.(type) {
|
||||
case qbtypes.QueryBuilderQuery[qbtypes.TraceAggregation], qbtypes.QueryBuilderTraceOperator:
|
||||
return telemetrytypes.SignalTraces, true
|
||||
case qbtypes.QueryBuilderQuery[qbtypes.LogAggregation]:
|
||||
return telemetrytypes.SignalLogs, true
|
||||
case qbtypes.QueryBuilderQuery[qbtypes.MetricAggregation]:
|
||||
return telemetrytypes.SignalMetrics, true
|
||||
case qbtypes.QueryBuilderJoin:
|
||||
// Joins can contain more than one signal. An unspecified signal keeps
|
||||
// family signal scopes in force while allowing every applicable family.
|
||||
return telemetrytypes.SignalUnspecified, true
|
||||
default:
|
||||
return telemetrytypes.SignalUnspecified, false
|
||||
}
|
||||
}
|
||||
|
||||
func semconvRequestSpellings(family semconv.Family, signal telemetrytypes.Signal) []string {
|
||||
spellings := append([]string{family.Current}, family.Old...)
|
||||
if signal != telemetrytypes.SignalMetrics {
|
||||
return spellings
|
||||
}
|
||||
|
||||
logical := slices.Clone(spellings)
|
||||
for _, name := range logical {
|
||||
normalized := strings.ReplaceAll(name, ".", "_")
|
||||
if !slices.Contains(spellings, normalized) {
|
||||
spellings = append(spellings, normalized)
|
||||
}
|
||||
if family.Kind == semconv.KindAttribute {
|
||||
for _, resourceName := range []string{"resource_" + name, "resource_" + normalized} {
|
||||
if !slices.Contains(spellings, resourceName) {
|
||||
spellings = append(spellings, resourceName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return spellings
|
||||
}
|
||||
|
||||
func containsSemconvRequestName(text, name string) bool {
|
||||
if containsSemconvName(text, name) {
|
||||
return true
|
||||
}
|
||||
// Filter expressions qualify attributes with their field context. A dot is
|
||||
// otherwise part of a semantic-convention name, so check the two contexts
|
||||
// that can contain schema attribute families explicitly. This still rejects
|
||||
// larger custom names such as custom.deployment.environment.
|
||||
for _, context := range []string{"attribute.", "resource."} {
|
||||
if containsSemconvName(text, context+name) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func containsSemconvName(text, name string) bool {
|
||||
for offset := 0; offset < len(text); {
|
||||
index := strings.Index(text[offset:], name)
|
||||
if index < 0 {
|
||||
return false
|
||||
}
|
||||
start := offset + index
|
||||
end := start + len(name)
|
||||
if hasSemconvNameStartBoundary(text, start) &&
|
||||
(end == len(text) || !isSemconvNameRune(rune(text[end]))) {
|
||||
return true
|
||||
}
|
||||
offset = start + 1
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func hasSemconvNameStartBoundary(text string, start int) bool {
|
||||
if start == 0 || !isSemconvNameRune(rune(text[start-1])) {
|
||||
return true
|
||||
}
|
||||
|
||||
for _, qualifier := range []string{"resource.", "attribute.", "tag.", "point."} {
|
||||
qualifierStart := start - len(qualifier)
|
||||
if qualifierStart >= 0 && text[qualifierStart:start] == qualifier &&
|
||||
(qualifierStart == 0 || !isSemconvNameRune(rune(text[qualifierStart-1]))) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isSemconvNameRune(r rune) bool {
|
||||
return unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_' || r == '.' || r == '-'
|
||||
}
|
||||
179
pkg/querier/semconv_resolutions_test.go
Normal file
179
pkg/querier/semconv_resolutions_test.go
Normal file
@@ -0,0 +1,179 @@
|
||||
package querier
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
qbtypes "github.com/SigNoz/signoz/pkg/types/querybuildertypes/querybuildertypesv5"
|
||||
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestSemconvResolutionsReportsOldTraceAttribute(t *testing.T) {
|
||||
req := &qbtypes.QueryRangeRequest{
|
||||
CompositeQuery: qbtypes.CompositeQuery{Queries: []qbtypes.QueryEnvelope{{
|
||||
Spec: qbtypes.QueryBuilderQuery[qbtypes.TraceAggregation]{
|
||||
Signal: telemetrytypes.SignalTraces,
|
||||
Filter: &qbtypes.Filter{Expression: "deployment.environment = 'prod'"},
|
||||
},
|
||||
}}},
|
||||
}
|
||||
|
||||
assert.Equal(t, []qbtypes.SemconvResolution{{
|
||||
Requested: "deployment.environment",
|
||||
Current: "deployment.environment.name",
|
||||
Members: []string{"deployment.environment.name", "deployment.environment"},
|
||||
Kind: "attribute",
|
||||
}}, semconvResolutionsForRequest(req), "old trace attribute should be reported as a family resolution")
|
||||
}
|
||||
|
||||
func TestSemconvResolutionsReportsContextQualifiedOldAttribute(t *testing.T) {
|
||||
var req qbtypes.QueryRangeRequest
|
||||
err := json.Unmarshal([]byte(`{
|
||||
"start": 1,
|
||||
"end": 2,
|
||||
"requestType": "raw",
|
||||
"compositeQuery": {
|
||||
"queries": [{
|
||||
"type": "builder_query",
|
||||
"spec": {
|
||||
"signal": "traces",
|
||||
"name": "A",
|
||||
"filter": {"expression": "resource.deployment.environment EXISTS"}
|
||||
}
|
||||
}]
|
||||
}
|
||||
}`), &req)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, []qbtypes.SemconvResolution{{
|
||||
Requested: "deployment.environment",
|
||||
Current: "deployment.environment.name",
|
||||
Members: []string{"deployment.environment.name", "deployment.environment"},
|
||||
Kind: "attribute",
|
||||
}}, semconvResolutionsForRequest(&req), "qualified old trace attribute should be reported after request decoding")
|
||||
}
|
||||
|
||||
func TestSemconvResolutionsReportsCurrentLogAttribute(t *testing.T) {
|
||||
req := &qbtypes.QueryRangeRequest{
|
||||
CompositeQuery: qbtypes.CompositeQuery{Queries: []qbtypes.QueryEnvelope{{
|
||||
Spec: qbtypes.QueryBuilderQuery[qbtypes.LogAggregation]{
|
||||
Signal: telemetrytypes.SignalLogs,
|
||||
SelectFields: []telemetrytypes.TelemetryFieldKey{{
|
||||
Name: "db.system.name",
|
||||
}},
|
||||
},
|
||||
}}},
|
||||
}
|
||||
|
||||
assert.Equal(t, []qbtypes.SemconvResolution{{
|
||||
Requested: "db.system.name",
|
||||
Current: "db.system.name",
|
||||
Members: []string{"db.system.name", "db.system"},
|
||||
Kind: "attribute",
|
||||
}}, semconvResolutionsForRequest(req), "current log attribute should identify its complete family")
|
||||
}
|
||||
|
||||
func TestSemconvResolutionsIgnoresExactFilterField(t *testing.T) {
|
||||
req := &qbtypes.QueryRangeRequest{
|
||||
CompositeQuery: qbtypes.CompositeQuery{Queries: []qbtypes.QueryEnvelope{{
|
||||
Spec: qbtypes.QueryBuilderQuery[qbtypes.TraceAggregation]{
|
||||
Signal: telemetrytypes.SignalTraces,
|
||||
Filter: &qbtypes.Filter{Expression: "exact(resource.deployment.environment) = 'prod'"},
|
||||
},
|
||||
}}},
|
||||
}
|
||||
|
||||
assert.Empty(t, semconvResolutionsForRequest(req), "an exact filter field should not be reported as a family resolution")
|
||||
}
|
||||
|
||||
func TestSemconvResolutionsIgnoresExactStructuredField(t *testing.T) {
|
||||
req := &qbtypes.QueryRangeRequest{
|
||||
CompositeQuery: qbtypes.CompositeQuery{Queries: []qbtypes.QueryEnvelope{{
|
||||
Spec: qbtypes.QueryBuilderQuery[qbtypes.LogAggregation]{
|
||||
Signal: telemetrytypes.SignalLogs,
|
||||
SelectFields: []telemetrytypes.TelemetryFieldKey{{
|
||||
Name: "db.system.name",
|
||||
FieldResolution: telemetrytypes.FieldResolutionExact,
|
||||
}},
|
||||
},
|
||||
}}},
|
||||
}
|
||||
|
||||
assert.Empty(t, semconvResolutionsForRequest(req), "an exact structured field should not be reported as a family resolution")
|
||||
}
|
||||
|
||||
func TestSemconvResolutionsReportsOnlyResolvedFieldFromMixedFilter(t *testing.T) {
|
||||
req := &qbtypes.QueryRangeRequest{
|
||||
CompositeQuery: qbtypes.CompositeQuery{Queries: []qbtypes.QueryEnvelope{{
|
||||
Spec: qbtypes.QueryBuilderQuery[qbtypes.TraceAggregation]{
|
||||
Signal: telemetrytypes.SignalTraces,
|
||||
Filter: &qbtypes.Filter{Expression: "exact(resource.deployment.environment) = 'old' AND resource.deployment.environment.name = 'current'"},
|
||||
},
|
||||
}}},
|
||||
}
|
||||
|
||||
assert.Equal(t, []qbtypes.SemconvResolution{{
|
||||
Requested: "deployment.environment.name",
|
||||
Current: "deployment.environment.name",
|
||||
Members: []string{"deployment.environment.name", "deployment.environment"},
|
||||
Kind: "attribute",
|
||||
}}, semconvResolutionsForRequest(req), "mixed filter should report only the family-resolved field")
|
||||
}
|
||||
|
||||
func TestSemconvResolutionsIgnoresRawSQL(t *testing.T) {
|
||||
req := &qbtypes.QueryRangeRequest{
|
||||
CompositeQuery: qbtypes.CompositeQuery{Queries: []qbtypes.QueryEnvelope{{
|
||||
Spec: qbtypes.ClickHouseQuery{Query: "SELECT attributes_string['deployment.environment']"},
|
||||
}}},
|
||||
}
|
||||
|
||||
assert.Empty(t, semconvResolutionsForRequest(req), "raw SQL is not rewritten and should not report a resolution")
|
||||
}
|
||||
|
||||
func TestSemconvResolutionsRequiresNameBoundary(t *testing.T) {
|
||||
req := &qbtypes.QueryRangeRequest{
|
||||
CompositeQuery: qbtypes.CompositeQuery{Queries: []qbtypes.QueryEnvelope{{
|
||||
Spec: qbtypes.QueryBuilderQuery[qbtypes.TraceAggregation]{
|
||||
Signal: telemetrytypes.SignalTraces,
|
||||
Filter: &qbtypes.Filter{Expression: "custom.deployment.environment = 'prod'"},
|
||||
},
|
||||
}}},
|
||||
}
|
||||
|
||||
assert.Empty(t, semconvResolutionsForRequest(req), "a family name embedded in a larger custom key must not match")
|
||||
}
|
||||
|
||||
func TestSemconvResolutionsForDecodedRequest(t *testing.T) {
|
||||
var req qbtypes.QueryRangeRequest
|
||||
require.NoError(t, json.Unmarshal([]byte(`{
|
||||
"requestType":"raw",
|
||||
"compositeQuery":{"queries":[{"type":"builder_query","spec":{
|
||||
"signal":"traces","name":"A","filter":{"expression":"resource.deployment.environment EXISTS"}
|
||||
}}]}
|
||||
}`), &req), "query request fixture should decode")
|
||||
assert.Equal(t, []qbtypes.SemconvResolution{{
|
||||
Requested: "deployment.environment",
|
||||
Current: "deployment.environment.name",
|
||||
Members: []string{"deployment.environment.name", "deployment.environment"},
|
||||
Kind: "attribute",
|
||||
}}, semconvResolutionsForRequest(&req), "decoded field should report its semantic-convention family")
|
||||
}
|
||||
|
||||
func TestSemconvResolutionsForDecodedExactField(t *testing.T) {
|
||||
var req qbtypes.QueryRangeRequest
|
||||
require.NoError(t, json.Unmarshal([]byte(`{
|
||||
"requestType":"raw",
|
||||
"compositeQuery":{"queries":[{"type":"builder_query","spec":{
|
||||
"signal":"traces","name":"A",
|
||||
"selectFields":[{
|
||||
"name":"deployment.environment",
|
||||
"fieldContext":"resource",
|
||||
"fieldDataType":"string",
|
||||
"fieldResolution":"exact"
|
||||
}]
|
||||
}}]}
|
||||
}`), &req), "exact field request fixture should decode")
|
||||
assert.Nil(t, semconvResolutionsForRequest(&req), "decoded exact field should not report a family resolution")
|
||||
}
|
||||
@@ -12,6 +12,8 @@ import (
|
||||
errorsV2 "github.com/SigNoz/signoz/pkg/errors"
|
||||
"github.com/SigNoz/signoz/pkg/query-service/model"
|
||||
v3 "github.com/SigNoz/signoz/pkg/query-service/model/v3"
|
||||
"github.com/SigNoz/signoz/pkg/semconv"
|
||||
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
|
||||
)
|
||||
|
||||
func (r *ClickHouseReader) GetQBFilterSuggestionsForLogs(
|
||||
@@ -248,17 +250,24 @@ func newRankingStrategy() attribRankingStrategy {
|
||||
|
||||
// Synonyms of interesting attributes should come next
|
||||
resourceHierarchy := fingerprint.ResourceHierarchy()
|
||||
for _, attr := range []string{
|
||||
for _, current := range []string{
|
||||
"service.name",
|
||||
"deployment.environment",
|
||||
"deployment.environment.name",
|
||||
"k8s.namespace.name",
|
||||
"k8s.pod.name",
|
||||
"k8s.container.name",
|
||||
"k8s.node.name",
|
||||
} {
|
||||
interestingResourceAttrsInDescRank = append(
|
||||
interestingResourceAttrsInDescRank, resourceHierarchy.Synonyms(attr)...,
|
||||
)
|
||||
members := semconv.Members(semconv.KindAttribute, telemetrytypes.FieldKeySelector{
|
||||
Name: current,
|
||||
FieldContext: telemetrytypes.FieldContextResource,
|
||||
})
|
||||
for _, member := range members {
|
||||
interestingResourceAttrsInDescRank = append(interestingResourceAttrsInDescRank, member)
|
||||
interestingResourceAttrsInDescRank = append(
|
||||
interestingResourceAttrsInDescRank, resourceHierarchy.Synonyms(member)...,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
interestingResourceAttrsInAscRank := interestingResourceAttrsInDescRank[:]
|
||||
|
||||
@@ -52,10 +52,10 @@ import (
|
||||
"github.com/SigNoz/signoz/pkg/query-service/constants"
|
||||
|
||||
chErrors "github.com/SigNoz/signoz/pkg/query-service/errors"
|
||||
"github.com/SigNoz/signoz/pkg/query-service/metrics"
|
||||
"github.com/SigNoz/signoz/pkg/query-service/model"
|
||||
v3 "github.com/SigNoz/signoz/pkg/query-service/model/v3"
|
||||
"github.com/SigNoz/signoz/pkg/query-service/utils"
|
||||
"github.com/SigNoz/signoz/pkg/semconv"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -3190,11 +3190,6 @@ func (r *ClickHouseReader) GetMetricAttributeValues(ctx context.Context, orgID v
|
||||
var rows driver.Rows
|
||||
var attributeValues v3.FilterAttributeValueResponse
|
||||
|
||||
normalized := true
|
||||
if constants.IsDotMetricsEnabled {
|
||||
normalized = false
|
||||
}
|
||||
|
||||
reductionEnabled := r.fl.BooleanOrEmpty(ctx, flagger.FeatureEnableMetricsReduction, featuretypes.NewFlaggerEvaluationContext(orgID))
|
||||
|
||||
if reductionEnabled {
|
||||
@@ -3205,8 +3200,7 @@ func (r *ClickHouseReader) GetMetricAttributeValues(ctx context.Context, orgID v
|
||||
if req.Limit != 0 {
|
||||
query = query + fmt.Sprintf(" LIMIT %d;", req.Limit)
|
||||
}
|
||||
names := []string{req.AggregateAttribute}
|
||||
names = append(names, metrics.GetTransitionedMetric(req.AggregateAttribute, normalized))
|
||||
names := semconv.MetricNames(req.AggregateAttribute)
|
||||
|
||||
rows, err = r.db.Query(ctx, query, req.FilterAttributeKey, names, req.FilterAttributeKey, fmt.Sprintf("%%%s%%", req.SearchText), common.PastDayRoundOff())
|
||||
|
||||
|
||||
@@ -1945,10 +1945,10 @@ func (aH *APIHandler) onboardConsumers(
|
||||
status = "1"
|
||||
}
|
||||
} else if key == "cgroup" {
|
||||
attribute = "messaging.kafka.consumer.group"
|
||||
attribute = "messaging.consumer.group.name"
|
||||
if intValue != 0 {
|
||||
status = "0"
|
||||
message = "messaging.kafka.consumer.group attribute is not present in your spans"
|
||||
message = "messaging.consumer.group.name attribute is not present in your spans"
|
||||
} else {
|
||||
status = "1"
|
||||
}
|
||||
@@ -1961,10 +1961,10 @@ func (aH *APIHandler) onboardConsumers(
|
||||
status = "1"
|
||||
}
|
||||
} else if key == "clientid" {
|
||||
attribute = "messaging.client_id"
|
||||
attribute = "messaging.client.id"
|
||||
if intValue != 0 {
|
||||
status = "0"
|
||||
message = "messaging.client_id attribute is not present in your spans"
|
||||
message = "messaging.client.id attribute is not present in your spans"
|
||||
} else {
|
||||
status = "1"
|
||||
}
|
||||
|
||||
@@ -203,7 +203,7 @@ var dotMetricMap = map[string]string{
|
||||
"k8s_hpa_scaletargetref_apiversion": "k8s.hpa.scaletargetref.apiversion",
|
||||
"k8s_job_uid": "k8s.job.uid",
|
||||
"k8s_kubelet_version": "k8s.kubelet.version",
|
||||
"container_runtime": "container.runtime",
|
||||
"container_runtime": "container.runtime.name",
|
||||
"container_runtime_version": "container.runtime.version",
|
||||
"os_description": "os.description",
|
||||
"openshift_clusterquota_uid": "openshift.clusterquota.uid",
|
||||
|
||||
@@ -335,7 +335,7 @@ Response in query range `table` format
|
||||
"status": "1"
|
||||
},
|
||||
{
|
||||
"attribute": "messaging.client_id",
|
||||
"attribute": "messaging.client.id",
|
||||
"error_message": "",
|
||||
"status": "1"
|
||||
},
|
||||
@@ -350,7 +350,7 @@ Response in query range `table` format
|
||||
"status": "1"
|
||||
},
|
||||
{
|
||||
"attribute": "messaging.kafka.consumer.group",
|
||||
"attribute": "messaging.consumer.group.name",
|
||||
"error_message": "",
|
||||
"status": "1"
|
||||
},
|
||||
@@ -392,7 +392,7 @@ Response in query range `table` format
|
||||
"status": "0"
|
||||
},
|
||||
{
|
||||
"attribute": "messaging.client_id",
|
||||
"attribute": "messaging.client.id",
|
||||
"error_message": "",
|
||||
"status": "1"
|
||||
},
|
||||
@@ -407,8 +407,8 @@ Response in query range `table` format
|
||||
"status": "1"
|
||||
},
|
||||
{
|
||||
"attribute": "messaging.kafka.consumer.group",
|
||||
"error_message": "messaging.kafka.consumer.group attribute is not present in your spans",
|
||||
"attribute": "messaging.consumer.group.name",
|
||||
"error_message": "messaging.consumer.group.name attribute is not present in your spans",
|
||||
"status": "0"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -2,8 +2,20 @@ package kafka
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/query-service/app/integrations/messagingQueues/semconvsql"
|
||||
)
|
||||
|
||||
var kafkaSemconvAttributes = []string{
|
||||
"messaging.destination.name",
|
||||
"messaging.consumer.group.name",
|
||||
"messaging.client.id",
|
||||
}
|
||||
|
||||
func resolveKafkaSemconvSQL(query string) string {
|
||||
return semconvsql.ResolveTraceStringAttributes(query, kafkaSemconvAttributes...)
|
||||
}
|
||||
|
||||
func generateConsumerSQL(start, end int64, topic, partition, consumerGroup, queueType string) string {
|
||||
timeRange := (end - start) / 1000000000
|
||||
tsBucketStart := (start / 1000000000) - 1800
|
||||
@@ -26,7 +38,7 @@ WITH consumer_query AS (
|
||||
AND attribute_string_messaging$$system = '%s'
|
||||
AND attributes_string['messaging.destination.name'] = '%s'
|
||||
AND attributes_string['messaging.destination.partition.id'] = '%s'
|
||||
AND attributes_string['messaging.kafka.consumer.group'] = '%s'
|
||||
AND attributes_string['messaging.consumer.group.name'] = '%s'
|
||||
GROUP BY resource_string_service$$name
|
||||
)
|
||||
|
||||
@@ -41,7 +53,7 @@ FROM
|
||||
ORDER BY
|
||||
resource_string_service$$name;
|
||||
`, start, end, tsBucketStart, tsBucketEnd, queueType, topic, partition, consumerGroup, timeRange)
|
||||
return query
|
||||
return resolveKafkaSemconvSQL(query)
|
||||
}
|
||||
|
||||
// S1 landing
|
||||
@@ -77,7 +89,7 @@ FROM
|
||||
ORDER BY
|
||||
topic;
|
||||
`, start, end, tsBucketStart, tsBucketEnd, queueType, timeRange)
|
||||
return query
|
||||
return resolveKafkaSemconvSQL(query)
|
||||
}
|
||||
|
||||
// S1 consumer
|
||||
@@ -88,7 +100,7 @@ func generateConsumerPartitionLatencySQL(start, end int64, topic, partition, que
|
||||
query := fmt.Sprintf(`
|
||||
WITH consumer_pl AS (
|
||||
SELECT
|
||||
attributes_string['messaging.kafka.consumer.group'] AS consumer_group,
|
||||
attributes_string['messaging.consumer.group.name'] AS consumer_group,
|
||||
resource_string_service$$name,
|
||||
quantile(0.99)(durationNano) / 1000000 AS p99,
|
||||
COUNT(*) AS total_requests,
|
||||
@@ -117,7 +129,7 @@ FROM
|
||||
ORDER BY
|
||||
consumer_group;
|
||||
`, start, end, tsBucketStart, tsBucketEnd, queueType, topic, partition, timeRange)
|
||||
return query
|
||||
return resolveKafkaSemconvSQL(query)
|
||||
}
|
||||
|
||||
// S3, producer overview
|
||||
@@ -153,7 +165,7 @@ SELECT
|
||||
FROM
|
||||
producer_latency
|
||||
`, start, end, tsBucketStart, tsBucketEnd, queueType, timeRange)
|
||||
return query
|
||||
return resolveKafkaSemconvSQL(query)
|
||||
}
|
||||
|
||||
// S3, producer topic/service overview
|
||||
@@ -189,7 +201,7 @@ SELECT
|
||||
FROM
|
||||
consumer_latency
|
||||
`, start, end, tsBucketStart, tsBucketEnd, service, queueType, topic, timeRange)
|
||||
return query
|
||||
return resolveKafkaSemconvSQL(query)
|
||||
}
|
||||
|
||||
// S3 consumer overview
|
||||
@@ -229,7 +241,7 @@ FROM
|
||||
ORDER BY
|
||||
topic;
|
||||
`, start, end, tsBucketStart, tsBucketEnd, queueType, timeRange, timeRange)
|
||||
return query
|
||||
return resolveKafkaSemconvSQL(query)
|
||||
}
|
||||
|
||||
// S3 consumer topic/service
|
||||
@@ -265,7 +277,7 @@ SELECT
|
||||
FROM
|
||||
consumer_latency
|
||||
`, start, end, tsBucketStart, tsBucketEnd, service, queueType, topic, timeRange)
|
||||
return query
|
||||
return resolveKafkaSemconvSQL(query)
|
||||
}
|
||||
|
||||
// s4
|
||||
@@ -315,7 +327,7 @@ GROUP BY
|
||||
producer_service,
|
||||
consumer_service
|
||||
`, start, end, start, end, queueType, queueType, evalTime, evalTime)
|
||||
return query
|
||||
return resolveKafkaSemconvSQL(query)
|
||||
}
|
||||
|
||||
func generateProducerSQL(start, end int64, topic, partition, queueType string) string {
|
||||
@@ -352,7 +364,7 @@ FROM
|
||||
ORDER BY
|
||||
resource_string_service$$name;
|
||||
`, start, end, tsBucketStart, tsBucketEnd, queueType, topic, partition, timeRange)
|
||||
return query
|
||||
return resolveKafkaSemconvSQL(query)
|
||||
}
|
||||
|
||||
func generateNetworkLatencyThroughputSQL(start, end int64, consumerGroup, partitionID, queueType string) string {
|
||||
@@ -361,7 +373,7 @@ func generateNetworkLatencyThroughputSQL(start, end int64, consumerGroup, partit
|
||||
tsBucketEnd := end / 1000000000
|
||||
query := fmt.Sprintf(`
|
||||
SELECT
|
||||
attributes_string['messaging.client_id'] AS client_id,
|
||||
attributes_string['messaging.client.id'] AS client_id,
|
||||
resources_string['service.instance.id'] AS service_instance_id,
|
||||
resource_string_service$$name AS service_name,
|
||||
count(*) / %d AS throughput
|
||||
@@ -373,12 +385,12 @@ WHERE
|
||||
AND ts_bucket_start <= '%d'
|
||||
AND kind = 5
|
||||
AND attribute_string_messaging$$system = '%s'
|
||||
AND attributes_string['messaging.kafka.consumer.group'] = '%s'
|
||||
AND attributes_string['messaging.consumer.group.name'] = '%s'
|
||||
AND attributes_string['messaging.destination.partition.id'] = '%s'
|
||||
GROUP BY service_name, client_id, service_instance_id
|
||||
ORDER BY throughput DESC
|
||||
`, timeRange, start, end, tsBucketStart, tsBucketEnd, queueType, consumerGroup, partitionID)
|
||||
return query
|
||||
return resolveKafkaSemconvSQL(query)
|
||||
}
|
||||
|
||||
func onboardProducersSQL(start, end int64, queueType string) string {
|
||||
@@ -398,7 +410,7 @@ WHERE
|
||||
AND timestamp <= '%d'
|
||||
AND ts_bucket_start >= '%d'
|
||||
AND ts_bucket_start <= '%d';`, queueType, start, end, tsBucketStart, tsBucketEnd)
|
||||
return query
|
||||
return resolveKafkaSemconvSQL(query)
|
||||
}
|
||||
|
||||
func onboardConsumerSQL(start, end int64, queueType string) string {
|
||||
@@ -412,9 +424,9 @@ SELECT
|
||||
COUNT(resource_string_service$$name) = 0 AS svc,
|
||||
COUNT(IF(has(attributes_string, 'messaging.destination.name'), 1, NULL)) = 0 AS destination,
|
||||
COUNT(IF(has(attributes_string, 'messaging.destination.partition.id'), 1, NULL)) = 0 AS partition,
|
||||
COUNT(IF(has(attributes_string, 'messaging.kafka.consumer.group'), 1, NULL)) = 0 AS cgroup,
|
||||
COUNT(IF(has(attributes_string, 'messaging.consumer.group.name'), 1, NULL)) = 0 AS cgroup,
|
||||
COUNT(IF(has(attributes_number, 'messaging.message.body.size'), 1, NULL)) = 0 AS bodysize,
|
||||
COUNT(IF(has(attributes_string, 'messaging.client_id'), 1, NULL)) = 0 AS clientid,
|
||||
COUNT(IF(has(attributes_string, 'messaging.client.id'), 1, NULL)) = 0 AS clientid,
|
||||
COUNT(IF(has(resources_string, 'service.instance.id'), 1, NULL)) = 0 AS instanceid
|
||||
FROM signoz_traces.distributed_signoz_index_v3
|
||||
WHERE
|
||||
@@ -422,5 +434,5 @@ WHERE
|
||||
AND timestamp <= '%d'
|
||||
AND ts_bucket_start >= '%d'
|
||||
AND ts_bucket_start <= '%d' ;`, queueType, start, end, tsBucketStart, tsBucketEnd)
|
||||
return query
|
||||
return resolveKafkaSemconvSQL(query)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/query-service/app/integrations/messagingQueues/semconvsql"
|
||||
v3 "github.com/SigNoz/signoz/pkg/query-service/model/v3"
|
||||
format "github.com/SigNoz/signoz/pkg/query-service/utils"
|
||||
)
|
||||
@@ -59,10 +60,7 @@ WITH
|
||||
ELSE 'undefined'
|
||||
END AS messaging_system,
|
||||
kind_string,
|
||||
COALESCE(
|
||||
NULLIF(attributes_string['messaging.destination.name'], ''),
|
||||
NULLIF(attributes_string['messaging.destination'], '')
|
||||
) AS destination,
|
||||
attributes_string['messaging.destination.name'] AS destination,
|
||||
durationNano,
|
||||
status_code
|
||||
FROM signoz_traces.distributed_signoz_index_v3
|
||||
@@ -113,5 +111,5 @@ ORDER BY
|
||||
whereSQL, timeRangeSecs,
|
||||
)
|
||||
|
||||
return query
|
||||
return semconvsql.ResolveTraceStringAttributes(query, "messaging.destination.name")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
// Package semconvsql expands current semantic-convention attribute names in
|
||||
// integration-owned SQL into current-first compatibility expressions.
|
||||
package semconvsql
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/SigNoz/signoz/pkg/semconv"
|
||||
"github.com/SigNoz/signoz/pkg/types/telemetrytypes"
|
||||
)
|
||||
|
||||
var traceAttributeSelector = telemetrytypes.FieldKeySelector{
|
||||
Signal: telemetrytypes.SignalTraces,
|
||||
FieldContext: telemetrytypes.FieldContextAttribute,
|
||||
}
|
||||
|
||||
// ResolveTraceStringAttributes replaces direct map reads and existence checks
|
||||
// for currentNames. Callers keep only current names in their SQL templates;
|
||||
// the generated family table supplies every historical spelling.
|
||||
func ResolveTraceStringAttributes(query string, currentNames ...string) string {
|
||||
for _, current := range currentNames {
|
||||
selector := traceAttributeSelector
|
||||
selector.Name = current
|
||||
members := semconv.Members(semconv.KindAttribute, selector)
|
||||
if len(members) < 2 {
|
||||
continue
|
||||
}
|
||||
|
||||
directRead := attributeRead(current)
|
||||
reads := make([]string, 0, len(members))
|
||||
exists := make([]string, 0, len(members))
|
||||
for _, member := range members {
|
||||
reads = append(reads, fmt.Sprintf("NULLIF(%s, '')", attributeRead(member)))
|
||||
exists = append(exists, fmt.Sprintf("has(attributes_string, '%s')", quoteName(member)))
|
||||
}
|
||||
|
||||
query = strings.ReplaceAll(query, directRead, "COALESCE("+strings.Join(reads, ", ")+")")
|
||||
query = strings.ReplaceAll(
|
||||
query,
|
||||
fmt.Sprintf("has(attributes_string, '%s')", quoteName(current)),
|
||||
"("+strings.Join(exists, " OR ")+")",
|
||||
)
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
func attributeRead(name string) string {
|
||||
return fmt.Sprintf("attributes_string['%s']", quoteName(name))
|
||||
}
|
||||
|
||||
func quoteName(name string) string {
|
||||
return strings.ReplaceAll(name, "'", "''")
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package semconvsql
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestResolveTraceStringAttributesExpandsDirectReads(t *testing.T) {
|
||||
query := `SELECT attributes_string['messaging.destination.name'] AS destination
|
||||
FROM spans`
|
||||
|
||||
resolved := ResolveTraceStringAttributes(query, "messaging.destination.name")
|
||||
|
||||
assert.Contains(t, resolved, "COALESCE(NULLIF(attributes_string['messaging.destination.name'], ''), NULLIF(attributes_string['messaging.destination'], ''))", "direct attribute read should coalesce every family member")
|
||||
}
|
||||
|
||||
func TestResolveTraceStringAttributesExpandsExistenceChecks(t *testing.T) {
|
||||
query := `SELECT count() FROM spans
|
||||
WHERE has(attributes_string, 'messaging.destination.name')`
|
||||
|
||||
resolved := ResolveTraceStringAttributes(query, "messaging.destination.name")
|
||||
|
||||
assert.Contains(t, resolved, "(has(attributes_string, 'messaging.destination.name') OR has(attributes_string, 'messaging.destination'))", "existence check should cover every family member")
|
||||
}
|
||||
|
||||
func TestResolveTraceStringAttributesKeepsCurrentNameFirst(t *testing.T) {
|
||||
query := `SELECT attributes_string['messaging.destination.name'] FROM spans`
|
||||
|
||||
resolved := ResolveTraceStringAttributes(query, "messaging.destination.name")
|
||||
|
||||
assert.Less(t, strings.Index(resolved, "messaging.destination.name"), strings.Index(resolved, "messaging.destination'"), "current name should remain the first fallback")
|
||||
}
|
||||
|
||||
func TestResolveTraceStringAttributesLeavesUnknownNameAlone(t *testing.T) {
|
||||
query := "SELECT attributes_string['custom.attribute']"
|
||||
|
||||
resolved := ResolveTraceStringAttributes(query, "custom.attribute")
|
||||
|
||||
assert.Equal(t, query, resolved, "unknown attributes should not be rewritten")
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user