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

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 @@ -5,6 +5,7 @@
* [CHANGE] Add support for s3 session token in static config [#2093](https://github.com/grafana/tempo/pull/2093) (@farodin91)
* [ENHANCEMENT] Metrics generator to make use of counters earlier [#2068](https://github.com/grafana/tempo/pull/2068) (@zalegrala)
* [ENHANCEMENT] Log when a trace is too large to compact [#2105](https://github.com/grafana/tempo/pull/2105) (@scalalang2)
* [ENHANCEMENT] Add support for arbitrary arithemtic to TraceQL queries [#2146](https://github.com/grafana/tempo/pull/2105) (@joe-elliott)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

oops, link sill points to 2105

* [ENHANCEMENT] tempo-cli: add command to migrate a tenant [#2130](https://github.com/grafana/tempo/pull/2130) (@kvrhdn)
* [BUGFIX] Apply `rate()` to bytes/s panel in tenant's dashboard. [#2081](https://github.com/grafana/tempo/pull/2081) (@mapno)
* [CHANGE] Update Go to 1.20 [#2079](https://github.com/grafana/tempo/pull/2079) (@scalalang2)
Expand Down
12 changes: 12 additions & 0 deletions docs/sources/tempo/traceql/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,18 @@ For example, find traces that have more than 3 spans with an attribute `http.sta
{ span.http.status = 200 } | count() > 3
```

## Arithmetic

TraceQL supports arbitrary arithmetic in your queries. This can be useful to make queries more human readable:
```
{ span.bytesProcessed > 10 * 1024 * 1024 }
```
to compare the ratios of two span attributes:
```
{ span.bytesProcessed < span.jobsProcessed * 10 }
```
or anything else that comes to mind.

## Examples

Find any trace with a span attribute or resource attribute `namespace` set to `prod`:
Expand Down
1 change: 0 additions & 1 deletion docs/sources/tempo/traceql/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ For more information about TraceQL’s design, refer to the [TraceQL Concepts de

### Future work

- Arithmetics
- Additional aggregates, such as `max()`, `min()`, and others.
- Grouping
- Structural Queries
Expand Down
8 changes: 5 additions & 3 deletions pkg/traceql/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -421,9 +421,11 @@ func (s Static) impliedType() StaticType {
}

func (s Static) Equals(other Static) bool {
// if they are different number types. compare them as floats. otherwise just fall through to the normal comparison
// which should be more efficient
differentNumberTypes := (s.Type == TypeInt && other.Type == TypeFloat) || (other.Type == TypeInt && s.Type == TypeFloat)
// if they are different number types. compare them as floats. however, if they are the same type just fall through to
// a normal comparison which should be more efficient
differentNumberTypes := (s.Type == TypeInt || s.Type == TypeFloat || s.Type == TypeDuration) &&
(other.Type == TypeInt || other.Type == TypeFloat || other.Type == TypeDuration) &&
s.Type != other.Type
if differentNumberTypes {
return s.asFloat() == other.asFloat()
}
Expand Down
11 changes: 8 additions & 3 deletions pkg/traceql/ast_execute.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package traceql
import (
"errors"
"fmt"
"math"
"regexp"

"github.com/go-kit/log/level"
Expand Down Expand Up @@ -162,12 +163,16 @@ func (o BinaryOperation) execute(span Span) (Static, error) {
}

switch o.Op {
// TODO implement arithmetics
case OpAdd:
return NewStaticFloat(lhs.asFloat() + rhs.asFloat()), nil
case OpSub:
return NewStaticFloat(lhs.asFloat() - rhs.asFloat()), nil
case OpDiv:
return NewStaticFloat(lhs.asFloat() / rhs.asFloat()), nil
case OpMod:
return NewStaticFloat(math.Mod(lhs.asFloat(), rhs.asFloat())), nil
case OpMult:
return NewStaticFloat(lhs.asFloat() * rhs.asFloat()), nil
case OpGreater:
return NewStaticBool(lhs.asFloat() > rhs.asFloat()), nil
case OpGreaterEqual:
Expand All @@ -177,6 +182,7 @@ func (o BinaryOperation) execute(span Span) (Static, error) {
case OpLessEqual:
return NewStaticBool(lhs.asFloat() <= rhs.asFloat()), nil
case OpPower:
return NewStaticFloat(math.Pow(lhs.asFloat(), rhs.asFloat())), nil
case OpEqual:
return NewStaticBool(lhs.Equals(rhs)), nil
case OpNotEqual:
Expand All @@ -194,10 +200,9 @@ func (o BinaryOperation) execute(span Span) (Static, error) {
default:
return NewStaticNil(), errors.New("unexpected operator " + o.Op.String())
}

return NewStaticNil(), errors.New("operator " + o.Op.String() + " is not yet implemented")
}

// why does this and the above exist?
func binOp(op Operator, lhs, rhs Static) (bool, error) {
lhsT := lhs.impliedType()
rhsT := rhs.impliedType()
Expand Down
Loading