Perform DNS lookup before ping (#3385)

This commit is contained in:
Vladimir S 2017-10-26 23:35:37 +03:00 committed by Daniel Nelson
parent 5885ef2c1c
commit 88ec171293
5 changed files with 61 additions and 22 deletions

View File

@ -28,11 +28,14 @@ urls = ["www.google.com"] # required
- packets_received ( from ping output )
- percent_reply_loss ( compute from packets_transmitted and reply_received )
- percent_packets_loss ( compute from packets_transmitted and packets_received )
- errors ( when host can not be found or wrong prameters is passed to application )
- errors ( when host can not be found or wrong parameters is passed to application )
- response time
- average_response_ms ( compute from minimum_response_ms and maximum_response_ms )
- minimum_response_ms ( from ping output )
- maximum_response_ms ( from ping output )
- result_code
- 0: success
- 1: no such host
### Tags:
@ -44,5 +47,5 @@ urls = ["www.google.com"] # required
```
$ ./telegraf --config telegraf.conf --input-filter ping --test
* Plugin: ping, Collection 1
ping,host=WIN-PBAPLP511R7,url=www.google.com average_response_ms=7i,maximum_response_ms=9i,minimum_response_ms=7i,packets_received=4i,packets_transmitted=4i,percent_packet_loss=0,percent_reply_loss=0,reply_received=4i 1469879119000000000
ping,host=WIN-PBAPLP511R7,url=www.google.com result_code=0i,average_response_ms=7i,maximum_response_ms=9i,minimum_response_ms=7i,packets_received=4i,packets_transmitted=4i,percent_packet_loss=0,percent_reply_loss=0,reply_received=4i 1469879119000000000
```

View File

@ -5,6 +5,7 @@ package ping
import (
"errors"
"fmt"
"net"
"os/exec"
"runtime"
"strconv"
@ -76,6 +77,17 @@ func (p *Ping) Gather(acc telegraf.Accumulator) error {
wg.Add(1)
go func(u string) {
defer wg.Done()
tags := map[string]string{"url": u}
fields := map[string]interface{}{"result_code": 0}
_, err := net.LookupHost(u)
if err != nil {
acc.AddError(err)
fields["result_code"] = 1
acc.AddFields("ping", fields, tags)
return
}
args := p.args(u)
totalTimeout := float64(p.Count)*p.Timeout + float64(p.Count-1)*p.PingInterval
@ -99,24 +111,23 @@ func (p *Ping) Gather(acc telegraf.Accumulator) error {
} else {
acc.AddError(err)
}
acc.AddFields("ping", fields, tags)
return
}
}
tags := map[string]string{"url": u}
trans, rec, min, avg, max, stddev, err := processPingOutput(out)
if err != nil {
// fatal error
acc.AddError(fmt.Errorf("%s: %s", err, u))
acc.AddFields("ping", fields, tags)
return
}
// Calculate packet loss percentage
loss := float64(trans-rec) / float64(trans) * 100.0
fields := map[string]interface{}{
"packets_transmitted": trans,
"packets_received": rec,
"percent_packet_loss": loss,
}
fields["packets_transmitted"] = trans
fields["packets_received"] = rec
fields["percent_packet_loss"] = loss
if min > 0 {
fields["minimum_response_ms"] = min
}
@ -194,7 +205,6 @@ func processPingOutput(out string) (int, int, float64, float64, float64, float64
for _, line := range lines {
if strings.Contains(line, "transmitted") &&
strings.Contains(line, "received") {
err = nil
stats := strings.Split(line, ", ")
// Transmitted packets
trans, err = strconv.Atoi(strings.Split(stats[0], " ")[0])
@ -209,8 +219,17 @@ func processPingOutput(out string) (int, int, float64, float64, float64, float64
} else if strings.Contains(line, "min/avg/max") {
stats := strings.Split(line, " ")[3]
min, err = strconv.ParseFloat(strings.Split(stats, "/")[0], 64)
if err != nil {
return trans, recv, min, avg, max, stddev, err
}
avg, err = strconv.ParseFloat(strings.Split(stats, "/")[1], 64)
if err != nil {
return trans, recv, min, avg, max, stddev, err
}
max, err = strconv.ParseFloat(strings.Split(stats, "/")[2], 64)
if err != nil {
return trans, recv, min, avg, max, stddev, err
}
stddev, err = strconv.ParseFloat(strings.Split(stats, "/")[3], 64)
if err != nil {
return trans, recv, min, avg, max, stddev, err

View File

@ -158,6 +158,7 @@ func TestPingGather(t *testing.T) {
"average_response_ms": 43.628,
"maximum_response_ms": 51.806,
"standard_deviation_ms": 5.325,
"result_code": 0,
}
acc.AssertContainsTaggedFields(t, "ping", fields, tags)
@ -198,6 +199,7 @@ func TestLossyPingGather(t *testing.T) {
"average_response_ms": 44.033,
"maximum_response_ms": 51.806,
"standard_deviation_ms": 5.325,
"result_code": 0,
}
acc.AssertContainsTaggedFields(t, "ping", fields, tags)
}
@ -230,6 +232,7 @@ func TestBadPingGather(t *testing.T) {
"packets_transmitted": 2,
"packets_received": 0,
"percent_packet_loss": 100.0,
"result_code": 0,
}
acc.AssertContainsTaggedFields(t, "ping", fields, tags)
}

View File

@ -4,6 +4,7 @@ package ping
import (
"errors"
"net"
"os/exec"
"regexp"
"strconv"
@ -158,6 +159,18 @@ func (p *Ping) Gather(acc telegraf.Accumulator) error {
wg.Add(1)
go func(u string) {
defer wg.Done()
tags := map[string]string{"url": u}
fields := map[string]interface{}{"result_code": 0}
_, err := net.LookupHost(u)
if err != nil {
errorChannel <- err
fields["result_code"] = 1
acc.AddFields("ping", fields, tags)
return
}
args := p.args(u)
totalTimeout := p.timeout() * float64(p.Count)
out, err := p.pingHost(totalTimeout, args...)
@ -167,7 +180,6 @@ func (p *Ping) Gather(acc telegraf.Accumulator) error {
// Combine go err + stderr output
pendingError = errors.New(strings.TrimSpace(out) + ", " + err.Error())
}
tags := map[string]string{"url": u}
trans, recReply, receivePacket, avg, min, max, err := processPingOutput(out)
if err != nil {
// fatal error
@ -175,24 +187,20 @@ func (p *Ping) Gather(acc telegraf.Accumulator) error {
errorChannel <- pendingError
}
errorChannel <- err
fields := map[string]interface{}{
"errors": 100.0,
}
fields["errors"] = 100.0
acc.AddFields("ping", fields, tags)
return
}
// Calculate packet loss percentage
lossReply := float64(trans-recReply) / float64(trans) * 100.0
lossPackets := float64(trans-receivePacket) / float64(trans) * 100.0
fields := map[string]interface{}{
"packets_transmitted": trans,
"reply_received": recReply,
"packets_received": receivePacket,
"percent_packet_loss": lossPackets,
"percent_reply_loss": lossReply,
}
fields["packets_transmitted"] = trans
fields["reply_received"] = recReply
fields["packets_received"] = receivePacket
fields["percent_packet_loss"] = lossPackets
fields["percent_reply_loss"] = lossReply
if avg > 0 {
fields["average_response_ms"] = float64(avg)
}

View File

@ -4,9 +4,10 @@ package ping
import (
"errors"
"testing"
"github.com/influxdata/telegraf/testutil"
"github.com/stretchr/testify/assert"
"testing"
)
// Windows ping format ( should support multilanguage ?)
@ -81,6 +82,7 @@ func TestPingGather(t *testing.T) {
"average_response_ms": 50.0,
"minimum_response_ms": 50.0,
"maximum_response_ms": 52.0,
"result_code": 0,
}
acc.AssertContainsTaggedFields(t, "ping", fields, tags)
@ -121,6 +123,7 @@ func TestBadPingGather(t *testing.T) {
"reply_received": 0,
"percent_packet_loss": 100.0,
"percent_reply_loss": 100.0,
"result_code": 0,
}
acc.AssertContainsTaggedFields(t, "ping", fields, tags)
}
@ -167,6 +170,7 @@ func TestLossyPingGather(t *testing.T) {
"average_response_ms": 115.0,
"minimum_response_ms": 114.0,
"maximum_response_ms": 119.0,
"result_code": 0,
}
acc.AssertContainsTaggedFields(t, "ping", fields, tags)
}
@ -269,6 +273,7 @@ func TestUnreachablePingGather(t *testing.T) {
"reply_received": 0,
"percent_packet_loss": 75.0,
"percent_reply_loss": 100.0,
"result_code": 0,
}
acc.AssertContainsTaggedFields(t, "ping", fields, tags)
@ -315,6 +320,7 @@ func TestTTLExpiredPingGather(t *testing.T) {
"reply_received": 0,
"percent_packet_loss": 75.0,
"percent_reply_loss": 100.0,
"result_code": 0,
}
acc.AssertContainsTaggedFields(t, "ping", fields, tags)