Support worker termination by collecting sum stats on exit. - #806
Conversation
07ccdc0 to
8a8de78
Compare
Signed-off-by: Jason Marshall <jdmarshall@users.noreply.github.com>
This removes a little bit of duplicate code from cluster.js and worker.js, and reduces some complexity in those functions to support new lifecycle functionality for process.exit() Signed-off-by: Jason Marshall <jdmarshall@users.noreply.github.com>
logic and the new util.waitFor function. This implementation stores the promise in the requests table, which will be needed to wait for in-flight metrics collections during an orderly shutdown. Signed-off-by: Jason Marshall <jdmarshall@users.noreply.github.com>
8a8de78 to
7ddd616
Compare
krajorama
left a comment
There was a problem hiding this comment.
First pass.
The general approach makes sense to me, but will need another pass to go into the details.
| try { | ||
| const metrics = [historicMetrics, ...event.metrics]; | ||
|
|
||
| historicMetrics = await Registry.aggregate(metrics).getMetricsAsArray(); |
There was a problem hiding this comment.
Seems to me these are just function calls, not promises, so no await needed?
| historicMetrics = await Registry.aggregate(metrics).getMetricsAsArray(); | |
| historicMetrics = Registry.aggregate(metrics).getMetricsAsArray(); |
There was a problem hiding this comment.
Hmm. That’s odd. One is sync and the rest are async. However did we manage that?
But I should double check that collect() is being called in the worker because I bet I missed one.
And this needs to be fixed in both.
Also there's an unhandledRejectionError surface area here that I missed. This code evolved during testing and I think I ran out of steam before it was finished.
Waits for metrics() to finish processing. Signed-off-by: Jason Marshall <jdmarshall@users.noreply.github.com>
7ddd616 to
4e6e7ae
Compare
|
Looks like maybe I didn't quite harden all of the race conditions in the tests. Oh, that test. Ugh. Edit: Looks like I missed one of the old tests. Fixed. |
krajorama
left a comment
There was a problem hiding this comment.
lgtm, llm claims some flakiness/cross pollination in test only - I'll open a PR for that afterwards, I need to understand it myself.
Please resolve the remaining small typo/fixe and I can approve.
This is prep work for tracking defunct workers. Signed-off-by: Jason Marshall <jdmarshall@users.noreply.github.com>
Signed-off-by: Jason Marshall <jdmarshall@users.noreply.github.com>
TODO: Needs example updated Signed-off-by: Jason Marshall <jdmarshall@users.noreply.github.com>
about space complexity. Signed-off-by: Jason Marshall <jdmarshall@users.noreply.github.com>
and warn of undefined behavior in production mode. This reduces the surface area of potential undefined behavior and puts the user on notice to review their application design if they are unintentionally triggering this in pre-prod or production modes. Add a big warning to the bottom of the README defining the bounds of expected behavior from this feature. Signed-off-by: Jason Marshall <jdmarshall@users.noreply.github.com>
avoid timing issues with tests. Signed-off-by: Jason Marshall <jdmarshall@users.noreply.github.com>
80514e8 to
d8be5a1
Compare
krajorama
left a comment
There was a problem hiding this comment.
LGTM, I've also done a simple smoke test locally. should be good for RC
|
Done. What this PR has taught be is that we need a more robust way to simulate workers in single-threaded unit tests. Or we need integration tests for this part of the code. I'm not sure which. But I only thought of better solutions to the problem of handling the lifecycle tests, some of which are in evidence. But they are still not good ones, let alone great ones. They simply suck less. This code needs additional coverage going forward. And maybe that should be excavating some more blocks of functional code and moving them to Util. |
This is the last PR required for the next semver-major release of the Prometheus Client. It addresses #803, via code changes, exposing additional lifecycle events for managing worker lifetimes, and documentation changes to warn of corner cases.
This change creates a retained mode for defunct workers where all of their final telemetry for 'sum' metrics is recorded in the aggregator process and aggregated down with each subsequent terminated worker. It also uses a call and response
system so that the worker can ensure that the flushed data was acknowledged by the collector before exiting.
As part of this work, most of the 'thenables' have been removed from the
clusterMetrics()code path, in favor of async/await which should also reduce the surface area of incompatibility with third party Promise libraries. And in general the code complexity ofclusterMetricshas been reduced close to the essential complexity of this code, to satisfy Kernighan's Law with respect to spotting bugs in the implementation.Pains are taken to make sure that the
workersandhistoricalMetricsfields are only ever read or written on the same tick, so that any shutdown operations that overlap with scraping don't smash into each other and cause data artifacts. You either get a scrape because the workers all replied before shutting down, or you get a transient timeout error that corrects itself on the subsequent collection.The collector thread only collects 'sum' metric types - a dead process cannot participate in average, max, or min calculations any longer and those outliers shouldn't be retained once the process exits. However counts and histograms must be kept in aggregate to prevent sawtooth patterns in the collected data due to elision of previously-reported data.
This PR also reworks a number of tests that relied on
delay()to instead watch the appropriate EventEmitters to watch for events that are being emitted asynchronously. There are a couple of cases where tests have around a 5-10% failure rate due to timing issues and if you run the suite over and over again, you will see false positives intermittently. Most of these should now be corrected.Because this is trying to keep two implementations in lockstep, it is unfortunately again a rather large PR, but hopefully not difficult to comprehend.