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

procstats patterns without pgrep #3559

Merged
merged 34 commits into from Feb 1, 2018

Conversation

vrecan
Copy link
Contributor

@vrecan vrecan commented Dec 8, 2017

I have pulled in a new dep for dealing with cross platform pattern matching for processes. I have validated everything on linux and I am going through some steps to validate it all on windows. Let me know if I did something incorrectly when I added the dependencies.

This fixes #3558

This is my first PR for telegraf. I have signed the CLA.

Required for all PRs:

  • Signed CLA.
  • [] Associated README.md updated.
  • [] Has appropriate unit tests.

@vrecan
Copy link
Contributor Author

vrecan commented Dec 15, 2017

I have reverted my change to gopsutil and just implemented the WMI queries here to make it work. WMI is the only way that I know to do this without using CGO. Let me know if there is another way you would like me to implement this or if there is anything you would like me to change!

I've also updated the readme with a section for using it in windows.

Thanks!

@danielnelson
Copy link
Contributor

I think we shoud create another PIDFinder, we can call it NativeFinder. We can implement the interface using regular gopsutil commands but for name/cmdline we can have it use the specialized WMI calls on Windows. Then in the procstat config we can introduce an option: finder = "pgrep" or finder = "native". Then we can move the regex matching into the NativeFinder.

There are a few spots in the code where there are small unneeded changes, can you also clean these up so that we only modify lines related to the patchset.

@vrecan
Copy link
Contributor Author

vrecan commented Dec 20, 2017

OK so you want me to create a new finder that fully implements everything for all platforms using gopsutil only? And then in that version it will use the special WMI calls for windows?

Just trying to make sure I understand what you want me to do before I implement it. I am open to implementing it however you want :)

@vrecan
Copy link
Contributor Author

vrecan commented Dec 20, 2017

There are a few things that are different for windows then unix. Windows has no pid files and it requires another WMI call to get processes by owner, it's a name though and not a UID.

@danielnelson
Copy link
Contributor

For the pid files, even though no one really uses them in Windows, maybe we can just use the same implementation. Then someone could use it if they wanted for some reason and we don't have to explain that this option doesn't work.

@danielnelson
Copy link
Contributor

A little more clarification, a user should be able to use either the native or pgrep finder on any plaform. We should have the default implementation use gopsutil, but we can have a windows specialization that uses the faster wmi calls as needed.

@vrecan
Copy link
Contributor Author

vrecan commented Dec 22, 2017

sounds good, thanks I will start working on that

@vrecan
Copy link
Contributor Author

vrecan commented Dec 23, 2017

@danielnelson do you mind looking at my current implementation. Does this look like what you want? If so I am going to add some more tests and update the readme

