Files
traces/pkg/traceql/enum_hints.go
cc86e98b04 Rewrite conditions on same attribute to equivalent array operation (#6353)
* Add operators IN, NOT IN, MATCH ANY, and MATCH NONE

* Implement Static.append()

* Print string arrays with '`' instead of '"'

Example ["aa", "bb"] -> [`aa`, `bb`]

* Rewrite binary operations to array equivalent

The rewriter handles the following cases:
- { .a =  "a" || .a =  "b" } => { .a IN  ["a", "b"] }
- { .a != "a" && .a != "b" } => { .a NOT IN ["a", "b"] }
- { .a =~ "a" || .a =~ "b" } => { .a MATCH ANY ["a", "b"] }
- { .a !~ "a" && .a !~ "b" } => { .a MATCH NONE ["a", "b"] }

* Add test cases with arrays to TestBinOp

* traceql.Parse() applies AST optimizations by default

* Rename predicate_test.go to predicates_test.go

* Add array predicates to parquetquery

* BREAKING CHANGE: more precise regex validation

BinaryOperation.validate() considered everythin a valid regex where
FieldExpression.EncodeToString(false) happened to return a valid regex.
With this change the RHS of a regex operation is required to be a string
or string array

* vp4: handle predicates with arrays correctly

* vp5: handle predicates with arrays correctly

* vp3: handle predicates with arrays correctly

* Add test cases for optimized queries

* Update query test examples with optimizable queries

* vp3: fix handling of array types

* CHANGELOG.md

* Pass array operators down to fetch layer

* Read to first virtual row after seeking on a low definition level

This helps avoid additional spans/op in queries with only
resource attributes

---------

Co-authored-by: Martin Disibio <[email protected]>
2026-02-22 00:55:23 -08:00

112 lines
2.6 KiB
Go

package traceql
import (
"time"
)
// The list of all traceql query hints. Although most of these are implementation-specific
// and not part of the language or engine, we organize them here in one place.
const (
HintSample = "sample"
HintTraceSample = "trace_sample"
HintSpanSample = "span_sample"
HintJobSize = "job_size"
HintTimeOverlapCutoff = "time_overlap_cutoff"
HintConcurrentBlocks = "concurrent_blocks"
HintExemplars = "exemplars"
HintMostRecent = "most_recent" // traceql search hint to return most recent results ordered by time
HintDebug = "debug"
HintInfo = "info"
HintDebugReturnIn = "debug_return_in" // performance testing hint to simulate query latency and return fake data
HintDebugStdDev = "debug_std_dev" // standard deviation for debug_return_in latency simulation
HintDebugDataFactor = "debug_data_factor" // performance testing hint to control the possibility of non-empty fake data
HintSkipOptimization = "skip_optimization" // don't apply AST optimizations
)
func isUnsafe(h string) bool {
switch h {
case HintSample, HintTraceSample, HintSpanSample, HintExemplars, HintMostRecent, HintSkipOptimization:
return false
default:
return true
}
}
type Hint struct {
Name string
Value Static
}
func newHint(k string, v Static) *Hint {
return &Hint{k, v}
}
type Hints struct {
Hints []*Hint
}
func newHints(h []*Hint) *Hints {
return &Hints{h}
}
func (h *Hints) GetFloat(k string, allowUnsafe bool) (v float64, ok bool) {
if v, ok := h.Get(k, TypeFloat, allowUnsafe); ok {
return v.Float(), ok
}
// If float not found, then try integer.
if v, ok := h.Get(k, TypeInt, allowUnsafe); ok {
n, _ := v.Int()
return float64(n), ok
}
return
}
func (h *Hints) GetInt(k string, allowUnsafe bool) (v int, ok bool) {
if v, ok := h.Get(k, TypeInt, allowUnsafe); ok {
n, _ := v.Int()
return n, ok
}
return
}
func (h *Hints) GetDuration(k string, allowUnsafe bool) (v time.Duration, ok bool) {
if v, ok := h.Get(k, TypeDuration, allowUnsafe); ok {
d, _ := v.Duration()
return d, ok
}
return
}
func (h *Hints) GetBool(k string, allowUnsafe bool) (v, ok bool) {
if v, ok := h.Get(k, TypeBoolean, allowUnsafe); ok {
b, _ := v.Bool()
return b, ok
}
return
}
func (h *Hints) Get(k string, t StaticType, allowUnsafe bool) (v Static, ok bool) {
if h == nil {
return
}
if isUnsafe(k) && !allowUnsafe {
return
}
for _, hh := range h.Hints {
if hh.Name == k && hh.Value.Type == t {
return hh.Value, true
}
}
return
}
var _ Element = (*Hints)(nil)