Add min/max response time on linux/darwin to ping (#2908)

This commit is contained in:
Heston Kan 2017-06-13 17:09:17 -04:00 committed by Daniel Nelson
parent 26e526df67
commit 075066f452
2 changed files with 30 additions and 10 deletions

View File

@ -83,7 +83,7 @@ func (p *Ping) Gather(acc telegraf.Accumulator) error {
strings.TrimSpace(out) + ", " + err.Error()))
}
tags := map[string]string{"url": u}
trans, rec, avg, stddev, err := processPingOutput(out)
trans, rec, min, avg, max, stddev, err := processPingOutput(out)
if err != nil {
// fatal error
acc.AddError(err)
@ -96,9 +96,15 @@ func (p *Ping) Gather(acc telegraf.Accumulator) error {
"packets_received": rec,
"percent_packet_loss": loss,
}
if min > 0 {
fields["minimum_response_ms"] = min
}
if avg > 0 {
fields["average_response_ms"] = avg
}
if max > 0 {
fields["maximum_response_ms"] = max
}
if stddev > 0 {
fields["standard_deviation_ms"] = stddev
}
@ -158,9 +164,9 @@ func (p *Ping) args(url string) []string {
// round-trip min/avg/max/stddev = 34.843/43.508/52.172/8.664 ms
//
// It returns (<transmitted packets>, <received packets>, <average response>)
func processPingOutput(out string) (int, int, float64, float64, error) {
func processPingOutput(out string) (int, int, float64, float64, float64, float64, error) {
var trans, recv int
var avg, stddev float64
var min, avg, max, stddev float64
// Set this error to nil if we find a 'transmitted' line
err := errors.New("Fatal error processing ping output")
lines := strings.Split(out, "\n")
@ -172,23 +178,25 @@ func processPingOutput(out string) (int, int, float64, float64, error) {
// Transmitted packets
trans, err = strconv.Atoi(strings.Split(stats[0], " ")[0])
if err != nil {
return trans, recv, avg, stddev, err
return trans, recv, min, avg, max, stddev, err
}
// Received packets
recv, err = strconv.Atoi(strings.Split(stats[1], " ")[0])
if err != nil {
return trans, recv, avg, stddev, err
return trans, recv, min, avg, max, stddev, err
}
} else if strings.Contains(line, "min/avg/max") {
stats := strings.Split(line, " ")[3]
min, err = strconv.ParseFloat(strings.Split(stats, "/")[0], 64)
avg, err = strconv.ParseFloat(strings.Split(stats, "/")[1], 64)
max, err = strconv.ParseFloat(strings.Split(stats, "/")[2], 64)
stddev, err = strconv.ParseFloat(strings.Split(stats, "/")[3], 64)
if err != nil {
return trans, recv, avg, stddev, err
return trans, recv, min, avg, max, stddev, err
}
}
}
return trans, recv, avg, stddev, err
return trans, recv, min, avg, max, stddev, err
}
func init() {

View File

@ -48,25 +48,29 @@ ping: -i interval too short: Operation not permitted
// Test that ping command output is processed properly
func TestProcessPingOutput(t *testing.T) {
trans, rec, avg, stddev, err := processPingOutput(bsdPingOutput)
trans, rec, min, avg, max, stddev, err := processPingOutput(bsdPingOutput)
assert.NoError(t, err)
assert.Equal(t, 5, trans, "5 packets were transmitted")
assert.Equal(t, 5, rec, "5 packets were transmitted")
assert.InDelta(t, 15.087, min, 0.001)
assert.InDelta(t, 20.224, avg, 0.001)
assert.InDelta(t, 27.263, max, 0.001)
assert.InDelta(t, 4.076, stddev, 0.001)
trans, rec, avg, stddev, err = processPingOutput(linuxPingOutput)
trans, rec, min, avg, max, stddev, err = processPingOutput(linuxPingOutput)
assert.NoError(t, err)
assert.Equal(t, 5, trans, "5 packets were transmitted")
assert.Equal(t, 5, rec, "5 packets were transmitted")
assert.InDelta(t, 35.225, min, 0.001)
assert.InDelta(t, 43.628, avg, 0.001)
assert.InDelta(t, 51.806, max, 0.001)
assert.InDelta(t, 5.325, stddev, 0.001)
}
// Test that processPingOutput returns an error when 'ping' fails to run, such
// as when an invalid argument is provided
func TestErrorProcessPingOutput(t *testing.T) {
_, _, _, _, err := processPingOutput(fatalPingOutput)
_, _, _, _, _, _, err := processPingOutput(fatalPingOutput)
assert.Error(t, err, "Error was expected from processPingOutput")
}
@ -150,7 +154,9 @@ func TestPingGather(t *testing.T) {
"packets_transmitted": 5,
"packets_received": 5,
"percent_packet_loss": 0.0,
"minimum_response_ms": 35.225,
"average_response_ms": 43.628,
"maximum_response_ms": 51.806,
"standard_deviation_ms": 5.325,
}
acc.AssertContainsTaggedFields(t, "ping", fields, tags)
@ -188,7 +194,9 @@ func TestLossyPingGather(t *testing.T) {
"packets_transmitted": 5,
"packets_received": 3,
"percent_packet_loss": 40.0,
"minimum_response_ms": 35.225,
"average_response_ms": 44.033,
"maximum_response_ms": 51.806,
"standard_deviation_ms": 5.325,
}
acc.AssertContainsTaggedFields(t, "ping", fields, tags)
@ -244,6 +252,10 @@ func TestFatalPingGather(t *testing.T) {
"Fatal ping should not have packet measurements")
assert.False(t, acc.HasMeasurement("percent_packet_loss"),
"Fatal ping should not have packet measurements")
assert.False(t, acc.HasMeasurement("minimum_response_ms"),
"Fatal ping should not have packet measurements")
assert.False(t, acc.HasMeasurement("average_response_ms"),
"Fatal ping should not have packet measurements")
assert.False(t, acc.HasMeasurement("maximum_response_ms"),
"Fatal ping should not have packet measurements")
}