Skip to content
This repository has been archived by the owner on Jul 12, 2024. It is now read-only.

Commit

Permalink
Update Summary metrics to support null min/max values
Browse files Browse the repository at this point in the history
As described in the spec:
https://github.com/newrelic/newrelic-telemetry-sdk-specs/blob/master/capabilities.md#summary

Summary metrics could contain null values in min or max fields. This
change adds support to instantiate Summary metrics using NaN values for
min/max fields.
  • Loading branch information
Toni Reina committed Jun 4, 2020
1 parent 9d3efb4 commit db4be85
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 12 deletions.
29 changes: 25 additions & 4 deletions telemetry/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package telemetry
import (
"bytes"
"encoding/json"
"math"
"time"

"github.com/newrelic/newrelic-telemetry-sdk-go/internal"
Expand Down Expand Up @@ -120,8 +121,6 @@ func (m Summary) validate() map[string]interface{} {
for _, v := range []float64{
m.Count,
m.Sum,
m.Min,
m.Max,
} {
if err := isFloatValid(v); err != nil {
return map[string]interface{}{
Expand All @@ -131,6 +130,20 @@ func (m Summary) validate() map[string]interface{} {
}
}
}

for _, v := range []float64{
m.Min,
m.Max,
} {
if math.IsInf(v, 0) {
return map[string]interface{}{
"message": "invalid summary field",
"name": m.Name,
"err": errFloatInfinity.Error(),
}
}
}

return nil
}

Expand All @@ -146,8 +159,16 @@ func (m Summary) writeJSON(buf *bytes.Buffer) {
vw := internal.JSONFieldsWriter{Buf: buf}
vw.FloatField("sum", m.Sum)
vw.FloatField("count", m.Count)
vw.FloatField("min", m.Min)
vw.FloatField("max", m.Max)
if math.IsNaN(m.Min) {
w.RawField("min", json.RawMessage(`null`))
} else {
vw.FloatField("min", m.Min)
}
if math.IsNaN(m.Max) {
vw.RawField("max", json.RawMessage(`null`))
} else {
vw.FloatField("max", m.Max)
}
buf.WriteByte('}')

writeTimestampInterval(&w, m.Timestamp, m.Interval)
Expand Down
35 changes: 27 additions & 8 deletions telemetry/metrics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ func TestMetricPayload(t *testing.T) {
Timestamp: now,
Value: 1.0,
})
h.RecordMetric(Summary{
Name: "another-metric",
Attributes: map[string]interface{}{"zip": "zap"},
Timestamp: now,
Count: 4.0,
Sum: 1.0,
Min: math.NaN(),
Max: 3.0,
})
h.lastHarvest = now
end := h.lastHarvest.Add(5 * time.Second)
reqs := h.swapOutMetrics(end)
Expand All @@ -37,7 +46,8 @@ func TestMetricPayload(t *testing.T) {
"attributes":{"zop":"zup"}
},
"metrics":[
{"name":"metric","type":"gauge","value":1,"timestamp":1417136460000,"attributes":{"zip":"zap"}}
{"name":"metric","type":"gauge","value":1,"timestamp":1417136460000,"attributes":{"zip":"zap"}},
{"name":"another-metric","type":"summary","value":{"sum":1,"count":4,"min":null,"max":3},"timestamp":1417136460000,"attributes":{"zip":"zap"}}
]
}]`
compactExpect := compactJSONString(expect)
Expand Down Expand Up @@ -151,11 +161,16 @@ func TestValidateGauge(t *testing.T) {
}

func TestValidateSummary(t *testing.T) {
want := map[string]interface{}{
expectNaNErr := map[string]interface{}{
"message": "invalid summary field",
"name": "my-summary",
"err": errFloatNaN.Error(),
}
expectInfErr := map[string]interface{}{
"message": "invalid summary field",
"name": "my-summary",
"err": errFloatInfinity.Error(),
}
testcases := []struct {
m Summary
fields map[string]interface{}
Expand All @@ -164,21 +179,25 @@ func TestValidateSummary(t *testing.T) {
m: Summary{Name: "my-summary", Count: 1.0, Sum: 2.0, Min: 3.0, Max: 4.0},
fields: nil,
},
{
m: Summary{Name: "my-summary", Count: 1.0, Sum: 2.0, Min: math.NaN(), Max: math.NaN()},
fields: nil,
},
{
m: Summary{Name: "my-summary", Count: math.NaN(), Sum: 2.0, Min: 3.0, Max: 4.0},
fields: want,
fields: expectNaNErr,
},
{
m: Summary{Name: "my-summary", Count: 1.0, Sum: math.NaN(), Min: 3.0, Max: 4.0},
fields: want,
fields: expectNaNErr,
},
{
m: Summary{Name: "my-summary", Count: 1.0, Sum: 2.0, Min: math.NaN(), Max: 4.0},
fields: want,
m: Summary{Name: "my-summary", Count: 1.0, Sum: 2.0, Min: math.Inf(-3), Max: 4.0},
fields: expectInfErr,
},
{
m: Summary{Name: "my-summary", Count: 1.0, Sum: 2.0, Min: 3.0, Max: math.NaN()},
fields: want,
m: Summary{Name: "my-summary", Count: 1.0, Sum: 2.0, Min: 3.0, Max: math.Inf(3)},
fields: expectInfErr,
},
}
for idx, tc := range testcases {
Expand Down

0 comments on commit db4be85

Please sign in to comment.