Skip to content

Commit

Permalink
[query] Add Graphite round function (#3648)
Browse files Browse the repository at this point in the history
  • Loading branch information
yyin-sc authored Aug 5, 2021
1 parent 0ab7b10 commit 1a0dca2
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 1 deletion.
36 changes: 35 additions & 1 deletion src/query/graphite/native/builtin_functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,33 @@ func keepLastValue(ctx *common.Context, input singlePathSpec, limit int) (ts.Ser
return r, nil
}

func roundFunction(ctx *common.Context, input singlePathSpec, precision int) (ts.SeriesList, error) {
output := make([]*ts.Series, 0, len(input.Values))
for _, series := range input.Values {
numSteps := series.Len()
vals := ts.NewValues(ctx, series.MillisPerStep(), numSteps)
for i := 0; i < numSteps; i++ {
value := series.ValueAt(i)
if !math.IsNaN(value) {
value = roundTo(value, int32(precision))
}
vals.SetValueAt(i, value)
}
name := ""
if precision == 0 {
name = fmt.Sprintf("roundFunction(%s)", series.Name())
} else {
name = fmt.Sprintf("roundFunction(%s,%d)", series.Name(), precision)
}
newSeries := ts.NewSeries(ctx, name, series.StartTime(), vals)
output = append(output, newSeries)
}

r := ts.SeriesList(input)
r.Values = output
return r, nil
}

type comparator func(float64, float64) bool

// equalFunc checks whether x is equal to y
Expand Down Expand Up @@ -1011,7 +1038,10 @@ func (impl *exponentialMovingAverageImpl) Evaluate(
}
}

func roundTo(n float64, decimals uint32) float64 {
func roundTo(n float64, decimals int32) float64 {
if decimals < 0 {
return math.Round(n/math.Pow(10, math.Abs(float64(decimals)))) * math.Pow(10, math.Abs(float64(decimals)))
}
return math.Round(n*math.Pow(10, float64(decimals))) / math.Pow(10, float64(decimals))
}

Expand Down Expand Up @@ -2942,6 +2972,9 @@ func init() {
MustRegisterFunction(removeEmptySeries).WithDefaultParams(map[uint8]interface{}{
2: 0.0, // xFilesFactor
})
MustRegisterFunction(roundFunction).WithDefaultParams(map[uint8]interface{}{
2: 0, // precision
})
MustRegisterFunction(scale)
MustRegisterFunction(scaleToSeconds)
MustRegisterFunction(sortBy).WithDefaultParams(map[uint8]interface{}{
Expand Down Expand Up @@ -3005,6 +3038,7 @@ func init() {
MustRegisterAliasedFunction("max", maxSeries)
MustRegisterAliasedFunction("min", minSeries)
MustRegisterAliasedFunction("randomWalk", randomWalkFunction)
MustRegisterAliasedFunction("round", roundFunction)
MustRegisterAliasedFunction("sum", sumSeries)
MustRegisterAliasedFunction("time", timeFunction)
}
54 changes: 54 additions & 0 deletions src/query/graphite/native/builtin_functions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1396,6 +1396,60 @@ func TestKeepLastValue(t *testing.T) {
}
}

func TestRoundFunction(t *testing.T) {
ctx := common.NewTestContext()
defer func() { _ = ctx.Close() }()

tests := []struct {
name string
inputs []float64
outputs []float64
outputName string
precision int
}{
{
"foo",
[]float64{111.1, math.NaN(), 111.11, math.NaN(), 111.111},
[]float64{110, math.NaN(), 110, math.NaN(), 110},
"roundFunction(foo,-1)",
-1,
},
{
"foo",
[]float64{1.1, math.NaN(), 1.11, math.NaN(), 1.111},
[]float64{1, math.NaN(), 1, math.NaN(), 1},
"roundFunction(foo)",
0,
},
{
"foo",
[]float64{1.1, math.NaN(), 1.11, math.NaN(), 1.111},
[]float64{1.1, math.NaN(), 1.1, math.NaN(), 1.1},
"roundFunction(foo,1)",
1,
},
{
"foo",
[]float64{1.1, math.NaN(), 1.11, math.NaN(), 1.111},
[]float64{1.10, math.NaN(), 1.11, math.NaN(), 1.11},
"roundFunction(foo,2)",
2,
},
}

start := time.Now()
for _, test := range tests {
input := ts.NewSeries(ctx, test.name, start, common.NewTestSeriesValues(ctx, 100, test.inputs))
outputs, err := roundFunction(ctx, singlePathSpec{
Values: []*ts.Series{input},
}, test.precision)
expected := common.TestSeries{Name: test.outputName, Data: test.outputs}
require.NoError(t, err)
common.CompareOutputsAndExpected(t, 100, start,
[]common.TestSeries{expected}, outputs.Values)
}
}

func TestSustainedAbove(t *testing.T) {
ctx := common.NewTestContext()
defer func() { _ = ctx.Close() }()
Expand Down

0 comments on commit 1a0dca2

Please sign in to comment.