From fbea9822eda90fd728037a0018749d3161d4861d Mon Sep 17 00:00:00 2001 From: Theodore Wahle Date: Thu, 10 Sep 2020 10:51:21 -0700 Subject: [PATCH 1/9] Added support for Graphite's and functions --- .../graphite/native/builtin_functions.go | 128 +++++++++++------- src/query/graphite/ts/series_reducer.go | 11 +- 2 files changed, 90 insertions(+), 49 deletions(-) diff --git a/src/query/graphite/native/builtin_functions.go b/src/query/graphite/native/builtin_functions.go index a8541e7c0f..622f70a8b7 100644 --- a/src/query/graphite/native/builtin_functions.go +++ b/src/query/graphite/native/builtin_functions.go @@ -486,36 +486,52 @@ func takeByFunction(input singlePathSpec, n int, sr ts.SeriesReducer, sort ts.Di return common.Head(r, n) } +func getReducer(f string) (ts.SeriesReducer, error) { + sa := ts.SeriesReducerApproach(f) + r, ok := sa.SafeReducer() + if !ok { + return r, errors.NewInvalidParamsError(fmt.Errorf("invalid function %s", f)) + } + return r, nil +} + +// highest takes one metric or a wildcard seriesList followed by an integer N and an aggregation function. +// Out of all metrics passed, draws only the N metrics with the highest +// aggregated value over the time period specified. +func highest(_ *common.Context, input singlePathSpec, n int, f string) (ts.SeriesList, error) { + reducer, err := getReducer(f) + if err != nil { + return ts.NewSeriesList(), err + } + return takeByFunction(input, n, reducer, ts.Descending) +} + // highestSum takes one metric or a wildcard seriesList followed by an integer // n. Out of all metrics passed, draws only the N metrics with the highest // total value in the time period specified. -func highestSum(_ *common.Context, input singlePathSpec, n int) (ts.SeriesList, error) { - sr := ts.SeriesReducerSum.Reducer() - return takeByFunction(input, n, sr, ts.Descending) +func highestSum(ctx *common.Context, input singlePathSpec, n int) (ts.SeriesList, error) { + return highest(ctx, input, n, "sum") } // highestMax takes one metric or a wildcard seriesList followed by an integer // n. Out of all metrics passed, draws only the N metrics with the highest // maximum value in the time period specified. -func highestMax(_ *common.Context, input singlePathSpec, n int) (ts.SeriesList, error) { - sr := ts.SeriesReducerMax.Reducer() - return takeByFunction(input, n, sr, ts.Descending) +func highestMax(ctx *common.Context, input singlePathSpec, n int) (ts.SeriesList, error) { + return highest(ctx, input, n, "max") } // highestCurrent takes one metric or a wildcard seriesList followed by an // integer n. Out of all metrics passed, draws only the N metrics with the // highest value at the end of the time period specified. -func highestCurrent(_ *common.Context, input singlePathSpec, n int) (ts.SeriesList, error) { - sr := ts.SeriesReducerLast.Reducer() - return takeByFunction(input, n, sr, ts.Descending) +func highestCurrent(ctx *common.Context, input singlePathSpec, n int) (ts.SeriesList, error) { + return highest(ctx, input, n, "current") } // highestAverage takes one metric or a wildcard seriesList followed by an // integer n. Out of all metrics passed, draws only the top N metrics with the // highest average value for the time period specified. -func highestAverage(_ *common.Context, input singlePathSpec, n int) (ts.SeriesList, error) { - sr := ts.SeriesReducerAvg.Reducer() - return takeByFunction(input, n, sr, ts.Descending) +func highestAverage(ctx *common.Context, input singlePathSpec, n int) (ts.SeriesList, error) { + return highest(ctx, input, n, "average") } // fallbackSeries takes one metric or a wildcard seriesList, and a second fallback metric. @@ -532,25 +548,60 @@ func fallbackSeries(_ *common.Context, input singlePathSpec, fallback singlePath // N. Draws the N most deviant metrics. To find the deviants, the standard // deviation (sigma) of each series is taken and ranked. The top N standard // deviations are returned. -func mostDeviant(_ *common.Context, input singlePathSpec, n int) (ts.SeriesList, error) { - sr := ts.SeriesReducerStdDev.Reducer() - return takeByFunction(input, n, sr, ts.Descending) +func mostDeviant(ctx *common.Context, input singlePathSpec, n int) (ts.SeriesList, error) { + return highest(ctx, input, n, "stddev") +} + +// lowest takes one metric or a wildcard seriesList followed by an integer N and an aggregation function. +// Out of all metrics passed, draws only the N metrics with the lowest +// aggregated value over the time period specified. +func lowest(_ *common.Context, input singlePathSpec, n int, f string) (ts.SeriesList, error) { + reducer, err := getReducer(f) + if err != nil { + return ts.NewSeriesList(), err + } + return takeByFunction(input, n, reducer, ts.Ascending) } // lowestAverage takes one metric or a wildcard seriesList followed by an // integer n. Out of all metrics passed, draws only the top N metrics with the // lowest average value for the time period specified. -func lowestAverage(_ *common.Context, input singlePathSpec, n int) (ts.SeriesList, error) { - sr := ts.SeriesReducerAvg.Reducer() - return takeByFunction(input, n, sr, ts.Ascending) +func lowestAverage(ctx *common.Context, input singlePathSpec, n int) (ts.SeriesList, error) { + return lowest(ctx, input, n, "average") } // lowestCurrent takes one metric or a wildcard seriesList followed by an // integer n. Out of all metrics passed, draws only the N metrics with the // lowest value at the end of the time period specified. -func lowestCurrent(_ *common.Context, input singlePathSpec, n int) (ts.SeriesList, error) { - sr := ts.SeriesReducerLast.Reducer() - return takeByFunction(input, n, sr, ts.Ascending) +func lowestCurrent(ctx *common.Context, input singlePathSpec, n int) (ts.SeriesList, error) { + return lowest(ctx, input, n, "current") +} + +// aggregateLine draws a horizontal line based the function applied to the series. +func aggregateLine(ctx *common.Context, seriesList singlePathSpec, f string) (ts.SeriesList, error) { + if len(seriesList.Values) == 0 { + return ts.NewSeriesList(), common.ErrEmptySeriesList + } + + sa := ts.SeriesReducerApproach(f) + r, ok := sa.SafeReducer() + if !ok { + return ts.NewSeriesList(), errors.NewInvalidParamsError(fmt.Errorf("invalid function %s", f)) + } + + value := r(seriesList.Values[0]) + name := fmt.Sprintf("aggregateLine(%s,"+common.FloatingPointFormat+")", + seriesList.Values[0].Specification, value) + series, err := constantLine(ctx, value) + if err != nil { + return ts.NewSeriesList(), err + } + + renamed := series.Values[0].RenamedTo(name) + return ts.SeriesList{ + Values: []*ts.Series{renamed}, + Metadata: seriesList.Metadata, + }, nil } // windowSizeFunc calculates window size for moving average calculation @@ -1556,33 +1607,6 @@ func randomWalkFunction(ctx *common.Context, name string, step int) (ts.SeriesLi return ts.NewSeriesListWithSeries(newSeries), nil } -// aggregateLine draws a horizontal line based the function applied to the series. -func aggregateLine(ctx *common.Context, seriesList singlePathSpec, f string) (ts.SeriesList, error) { - if len(seriesList.Values) == 0 { - return ts.NewSeriesList(), common.ErrEmptySeriesList - } - - sa := ts.SeriesReducerApproach(f) - r, ok := sa.SafeReducer() - if !ok { - return ts.NewSeriesList(), errors.NewInvalidParamsError(fmt.Errorf("invalid function %s", f)) - } - - value := r(seriesList.Values[0]) - name := fmt.Sprintf("aggregateLine(%s,"+common.FloatingPointFormat+")", - seriesList.Values[0].Specification, value) - series, err := constantLine(ctx, value) - if err != nil { - return ts.NewSeriesList(), err - } - - renamed := series.Values[0].RenamedTo(name) - return ts.SeriesList{ - Values: []*ts.Series{renamed}, - Metadata: seriesList.Metadata, - }, nil -} - // changed takes one metric or a wildcard seriesList. // Output 1 when the value changed, 0 when null or the same. func changed(ctx *common.Context, seriesList singlePathSpec) (ts.SeriesList, error) { @@ -1893,6 +1917,10 @@ func init() { MustRegisterFunction(group) MustRegisterFunction(groupByNode) MustRegisterFunction(groupByNodes) + MustRegisterFunction(highest).WithDefaultParams(map[uint8]interface{}{ + 2: 1, // n, + 3: "average", // f + }) MustRegisterFunction(highestAverage) MustRegisterFunction(highestCurrent) MustRegisterFunction(highestMax) @@ -1911,6 +1939,10 @@ func init() { MustRegisterFunction(logarithm).WithDefaultParams(map[uint8]interface{}{ 2: 10, // base }) + MustRegisterFunction(lowest).WithDefaultParams(map[uint8]interface{}{ + 2: 1, // n, + 3: "average", // f + }) MustRegisterFunction(lowestAverage) MustRegisterFunction(lowestCurrent) MustRegisterFunction(maxSeries) diff --git a/src/query/graphite/ts/series_reducer.go b/src/query/graphite/ts/series_reducer.go index 6afa96a146..5ca315c4df 100644 --- a/src/query/graphite/ts/series_reducer.go +++ b/src/query/graphite/ts/series_reducer.go @@ -28,11 +28,16 @@ type SeriesReducerApproach string // The standard set of reducers const ( SeriesReducerAvg SeriesReducerApproach = "avg" - SeriesReducerSum SeriesReducerApproach = "total" + SeriesReducerSum SeriesReducerApproach = "sum" SeriesReducerMin SeriesReducerApproach = "min" SeriesReducerMax SeriesReducerApproach = "max" SeriesReducerStdDev SeriesReducerApproach = "stddev" SeriesReducerLast SeriesReducerApproach = "last" + + SeriesReducerAverage SeriesReducerApproach = "average" // alias for "avg" + SeriesReducerTotal SeriesReducerApproach = "total" // alias for "sum" + SeriesReducerCurrent SeriesReducerApproach = "current" // alias for "last" + ) // SeriesReducer reduces a series to a single value. @@ -56,9 +61,13 @@ func (sa SeriesReducerApproach) Reducer() SeriesReducer { var seriesReducers = map[SeriesReducerApproach]SeriesReducer{ SeriesReducerAvg: func(b *Series) float64 { return b.SafeAvg() }, + SeriesReducerAverage: func(b *Series) float64 { return b.SafeAvg() }, + SeriesReducerTotal: func(b *Series) float64 { return b.SafeSum() }, SeriesReducerSum: func(b *Series) float64 { return b.SafeSum() }, SeriesReducerMin: func(b *Series) float64 { return b.SafeMin() }, SeriesReducerMax: func(b *Series) float64 { return b.SafeMax() }, SeriesReducerStdDev: func(b *Series) float64 { return b.SafeStdDev() }, SeriesReducerLast: func(b *Series) float64 { return b.SafeLastValue() }, + SeriesReducerCurrent: func(b *Series) float64 { return b.SafeLastValue() }, + } From b2dd764cc84ac775ec24295b8684b8266e11e7a5 Mon Sep 17 00:00:00 2001 From: teddywahle <69990143+teddywahle@users.noreply.github.com> Date: Thu, 10 Sep 2020 11:28:52 -0700 Subject: [PATCH 2/9] Update src/query/graphite/native/builtin_functions.go --- .../graphite/native/builtin_functions.go | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/src/query/graphite/native/builtin_functions.go b/src/query/graphite/native/builtin_functions.go index d13b79c2e4..3bfca16efa 100644 --- a/src/query/graphite/native/builtin_functions.go +++ b/src/query/graphite/native/builtin_functions.go @@ -653,31 +653,6 @@ func lowestCurrent(ctx *common.Context, input singlePathSpec, n int) (ts.SeriesL return lowest(ctx, input, n, "current") } -// aggregateLine draws a horizontal line based the function applied to the series. -func aggregateLine(ctx *common.Context, seriesList singlePathSpec, f string) (ts.SeriesList, error) { - if len(seriesList.Values) == 0 { - return ts.NewSeriesList(), common.ErrEmptySeriesList - } - - sa := ts.SeriesReducerApproach(f) - r, ok := sa.SafeReducer() - if !ok { - return ts.NewSeriesList(), errors.NewInvalidParamsError(fmt.Errorf("invalid function %s", f)) - } - - value := r(seriesList.Values[0]) - name := fmt.Sprintf("aggregateLine(%s,"+common.FloatingPointFormat+")", - seriesList.Values[0].Specification, value) - series, err := constantLine(ctx, value) - if err != nil { - return ts.NewSeriesList(), err - } - - renamed := series.Values[0].RenamedTo(name) - return ts.SeriesList{ - Values: []*ts.Series{renamed}, - Metadata: seriesList.Metadata, - }, nil } // windowSizeFunc calculates window size for moving average calculation From ef501b5837f89900402259cd4b1ad93b6688e4f8 Mon Sep 17 00:00:00 2001 From: teddywahle <69990143+teddywahle@users.noreply.github.com> Date: Thu, 10 Sep 2020 11:29:26 -0700 Subject: [PATCH 3/9] Update src/query/graphite/native/builtin_functions.go --- .../graphite/native/builtin_functions.go | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/query/graphite/native/builtin_functions.go b/src/query/graphite/native/builtin_functions.go index 3bfca16efa..9e6c72d3af 100644 --- a/src/query/graphite/native/builtin_functions.go +++ b/src/query/graphite/native/builtin_functions.go @@ -1658,6 +1658,31 @@ func randomWalkFunction(ctx *common.Context, name string, step int) (ts.SeriesLi return ts.NewSeriesListWithSeries(newSeries), nil } +// aggregateLine draws a horizontal line based the function applied to the series. +func aggregateLine(ctx *common.Context, seriesList singlePathSpec, f string) (ts.SeriesList, error) { + if len(seriesList.Values) == 0 { + return ts.NewSeriesList(), common.ErrEmptySeriesList + } + + sa := ts.SeriesReducerApproach(f) + r, ok := sa.SafeReducer() + if !ok { + return ts.NewSeriesList(), errors.NewInvalidParamsError(fmt.Errorf("invalid function %s", f)) + } + + value := r(seriesList.Values[0]) + name := fmt.Sprintf("aggregateLine(%s,"+common.FloatingPointFormat+")", + seriesList.Values[0].Specification, value) + series, err := constantLine(ctx, value) + if err != nil { + return ts.NewSeriesList(), err + } + + renamed := series.Values[0].RenamedTo(name) + return ts.SeriesList{ + Values: []*ts.Series{renamed}, + Metadata: seriesList.Metadata, + }, nil // changed takes one metric or a wildcard seriesList. // Output 1 when the value changed, 0 when null or the same. func changed(ctx *common.Context, seriesList singlePathSpec) (ts.SeriesList, error) { From 3becb98326570fd548765621d06df4594f7aa899 Mon Sep 17 00:00:00 2001 From: teddywahle <69990143+teddywahle@users.noreply.github.com> Date: Thu, 10 Sep 2020 11:29:57 -0700 Subject: [PATCH 4/9] Update src/query/graphite/native/builtin_functions.go --- src/query/graphite/native/builtin_functions.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/query/graphite/native/builtin_functions.go b/src/query/graphite/native/builtin_functions.go index 9e6c72d3af..69baeffd85 100644 --- a/src/query/graphite/native/builtin_functions.go +++ b/src/query/graphite/native/builtin_functions.go @@ -1683,6 +1683,8 @@ func aggregateLine(ctx *common.Context, seriesList singlePathSpec, f string) (ts Values: []*ts.Series{renamed}, Metadata: seriesList.Metadata, }, nil +} + // changed takes one metric or a wildcard seriesList. // Output 1 when the value changed, 0 when null or the same. func changed(ctx *common.Context, seriesList singlePathSpec) (ts.SeriesList, error) { From e7cc419c29e0587638bc3679787add45483b90b3 Mon Sep 17 00:00:00 2001 From: teddywahle <69990143+teddywahle@users.noreply.github.com> Date: Thu, 10 Sep 2020 11:30:32 -0700 Subject: [PATCH 5/9] Update src/query/graphite/native/builtin_functions.go --- src/query/graphite/native/builtin_functions.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/query/graphite/native/builtin_functions.go b/src/query/graphite/native/builtin_functions.go index 69baeffd85..70e9ea1579 100644 --- a/src/query/graphite/native/builtin_functions.go +++ b/src/query/graphite/native/builtin_functions.go @@ -653,8 +653,6 @@ func lowestCurrent(ctx *common.Context, input singlePathSpec, n int) (ts.SeriesL return lowest(ctx, input, n, "current") } -} - // windowSizeFunc calculates window size for moving average calculation type windowSizeFunc func(stepSize int) int From 8dded93a432dd89d97b33511d9e1a0cb7dff7a30 Mon Sep 17 00:00:00 2001 From: Theodore Wahle Date: Thu, 10 Sep 2020 13:47:50 -0700 Subject: [PATCH 6/9] finished testing for highest and lowest --- .../graphite/native/builtin_functions_test.go | 124 ++++++++++++++++++ 1 file changed, 124 insertions(+) diff --git a/src/query/graphite/native/builtin_functions_test.go b/src/query/graphite/native/builtin_functions_test.go index 8becf9fe8e..3e96d3cbdc 100644 --- a/src/query/graphite/native/builtin_functions_test.go +++ b/src/query/graphite/native/builtin_functions_test.go @@ -1003,10 +1003,22 @@ type nIntParamGoldenData struct { outputs []common.TestSeries } +// nIntParamGoldenDataWithAgg holds test data for functions that take an additional "n" int parameter +// It also holds an aggregation function +type nIntParamGoldenDataWithAgg struct { + nIntParamGoldenData + aggFunc string +} + + // rankingFunc selects the n lowest or highest series based on certain metric of the // series (e.g., maximum, minimum, average). type rankingFunc func(ctx *common.Context, input singlePathSpec, n int) (ts.SeriesList, error) + +// testRanking can be used to test the ranking alias functions +// (e.g. lowestAverage, highestMax, highestAverage, lowestCurrent) +// these functions are all aliases of the "meta-ranking" functions (i.e. highest and lowest) func testRanking(t *testing.T, ctx *common.Context, tests []nIntParamGoldenData, f rankingFunc) { start := time.Now() step := 100 @@ -1026,6 +1038,73 @@ func testRanking(t *testing.T, ctx *common.Context, tests []nIntParamGoldenData, } } +// testOrderedAggregationFunc is a helper function for testing lowest and highest +func testOrderedAggregationFunc(t *testing.T, ctx *common.Context, tests []nIntParamGoldenDataWithAgg, isLowest bool) { + f := highest + if isLowest { + f = lowest + } + + start := time.Now() + step := 100 + for _, test := range tests { + input := singlePathSpec{Values: generateSeriesList(ctx, start, test.inputs, step),} + outputs, err := f(ctx, input, test.n, test.aggFunc) + + if test.n < 0 { + require.NotNil(t, err) + require.Equal(t, "n must be positive", err.Error()) + assert.Nil(t, outputs.Values, "Nil timeseries should be returned") + continue + } + + require.NoError(t, err) + common.CompareOutputsAndExpected(t, step, start, + test.outputs, outputs.Values) + } +} + +func TestHighest(t *testing.T) { + ctx := common.NewTestContext() + defer ctx.Close() + + tests := []nIntParamGoldenDataWithAgg{ + { + nIntParamGoldenData { + testInput, + 0, + nil, + }, + "sum", + }, + { + nIntParamGoldenData { + testInput, + 1, + []common.TestSeries{testInput[0]}, + }, + "current", + }, + { + nIntParamGoldenData { + testInput, + 2, + []common.TestSeries{testInput[4], testInput[2]}, + }, + "average", + }, + { + nIntParamGoldenData { + testInput, + len(testInput) + 10, // force sort + []common.TestSeries{testInput[0], testInput[3], testInput[4], testInput[2], testInput[1]}, + }, + "last", + }, + } + testOrderedAggregationFunc(t, ctx, tests, false) +} + func TestHighestCurrent(t *testing.T) { ctx := common.NewTestContext() defer ctx.Close() @@ -1196,6 +1275,47 @@ func TestMostDeviant(t *testing.T) { testRanking(t, ctx, tests, mostDeviant) } +func TestLowest(t *testing.T) { + ctx := common.NewTestContext() + defer ctx.Close() + + tests := []nIntParamGoldenDataWithAgg{ + { + nIntParamGoldenData { + testInput, + 0, + nil, + }, + "max", + }, + { + nIntParamGoldenData { + testInput, + 2, + []common.TestSeries{testInput[1], testInput[3]}, + }, + "sum", + }, + { + nIntParamGoldenData { + testInput, + 2, + []common.TestSeries{testInput[1], testInput[2]}, + }, + "current", + }, + { + nIntParamGoldenData { + testInput, + 3, + []common.TestSeries{testInput[1], testInput[3], testInput[0]}, + }, + "average", + }, + } + testOrderedAggregationFunc(t, ctx, tests, true) +} + func TestLowestAverage(t *testing.T) { ctx := common.NewTestContext() defer ctx.Close() @@ -1225,6 +1345,8 @@ func TestLowestAverage(t *testing.T) { testRanking(t, ctx, tests, lowestAverage) } + + func TestLowestCurrent(t *testing.T) { ctx := common.NewTestContext() defer ctx.Close() @@ -3035,6 +3157,7 @@ func TestFunctionsRegistered(t *testing.T) { "group", "groupByNode", "groupByNodes", + "highest", "highestAverage", "highestCurrent", "highestMax", @@ -3050,6 +3173,7 @@ func TestFunctionsRegistered(t *testing.T) { "limit", "log", "logarithm", + "lowest", "lowestAverage", "lowestCurrent", "max", From 3fe9da1594e6d4082b2f50a7e35cb53e5a96803d Mon Sep 17 00:00:00 2001 From: Theodore Wahle Date: Mon, 21 Sep 2020 06:45:22 -0700 Subject: [PATCH 7/9] ran go fmt --- .../graphite/native/builtin_functions.go | 19 +++---- .../graphite/native/builtin_functions_test.go | 50 +++++++++---------- src/query/graphite/ts/series_reducer.go | 27 +++++----- 3 files changed, 44 insertions(+), 52 deletions(-) diff --git a/src/query/graphite/native/builtin_functions.go b/src/query/graphite/native/builtin_functions.go index 7746685893..f9825df109 100644 --- a/src/query/graphite/native/builtin_functions.go +++ b/src/query/graphite/native/builtin_functions.go @@ -271,7 +271,7 @@ func delay( func delayValuesHelper(ctx *common.Context, series *ts.Series, steps int) ts.Values { output := ts.NewValues(ctx, series.MillisPerStep(), series.Len()) for i := steps; i < series.Len(); i++ { - output.SetValueAt(i, series.ValueAt(i - steps)) + output.SetValueAt(i, series.ValueAt(i-steps)) } return output } @@ -281,7 +281,7 @@ func delayValuesHelper(ctx *common.Context, series *ts.Series, steps int) ts.Val // Useful for filtering out a part of a series of data from a wider range of data. func timeSlice(ctx *common.Context, inputPath singlePathSpec, start string, end string) (ts.SeriesList, error) { var ( - now = time.Now() + now = time.Now() tzOffsetForAbsoluteTime time.Duration ) startTime, err := graphite.ParseTime(start, now, tzOffsetForAbsoluteTime) @@ -657,8 +657,8 @@ func lowestCurrent(ctx *common.Context, input singlePathSpec, n int) (ts.SeriesL type windowSizeFunc func(stepSize int) int type windowSizeParsed struct { - deltaValue time.Duration - stringValue string + deltaValue time.Duration + stringValue string windowSizeFunc windowSizeFunc } @@ -865,7 +865,7 @@ func exponentialMovingAverage(ctx *common.Context, input singlePathSpec, windowS curr := bootstrap.ValueAt(i + offset) if !math.IsNaN(curr) { // formula: ema(current) = constant * (Current Value) + (1 - constant) * ema(previous) - ema = emaConstant * curr + (1 - emaConstant) * ema + ema = emaConstant*curr + (1-emaConstant)*ema vals.SetValueAt(i, ema) } else { vals.SetValueAt(i, math.NaN()) @@ -1822,8 +1822,6 @@ func movingMinHelper(window []float64, vals ts.MutableValues, windowPoints int, } } - - func newMovingBinaryTransform( ctx *common.Context, input singlePathSpec, @@ -1854,7 +1852,7 @@ func newMovingBinaryTransform( bootstrapStartTime, bootstrapEndTime := ctx.StartTime.Add(-interval), ctx.StartTime return &binaryContextShifter{ - ContextShiftFunc: contextShiftingFn, + ContextShiftFunc: contextShiftingFn, BinaryTransformer: func(bootstrapped, original ts.SeriesList) (ts.SeriesList, error) { bootstrapList, err := combineBootstrapWithOriginal(ctx, bootstrapStartTime, bootstrapEndTime, @@ -1934,7 +1932,6 @@ func movingMin(ctx *common.Context, input singlePathSpec, windowSize genericInte return newMovingBinaryTransform(ctx, input, windowSize, "movingMin", movingMinHelper) } - // legendValue takes one metric or a wildcard seriesList and a string in quotes. // Appends a value to the metric name in the legend. Currently one or several of: // "last", "avg", "total", "min", "max". @@ -2161,7 +2158,7 @@ func init() { MustRegisterFunction(groupByNode) MustRegisterFunction(groupByNodes) MustRegisterFunction(highest).WithDefaultParams(map[uint8]interface{}{ - 2: 1, // n, + 2: 1, // n, 3: "average", // f }) MustRegisterFunction(highestAverage) @@ -2183,7 +2180,7 @@ func init() { 2: 10, // base }) MustRegisterFunction(lowest).WithDefaultParams(map[uint8]interface{}{ - 2: 1, // n, + 2: 1, // n, 3: "average", // f }) MustRegisterFunction(lowestAverage) diff --git a/src/query/graphite/native/builtin_functions_test.go b/src/query/graphite/native/builtin_functions_test.go index 7ae100a6c2..f9736e73f5 100644 --- a/src/query/graphite/native/builtin_functions_test.go +++ b/src/query/graphite/native/builtin_functions_test.go @@ -643,8 +643,8 @@ func testMovingFunction(t *testing.T, target, expectedName string, values, boots } var ( - testGeneralFunctionStart = time.Now().Add(time.Minute * -11).Truncate(time.Minute) - testGeneralFunctionEnd = time.Now().Add(time.Minute * -3).Truncate(time.Minute) + testGeneralFunctionStart = time.Now().Add(time.Minute * -11).Truncate(time.Minute) + testGeneralFunctionEnd = time.Now().Add(time.Minute * -3).Truncate(time.Minute) ) // testGeneralFunction is a copy of testMovingFunction but without any logic for bootstrapping values @@ -654,8 +654,8 @@ func testGeneralFunction(t *testing.T, target, expectedName string, values, outp engine := NewEngine( &common.MovingFunctionStorage{ - StepMillis: 60000, - Values: values, + StepMillis: 60000, + Values: values, }, ) phonyContext := common.NewContext(common.ContextOptions{ @@ -694,11 +694,11 @@ func TestMovingAverageSuccess(t *testing.T) { func TestExponentialMovingAverageSuccess(t *testing.T) { tests := []struct { - target string + target string expectedName string - bootstrap []float64 - inputs []float64 - expected []float64 + bootstrap []float64 + inputs []float64 + expected []float64 }{ { "exponentialMovingAverage(foo.bar.baz, 3)", @@ -1097,12 +1097,10 @@ type nIntParamGoldenDataWithAgg struct { aggFunc string } - // rankingFunc selects the n lowest or highest series based on certain metric of the // series (e.g., maximum, minimum, average). type rankingFunc func(ctx *common.Context, input singlePathSpec, n int) (ts.SeriesList, error) - // testRanking can be used to test the ranking alias functions // (e.g. lowestAverage, highestMax, highestAverage, lowestCurrent) // these functions are all aliases of the "meta-ranking" functions (i.e. highest and lowest) @@ -1135,7 +1133,7 @@ func testOrderedAggregationFunc(t *testing.T, ctx *common.Context, tests []nIntP start := time.Now() step := 100 for _, test := range tests { - input := singlePathSpec{Values: generateSeriesList(ctx, start, test.inputs, step),} + input := singlePathSpec{Values: generateSeriesList(ctx, start, test.inputs, step)} outputs, err := f(ctx, input, test.n, test.aggFunc) if test.n < 0 { @@ -1157,7 +1155,7 @@ func TestHighest(t *testing.T) { tests := []nIntParamGoldenDataWithAgg{ { - nIntParamGoldenData { + nIntParamGoldenData{ testInput, 0, nil, @@ -1165,7 +1163,7 @@ func TestHighest(t *testing.T) { "sum", }, { - nIntParamGoldenData { + nIntParamGoldenData{ testInput, 1, []common.TestSeries{testInput[0]}, @@ -1173,7 +1171,7 @@ func TestHighest(t *testing.T) { "current", }, { - nIntParamGoldenData { + nIntParamGoldenData{ testInput, 2, []common.TestSeries{testInput[4], testInput[2]}, @@ -1181,7 +1179,7 @@ func TestHighest(t *testing.T) { "average", }, { - nIntParamGoldenData { + nIntParamGoldenData{ testInput, len(testInput) + 10, // force sort []common.TestSeries{testInput[0], testInput[3], testInput[4], testInput[2], testInput[1]}, @@ -1368,7 +1366,7 @@ func TestLowest(t *testing.T) { tests := []nIntParamGoldenDataWithAgg{ { - nIntParamGoldenData { + nIntParamGoldenData{ testInput, 0, nil, @@ -1376,7 +1374,7 @@ func TestLowest(t *testing.T) { "max", }, { - nIntParamGoldenData { + nIntParamGoldenData{ testInput, 2, []common.TestSeries{testInput[1], testInput[3]}, @@ -1384,7 +1382,7 @@ func TestLowest(t *testing.T) { "sum", }, { - nIntParamGoldenData { + nIntParamGoldenData{ testInput, 2, []common.TestSeries{testInput[1], testInput[2]}, @@ -1392,7 +1390,7 @@ func TestLowest(t *testing.T) { "current", }, { - nIntParamGoldenData { + nIntParamGoldenData{ testInput, 3, []common.TestSeries{testInput[1], testInput[3], testInput[0]}, @@ -1432,8 +1430,6 @@ func TestLowestAverage(t *testing.T) { testRanking(t, ctx, tests, lowestAverage) } - - func TestLowestCurrent(t *testing.T) { ctx := common.NewTestContext() defer ctx.Close() @@ -3105,8 +3101,8 @@ func TestDelay(t *testing.T) { } var ( - testDelayStart = time.Now().Truncate(time.Minute) - testDelayEnd = testMovingFunctionEnd.Add(time.Minute) + testDelayStart = time.Now().Truncate(time.Minute) + testDelayEnd = testMovingFunctionEnd.Add(time.Minute) ) func testDelay(t *testing.T, target, expectedName string, values, output []float64) { @@ -3115,8 +3111,8 @@ func testDelay(t *testing.T, target, expectedName string, values, output []float engine := NewEngine( &common.MovingFunctionStorage{ - StepMillis: 10000, - Values: values, + StepMillis: 10000, + Values: values, }, ) phonyContext := common.NewContext(common.ContextOptions{ @@ -3142,8 +3138,8 @@ func testDelay(t *testing.T, target, expectedName string, values, output []float } func TestTimeSlice(t *testing.T) { - values := []float64{math.NaN(),1.0,2.0,3.0,math.NaN(),5.0,6.0,math.NaN(),7.0,8.0,9.0} - expected := []float64{math.NaN(),math.NaN(),math.NaN(),3.0,math.NaN(),5.0,6.0,math.NaN(),7.0,math.NaN(),math.NaN()} + values := []float64{math.NaN(), 1.0, 2.0, 3.0, math.NaN(), 5.0, 6.0, math.NaN(), 7.0, 8.0, 9.0} + expected := []float64{math.NaN(), math.NaN(), math.NaN(), 3.0, math.NaN(), 5.0, 6.0, math.NaN(), 7.0, math.NaN(), math.NaN()} testGeneralFunction(t, "timeSlice(foo.bar.baz, '-9min','-3min')", "timeSlice(foo.bar.baz, -9min, -3min)", values, expected) } diff --git a/src/query/graphite/ts/series_reducer.go b/src/query/graphite/ts/series_reducer.go index 5ca315c4df..ca9608967e 100644 --- a/src/query/graphite/ts/series_reducer.go +++ b/src/query/graphite/ts/series_reducer.go @@ -28,15 +28,15 @@ type SeriesReducerApproach string // The standard set of reducers const ( SeriesReducerAvg SeriesReducerApproach = "avg" - SeriesReducerSum SeriesReducerApproach = "sum" + SeriesReducerSum SeriesReducerApproach = "sum" SeriesReducerMin SeriesReducerApproach = "min" SeriesReducerMax SeriesReducerApproach = "max" SeriesReducerStdDev SeriesReducerApproach = "stddev" SeriesReducerLast SeriesReducerApproach = "last" - SeriesReducerAverage SeriesReducerApproach = "average" // alias for "avg" - SeriesReducerTotal SeriesReducerApproach = "total" // alias for "sum" - SeriesReducerCurrent SeriesReducerApproach = "current" // alias for "last" + SeriesReducerAverage SeriesReducerApproach = "average" // alias for "avg" + SeriesReducerTotal SeriesReducerApproach = "total" // alias for "sum" + SeriesReducerCurrent SeriesReducerApproach = "current" // alias for "last" ) @@ -60,14 +60,13 @@ func (sa SeriesReducerApproach) Reducer() SeriesReducer { } var seriesReducers = map[SeriesReducerApproach]SeriesReducer{ - SeriesReducerAvg: func(b *Series) float64 { return b.SafeAvg() }, - SeriesReducerAverage: func(b *Series) float64 { return b.SafeAvg() }, - SeriesReducerTotal: func(b *Series) float64 { return b.SafeSum() }, - SeriesReducerSum: func(b *Series) float64 { return b.SafeSum() }, - SeriesReducerMin: func(b *Series) float64 { return b.SafeMin() }, - SeriesReducerMax: func(b *Series) float64 { return b.SafeMax() }, - SeriesReducerStdDev: func(b *Series) float64 { return b.SafeStdDev() }, - SeriesReducerLast: func(b *Series) float64 { return b.SafeLastValue() }, - SeriesReducerCurrent: func(b *Series) float64 { return b.SafeLastValue() }, - + SeriesReducerAvg: func(b *Series) float64 { return b.SafeAvg() }, + SeriesReducerAverage: func(b *Series) float64 { return b.SafeAvg() }, + SeriesReducerTotal: func(b *Series) float64 { return b.SafeSum() }, + SeriesReducerSum: func(b *Series) float64 { return b.SafeSum() }, + SeriesReducerMin: func(b *Series) float64 { return b.SafeMin() }, + SeriesReducerMax: func(b *Series) float64 { return b.SafeMax() }, + SeriesReducerStdDev: func(b *Series) float64 { return b.SafeStdDev() }, + SeriesReducerLast: func(b *Series) float64 { return b.SafeLastValue() }, + SeriesReducerCurrent: func(b *Series) float64 { return b.SafeLastValue() }, } From d8da4c581f4abb8bd06215d3baa88e4d9c281169 Mon Sep 17 00:00:00 2001 From: teddywahle <69990143+teddywahle@users.noreply.github.com> Date: Mon, 21 Sep 2020 06:46:12 -0700 Subject: [PATCH 8/9] Update src/query/graphite/native/builtin_functions.go --- src/query/graphite/native/builtin_functions.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/query/graphite/native/builtin_functions.go b/src/query/graphite/native/builtin_functions.go index f9825df109..88c959271d 100644 --- a/src/query/graphite/native/builtin_functions.go +++ b/src/query/graphite/native/builtin_functions.go @@ -281,7 +281,7 @@ func delayValuesHelper(ctx *common.Context, series *ts.Series, steps int) ts.Val // Useful for filtering out a part of a series of data from a wider range of data. func timeSlice(ctx *common.Context, inputPath singlePathSpec, start string, end string) (ts.SeriesList, error) { var ( - now = time.Now() + now = time.Now() tzOffsetForAbsoluteTime time.Duration ) startTime, err := graphite.ParseTime(start, now, tzOffsetForAbsoluteTime) From f02ab8e37940cbf3efc9c34668d0bdb7333a9fd6 Mon Sep 17 00:00:00 2001 From: teddywahle <69990143+teddywahle@users.noreply.github.com> Date: Mon, 21 Sep 2020 06:47:03 -0700 Subject: [PATCH 9/9] Update src/query/graphite/ts/series_reducer.go --- src/query/graphite/ts/series_reducer.go | 1 - 1 file changed, 1 deletion(-) diff --git a/src/query/graphite/ts/series_reducer.go b/src/query/graphite/ts/series_reducer.go index ca9608967e..51a400c10e 100644 --- a/src/query/graphite/ts/series_reducer.go +++ b/src/query/graphite/ts/series_reducer.go @@ -37,7 +37,6 @@ const ( SeriesReducerAverage SeriesReducerApproach = "average" // alias for "avg" SeriesReducerTotal SeriesReducerApproach = "total" // alias for "sum" SeriesReducerCurrent SeriesReducerApproach = "current" // alias for "last" - ) // SeriesReducer reduces a series to a single value.