-
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
First refactor of the system module - system/cpu and system/core #25771
First refactor of the system module - system/cpu and system/core #25771
Conversation
Pinging @elastic/integrations (Team:Integrations) |
💚 Build Succeeded
Expand to view the summary
Build stats
Test stats 🧪
Trends 🧪💚 Flaky test reportTests succeeded. Expand to view the summary
Test stats 🧪
|
/test |
1 similar comment
/test |
if err != nil { | ||
errs = append(errs, err) | ||
} | ||
cpuData.User = metrics.OptUintWith(user) |
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.
We never return early. As we have an OptUint, do we really want to report 0, or shall the optional be unset?
Not really required to change this here, but ways to reduce repetition:
tryParseUint := func(name, field string) (v metrics.OptUint) {
u, err := touint(field)
if err != nil {
errs = append(errs, fmt.Errorf("failed to parse %v: %w", name, field))
} else {
v = metrics.OptUintWith(u)
}
return v
}
and use it like:
cpuData.User = tryParseUint("user", fields[1])
cpuData.Nice = tryparseUint("nice", fields[2])
Now the error message tells you which field failed to parse, plus we don't have to live with all those if-else blocks.
The tryParseUint not return an uninitialized Opt value if parsing failed. The curent code just returns 0. Not sure which one would fit better here. But given we have an optional type I would assume we don't use 0.
For 'bigger' use cases one might want to turn the closure into a custom type.
In case you want to allow custom parser functions (hex vs. decimal representation) the helper could be written like this:
tryParse := func(u uint, err error) (v metrics.OptUint) {
if err != nil {
errs = append(errs, error)
} else {
v = metrics.OptUintWith(u)
}
return v
}
This function will be used like this (if number of returned values matches number of parameters we can just chain them):
cpuData.User = tryParse(touint(fields[1])
cpuData.Nice = tryPaese(touint(fields[2])
Unfortunately with that approach we loose the nice error messages.
metricbeat/internal/metrics/opt.go
Outdated
} | ||
|
||
// Value returns the value, and the bool indicating if it exists | ||
func (opt OptUint) Value() (uint64, bool) { |
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 don't mind the name Value
vs. Get
. But given that we already have IsZero
, I would not return the second bool.
metricbeat/internal/metrics/opt.go
Outdated
// ValueOrZero returns the stored value, or zero | ||
// Please do not use this for populating reported data, | ||
// as we actually want to avoid sending zeros where values are functionally null | ||
func (opt OptUint) ValueOrZero() uint64 { |
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'd prefer if we can configure the value to return if opt is not set. The 0
value is the neutral element for sumation, but not multiplication. Instead of having a ValueOrOne
, try have a small API and give me ValueOr(0)
or ValueOr(1)
.
Thanks for the suggestion @urso ! ended up going with your idea for the |
Oooops. That's what I get for fixing things at 9PM. Fixed again. |
/test |
…stic#25771) * initial commit * finux linux refactor * fix up freebsd * port main metricset, start openbsd * start work on openbsd vagrantfile * refactors of API, add darwin support * fix darwin implementation * refactor API, move tests, remove old code, take a crack at AIX * fix aix init func * fix tests * regenerate core data.json * small fixes, fix host field * update tests * run correct mage commands * try to fix system tests * more fixes for windows python tests * refactor CPU struct, use reflection * refactor reflection code, add validation * move metrics to its own internal folder * move directories, again * move directories, again * use optional Uint type * cleanup opt files * move around naming of opt types * fix up if block * change opt names * move around opt methods, cpu stat reader refactor * fix IsZero usage * add changelog
…stic#25771) * initial commit * finux linux refactor * fix up freebsd * port main metricset, start openbsd * start work on openbsd vagrantfile * refactors of API, add darwin support * fix darwin implementation * refactor API, move tests, remove old code, take a crack at AIX * fix aix init func * fix tests * regenerate core data.json * small fixes, fix host field * update tests * run correct mage commands * try to fix system tests * more fixes for windows python tests * refactor CPU struct, use reflection * refactor reflection code, add validation * move metrics to its own internal folder * move directories, again * move directories, again * use optional Uint type * cleanup opt files * move around naming of opt types * fix up if block * change opt names * move around opt methods, cpu stat reader refactor * fix IsZero usage * add changelog (cherry picked from commit 2871d29)
* master: (25 commits) Fix UBI source URL (elastic#26384) Skip test_rotating_file in osx and windows (elastic#26379) Remove outdated k8s manifests for managed elastic-agent (elastic#26368) Enable agent to send custom headers to kibana/ES (elastic#26275) [Automation] Update elastic stack version to 8.0.0-943ef2c0 for testing (elastic#26354) Make the Syslog input GA (elastic#26293) Move Kerberos FAST config flag to shared kerberos config (elastic#26141) Add k8s cluster identifiers (elastic#26056) Store message from MongoDB json logs in message field (elastic#26338) update threatintel ECS version (elastic#26274) update envoyproxy ECS version (elastic#26277) [Filebeat] [MongoDB] Support MongoDB 4.4 json logs (elastic#24774) Update go-structform to 0.0.9 (elastic#26251) Forward port 7.13.2 changelog to master (elastic#26323) Updated filter expression for filtering 86 artifacts (elastic#26313) Osquerybeat: Align with the rest of the beats, set the ECS version (elastic#26324) [Packetbeat] Add `url.extension` to Packetbeat HTTP events (elastic#25999) Change link to snapshots in README (elastic#26317) Don't include full ES index template in errors (elastic#25743) First refactor of the system module - system/cpu and system/core (elastic#25771) ...
) (#26359) * initial commit * finux linux refactor * fix up freebsd * port main metricset, start openbsd * start work on openbsd vagrantfile * refactors of API, add darwin support * fix darwin implementation * refactor API, move tests, remove old code, take a crack at AIX * fix aix init func * fix tests * regenerate core data.json * small fixes, fix host field * update tests * run correct mage commands * try to fix system tests * more fixes for windows python tests * refactor CPU struct, use reflection * refactor reflection code, add validation * move metrics to its own internal folder * move directories, again * move directories, again * use optional Uint type * cleanup opt files * move around naming of opt types * fix up if block * change opt names * move around opt methods, cpu stat reader refactor * fix IsZero usage * add changelog (cherry picked from commit 2871d29)
What does this PR do?
This is part of a long-discussed refactor of the system module focused on preparing the system module for fleet GA. This is just
system/cpu
andsystem/core
, and by starting off the refactor with just two metricsets, I'm hoping to get feedback on the new structure of the system integration, as the design of a separatemetrics
library, with different implementation around wrapper functions, will be a template for the refactor going forward. This design is based on the go standard library, which takes a similar approach to implementing OS-specific APIs. seeos/file*.go
for an example of this.As this change is entirely backwards compatible, we don't need any special logic to determine if we're running on fleet or metricbeat. That will probably become an issue in future PRs, where we'll want wrappers to prevent us from changing field names or metricset locations in metricbeat.
Right now, the only part of
gosigar
that remains issys/windows
, which I'd like feedback from @narph on. Most of this library is autogenerated bygo generate
, so I'm not sure it makes sense to "break it up" by metricset, as it just makes more work if we have to update it in the future. Do we want to to move this library intolibbeat
ormetricbeat/module/system
, or should we spit apart and re-generate the code based on what API calls are used by what metricset?I'm also fairly ambivalent about the public API here. The design of
Percentages(*common.MapStr)
is mostly a matter of convenience for the conditional logic that fills in the event MapStr, and returning separate MapStr objects would require us to just do a deep merge later. Still, I'm open to other ideas, if someone has them.EDIT: I'm still thinking of "less ugly" ways of dealing with OS-specific data, as opposed to just returning an opaque
MapStr
. I wonder if we can add OS fields to the tag structs, and then implement aMapStr
unmarshaller that filters the values based on the OS. For example:Why is it important?
This refactor has a few goals in mind:
libbeat/metric/
andgosigar
that was unused outside outside of the system module has been moved into the newcpu/metrics
library.Option<T>
type we can put on struct fields or anything, so the next best thing are hashmaps, which aren't perfect. We've worked around this in the past by developing a mess ofif runtime.GOOS == ...
logic, which isn't particularly pretty.metrics_PLATFORM.go
is the only component that needs to worry about what is compatible with what, and logic that cares about OS-specific metrics remains in one place.gosigar
. Large portions of this library are exclusively used by the system module., and most other beats components usego-sysinfo
instead.Checklist
CHANGELOG.next.asciidoc
orCHANGELOG-developer.next.asciidoc
.Author's Checklist
gosigar/sys/windows
metrics
up the library, as it's used by two metricsets.How to test this PR locally
metricbeat
, and run thesystem/cpu
andsystem/core
metricsets to make sure we're generating data correctly.freebsd
andopenbsd
boxes have been updated, and should work without much further tinkering.