user, err := p.Username()
if err != nil {
//skip, this can happen if we don't have permissions or
//the pid no longer exists
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs continue?

@@ -0,0 +1,59 @@
// +build !windows
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call this file native_finder_notwindows.go

@@ -0,0 +1,109 @@
// +build windows
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call this file native_finder_windows.go

var Timeout = 5 * time.Second

func init() {
wmi.DefaultClient.AllowMissingFields = true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should try to arrange for a new wmi.Client to be created and used once for each plugin. This will avoid needing to modify the default client which might have unwanted effects on other pieces of code due to it being global.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should I have a seperate native finder struct for windows so that I can store it there?

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 was able to remove this and my queries still work. I took this from the gopsutil implementation and it looks like it's not really needed for our queries.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

// }

//Pattern matches on the process name
func (pg *NativeFinder) Pattern(pattern string) ([]PID, error) {
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 this looks the same as the notwindows version, lets put shared implementation in a native_finder.go file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed

func getWin32ProcsByVariable(variable string, qType queryType, value string, timeout time.Duration) ([]process.Win32_Process, error) {
var dst []process.Win32_Process
var query string
query = fmt.Sprint("WHERE ", variable, " ", qType, " \"", value, "\"")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use fmt.Sprintf for readability. I'm nervous about escaping here, variable and value need to be escaped more rigorously.

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 changed to sprintf, how would you like me to protect against escaping? based on this I should be able to just escape backslash and single quote for the value. On the variable I can just fail anytime any of the non standard characters are in it. What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case you can probably use the %q pattern, it will escape double quote and backslash using backslash, and it will add the outer quotation marks:

"WHERE %s %s %q"

## pgrep tries to exec pgrep
## native will work on all platforms, unix systems will use regexp.
## Windows will use WMI calls with like queries
pid_finder = native
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs quotes: pid_finder = "native"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

fmt.Println("PIDFINDER: ", p.PidFinder)
switch p.PidFinder {
case "native":
fmt.Println("pid finder is now native")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't forget to cleanup debugging statements

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -1,3 +1,5 @@
// +build !windows
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to remove this build flag

Copy link
Contributor Author

@vrecan vrecan Jan 12, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when I remove the build tag I get this error on windows:

--- FAIL: TestGather_cgroupPIDs (0.00s)
        Error Trace:    procstat_test.go:363
        Error:          Received unexpected error:
                        open \sys\fs\cgroup\C:\Users\Vrecan\AppData\Local\Temp\565977507\cgroup.procs: The filename, directory name, or volume label syntax is incorrect.

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 addressed this by skipping the test in windows

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if it will be enough, but we should use filepath.Join here: https://github.com/influxdata/telegraf/blob/master/plugins/inputs/procstat/procstat.go#L336

@@ -27,8 +27,28 @@ Additionally the plugin will tag processes by their PID (pid_tag = true in the c
* pid
* process_name


### Windows
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will have to remember to take a second pass at this documentation, so that it matches the current design

@vrecan
Copy link
Contributor Author

vrecan commented Jan 12, 2018

thanks for the comments, I am going to take a look at this today or tomorrow and update the PR

@danielnelson
Copy link
Contributor

Will need to rebase to fix the test error in cratedb

@vrecan
Copy link
Contributor Author

vrecan commented Jan 24, 2018

I pulled in master and I am still getting test failures. This time in leofs. What should I do to get this resolved and merged? What kind of documentation are you looking for?

Thanks for your help!

Copy link
Contributor

@danielnelson danielnelson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests were just an intermittent failure, sorry about that. We also still need to rename the camel case files like nativeFinder.go to native_finder.go

@@ -349,6 +350,10 @@ func TestGather_systemdUnitPIDs(t *testing.T) {
}

func TestGather_cgroupPIDs(t *testing.T) {
//no cgroups in windows
if runtime.GOOS == "windows" {
t.SkipNow()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can put the comment in here like: .Skip("no cgroups in windows")

var dst []process.Win32_Process
var query string
// should look like "WHERE CommandLine LIKE "procstat"
query = fmt.Sprintf("WHERE %s %s '%s'", variable, qType, value)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use %q here to get quoting with escaping of value. "WHERE %s %s %q"

}

//getPidsByUser ...
func getPidsByUser(username string) ([]PID, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just merge this into func (pg *NativeFinder) Uid(user string) ([]PID, error) since it doesn't add any new abstraction.

@vrecan
Copy link
Contributor Author

vrecan commented Jan 30, 2018

@danielnelson I believe I have addressed all of your comments.

@danielnelson danielnelson added this to the 1.6.0 milestone Feb 1, 2018
@danielnelson danielnelson added the feat Improvement on an existing feature such as adding a new setting/mode to an existing plugin label Feb 1, 2018
@danielnelson danielnelson merged commit a7571d5 into influxdata:master Feb 1, 2018
@danielnelson
Copy link
Contributor

@vrecan Merged in for 1.6, thanks. I also did some updates to the procstat README so if you have a chance could you take a look and make sure it is correct?

@vrecan
Copy link
Contributor Author

vrecan commented Feb 2, 2018

Thanks for merging this, I will look at the docs now.

mkboudreau added a commit to mkboudreau/telegraf that referenced this pull request Feb 16, 2018
* master: (59 commits)
  Added additional SQL Server performance counters (influxdata#3770)
  Update changelog
  Fix ping plugin not reporting zero durations (influxdata#3778)
  Adjust time of nightly build
  Update changelog
  Add TLS support to the mesos input plugin (influxdata#3769)
  Install new requirements for fpm gem install
  Update changelog
  Add additional metrics and reverse metric names option to openldap (influxdata#3722)
  Update paho mqtt to latest release
  Update changelog
  Remove userinfo from url tag in prometheus input (influxdata#3743)
  Update sample config in contributing docs
  Run nightly build sequentially
  Fix Makefile on Windows and use in AppVeyor build (influxdata#3748)
  Fix example source_override values in wavefront output (influxdata#3744)
  Update gitignore
  Update changelog
  Improve procstat readme
  Add native Go method for finding pids to procstat (influxdata#3559)
  ...
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 for using procstat without pgrep
2 participants