Ignore fields with NaN or Inf floats in the JSON serializer (#7426)

This commit is contained in:
Daniel Nelson 2020-04-28 13:41:25 -07:00 committed by GitHub
parent 7ee776d67a
commit c4e9f72936
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 64 additions and 5 deletions

View File

@ -2,6 +2,7 @@ package json
import ( import (
"encoding/json" "encoding/json"
"math"
"time" "time"
"github.com/influxdata/telegraf" "github.com/influxdata/telegraf"
@ -49,8 +50,26 @@ func (s *serializer) SerializeBatch(metrics []telegraf.Metric) ([]byte, error) {
func (s *serializer) createObject(metric telegraf.Metric) map[string]interface{} { func (s *serializer) createObject(metric telegraf.Metric) map[string]interface{} {
m := make(map[string]interface{}, 4) m := make(map[string]interface{}, 4)
m["tags"] = metric.Tags()
m["fields"] = metric.Fields() tags := make(map[string]string, len(metric.TagList()))
for _, tag := range metric.TagList() {
tags[tag.Key] = tag.Value
}
m["tags"] = tags
fields := make(map[string]interface{}, len(metric.FieldList()))
for _, field := range metric.FieldList() {
switch fv := field.Value.(type) {
case float64:
// JSON does not support these special values
if math.IsNaN(fv) || math.IsInf(fv, 0) {
continue
}
}
fields[field.Key] = field.Value
}
m["fields"] = fields
m["name"] = metric.Name() m["name"] = metric.Name()
m["timestamp"] = metric.Time().UnixNano() / int64(s.TimestampUnits) m["timestamp"] = metric.Time().UnixNano() / int64(s.TimestampUnits)
return m return m

View File

@ -2,14 +2,15 @@ package json
import ( import (
"fmt" "fmt"
"math"
"testing" "testing"
"time" "time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/influxdata/telegraf" "github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/metric" "github.com/influxdata/telegraf/metric"
"github.com/influxdata/telegraf/testutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
func MustMetric(v telegraf.Metric, err error) telegraf.Metric { func MustMetric(v telegraf.Metric, err error) telegraf.Metric {
@ -193,3 +194,42 @@ func TestSerializeBatch(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, []byte(`{"metrics":[{"fields":{"value":42},"name":"cpu","tags":{},"timestamp":0},{"fields":{"value":42},"name":"cpu","tags":{},"timestamp":0}]}`), buf) require.Equal(t, []byte(`{"metrics":[{"fields":{"value":42},"name":"cpu","tags":{},"timestamp":0},{"fields":{"value":42},"name":"cpu","tags":{},"timestamp":0}]}`), buf)
} }
func TestSerializeBatchSkipInf(t *testing.T) {
metrics := []telegraf.Metric{
testutil.MustMetric(
"cpu",
map[string]string{},
map[string]interface{}{
"inf": math.Inf(1),
"time_idle": 42,
},
time.Unix(0, 0),
),
}
s, err := NewSerializer(0)
require.NoError(t, err)
buf, err := s.SerializeBatch(metrics)
require.NoError(t, err)
require.Equal(t, []byte(`{"metrics":[{"fields":{"time_idle":42},"name":"cpu","tags":{},"timestamp":0}]}`), buf)
}
func TestSerializeBatchSkipInfAllFields(t *testing.T) {
metrics := []telegraf.Metric{
testutil.MustMetric(
"cpu",
map[string]string{},
map[string]interface{}{
"inf": math.Inf(1),
},
time.Unix(0, 0),
),
}
s, err := NewSerializer(0)
require.NoError(t, err)
buf, err := s.SerializeBatch(metrics)
require.NoError(t, err)
require.Equal(t, []byte(`{"metrics":[{"fields":{},"name":"cpu","tags":{},"timestamp":0}]}`), buf)
}