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 - Add support for scoped intrinsics using : #3629

Merged
merged 6 commits into from
May 3, 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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
* [ENHANCEMENT] Add tenant to frontend job cache key. [#3527](https://github.com/grafana/tempo/pull/3527) (@joe-elliott)
* [ENHANCEMENT] Better compaction throughput and memory usage [#3579](https://github.com/grafana/tempo/pull/3579) (@mdisibio)
* [ENHANCEMENT] Add support for sharded ingester queries [#3574](https://github.com/grafana/tempo/pull/3574) (@zalegrala)
* [ENHANCEMENT] TraceQL - Add support for scoped intrinsics using `:` [#3629](https://github.com/grafana/tempo/pull/3629) (@ie-pham)
joe-elliott marked this conversation as resolved.
Show resolved Hide resolved
available scoped intrinsics: trace:duration, trace:rootName, trace:rootService, span:duration, span:kind, span:name, span:status, span:statusMessage
* [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
25 changes: 12 additions & 13 deletions docs/sources/tempo/traceql/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,23 +71,22 @@ TraceQL differentiates between two types of span data: intrinsics, which are fun

In TraceQL, curly brackets `{}` always select a set of spans from the current trace. They are commonly paired with a condition to reduce the spans being passed in.


### Intrinsic fields

Intrinsic fields are fundamental to spans. These fields can be referenced when selecting spans. Note that custom attributes are prefixed with `.`, `span.` or `resource.` whereas intrinsics are typed directly.

The following table shows the current intrinsic fields:

| **Field** | **Type** | **Definition** | **Example** |
| --------------- | ----------- | --------------------------------------------------------------- | --------------------------------- |
| `status` | status enum | status: error, ok, or unset | `{ status = ok }` |
| `statusMessage` | string | optional text accompanying the span status | `{ statusMessage = "Forbidden" }` |
| `duration` | duration | end - start time of the span | `{ duration > 100ms }` |
| `name` | string | operation or span name | `{ name = "HTTP POST" }` |
| `kind` | kind enum | kind: server, client, producer, consumer, internal, unspecified | `{ kind = server }` |
| `traceDuration` | duration | max(end) - min(start) time of the spans in the trace | `{ traceDuration > 100ms }` |
| `rootName` | string | if it exists the name of the root span in the trace | `{ rootName = "HTTP GET" }` |
| `rootServiceName` | string | if it exists the service name of the root span in the trace | `{ rootServiceName = "gateway" }` |
The following table shows the current available scoped intrinsic fields:
joe-elliott marked this conversation as resolved.
Show resolved Hide resolved

| **Field** | **Type** | **Definition** | **Example** |
| ----------------------- | ----------- | --------------------------------------------------------------- | -------------------------------------- |
| `span:status` | status enum | status: error, ok, or unset | `{ span:status = ok }` |
| `span:statusMessage` | string | optional text accompanying the span status | `{ span:statusMessage = "Forbidden" }` |
| `span:duration` | duration | end - start time of the span | `{ span:duration > 100ms }` |
| `span:name` | string | operation or span name | `{ span:name = "HTTP POST" }` |
| `span:kind` | kind enum | kind: server, client, producer, consumer, internal, unspecified | `{ span:kind = server }` |
| `trace:duration` | duration | max(end) - min(start) time of the spans in the trace | `{ trace:duration > 100ms }` |
| `trace:rootName` | string | if it exists the name of the root span in the trace | `{ trace:rootName = "HTTP GET" }` |
| `trace:rootServiceName` | string | if it exists the service name of the root span in the trace | `{ trace:rootServiceName = "gateway" }`|

{{< admonition type="note" >}}
`traceDuration`, `rootName`, and `rootServiceName` are trace-level intrinsics and will be the same for all spans in the same trace. Additionally,
Expand Down
2 changes: 1 addition & 1 deletion pkg/traceql/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -722,7 +722,7 @@ func (Attribute) referencesSpan() bool {
func NewScopedAttribute(scope AttributeScope, parent bool, att string) Attribute {
intrinsic := IntrinsicNone
// if we are explicitly passed a resource or span scopes then we shouldn't parse for intrinsic
if scope != AttributeScopeResource && scope != AttributeScopeSpan {
if scope == AttributeScopeNone && !parent {
joe-elliott marked this conversation as resolved.
Show resolved Hide resolved
intrinsic = intrinsicFromString(att)
}

Expand Down
27 changes: 23 additions & 4 deletions pkg/traceql/expr.y
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import (
intrinsicField Attribute
attributeField Attribute
attribute Attribute
scopedIntrinsicField Attribute

binOp Operator
staticInt int
Expand Down Expand Up @@ -75,6 +76,7 @@ import (
%type <static> static
%type <intrinsicField> intrinsicField
%type <attributeField> attributeField
%type <scopedIntrinsicField> scopedIntrinsicField
%type <attribute> attribute

%type <numericList> numericList
Expand All @@ -90,8 +92,9 @@ 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 NESTEDSETLEFT NESTEDSETRIGHT NESTEDSETPARENT
PARENT_DOT RESOURCE_DOT SPAN_DOT
IDURATION CHILDCOUNT NAME STATUS STATUS_MESSAGE PARENT KIND ROOTNAME ROOTSERVICENAME
ROOTSERVICE TRACEDURATION NESTEDSETLEFT NESTEDSETRIGHT NESTEDSETPARENT
PARENT_DOT RESOURCE_DOT SPAN_DOT TRACE_COLON SPAN_COLON
COUNT AVG MAX MIN SUM
BY COALESCE SELECT
END_ATTRIBUTE
Expand Down Expand Up @@ -167,8 +170,9 @@ selectOperation:
;

attribute:
intrinsicField { $$ = $1 }
| attributeField { $$ = $1 }
intrinsicField { $$ = $1 }
Copy link
Member

Choose a reason for hiding this comment

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

can we add a comment above the intrinsicField definition that we are no longer adding these?

| attributeField { $$ = $1 }
| scopedIntrinsicField { $$ = $1 }
;

attributeList:
Expand Down Expand Up @@ -328,6 +332,7 @@ fieldExpression:
| static { $$ = $1 }
| intrinsicField { $$ = $1 }
| attributeField { $$ = $1 }
| scopedIntrinsicField { $$ = $1 }
;

// **********************
Expand All @@ -352,6 +357,8 @@ static:
| KIND_CONSUMER { $$ = NewStaticKind(KindConsumer) }
;

// ** DO NOT ADD MORE FEATURES **
// Going forward with scoped intrinsics only
intrinsicField:
IDURATION { $$ = NewIntrinsic(IntrinsicDuration) }
| CHILDCOUNT { $$ = NewIntrinsic(IntrinsicChildCount) }
Expand All @@ -368,6 +375,18 @@ intrinsicField:
| NESTEDSETPARENT { $$ = NewIntrinsic(IntrinsicNestedSetParent) }
;

scopedIntrinsicField:
// trace:
TRACE_COLON IDURATION { $$ = NewIntrinsic(IntrinsicTraceDuration) }
| TRACE_COLON ROOTNAME { $$ = NewIntrinsic(IntrinsicTraceRootSpan) }
| TRACE_COLON ROOTSERVICE { $$ = NewIntrinsic(IntrinsicTraceRootService) }
// span:
| SPAN_COLON IDURATION { $$ = NewIntrinsic(IntrinsicDuration) }
| SPAN_COLON NAME { $$ = NewIntrinsic(IntrinsicName) }
| SPAN_COLON KIND { $$ = NewIntrinsic(IntrinsicKind) }
| SPAN_COLON STATUS { $$ = NewIntrinsic(IntrinsicStatus) }
| SPAN_COLON STATUS_MESSAGE { $$ = NewIntrinsic(IntrinsicStatusMessage) }

attributeField:
DOT IDENTIFIER END_ATTRIBUTE { $$ = NewAttribute($2) }
| RESOURCE_DOT IDENTIFIER END_ATTRIBUTE { $$ = NewScopedAttribute(AttributeScopeResource, false, $2) }
Expand Down
Loading
Loading