-
Notifications
You must be signed in to change notification settings - Fork 5.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove dependency on system binary from ping input plugin #6050
Conversation
Arguments []string | ||
|
||
// Whether to resolve addresses using ipv6 or not. | ||
IPv6 bool | ||
|
||
// host ping function | ||
pingHost HostPinger |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this functionality still used? If not, clean this up and remove. That said, in my mind it would probably be best to turn this into an interface that can be implemented by both the exec code and the native code. This reduces the need to deal with branches and gives a nice "fold" to fake data for unit tests, making testing easier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not certain I follow. This is used to use an ipv6 address a hostname resolves to. It's similar to the current exec version doing a ping -6
or specifying binary = ping6
. It's there as a way to ensure only ipv6 is used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment was attempting to refer to the pingHost field.
plugins/inputs/ping/ping.go
Outdated
return nil | ||
} | ||
|
||
if len(p.Arguments) == 0 && p.Method == "native" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should use the native ping when method = "native"
, not taking into account p.Arguments.
plugins/inputs/ping/ping.go
Outdated
if len(p.Arguments) > 0 { | ||
return append(p.Arguments, url) | ||
func (p *Ping) pingToURLNative(destination string, acc telegraf.Accumulator) { | ||
defer p.wg.Done() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Put the defer in the function that calls this function, this is something I always do to avoid splitting the "are we in a goroutine or not" logic across functions.
plugins/inputs/ping/ping.go
Outdated
Seq: seq, | ||
}) | ||
if err != nil { | ||
// likely a timeout error, ignore |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make sure that it's a timeout error, we will want to log anything else. In my testing, I initially got error listening for ICMP packets: listen ip4:icmp : socket: operation not permitted: socket: permission denied
because I can't be bothered to read the docs.
Also, it seems that ping returns an error result if any ping times out, so we probably want to do something similar.
plugins/inputs/ping/ping.go
Outdated
if err != nil { | ||
return trans, recv, ttl, min, avg, max, stddev, err | ||
} | ||
resps := make(chan *ping.Response, chanLength) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since you read this in a goroutine, you can make the channel much smaller, even unbuffered. Alternately, since we are expecting a low number of concurrent requests, if you size the channel and skip the goroutine moving it after the send loop.
plugins/inputs/ping/ping.go
Outdated
if err != nil { | ||
return min, avg, max, stddev, err | ||
stdDev := time.Duration(math.Sqrt(float64(sumsquares / time.Duration(packetsRcvd)))) | ||
if ttl > 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These tests are a bit strange, why don't we just send all the values for ttl, min, max, average, stddev? I'm guessing this mirrors the exec ping, but I think we can skip it here. In exec ping this indicates that the summary stats couldn't be parsed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it was to mirror the exec ping, if they were 0, it would likely have returned before this. Does it make sense to keep checking and prevent ttl
from showing up in windows (it will be 0 until it's supported).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think in the original code we returned these stats from a function as non-pointer values, and lose the ability to tell the difference between "don't know" and 0. This seems like a minor bug in the old code.
In general, when we don't know what one of the values is we don't want to set it and if we do know, even if its zero, we should. Here I think we have 2 cases: TTL doesn't work on Windows and TTL is legitimately 0 (not sure if this is possible, maybe it can only go to 1, but doesn't actually matter).
If the TTL isn't supported in Windows, we should simply check if we are on Windows and not report TTL. This is a more direct way of dealing with shortcoming that are platform specific; add a comment that TTL is not supported on Windows with the go icmp package.
If the TTL is zero, I think we just report it, same goes for min/max/mean/stddev, zero seems valid though unlikely for all of these.
plugins/inputs/ping/ping.go
Outdated
Binary: "ping", | ||
Arguments: []string{}, | ||
ctx: context.Background(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Boo for ctx on struct... but is this even used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope, looks like a relic.
@@ -339,3 +339,20 @@ func TestPingBinary(t *testing.T) { | |||
} | |||
acc.GatherError(p.Gather) | |||
} | |||
|
|||
// Test that Gather function works using native ping | |||
func TestPingGatherNative(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally we could fake the data from the pinger, which would allow better test coverage without hitting external services.
plugins/inputs/ping/ping_test.go
Outdated
|
||
var acc testutil.Accumulator | ||
p := Ping{ | ||
Urls: []string{"www.google.com", "www.reddit.com"}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think here we should only use "example.org" or "127.0.0.1"
for p.Count <= 0 || packetsSent < p.Count { | ||
select { | ||
case <-ctx.Done(): | ||
goto finish |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just an observation, you don't need to change anything... To me this is an indication flag that this function is too big. If you split it up in the right spots I think error handling could be easier, less variable name aliasing, and no more ugly goto.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes.. I'd love any pointers if you find yourself with some time
This adds native ping capabilities to the ping input plugin, removing the dependency on a system installed
ping
. This also allows ping to work on non-english hosts (a downside to the previous version where the output of a system command was being parsed).Resolves #2833