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 957740f64f
commit ba551c4bb0
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 ) - packets_received ( from ping output )
- percent_reply_loss ( compute from packets_transmitted and reply_received ) - percent_reply_loss ( compute from packets_transmitted and reply_received )
- percent_packets_loss ( compute from packets_transmitted and packets_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 - response time
- average_response_ms ( compute from minimum_response_ms and maximum_response_ms ) - average_response_ms ( compute from minimum_response_ms and maximum_response_ms )
- minimum_response_ms ( from ping output ) - minimum_response_ms ( from ping output )
- maximum_response_ms ( from ping output ) - maximum_response_ms ( from ping output )
- result_code
- 0: success
- 1: no such host
### Tags: ### Tags:
@ -44,5 +47,5 @@ urls = ["www.google.com"] # required
``` ```
$ ./telegraf --config telegraf.conf --input-filter ping --test $ ./telegraf --config telegraf.conf --input-filter ping --test
* Plugin: ping, Collection 1 * 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 ( import (
"errors" "errors"
"fmt" "fmt"
"net"
"os/exec" "os/exec"
"runtime" "runtime"
"strconv" "strconv"
@ -76,6 +77,17 @@ func (p *Ping) Gather(acc telegraf.Accumulator) error {
wg.Add(1) wg.Add(1)
go func(u string) { go func(u string) {
defer wg.Done() 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) args := p.args(u)
totalTimeout := float64(p.Count)*p.Timeout + float64(p.Count-1)*p.PingInterval 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 { } else {
acc.AddError(err) acc.AddError(err)
} }
acc.AddFields("ping", fields, tags)
return return
} }
} }
tags := map[string]string{"url": u}
trans, rec, min, avg, max, stddev, err := processPingOutput(out) trans, rec, min, avg, max, stddev, err := processPingOutput(out)
if err != nil { if err != nil {
// fatal error // fatal error
acc.AddError(fmt.Errorf("%s: %s", err, u)) acc.AddError(fmt.Errorf("%s: %s", err, u))
acc.AddFields("ping", fields, tags)
return return
} }
// Calculate packet loss percentage // Calculate packet loss percentage
loss := float64(trans-rec) / float64(trans) * 100.0 loss := float64(trans-rec) / float64(trans) * 100.0
fields := map[string]interface{}{ fields["packets_transmitted"] = trans
"packets_transmitted": trans, fields["packets_received"] = rec
"packets_received": rec, fields["percent_packet_loss"] = loss
"percent_packet_loss": loss,
}
if min > 0 { if min > 0 {
fields["minimum_response_ms"] = min fields["minimum_response_ms"] = min
} }
@ -194,7 +205,6 @@ func processPingOutput(out string) (int, int, float64, float64, float64, float64
for _, line := range lines { for _, line := range lines {
if strings.Contains(line, "transmitted") && if strings.Contains(line, "transmitted") &&
strings.Contains(line, "received") { strings.Contains(line, "received") {
err = nil
stats := strings.Split(line, ", ") stats := strings.Split(line, ", ")
// Transmitted packets // Transmitted packets
trans, err = strconv.Atoi(strings.Split(stats[0], " ")[0]) 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") { } else if strings.Contains(line, "min/avg/max") {
stats := strings.Split(line, " ")[3] stats := strings.Split(line, " ")[3]
min, err = strconv.ParseFloat(strings.Split(stats, "/")[0], 64) 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) 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) 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) stddev, err = strconv.ParseFloat(strings.Split(stats, "/")[3], 64)
if err != nil { if err != nil {
return trans, recv, min, avg, max, stddev, err return trans, recv, min, avg, max, stddev, err

View File

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

View File

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

View File

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