From c0e0da7ef6364ee682174e8cd3b218d6ff75ab69 Mon Sep 17 00:00:00 2001 From: Daniel Nelson Date: Mon, 4 Mar 2019 12:35:57 -0800 Subject: [PATCH] Fix conversion from string float to integer (#5518) --- plugins/processors/converter/converter.go | 28 +++++++++++---- .../processors/converter/converter_test.go | 34 ++++++++++++------- 2 files changed, 43 insertions(+), 19 deletions(-) diff --git a/plugins/processors/converter/converter.go b/plugins/processors/converter/converter.go index 50fd195e01e77..3c9b74f3fe165 100644 --- a/plugins/processors/converter/converter.go +++ b/plugins/processors/converter/converter.go @@ -336,7 +336,7 @@ func toInteger(v interface{}) (int64, bool) { } else if value > float64(math.MaxInt64) { return math.MaxInt64, true } else { - return int64(value), true + return int64(Round(value)), true } case bool: if value { @@ -345,8 +345,11 @@ func toInteger(v interface{}) (int64, bool) { return 0, true } case string: - result, err := strconv.ParseInt(value, 10, 64) - return result, err == nil + result, err := strconv.ParseFloat(value, 64) + if err != nil { + return 0, false + } + return toInteger(result) } return 0, false } @@ -367,7 +370,7 @@ func toUnsigned(v interface{}) (uint64, bool) { } else if value > float64(math.MaxUint64) { return math.MaxUint64, true } else { - return uint64(value), true + return uint64(Round(value)), true } case bool: if value { @@ -376,8 +379,11 @@ func toUnsigned(v interface{}) (uint64, bool) { return 0, true } case string: - result, err := strconv.ParseUint(value, 10, 64) - return result, err == nil + result, err := strconv.ParseFloat(value, 64) + if err != nil { + return 0, false + } + return toUnsigned(result) } return 0, false } @@ -419,6 +425,16 @@ func toString(v interface{}) (string, bool) { return "", false } +// math.Round was not added until Go 1.10, can be removed when support for Go +// 1.9 is dropped. +func Round(x float64) float64 { + t := math.Trunc(x) + if math.Abs(x-t) >= 0.5 { + return t + math.Copysign(1, x) + } + return t +} + func logPrintf(format string, v ...interface{}) { log.Printf("D! [processors.converter] "+format, v...) } diff --git a/plugins/processors/converter/converter_test.go b/plugins/processors/converter/converter_test.go index 76839760d9ced..1b00cedf93935 100644 --- a/plugins/processors/converter/converter_test.go +++ b/plugins/processors/converter/converter_test.go @@ -129,8 +129,8 @@ func TestConverter(t *testing.T) { converter: &Converter{ Fields: &Conversion{ String: []string{"a"}, - Integer: []string{"b"}, - Unsigned: []string{"c"}, + Integer: []string{"b", "b1", "b2"}, + Unsigned: []string{"c", "c1", "c2"}, Boolean: []string{"d"}, Float: []string{"e"}, Tag: []string{"f"}, @@ -141,12 +141,16 @@ func TestConverter(t *testing.T) { "cpu", map[string]string{}, map[string]interface{}{ - "a": "howdy", - "b": "42", - "c": "42", - "d": "true", - "e": "42.0", - "f": "foo", + "a": "howdy", + "b": "42", + "b1": "42.2", + "b2": "42.5", + "c": "42", + "c1": "42.2", + "c2": "42.5", + "d": "true", + "e": "42.0", + "f": "foo", }, time.Unix(0, 0), ), @@ -158,11 +162,15 @@ func TestConverter(t *testing.T) { "f": "foo", }, map[string]interface{}{ - "a": "howdy", - "b": int64(42), - "c": uint64(42), - "d": true, - "e": 42.0, + "a": "howdy", + "b": int64(42), + "b1": int64(42), + "b2": int64(43), + "c": uint64(42), + "c1": uint64(42), + "c2": uint64(43), + "d": true, + "e": 42.0, }, time.Unix(0, 0), ),