Skip to content

Commit

Permalink
Add min/max response time on linux/darwin to ping (influxdata#2908)
Browse files Browse the repository at this point in the history
  • Loading branch information
hestonk authored and jeichorn committed Jul 24, 2017
1 parent 831e82e commit 800f5a4
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 10 deletions.
22 changes: 15 additions & 7 deletions plugins/inputs/ping/ping.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
}
Expand Down Expand Up @@ -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")
Expand All @@ -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() {
Expand Down
18 changes: 15 additions & 3 deletions plugins/inputs/ping/ping_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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")
}

0 comments on commit 800f5a4

Please sign in to comment.