Skip to content

Commit 2e18672

Browse files
committed
[aggregator] Use NaN instead of math.MaxFloat64 and add sentinel guards
1 parent 166bdb3 commit 2e18672

File tree

2 files changed

+55
-10
lines changed

2 files changed

+55
-10
lines changed

src/aggregator/aggregation/gauge.go

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,6 @@ import (
2727
"github.com/m3db/m3/src/metrics/aggregation"
2828
)
2929

30-
const (
31-
minFloat64 = -math.MaxFloat64
32-
)
33-
3430
// Gauge aggregates gauge values.
3531
type Gauge struct {
3632
Options
@@ -48,13 +44,18 @@ type Gauge struct {
4844
func NewGauge(opts Options) Gauge {
4945
return Gauge{
5046
Options: opts,
51-
max: minFloat64,
52-
min: math.MaxFloat64,
47+
max: math.NaN(),
48+
min: math.NaN(),
5349
}
5450
}
5551

5652
// Update updates the gauge value.
5753
func (g *Gauge) Update(timestamp time.Time, value float64) {
54+
// If this is not a valid value, drop it.
55+
if math.IsNaN(value) {
56+
return
57+
}
58+
5859
if g.lastAt.IsZero() || timestamp.After(g.lastAt) {
5960
// NB(r): Only set the last value if this value arrives
6061
// after the wall clock timestamp of previous values, not
@@ -67,10 +68,10 @@ func (g *Gauge) Update(timestamp time.Time, value float64) {
6768

6869
g.sum += value
6970
g.count++
70-
if g.max < value {
71+
if math.IsNaN(g.max) || g.max < value {
7172
g.max = value
7273
}
73-
if g.min > value {
74+
if math.IsNaN(g.min) || g.min > value {
7475
g.min = value
7576
}
7677

@@ -108,10 +109,20 @@ func (g *Gauge) Stdev() float64 {
108109
}
109110

110111
// Min returns the minimum gauge value.
111-
func (g *Gauge) Min() float64 { return g.min }
112+
func (g *Gauge) Min() float64 {
113+
if math.IsNaN(g.min) {
114+
return 0.0
115+
}
116+
return g.min
117+
}
112118

113119
// Max returns the maximum gauge value.
114-
func (g *Gauge) Max() float64 { return g.max }
120+
func (g *Gauge) Max() float64 {
121+
if math.IsNaN(g.max) {
122+
return 0.0
123+
}
124+
return g.max
125+
}
115126

116127
// ValueOf returns the value for the aggregation type.
117128
func (g *Gauge) ValueOf(aggType aggregation.Type) float64 {

src/aggregator/aggregation/gauge_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ func TestGaugeDefaultAggregationType(t *testing.T) {
4242
require.Equal(t, 100.0, g.ValueOf(aggregation.Count))
4343
require.Equal(t, 50.5, g.ValueOf(aggregation.Mean))
4444
require.Equal(t, 0.0, g.ValueOf(aggregation.SumSq))
45+
46+
g = NewGauge(NewOptions(instrument.NewOptions()))
47+
require.Equal(t, 0.0, g.Last())
48+
require.Equal(t, 0.0, g.ValueOf(aggregation.Last))
49+
require.Equal(t, 0.0, g.ValueOf(aggregation.Count))
50+
require.Equal(t, 0.0, g.ValueOf(aggregation.Mean))
51+
require.Equal(t, 0.0, g.ValueOf(aggregation.SumSq))
4552
}
4653

4754
func TestGaugeCustomAggregationType(t *testing.T) {
@@ -80,6 +87,33 @@ func TestGaugeCustomAggregationType(t *testing.T) {
8087
require.False(t, aggType.IsValidForGauge())
8188
}
8289
}
90+
91+
g = NewGauge(opts)
92+
require.Equal(t, 0.0, g.Last())
93+
for aggType := range aggregation.ValidTypes {
94+
v := g.ValueOf(aggType)
95+
switch aggType {
96+
case aggregation.Last:
97+
require.Equal(t, 0.0, v)
98+
case aggregation.Min:
99+
require.Equal(t, 0.0, v)
100+
case aggregation.Max:
101+
require.Equal(t, 0.0, v)
102+
case aggregation.Mean:
103+
require.Equal(t, 0.0, v)
104+
case aggregation.Count:
105+
require.Equal(t, 0.0, v)
106+
case aggregation.Sum:
107+
require.Equal(t, 0.0, v)
108+
case aggregation.SumSq:
109+
require.Equal(t, 0.0, v)
110+
case aggregation.Stdev:
111+
require.InDelta(t, 0.0, v, 0.0)
112+
default:
113+
require.Equal(t, 0.0, v)
114+
require.False(t, aggType.IsValidForGauge())
115+
}
116+
}
83117
}
84118

85119
func TestGaugeLastOutOfOrderValues(t *testing.T) {

0 commit comments

Comments
 (0)