Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion app/vtselect/traces/query/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,12 @@ func getTraceIDList(ctx context.Context, cp *tracecommon.CommonParams, param *Tr
}
if len(param.Attributes) > 0 {
for k, v := range param.Attributes {
qStr += fmt.Sprintf(`AND %q:=%q `, k, v)
Comment thread
jiekun marked this conversation as resolved.
if strings.HasPrefix(v, "~") {
// ~ prefix forces regex (e.g. tags={"key":"~value.*"})
qStr += fmt.Sprintf(`AND %q:re(%s) `, k, strconv.Quote(v[1:]))
Comment thread
emamihe marked this conversation as resolved.
} else {
qStr += fmt.Sprintf(`AND %q:=%q `, k, v)
}
}
}
if param.DurationMin > 0 {
Expand Down
47 changes: 47 additions & 0 deletions apptest/tests/otlp_ingestion_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ func getDefaultIngestRequestAndAssertFunc(tc *at.TestCase, sut at.VictoriaTraces
cmpopts.IgnoreFields(at.JaegerAPITracesResponse{}, "Errors", "Limit", "Offset", "Total"),
},
})

// check single trace data via /select/jaeger/api/traces/<trace_id>
tc.Assert(&at.AssertOptions{
Msg: "unexpected /select/jaeger/api/traces/<trace_id> response",
Expand All @@ -263,6 +264,52 @@ func getDefaultIngestRequestAndAssertFunc(tc *at.TestCase, sut at.VictoriaTraces
cmpopts.IgnoreFields(at.JaegerAPITraceResponse{}, "Errors", "Limit", "Offset", "Total"),
},
})

// check traces data via /select/jaeger/api/traces with regex tag filter: NOT match, empty result
tc.Assert(&at.AssertOptions{
Msg: "unexpected /select/jaeger/api/traces response",
Got: func() any {
return sut.JaegerAPITraces(t, at.JaegerQueryParam{
TraceQueryParam: query.TraceQueryParam{
ServiceName: serviceName,
StartTimeMin: spanTime.Add(-10 * time.Minute),
StartTimeMax: spanTime.Add(10 * time.Minute),
Attributes: map[string]string{
"testTag": "~INVALID.*",
},
},
}, at.QueryOpts{})
},
Want: &at.JaegerAPITracesResponse{
Data: []at.TracesResponseData{},
},
CmpOpts: []cmp.Option{
cmpopts.IgnoreFields(at.JaegerAPITracesResponse{}, "Errors", "Limit", "Offset", "Total"),
},
})

// check traces data via /select/jaeger/api/traces with regex tag filter: match
tc.Assert(&at.AssertOptions{
Msg: "unexpected /select/jaeger/api/traces response",
Got: func() any {
return sut.JaegerAPITraces(t, at.JaegerQueryParam{
TraceQueryParam: query.TraceQueryParam{
ServiceName: serviceName,
StartTimeMin: spanTime.Add(-10 * time.Minute),
StartTimeMax: spanTime.Add(10 * time.Minute),
Attributes: map[string]string{
"testTag": "~test.*",
},
},
}, at.QueryOpts{})
},
Want: &at.JaegerAPITracesResponse{
Data: expectTraceData,
},
CmpOpts: []cmp.Option{
cmpopts.IgnoreFields(at.JaegerAPITracesResponse{}, "Errors", "Limit", "Offset", "Total"),
},
})
}
return req, assertFunc
}
1 change: 1 addition & 0 deletions docs/victoriatraces/changelog/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ The following `tip` changes can be tested by building VictoriaTraces components

* FEATURE: [Single-node VictoriaTraces](https://docs.victoriametrics.com/victoriatraces/) and vtstorage in [VictoriaTraces cluster](https://docs.victoriametrics.com/victoriatraces/cluster/): allow generating service graph relation by database client span. The client span contains `db.system.name` attribute will generate a `service.name:db.system.name` (example: `account_service:mysql`) relation. It can be disabled by setting `-servicegraph.databaseTaskLimit=0`. Thank @wsx864321 for [the pull request #117](https://github.com/VictoriaMetrics/VictoriaTraces/pull/117).
* FEATURE: [dashboards/single-node](https://grafana.com/grafana/dashboards/24136), [dashboards/cluster](https://grafana.com/grafana/dashboards/24134): add clickable source code links to the `Logging rate` panel in `Overview`. Users can use it to navigate directly to the source code location that generated those logs, making debugging and code exploration easier. See [#106](https://github.com/VictoriaMetrics/VictoriaTraces/pull/106).
* FEATURE: [Single-node VictoriaTraces](https://docs.victoriametrics.com/victoriatraces/) and vtselect in [VictoriaTraces cluster](https://docs.victoriametrics.com/victoriatraces/cluster/): support positive regex matching in the Jaeger query API when filtering traces by tags. See [the pull request #116](https://github.com/VictoriaMetrics/VictoriaTraces/pull/116) for examples. Thank @emamihe for the pull request.

## [v0.8.0](https://github.com/VictoriaMetrics/VictoriaTraces/releases/tag/v0.8.0)

Expand Down
5 changes: 4 additions & 1 deletion docs/victoriatraces/querying/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ The `/select/jaeger/api/traces` HTTP endpoint provides the following params:

@cubic-dev-ai cubic-dev-ai Bot Mar 5, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The docs now show two different formats for the tags query param (space-separated key=value vs JSON map). The backend only accepts JSON (json.Unmarshal on tags), so leaving the space‑separated instructions while adding JSON regex examples is misleading and can result in invalid requests. Please make the tags format consistent in the examples/description.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At docs/victoriatraces/querying/README.md, line 219:

<comment>The docs now show two different formats for the `tags` query param (space-separated `key=value` vs JSON map). The backend only accepts JSON (`json.Unmarshal` on `tags`), so leaving the space‑separated instructions while adding JSON regex examples is misleading and can result in invalid requests. Please make the `tags` format consistent in the examples/description.</comment>

<file context>
@@ -216,3 +216,4 @@ Some valid filter examples:
 - Multiple span attribute filters: `error=unset otel.scope.name=redis-manual`
 - Single resource attribute filter: `resource_attr:telemetry.sdk.language=go`
 - Span attribute and resource attribute filters: `span.kind=client resource_attr:os.type=linux`
+- Regex filter: prefix the value with `~` to match by regex, e.g. `{"order_id":"~abc.*"}` or `{"http.status_code":"~^2"}` for values starting with "2"
</file context>
Fix with Cubic

- `service`: the service name.
- `operation`: the span name (also known as the operation name in Jaeger).
- `tags`: the attributes (also known as tags) filter, example: `{"key":"value"}`
- `tags`: the attributes (also known as tags) filter, example: `{"key":"value"}`. Prefix a value with `~` to use regex matching, e.g. `{"key":"~value.*"}`
- `start`: the start timestamp in unix microseconds.
- `end`: the end timestamp in unix microseconds.
- `minDuration`: the minimum duration of the span, with units `ns`, `us`, `ms`, `s`, `m`, or `h`.
Expand Down Expand Up @@ -216,3 +216,6 @@ Some valid filter examples:
- Multiple span attribute filters: `error=unset otel.scope.name=redis-manual`
- Single resource attribute filter: `resource_attr:telemetry.sdk.language=go`
- Span attribute and resource attribute filters: `span.kind=client resource_attr:os.type=linux`
- Multiple regex filters: `span.kind=~cli.* http.status_code:~^2`

Note that the examples are for user input on the Jaeger frontend, which parses and sends the request in JSON format later.
Loading