From 562804944074b39b2d02abf06ddb8428e5e0e78d Mon Sep 17 00:00:00 2001
From: Denis Orlikhin <qbikk@yandex.ru>
Date: Mon, 5 Sep 2016 16:29:14 +0300
Subject: [PATCH] Handle negative integers coming as unsigned integers from
 Aerospike (#1679)

* Handle negative integers coming as unsigned integers from Aerospike stats

* skip values with overflow

* aerospike stat values parsing tests

* better tests
---
 plugins/inputs/aerospike/aerospike.go      | 27 +++++++++++++++++-----
 plugins/inputs/aerospike/aerospike_test.go | 17 ++++++++++++++
 2 files changed, 38 insertions(+), 6 deletions(-)

diff --git a/plugins/inputs/aerospike/aerospike.go b/plugins/inputs/aerospike/aerospike.go
index 47777277..f7c90019 100644
--- a/plugins/inputs/aerospike/aerospike.go
+++ b/plugins/inputs/aerospike/aerospike.go
@@ -1,6 +1,8 @@
 package aerospike
 
 import (
+	"errors"
+	"log"
 	"net"
 	"strconv"
 	"strings"
@@ -82,7 +84,12 @@ func (a *Aerospike) gatherServer(hostport string, acc telegraf.Accumulator) erro
 			return err
 		}
 		for k, v := range stats {
-			fields[strings.Replace(k, "-", "_", -1)] = parseValue(v)
+			val, err := parseValue(v)
+			if err == nil {
+				fields[strings.Replace(k, "-", "_", -1)] = val
+			} else {
+				log.Printf("skipping aerospike field %v with int64 overflow", k)
+			}
 		}
 		acc.AddFields("aerospike_node", fields, tags, time.Now())
 
@@ -110,7 +117,12 @@ func (a *Aerospike) gatherServer(hostport string, acc telegraf.Accumulator) erro
 				if len(parts) < 2 {
 					continue
 				}
-				nFields[strings.Replace(parts[0], "-", "_", -1)] = parseValue(parts[1])
+				val, err := parseValue(parts[1])
+				if err == nil {
+					nFields[strings.Replace(parts[0], "-", "_", -1)] = val
+				} else {
+					log.Printf("skipping aerospike field %v with int64 overflow", parts[0])
+				}
 			}
 			acc.AddFields("aerospike_namespace", nFields, nTags, time.Now())
 		}
@@ -118,13 +130,16 @@ func (a *Aerospike) gatherServer(hostport string, acc telegraf.Accumulator) erro
 	return nil
 }
 
-func parseValue(v string) interface{} {
+func parseValue(v string) (interface{}, error) {
 	if parsed, err := strconv.ParseInt(v, 10, 64); err == nil {
-		return parsed
+		return parsed, nil
+	} else if _, err := strconv.ParseUint(v, 10, 64); err == nil {
+		// int64 overflow, yet valid uint64
+		return nil, errors.New("Number is too large")
 	} else if parsed, err := strconv.ParseBool(v); err == nil {
-		return parsed
+		return parsed, nil
 	} else {
-		return v
+		return v, nil
 	}
 }
 
diff --git a/plugins/inputs/aerospike/aerospike_test.go b/plugins/inputs/aerospike/aerospike_test.go
index 5f80b519..b20af165 100644
--- a/plugins/inputs/aerospike/aerospike_test.go
+++ b/plugins/inputs/aerospike/aerospike_test.go
@@ -48,3 +48,20 @@ func TestAerospikeStatisticsPartialErr(t *testing.T) {
 	assert.True(t, acc.HasMeasurement("aerospike_namespace"))
 	assert.True(t, acc.HasIntField("aerospike_node", "batch_error"))
 }
+
+func TestAerospikeParseValue(t *testing.T) {
+	// uint64 with value bigger than int64 max
+	val, err := parseValue("18446744041841121751")
+	assert.Nil(t, val)
+	assert.Error(t, err)
+
+	// int values
+	val, err = parseValue("42")
+	assert.NoError(t, err)
+	assert.Equal(t, val, int64(42), "must be parsed as int")
+
+	// string values
+	val, err = parseValue("BB977942A2CA502")
+	assert.NoError(t, err)
+	assert.Equal(t, val, `BB977942A2CA502`, "must be left as string")
+}
-- 
GitLab