Skip to content
This repository was archived by the owner on Aug 23, 2023. It is now read-only.

Commit a958b51

Browse files
committed
Merge branch 'highestlowest'
2 parents 4fa6704 + 841952e commit a958b51

File tree

5 files changed

+668
-10
lines changed

5 files changed

+668
-10
lines changed

consolidation/consolidation.go

+9-9
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,8 @@ func FromConsolidateBy(c string) Consolidator {
107107
return Avg
108108
case "cnt":
109109
return Cnt // bonus. not supported by graphite
110-
case "lst", "last":
111-
return Lst // bonus. not supported by graphite
110+
case "lst", "last", "current":
111+
return Lst
112112
case "min":
113113
return Min
114114
case "max":
@@ -121,9 +121,9 @@ func FromConsolidateBy(c string) Consolidator {
121121
return Diff
122122
case "stddev":
123123
return StdDev
124-
case "range":
124+
case "range", "rangeOf":
125125
return Range
126-
case "sum":
126+
case "sum", "total":
127127
return Sum
128128
}
129129
return None
@@ -160,17 +160,17 @@ func GetAggFunc(consolidator Consolidator) batch.AggFunc {
160160
}
161161

162162
func Validate(fn string) error {
163-
if fn == "avg" ||
164-
fn == "average" ||
165-
fn == "count" || fn == "last" || // bonus
163+
if fn == "avg" || fn == "average" ||
164+
fn == "count" ||
165+
fn == "last" || fn == "current" ||
166166
fn == "min" ||
167167
fn == "max" ||
168168
fn == "mult" || fn == "multiply" ||
169169
fn == "med" || fn == "median" ||
170170
fn == "diff" ||
171171
fn == "stddev" ||
172-
fn == "range" ||
173-
fn == "sum" {
172+
fn == "range" || fn == "rangeOf" ||
173+
fn == "sum" || fn == "total" {
174174
return nil
175175
}
176176
return errUnknownConsolidationFunction

docs/graphite.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,14 @@ Here are the currently included functions:
4343
| filterSeries(seriesList, func, operator, threshold) seriesList | | Stable |
4444
| grep(seriesList, pattern) seriesList | | Stable |
4545
| groupByTags(seriesList, func, tagList) seriesList | | Stable |
46+
| highest(seriesList, n, func) seriesList | | Stable |
47+
| highestAverage(seriesList, n, func) seriesList | | Stable |
48+
| highestCurrent(seriesList, n, func) seriesList | | Stable |
49+
| highestMax(seriesList, n, func) seriesList | | Stable |
4650
| isNonNull(seriesList) seriesList | | Stable |
51+
| lowest(seriesList, n, func) seriesList | | Stable |
52+
| lowestAverage(seriesList, n, func) seriesList | | Stable |
53+
| lowestCurrent(seriesList, n, func) seriesList | | Stable |
4754
| maxSeries(seriesList) series | max | Stable |
4855
| minSeries(seriesList) series | min | Stable |
4956
| multiplySeries(seriesList) series | | Stable |
@@ -58,4 +65,3 @@ Here are the currently included functions:
5865
| sumSeries(seriesLists) series | sum | Stable |
5966
| summarize(seriesList) seriesList | | Stable |
6067
| transformNull(seriesList, default=0) seriesList | | Stable |
61-

expr/func_highestlowest.go

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package expr
2+
3+
import (
4+
"math"
5+
"sort"
6+
7+
"github.com/grafana/metrictank/consolidation"
8+
9+
"github.com/grafana/metrictank/api/models"
10+
)
11+
12+
type FuncHighestLowest struct {
13+
in GraphiteFunc
14+
n int64
15+
fn string
16+
highest bool
17+
}
18+
19+
func NewHighestLowestConstructor(fn string, highest bool) func() GraphiteFunc {
20+
return func() GraphiteFunc {
21+
return &FuncHighestLowest{fn: fn, highest: highest}
22+
}
23+
}
24+
25+
func (s *FuncHighestLowest) Signature() ([]Arg, []Arg) {
26+
if s.fn != "" {
27+
return []Arg{
28+
ArgSeriesList{val: &s.in},
29+
ArgInt{key: "n", val: &s.n},
30+
}, []Arg{ArgSeriesList{}}
31+
}
32+
return []Arg{
33+
ArgSeriesList{val: &s.in},
34+
ArgInt{key: "n", val: &s.n},
35+
ArgString{key: "func", val: &s.fn, validator: []Validator{IsConsolFunc}},
36+
}, []Arg{ArgSeriesList{}}
37+
}
38+
39+
func (s *FuncHighestLowest) Context(context Context) Context {
40+
return context
41+
}
42+
43+
type ScoredSeries struct {
44+
score float64
45+
serie models.Series
46+
}
47+
48+
func (s *FuncHighestLowest) Exec(cache map[Req][]models.Series) ([]models.Series, error) {
49+
series, err := s.in.Exec(cache)
50+
if err != nil {
51+
return nil, err
52+
}
53+
54+
if len(series) == 0 {
55+
return series, nil
56+
}
57+
58+
consolidationFunc := consolidation.GetAggFunc(consolidation.FromConsolidateBy(s.fn))
59+
60+
// score series by their consolidated value
61+
scored := make([]ScoredSeries, len(series))
62+
for i, serie := range series {
63+
scored[i] = ScoredSeries{
64+
score: consolidationFunc(serie.Datapoints),
65+
serie: serie,
66+
}
67+
}
68+
69+
sort.SliceStable(scored, func(i, j int) bool {
70+
iVal := scored[i].score
71+
jVal := scored[j].score
72+
if s.highest {
73+
return math.IsNaN(jVal) && !math.IsNaN(iVal) || iVal > jVal
74+
}
75+
return math.IsNaN(jVal) && !math.IsNaN(iVal) || iVal < jVal
76+
})
77+
78+
if s.n > int64(len(series)) {
79+
s.n = int64(len(series))
80+
}
81+
82+
for i := 0; i < int(s.n); i++ {
83+
series[i] = scored[i].serie
84+
}
85+
86+
return series[:s.n], nil
87+
}

0 commit comments

Comments
 (0)