Fix powerdns integer parse error handling

closes #1751
This commit is contained in:
Cameron Sparr 2016-09-23 15:45:18 +01:00
parent 2cf1db0837
commit ddc07f9ef8
3 changed files with 154 additions and 9 deletions

View File

@ -31,6 +31,7 @@
- [#1530](https://github.com/influxdata/telegraf/issues/1530): Fix prometheus_client reload panic - [#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. - [#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. - [#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] ## v1.0.1 [unreleased]

View File

@ -4,6 +4,7 @@ import (
"bufio" "bufio"
"fmt" "fmt"
"io" "io"
"log"
"net" "net"
"strconv" "strconv"
"strings" "strings"
@ -86,10 +87,7 @@ func (p *Powerdns) gatherServer(address string, acc telegraf.Accumulator) error
metrics := string(buf) metrics := string(buf)
// Process data // Process data
fields, err := parseResponse(metrics) fields := parseResponse(metrics)
if err != nil {
return err
}
// Add server socket as a tag // Add server socket as a tag
tags := map[string]string{"server": address} tags := map[string]string{"server": address}
@ -99,22 +97,27 @@ func (p *Powerdns) gatherServer(address string, acc telegraf.Accumulator) error
return nil return nil
} }
func parseResponse(metrics string) (map[string]interface{}, error) { func parseResponse(metrics string) map[string]interface{} {
values := make(map[string]interface{}) values := make(map[string]interface{})
s := strings.Split(metrics, ",") s := strings.Split(metrics, ",")
for _, metric := range s[:len(s)-1] { for _, metric := range s[:len(s)-1] {
m := strings.Split(metric, "=") m := strings.Split(metric, "=")
if len(m) < 2 {
continue
}
i, err := strconv.ParseInt(m[1], 10, 64) i, err := strconv.ParseInt(m[1], 10, 64)
if err != nil { if err != nil {
return values, err log.Printf("powerdns: Error parsing integer for metric [%s]: %s",
metric, err)
continue
} }
values[m[0]] = i values[m[0]] = i
} }
return values, nil return values
} }
func init() { func init() {

View File

@ -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," + "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," "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) { func (s statServer) serverSocket(l net.Listener) {
for { for {
@ -86,8 +110,7 @@ func TestMemcachedGeneratesMetrics(t *testing.T) {
} }
func TestPowerdnsParseMetrics(t *testing.T) { func TestPowerdnsParseMetrics(t *testing.T) {
values, err := parseResponse(metrics) values := parseResponse(metrics)
require.NoError(t, err, "Error parsing memcached response")
tests := []struct { tests := []struct {
key string 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)
}
}
}