Skip to content

Commit

Permalink
Traceql arithmetic (#2146)
Browse files Browse the repository at this point in the history
* added arithmetic

Signed-off-by: Joe Elliott <[email protected]>

* added bench

Signed-off-by: Joe Elliott <[email protected]>

* make duration work as a number

Signed-off-by: Joe Elliott <[email protected]>

* benchmarkin'

Signed-off-by: Joe Elliott <[email protected]>

* make arithmetic valid

Signed-off-by: Joe Elliott <[email protected]>

* changelog

Signed-off-by: Joe Elliott <[email protected]>

* docs

Signed-off-by: Joe Elliott <[email protected]>

---------

Signed-off-by: Joe Elliott <[email protected]>
  • Loading branch information
joe-elliott authored Mar 3, 2023
1 parent 7242b04 commit 62ddaac
Show file tree
Hide file tree
Showing 9 changed files with 395 additions and 195 deletions.
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)
* [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

0 comments on commit 62ddaac

Please sign in to comment.