-
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
[Metricbeat] Update Couchdb to v2 #16455
Conversation
55d8f8a
to
08448cd
Compare
|
||
// Parse db version from HTTP response | ||
func getVersionFromInfo(info *CommonInfo) (*version, error) { | ||
versionSlice := strings.Split(info.Version, ".") |
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 it looks similarly to libbeat/common/version.go
(semver parsing).
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.
Good catch!
}, nil | ||
} | ||
|
||
// Fetch methods implements the data gathering and data conversion to the right | ||
// format. It publishes the event which is then forwarded to the output. In case | ||
// of an error set the Error field of mb.Event or simply call report.Error(). | ||
func (m *MetricSet) Fetch(reporter mb.ReporterV2) error { | ||
info, err := m.getInfoFromCouchdbHost(m.Host()) |
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 convinced about the version checking routine being called during every Fetch()
. I wonder if it's not better to determine it once and then use it. You can also revalidate it in case of an error (e.g. invalid schema) - to cover the case of potential upgrade.
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.
Historically this was the preferred way to achieve this. Even in very heavy operations like opening connections to SQL databases. Frankly, I never liked very much the idea but I understood the implications (a long living SQL connection that may drop and leave the beat requiring a restart.
Revalidation using schema errors or any other more complex stuff is against the common "guides" (written nowhere) in Beats of trying to have explicit, easy to reason / easy to code / easy to maintain codebase. In Couchdb it's not a very good idea because the differences are very very small and can lead to unexpected results. An example are incomplete JSON returns by design or a mix of errors from the http transport layer with the database layer that can make your life a hell 😄
TLDR: I'll disagree and commit and move it to New
😉
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.
Hmm... I wonder if it can lead to a potential problem - beats app starts before couchdb so it can't determine the API version.
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.
Hmm... I wonder if it can lead to a potential problem - beats app starts before couchdb so it can't determine the API version.
Yes! We ran into this exact issue with a couple of the stack monitoring modules in Metricbeat and had to move some API calls from New
into Fetch
. See #15258 (fixed by #15270) and #15276 (fixed by #15306).
One solution I've seen in the past is caching such "infrequently changing" information for some period of time to save on checking it every Fetch()
period. But that can introduce its own issues such as staleness so it might not be worth it. In general I err towards keeping it simple until it starts to be a problem.
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.
Regarding the offline discussion - I think you can move the code determining API version just before calling the right fetcher. Both fetchers should be stateless, so you freely initialize them in New()
and get rid of any unnecessary mem allocations in Fetch
.
|
||
switch v.major { | ||
case "1": | ||
m.fetcher = &V1{} |
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.
Do you think this can be optimized to not create a new instance every time the Fetch
is called?
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.
See above
7d09b5f
to
9095c0c
Compare
37c4662
to
f3b54a8
Compare
jenkins, test this |
e62104e
to
d5b59c4
Compare
I have done a last update by fetching on Let's park the implementation here until we have any feedback from community and users before over engineering this more. The real problem here is that a JSON parsing from v1 vs v2 won't raise any error. A custom JSON parser must be implemented to prevent silent errors on hot upgrades. As this is a very short-living corner case, it's reasonable to stop here. |
@@ -76,8 +95,76 @@ func (m *MetricSet) Fetch(reporter mb.ReporterV2) error { | |||
return errors.Wrap(err, "error in http fetch") | |||
} | |||
|
|||
event, _ := eventMapping(content) | |||
reporter.Event(mb.Event{MetricSetFields: event}) | |||
if m.fetcher == 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.
nit: I would hide this condition inside retrieveFetcher. The provider creates an instance if it's not ready.
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.
Moved it inside, thanks!
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.
Only one nit-pick
d5b59c4
to
230788c
Compare
230788c
to
1ebf51a
Compare
(cherry picked from commit 21be671)
What does this PR do?
Updates module to use a Strategy patern and decide between v1 and v2 Couchdb parsing. To do so, it has to do a pre HTTP request to root path
/
to know which version is deployed on each fetch (done in fetch to allow hot upgrades in container environment).I have removed
testdata
tests because one of them was a bit unnecessary with our currenttestdata
implementation (a timeout test which was testingtestdata
framework more than the module itself). The othertestdata
doesn't work anymore because more than one request is necessary now to check version.Because we can only test in CI with a single version, I maintained current Dockerfile
Why is it important?
ATM, we were only parsing v1 metrics and v3 is going to be released soon. This PR introduces v2 parsing maintaining compatibility with our previous version.
Checklist
- [ ] I have made corresponding change to the default configuration filesHow to test this PR locally
./metricbeat modules enable couchdb
and leave config similar to this:service.version
and theservice.id
must be the same for all paths of v2.Related issues
Screenshots
I checked that dashboard still works.