Skip to content
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

Merged
merged 17 commits into from
Jul 11, 2019

Conversation

glinton
Copy link
Contributor

@glinton glinton commented Jun 27, 2019

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

@glinton glinton added the feat Improvement on an existing feature such as adding a new setting/mode to an existing plugin label Jun 27, 2019
Arguments []string

// Whether to resolve addresses using ipv6 or not.
IPv6 bool

// host ping function
pingHost HostPinger
Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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.

return nil
}

if len(p.Arguments) == 0 && p.Method == "native" {
Copy link
Contributor

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.

if len(p.Arguments) > 0 {
return append(p.Arguments, url)
func (p *Ping) pingToURLNative(destination string, acc telegraf.Accumulator) {
defer p.wg.Done()
Copy link
Contributor

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.

Seq: seq,
})
if err != nil {
// likely a timeout error, ignore
Copy link
Contributor

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.

if err != nil {
return trans, recv, ttl, min, avg, max, stddev, err
}
resps := make(chan *ping.Response, chanLength)
Copy link
Contributor

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.

if err != nil {
return min, avg, max, stddev, err
stdDev := time.Duration(math.Sqrt(float64(sumsquares / time.Duration(packetsRcvd))))
if ttl > 0 {
Copy link
Contributor

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.

Copy link
Contributor Author

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).

Copy link
Contributor

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.

Binary: "ping",
Arguments: []string{},
ctx: context.Background(),
Copy link
Contributor

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?

Copy link
Contributor Author

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) {
Copy link
Contributor

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.


var acc testutil.Accumulator
p := Ping{
Urls: []string{"www.google.com", "www.reddit.com"},
Copy link
Contributor

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
Copy link
Contributor

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.

Copy link
Contributor Author

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

@danielnelson danielnelson merged commit ea6b398 into master Jul 11, 2019
@danielnelson danielnelson deleted the feat/2833 branch July 11, 2019 22:08
@danielnelson danielnelson added this to the 1.12.0 milestone Jul 11, 2019
bitcharmer pushed a commit to bitcharmer/telegraf that referenced this pull request Oct 18, 2019
athoune pushed a commit to bearstech/telegraf that referenced this pull request Apr 17, 2020
idohalevi pushed a commit to idohalevi/telegraf that referenced this pull request Sep 29, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feat Improvement on an existing feature such as adding a new setting/mode to an existing plugin
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support a native ping
3 participants