Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TraceQL: Nested set intrinsics #3497

Merged
merged 7 commits into from
Mar 21, 2024
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* [CHANGE] Align metrics query time ranges to the step parameter [#3490](https://github.com/grafana/tempo/pull/3490) (@mdisibio)
* [ENHANCEMENT] Add string interning to TraceQL queries [#3411](https://github.com/grafana/tempo/pull/3411) (@mapno)
* [ENHANCEMENT] Add new (unsafe) query hints for metrics queries [#3396](https://github.com/grafana/tempo/pull/3396) (@mdisibio)
* [ENHANCEMENT] Add nestedSetLeft/Right/Parent instrinsics to TraceQL. [#3497](https://github.com/grafana/tempo/pull/3497) (@joe-elliott)
* [BUGFIX] Fix metrics query results when filtering and rating on the same attribute [#3428](https://github.com/grafana/tempo/issues/3428) (@mdisibio)
* [BUGFIX] Fix metrics query results when series contain empty strings or nil values [#3429](https://github.com/grafana/tempo/issues/3429) (@mdisibio)
* [BUGFIX] Fix metrics query duration check, add per-tenant override for max metrics query duration [#3479](https://github.com/grafana/tempo/issues/3479) (@mdisibio)
Expand Down
6 changes: 6 additions & 0 deletions pkg/search/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,11 @@ func GetVirtualIntrinsicValues() []string {
traceql.IntrinsicTraceDuration.String(),
traceql.IntrinsicTraceRootService.String(),
traceql.IntrinsicTraceRootSpan.String(),
/* these are technically intrinsics that can be requested, but they are not generally of interest to a user
typing a query. for simplicity and clarity we are leaving them out of autocomplete
IntrinsicNestedSetLeft
IntrinsicNestedSetRight
IntrinsicNestedSetParent
*/
}
}
6 changes: 6 additions & 0 deletions pkg/traceql/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,12 @@ func (a Attribute) impliedType() StaticType {
return TypeString
case IntrinsicTraceRootSpan:
return TypeString
case IntrinsicNestedSetLeft:
return TypeInt
case IntrinsicNestedSetRight:
return TypeInt
case IntrinsicNestedSetParent:
return TypeInt
}

return TypeAttribute
Expand Down
49 changes: 49 additions & 0 deletions pkg/traceql/ast_conditions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,55 @@ func TestScalarFilter_extractConditions(t *testing.T) {
}
}

func TestStructuralNestedSet_extractConditions(t *testing.T) {
tests := []struct {
query string
conditions []Condition
allConditions bool
}{
{
query: `{} >> {}`,
conditions: []Condition{
newCondition(NewIntrinsic(IntrinsicStructuralDescendant), OpNone),
},
allConditions: false,
},
{
query: `{ nestedSetRight = 2 }`,
conditions: []Condition{
newCondition(NewIntrinsic(IntrinsicNestedSetRight), OpEqual, NewStaticInt(2)),
},
allConditions: true,
},

{
query: `{ nestedSetParent = 1 } > { nestedSetLeft < 3 }`,
conditions: []Condition{
newCondition(NewIntrinsic(IntrinsicStructuralChild), OpNone),
newCondition(NewIntrinsic(IntrinsicNestedSetParent), OpEqual, NewStaticInt(1)),
newCondition(NewIntrinsic(IntrinsicNestedSetLeft), OpLess, NewStaticInt(3)),
},
allConditions: false,
},
}
for _, tt := range tests {
t.Run(tt.query, func(t *testing.T) {
expr, err := Parse(tt.query)
require.NoError(t, err)

req := &FetchSpansRequest{
Conditions: []Condition{},
AllConditions: true,
}
expr.Pipeline.extractConditions(req)

assert.Equal(t, tt.conditions, req.Conditions)
assert.Nil(t, req.SecondPassConditions)
assert.Equal(t, tt.allConditions, req.AllConditions, "FetchSpansRequest.AllConditions")
})
}
}

func TestSelect_extractConditions(t *testing.T) {
tests := []struct {
query string
Expand Down
18 changes: 18 additions & 0 deletions pkg/traceql/enum_attributes.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ const (
IntrinsicTraceRootService
IntrinsicTraceRootSpan
IntrinsicTraceDuration
IntrinsicNestedSetLeft
IntrinsicNestedSetRight
IntrinsicNestedSetParent

// not yet implemented in traceql but will be
IntrinsicParent
Expand Down Expand Up @@ -91,6 +94,9 @@ var (
IntrinsicTraceRootSpanAttribute = NewIntrinsic(IntrinsicTraceRootSpan)
IntrinsicTraceDurationAttribute = NewIntrinsic(IntrinsicTraceDuration)
IntrinsicSpanStartTimeAttribute = NewIntrinsic(IntrinsicSpanStartTime)
IntrinsicNestedSetLeftAttribute = NewIntrinsic(IntrinsicNestedSetLeft)
IntrinsicNestedSetRightAttribute = NewIntrinsic(IntrinsicNestedSetRight)
IntrinsicNestedSetParentAttribute = NewIntrinsic(IntrinsicNestedSetParent)
)

func (i Intrinsic) String() string {
Expand Down Expand Up @@ -126,6 +132,12 @@ func (i Intrinsic) String() string {
return "spanID"
case IntrinsicSpanStartTime:
return "spanStartTime"
case IntrinsicNestedSetLeft:
return "nestedSetLeft"
case IntrinsicNestedSetRight:
return "nestedSetRight"
case IntrinsicNestedSetParent:
return "nestedSetParent"
}

return fmt.Sprintf("intrinsic(%d)", i)
Expand Down Expand Up @@ -163,6 +175,12 @@ func intrinsicFromString(s string) Intrinsic {
return IntrinsicSpanID
case "spanStartTime":
return IntrinsicSpanStartTime
case "nestedSetLeft":
return IntrinsicNestedSetLeft
case "nestedSetRight":
return IntrinsicNestedSetRight
case "nestedSetParent":
return IntrinsicNestedSetParent
}

return IntrinsicNone
Expand Down
5 changes: 4 additions & 1 deletion pkg/traceql/expr.y
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ import (
%token <val> DOT OPEN_BRACE CLOSE_BRACE OPEN_PARENS CLOSE_PARENS COMMA
NIL TRUE FALSE STATUS_ERROR STATUS_OK STATUS_UNSET
KIND_UNSPECIFIED KIND_INTERNAL KIND_SERVER KIND_CLIENT KIND_PRODUCER KIND_CONSUMER
IDURATION CHILDCOUNT NAME STATUS STATUS_MESSAGE PARENT KIND ROOTNAME ROOTSERVICENAME TRACEDURATION
IDURATION CHILDCOUNT NAME STATUS STATUS_MESSAGE PARENT KIND ROOTNAME ROOTSERVICENAME TRACEDURATION NESTEDSETLEFT NESTEDSETRIGHT NESTEDSETPARENT
PARENT_DOT RESOURCE_DOT SPAN_DOT
COUNT AVG MAX MIN SUM
BY COALESCE SELECT
Expand Down Expand Up @@ -345,6 +345,9 @@ intrinsicField:
| ROOTNAME { $$ = NewIntrinsic(IntrinsicTraceRootSpan) }
| ROOTSERVICENAME { $$ = NewIntrinsic(IntrinsicTraceRootService) }
| TRACEDURATION { $$ = NewIntrinsic(IntrinsicTraceDuration) }
| NESTEDSETLEFT { $$ = NewIntrinsic(IntrinsicNestedSetLeft) }
| NESTEDSETRIGHT { $$ = NewIntrinsic(IntrinsicNestedSetRight) }
| NESTEDSETPARENT { $$ = NewIntrinsic(IntrinsicNestedSetParent) }
;

attributeField:
Expand Down
Loading
Loading