From 8d87f3933c388c35f6e9dd67630580011c2b2dde Mon Sep 17 00:00:00 2001 From: Daniel Nelson Date: Wed, 18 Apr 2018 12:13:25 -0700 Subject: [PATCH] Fix graphite serialization of unsigned ints (#4033) --- plugins/serializers/graphite/graphite.go | 44 ++++++++++++++----- plugins/serializers/graphite/graphite_test.go | 16 +++++++ 2 files changed, 50 insertions(+), 10 deletions(-) diff --git a/plugins/serializers/graphite/graphite.go b/plugins/serializers/graphite/graphite.go index ee390d17f0ab5..0f7fcd8f50b38 100644 --- a/plugins/serializers/graphite/graphite.go +++ b/plugins/serializers/graphite/graphite.go @@ -2,8 +2,10 @@ package graphite import ( "fmt" + "math" "regexp" "sort" + "strconv" "strings" "github.com/influxdata/telegraf" @@ -43,20 +45,14 @@ func (s *GraphiteSerializer) Serialize(metric telegraf.Metric) ([]byte, error) { } for fieldName, value := range metric.Fields() { - switch v := value.(type) { - case string: + fieldValue := formatValue(value) + if fieldValue == "" { continue - case bool: - if v { - value = 1 - } else { - value = 0 - } } - metricString := fmt.Sprintf("%s %#v %d\n", + metricString := fmt.Sprintf("%s %s %d\n", // insert "field" section of template sanitize(InsertField(bucket, fieldName)), - value, + fieldValue, timestamp) point := []byte(metricString) out = append(out, point...) @@ -64,6 +60,34 @@ func (s *GraphiteSerializer) Serialize(metric telegraf.Metric) ([]byte, error) { return out, nil } +func formatValue(value interface{}) string { + switch v := value.(type) { + case string: + return "" + case bool: + if v { + return "1" + } else { + return "0" + } + case uint64: + return strconv.FormatUint(v, 10) + case int64: + return strconv.FormatInt(v, 10) + case float64: + if math.IsNaN(v) { + return "" + } + + if math.IsInf(v, 0) { + return "" + } + return strconv.FormatFloat(v, 'f', -1, 64) + } + + return "" +} + // SerializeBucketName will take the given measurement name and tags and // produce a graphite bucket. It will use the GraphiteSerializer.Template // to generate this, or DEFAULT_TEMPLATE. diff --git a/plugins/serializers/graphite/graphite_test.go b/plugins/serializers/graphite/graphite_test.go index 94792112fe19d..e08f47593c496 100644 --- a/plugins/serializers/graphite/graphite_test.go +++ b/plugins/serializers/graphite/graphite_test.go @@ -218,6 +218,22 @@ func TestSerializeValueBoolean(t *testing.T) { assert.Equal(t, expS, mS) } +func TestSerializeValueUnsigned(t *testing.T) { + now := time.Unix(0, 0) + tags := map[string]string{} + fields := map[string]interface{}{ + "free": uint64(42), + } + m, err := metric.New("mem", tags, fields, now) + require.NoError(t, err) + + s := GraphiteSerializer{} + buf, err := s.Serialize(m) + require.NoError(t, err) + + require.Equal(t, buf, []byte(".mem.free 42 0\n")) +} + // test that fields with spaces get fixed. func TestSerializeFieldWithSpaces(t *testing.T) { now := time.Now()