diff --git a/plugins/inputs/ping/ping.go b/plugins/inputs/ping/ping.go index 089248efe237f..82fc3e53509fb 100644 --- a/plugins/inputs/ping/ping.go +++ b/plugins/inputs/ping/ping.go @@ -84,7 +84,7 @@ func (p *Ping) Gather(acc telegraf.Accumulator) error { strings.TrimSpace(out) + ", " + err.Error()) } tags := map[string]string{"url": u} - trans, rec, avg, err := processPingOutput(out) + trans, rec, avg, jit, err := processPingOutput(out) if err != nil { // fatal error errorChannel <- err @@ -100,6 +100,9 @@ func (p *Ping) Gather(acc telegraf.Accumulator) error { if avg > 0 { fields["average_response_ms"] = avg } + if jit > 0 { + fields["jitter_response_ms"] = jit + } acc.AddFields("ping", fields, tags) }(url) } @@ -166,9 +169,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 (, , ) -func processPingOutput(out string) (int, int, float64, error) { +func processPingOutput(out string) (int, int, float64, float64, error) { var trans, recv int - var avg float64 + var avg, jit 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") @@ -180,22 +183,23 @@ func processPingOutput(out string) (int, int, float64, error) { // Transmitted packets trans, err = strconv.Atoi(strings.Split(stats[0], " ")[0]) if err != nil { - return trans, recv, avg, err + return trans, recv, avg, jit, err } // Received packets recv, err = strconv.Atoi(strings.Split(stats[1], " ")[0]) if err != nil { - return trans, recv, avg, err + return trans, recv, avg, jit, err } } else if strings.Contains(line, "min/avg/max") { - stats := strings.Split(line, " = ")[1] + stats := strings.Split(line, " ")[3] avg, err = strconv.ParseFloat(strings.Split(stats, "/")[1], 64) + jit, err = strconv.ParseFloat(strings.Split(stats, "/")[3], 64) if err != nil { - return trans, recv, avg, err + return trans, recv, avg, jit, err } } } - return trans, recv, avg, err + return trans, recv, avg, jit, err } func init() { diff --git a/plugins/inputs/ping/ping_test.go b/plugins/inputs/ping/ping_test.go index b5d0d16e71874..77e53b28d67b8 100644 --- a/plugins/inputs/ping/ping_test.go +++ b/plugins/inputs/ping/ping_test.go @@ -48,23 +48,25 @@ ping: -i interval too short: Operation not permitted // Test that ping command output is processed properly func TestProcessPingOutput(t *testing.T) { - trans, rec, avg, err := processPingOutput(bsdPingOutput) + trans, rec, avg, jit, 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, 20.224, avg, 0.001) + assert.InDelta(t, 4.076, jit, 0.001) - trans, rec, avg, err = processPingOutput(linuxPingOutput) + trans, rec, avg, jit, 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, 43.628, avg, 0.001) + assert.InDelta(t, 5.325, jit, 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") } @@ -149,6 +151,7 @@ func TestPingGather(t *testing.T) { "packets_received": 5, "percent_packet_loss": 0.0, "average_response_ms": 43.628, + "jitter_response_ms": 5.325, } acc.AssertContainsTaggedFields(t, "ping", fields, tags) @@ -186,6 +189,7 @@ func TestLossyPingGather(t *testing.T) { "packets_received": 3, "percent_packet_loss": 40.0, "average_response_ms": 44.033, + "jitter_response_ms": 5.325, } acc.AssertContainsTaggedFields(t, "ping", fields, tags) }