diff --git a/CHANGELOG.md b/CHANGELOG.md index 64576dcf3..887134ad0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ - [#1530](https://github.com/influxdata/telegraf/issues/1530): Fix prometheus_client reload panic - [#1764](https://github.com/influxdata/telegraf/issues/1764): Fix kafka consumer panic when nil error is returned down errs channel. - [#1768](https://github.com/influxdata/telegraf/pull/1768): Speed up statsd parsing. +- [#1751](https://github.com/influxdata/telegraf/issues/1751): Fix powerdns integer parse error handling. ## v1.0.1 [unreleased] diff --git a/plugins/inputs/powerdns/powerdns.go b/plugins/inputs/powerdns/powerdns.go index 0824ff672..75d212a9a 100644 --- a/plugins/inputs/powerdns/powerdns.go +++ b/plugins/inputs/powerdns/powerdns.go @@ -4,6 +4,7 @@ import ( "bufio" "fmt" "io" + "log" "net" "strconv" "strings" @@ -86,10 +87,7 @@ func (p *Powerdns) gatherServer(address string, acc telegraf.Accumulator) error metrics := string(buf) // Process data - fields, err := parseResponse(metrics) - if err != nil { - return err - } + fields := parseResponse(metrics) // Add server socket as a tag tags := map[string]string{"server": address} @@ -99,22 +97,27 @@ func (p *Powerdns) gatherServer(address string, acc telegraf.Accumulator) error return nil } -func parseResponse(metrics string) (map[string]interface{}, error) { +func parseResponse(metrics string) map[string]interface{} { values := make(map[string]interface{}) s := strings.Split(metrics, ",") for _, metric := range s[:len(s)-1] { m := strings.Split(metric, "=") + if len(m) < 2 { + continue + } i, err := strconv.ParseInt(m[1], 10, 64) if err != nil { - return values, err + log.Printf("powerdns: Error parsing integer for metric [%s]: %s", + metric, err) + continue } values[m[0]] = i } - return values, nil + return values } func init() { diff --git a/plugins/inputs/powerdns/powerdns_test.go b/plugins/inputs/powerdns/powerdns_test.go index b0d883d0b..78845c23d 100644 --- a/plugins/inputs/powerdns/powerdns_test.go +++ b/plugins/inputs/powerdns/powerdns_test.go @@ -25,6 +25,30 @@ var metrics = "corrupt-packets=0,deferred-cache-inserts=0,deferred-cache-lookup= "key-cache-size=0,latency=26,meta-cache-size=0,qsize-q=0," + "signature-cache-size=0,sys-msec=2889,uptime=86317,user-msec=2167," +// first metric has no "=" +var corruptMetrics = "corrupt-packets--0,deferred-cache-inserts=0,deferred-cache-lookup=0," + + "dnsupdate-answers=0,dnsupdate-changes=0,dnsupdate-queries=0," + + "dnsupdate-refused=0,packetcache-hit=0,packetcache-miss=1,packetcache-size=0," + + "query-cache-hit=0,query-cache-miss=6,rd-queries=1,recursing-answers=0," + + "recursing-questions=0,recursion-unanswered=0,security-status=3," + + "servfail-packets=0,signatures=0,tcp-answers=0,tcp-queries=0," + + "timedout-packets=0,udp-answers=1,udp-answers-bytes=50,udp-do-queries=0," + + "udp-queries=0,udp4-answers=1,udp4-queries=1,udp6-answers=0,udp6-queries=0," + + "key-cache-size=0,latency=26,meta-cache-size=0,qsize-q=0," + + "signature-cache-size=0,sys-msec=2889,uptime=86317,user-msec=2167," + +// integer overflow +var intOverflowMetrics = "corrupt-packets=18446744073709550195,deferred-cache-inserts=0,deferred-cache-lookup=0," + + "dnsupdate-answers=0,dnsupdate-changes=0,dnsupdate-queries=0," + + "dnsupdate-refused=0,packetcache-hit=0,packetcache-miss=1,packetcache-size=0," + + "query-cache-hit=0,query-cache-miss=6,rd-queries=1,recursing-answers=0," + + "recursing-questions=0,recursion-unanswered=0,security-status=3," + + "servfail-packets=0,signatures=0,tcp-answers=0,tcp-queries=0," + + "timedout-packets=0,udp-answers=1,udp-answers-bytes=50,udp-do-queries=0," + + "udp-queries=0,udp4-answers=1,udp4-queries=1,udp6-answers=0,udp6-queries=0," + + "key-cache-size=0,latency=26,meta-cache-size=0,qsize-q=0," + + "signature-cache-size=0,sys-msec=2889,uptime=86317,user-msec=2167," + func (s statServer) serverSocket(l net.Listener) { for { @@ -86,8 +110,7 @@ func TestMemcachedGeneratesMetrics(t *testing.T) { } func TestPowerdnsParseMetrics(t *testing.T) { - values, err := parseResponse(metrics) - require.NoError(t, err, "Error parsing memcached response") + values := parseResponse(metrics) tests := []struct { key string @@ -145,3 +168,121 @@ func TestPowerdnsParseMetrics(t *testing.T) { } } } + +func TestPowerdnsParseCorruptMetrics(t *testing.T) { + values := parseResponse(corruptMetrics) + + tests := []struct { + key string + value int64 + }{ + {"deferred-cache-inserts", 0}, + {"deferred-cache-lookup", 0}, + {"dnsupdate-answers", 0}, + {"dnsupdate-changes", 0}, + {"dnsupdate-queries", 0}, + {"dnsupdate-refused", 0}, + {"packetcache-hit", 0}, + {"packetcache-miss", 1}, + {"packetcache-size", 0}, + {"query-cache-hit", 0}, + {"query-cache-miss", 6}, + {"rd-queries", 1}, + {"recursing-answers", 0}, + {"recursing-questions", 0}, + {"recursion-unanswered", 0}, + {"security-status", 3}, + {"servfail-packets", 0}, + {"signatures", 0}, + {"tcp-answers", 0}, + {"tcp-queries", 0}, + {"timedout-packets", 0}, + {"udp-answers", 1}, + {"udp-answers-bytes", 50}, + {"udp-do-queries", 0}, + {"udp-queries", 0}, + {"udp4-answers", 1}, + {"udp4-queries", 1}, + {"udp6-answers", 0}, + {"udp6-queries", 0}, + {"key-cache-size", 0}, + {"latency", 26}, + {"meta-cache-size", 0}, + {"qsize-q", 0}, + {"signature-cache-size", 0}, + {"sys-msec", 2889}, + {"uptime", 86317}, + {"user-msec", 2167}, + } + + for _, test := range tests { + value, ok := values[test.key] + if !ok { + t.Errorf("Did not find key for metric %s in values", test.key) + continue + } + if value != test.value { + t.Errorf("Metric: %s, Expected: %d, actual: %d", + test.key, test.value, value) + } + } +} + +func TestPowerdnsParseIntOverflowMetrics(t *testing.T) { + values := parseResponse(intOverflowMetrics) + + tests := []struct { + key string + value int64 + }{ + {"deferred-cache-inserts", 0}, + {"deferred-cache-lookup", 0}, + {"dnsupdate-answers", 0}, + {"dnsupdate-changes", 0}, + {"dnsupdate-queries", 0}, + {"dnsupdate-refused", 0}, + {"packetcache-hit", 0}, + {"packetcache-miss", 1}, + {"packetcache-size", 0}, + {"query-cache-hit", 0}, + {"query-cache-miss", 6}, + {"rd-queries", 1}, + {"recursing-answers", 0}, + {"recursing-questions", 0}, + {"recursion-unanswered", 0}, + {"security-status", 3}, + {"servfail-packets", 0}, + {"signatures", 0}, + {"tcp-answers", 0}, + {"tcp-queries", 0}, + {"timedout-packets", 0}, + {"udp-answers", 1}, + {"udp-answers-bytes", 50}, + {"udp-do-queries", 0}, + {"udp-queries", 0}, + {"udp4-answers", 1}, + {"udp4-queries", 1}, + {"udp6-answers", 0}, + {"udp6-queries", 0}, + {"key-cache-size", 0}, + {"latency", 26}, + {"meta-cache-size", 0}, + {"qsize-q", 0}, + {"signature-cache-size", 0}, + {"sys-msec", 2889}, + {"uptime", 86317}, + {"user-msec", 2167}, + } + + for _, test := range tests { + value, ok := values[test.key] + if !ok { + t.Errorf("Did not find key for metric %s in values", test.key) + continue + } + if value != test.value { + t.Errorf("Metric: %s, Expected: %d, actual: %d", + test.key, test.value, value) + } + } +}