-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
New module windows for metricbeat #3758
New module windows for metricbeat #3758
Conversation
Jenkins standing by to test this. If you aren't a maintainer, you can ignore this comment. Someone with commit access, please review this and clear it for Jenkins to run. |
1 similar comment
Jenkins standing by to test this. If you aren't a maintainer, you can ignore this comment. Someone with commit access, please review this and clear it for Jenkins to run. |
Is there some flag which says this module is only for windows? |
c610ab3
to
331a56f
Compare
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.
Thanks for opening up a PR for this. 👍
I left some minor feedback about error handling. After you address that I'll probably take the code for a test drive.
Could you please add some tests (like a pdh_windows_test.go
file) that exercises the code by querying some counters. And maybe a negative test case where a counter does not exist.
It looks like you accidentally committed a copy of libbeat/dashboards/import_dashboards
. Please remove that.
@@ -0,0 +1,83 @@ | |||
package perfmon |
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.
You can use // +build windows
to make files like this compile only for Windows. Or you can rename them to include a _windows.go
suffix. This behavior is described here: https://golang.org/pkg/go/build/
} | ||
|
||
for _, v := range config.CounterConfig { | ||
if len(v.Name) <= 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.
ucfg can apply this sort of validation automatically if you annotate a the fields with validation info. (see docs) For example,
type CounterConfig struct {
Name string `config:"group" validate:"required"`
Group []CounterConfigGroup `config:"collectors" validate:"required"`
}
|
||
if err != 0 { | ||
logp.Err("%v", err) | ||
return nil, errors.New("Initialization fails with error: " + strconv.Itoa(err)) |
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.
It's not a best practice to log errors and return them. I would just return the error and let the caller decide if it is supposed to be logged or not. Please review the whole PR and make the appropriate changes.
|
||
//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output pdh_windows.go pdh.go | ||
// Windows API calls | ||
//sys _PdhOpenQuery(dataSource uintptr, userData uintptr, query *uintptr) (err int) = pdh.PdhOpenQuery |
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 recommend changing the method signature of all these functions to return (err error)
. The newly generated code will then check the int return value and return the appropriate error
. This make all the code that uses theses function conform to the standard Go conventions.
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 have change the signature to error
. Now it generate this function
func _PdhOpenQuery(dataSource uintptr, userData uintptr, query *uintptr) (err error) {
r1, _, e1 := syscall.Syscall(procPdhOpenQuery.Addr(), 3, uintptr(dataSource), uintptr(userData), uintptr(unsafe.Pointer(query)))
if r1 == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}
Now i always get Invalid argument
error. How should i handle this error. Is it not better to return nil
?
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.
Done
|
||
for _, v := range config.CounterConfig { | ||
if len(v.Name) <= 0 { | ||
err := errors.New("Group cannot be empty") |
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.
Error strings should not be capitalized. explanation
- group: "processor" | ||
collectors: | ||
- alias: "processor_perfomance" | ||
query: "\\Processor Information(_Total)\\% Processor Performance" |
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.
If you use single quotes here, can the double backslashes be replaced with a single backslash? I would prefer that, unless of course using double backslashes is common in the perfmon world.
metricsets: ["perfmon"] | ||
enabled: true | ||
period: 1s | ||
counters: |
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.
For metricset specific configs we (recently) created the convention to have it under a namespace. Means here it would be perfmon.counters:
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.
In source i then have to write this config:"perfmon.counters" validate:"required"
?
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
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.
Thanks a lot for taking this on. Having platform specific modules is something new in metricbeat.
I'm not too happy about the metricset name yet, but I couldn't come up with an alternative name yet.
Any chance you could share some example outputs for the example config you created. I'm curious to see how the events will look.
I left you a few comments which are mostly related to the assumption, that this is a dynamic metricset.
// descriptive error must be returned. | ||
func (m *MetricSet) Fetch() (common.MapStr, error) { | ||
|
||
data, err := m.handle.readData() |
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.
As far as I understand, this is a "dynamic" metricset. If yes, this would need also a namespace. See https://github.com/elastic/beats/blob/master/metricbeat/module/jolokia/jmx/jmx.go#L93 for an example.
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.
With dynamic metricset i suppose you mean that there can be multiple groups of counters, right?
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 mean that the data structure / output depends on the user configuration. In most metricsets we know in advance the exact data structure. With metricsets like jmx it depends on the user configuration and we can't ship a predefined mapping.
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.
Ok, then it's definitely a dynamic metricset.
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.
Yeah, but I need to find a better name for the dynamic
part, as I already confused @andrewkroh with that ...
@@ -0,0 +1,26 @@ | |||
- name: perfmon |
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.
For dynamic metricsets, this will change so what we nomrally do is just define windows (module) part and leave the rest empty. Check the jmx metricset as an example.
metricsets: ["perfmon"] | ||
enabled: true | ||
period: 1s | ||
perfmon.counters: |
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.
It's great to have these example coutners which can be used. The way we handled it in the jmx metricset is that we defined only perfmon.counters:
but left it empty (https://github.com/elastic/beats/blob/master/metricbeat/module/jolokia/_meta/config.yml#L8) and move the examples to the docs: https://github.com/elastic/beats/blob/master/metricbeat/module/jolokia/jmx/_meta/docs.asciidoc
@@ -0,0 +1,9 @@ | |||
- key: windows | |||
title: "Windows" | |||
description: > |
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.
// Part of new is also setting up the configuration by processing additional | ||
// configuration entries if needed. | ||
func New(base mb.BaseMetricSet) (mb.MetricSet, error) { | ||
|
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.
A log message should be added to make it clear it is beta: https://github.com/elastic/beats/blob/master/metricbeat/module/jolokia/jmx/jmx.go#L49 We do this for all new modules / metricsets to test them first.
- module: windows | ||
metricsets: ["perfmon"] | ||
enabled: true | ||
period: 1s |
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.
Our default is 10s
Hi @ruflin, thanks for your review. I'm also not happy with the naming, but i think i get something better. |
Hi @ruflin, here is an example output
|
Todo:
|
Most counters require two sample values in order to compute a displayable value. This means to display the first result we need two values
+1 on having this in the windows module. |
@maddin2016 Could you update the CHANGELOG.asciidoc ? About the config options structure not sure what we should do. Would like to get the input from @andrewkroh too. I tend to the in the direction of the "flatter" one as it makes the code simpler and has less indentations to get wrong, but we loose the grouping concept. The nice thing about having it in beat, we still have the possibility to change it later in case we see people use it very differently. |
I update the asciidoc. What about the
|
You need a |
The |
As long as there is no special implementation on the module level, the file is not needed and a "default module" will be initialised. |
What about the failing tests. Seems it tries to build for linux and mac. Something is have missed? |
The first part which is failing is because of the linting. Make sure to run |
The crosscompile error is because you are missing the |
@ruflin, can you rebuild travis again. I don't see any output whats going wrong. |
@maddin2016 I think travis is a bit grumpy today. Have the same issue on other PRs. Probably we just have to wait :-( |
Ok 👍 |
How i can |
You can either call it |
On top i had specified |
🎉 |
@maddin2016 All green, great! So we are going to merge this is and would like to iterate on it with some additional (smaller) PRs. We're starting a meta issue to track some changes to the module. Hopefully you can help us with these changes. Thanks for the contribution!! |
Of course!! |
I'm experimenting with the metricbeat-6.0.0-alpha1 and I have an issue/concern. Forgive the noob question but do I report that here? |
@sy43165 Please use https://discuss.elastic.co/c/beats. |
This PR implements a new module called windows for metricbeat. The first metricset within this module is perfmonbeat which is able to collect data from windows performance counters.