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

Commit 155081d

Browse files
authored
Merge pull request #1792 from bloomberg/min_max
Implement minMax function natively
2 parents c2c86e4 + 024152f commit 155081d

File tree

4 files changed

+402
-1
lines changed

4 files changed

+402
-1
lines changed

docs/graphite.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ See also:
113113
| maxSeries(seriesList) series | max | Stable |
114114
| minimumAbove | | Stable |
115115
| minimumBelow | | Stable |
116-
| minMax | | No |
116+
| minMax | | Stable |
117117
| minSeries(seriesList) series | min | Stable |
118118
| mostDeviant | | No |
119119
| movingAverage(seriesLists, windowSize) seriesList | | Unstable |

expr/func_minmax.go

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package expr
2+
3+
import (
4+
"fmt"
5+
"math"
6+
7+
"github.com/grafana/metrictank/api/models"
8+
"github.com/grafana/metrictank/batch"
9+
"github.com/grafana/metrictank/schema"
10+
)
11+
12+
type FuncMinMax struct {
13+
in GraphiteFunc
14+
}
15+
16+
func NewMinMax() GraphiteFunc {
17+
return &FuncMinMax{}
18+
}
19+
20+
func (s *FuncMinMax) Signature() ([]Arg, []Arg) {
21+
return []Arg{
22+
ArgSeriesList{val: &s.in}}, []Arg{ArgSeriesList{}}
23+
}
24+
25+
func (s *FuncMinMax) Context(context Context) Context {
26+
return context
27+
}
28+
29+
func (s *FuncMinMax) Exec(dataMap DataMap) ([]models.Series, error) {
30+
series, err := s.in.Exec(dataMap)
31+
if err != nil {
32+
return nil, err
33+
}
34+
35+
outputs := make([]models.Series, len(series))
36+
37+
valOrDefault := func(val float64, def float64) float64 {
38+
if math.IsNaN(val) {
39+
return def
40+
}
41+
return val
42+
}
43+
44+
minMax := func(val float64, min float64, max float64) float64 {
45+
if math.IsNaN(val) {
46+
return val
47+
}
48+
if max-min == 0 {
49+
return 0
50+
}
51+
return (val - min) / (max - min)
52+
}
53+
54+
for i, serie := range series {
55+
out := pointSlicePool.Get().([]schema.Point)
56+
57+
minVal := valOrDefault(batch.Min(serie.Datapoints), 0)
58+
maxVal := valOrDefault(batch.Max(serie.Datapoints), 0)
59+
60+
for _, p := range serie.Datapoints {
61+
out = append(out, schema.Point{Val: minMax(p.Val, minVal, maxVal), Ts: p.Ts})
62+
}
63+
64+
s := models.Series{
65+
Target: fmt.Sprintf("minMax(%s)", serie.Target),
66+
QueryPatt: fmt.Sprintf("minMax(%s)", serie.QueryPatt),
67+
Tags: serie.CopyTagsWith("minMax", "1"),
68+
Datapoints: out,
69+
Interval: serie.Interval,
70+
Meta: serie.Meta,
71+
QueryMDP: serie.QueryMDP,
72+
QueryPNGroup: serie.QueryPNGroup,
73+
}
74+
outputs[i] = s
75+
}
76+
dataMap.Add(Req{}, outputs...)
77+
return outputs, nil
78+
}

0 commit comments

Comments
 (0)