-
Notifications
You must be signed in to change notification settings - Fork 415
Support worker termination by collecting sum stats on exit. #806
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
Merged
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
62de49f
Documentation on the care and feeding of flaky or short-lived workers.
jdmarshall 67679c3
Add a function to handle timeouts.
jdmarshall 7dd391b
rework clusterMetrics() and workerMetrics() to use simpler async
jdmarshall 6bcd9f0
Orderly shutdown of the aggregator.
jdmarshall b20c7b5
Add filtering support to Registry.
jdmarshall ef1cea2
Add shutdown lifecycle for workers.
jdmarshall 8d446a5
Copy new shutdown logic from worker.js to cluster.js
jdmarshall aea554a
Update the advice in Workers.md to include options and a conversation
jdmarshall a4cb92a
Rework replaceListener to only do cleanup in test and dev mode ('watch')
jdmarshall d8be5a1
Apply same timing fix for ANNOUNCEMENT that I applied to other tests to
jdmarshall File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,81 @@ | ||||||
| # Notes on collection and short-lived processes | ||||||
|
|
||||||
| ## Introduction | ||||||
|
|
||||||
| Worker threads present a large surface area for potential loss of telemetry data. In order to avoid | ||||||
| strange artifacts in your statistics, it's recommended that you hook the process lifecycle events | ||||||
| in order to guarantee that the aggregator does not lose access to historical data when the worker | ||||||
| exits. | ||||||
|
|
||||||
| While the examples here are specific to worker threads, the same general advice also applies to | ||||||
| cluster workers as well, as the implementations are nearly identical. | ||||||
|
|
||||||
| ## Background | ||||||
|
|
||||||
| Statsd uses a fire and forget method for dumping stats to an external handler that is responsible | ||||||
| for the persistence of that data. OpenTelemetry and Prometheus, in contrast, assume that the | ||||||
| services are stable enough that we can ask them every so often for the data, and rely on them still | ||||||
| being there when we ask again later. This creates some challenges for gathering telemetry from | ||||||
| short running programs, child processes, and isolates. | ||||||
|
|
||||||
| Telemetry data is a mixture of values, such as Gauges, and sums, such as Counts and | ||||||
| Histograms. If a process crashes or becomes unresponsive, then it is no longer available to report | ||||||
| those sum values, causing them to be deducted from the aggregated data. This causes artifacts | ||||||
| in the telemetry data - places where numbers go down or remain flat when they should be | ||||||
| monotonically increasing. These data artifacts can and do result in judgment errors by human | ||||||
| operators performing triage, capacity planning, and a number of other tasks. As the person gathering | ||||||
| the telemetry, it is incumbent upon you to do your level best to avoid bad data being recorded. | ||||||
|
|
||||||
| We generally let processes crash on unhandled exceptions and rejections, but that complicates | ||||||
| telemetry collection. If you're thinking of adding Prometheus telemetry to your application, or to | ||||||
| a worker thread, one of your first concerns should be in reducing the number of unrecoverable errors | ||||||
| your code contains. | ||||||
|
|
||||||
| ## Strategies | ||||||
|
|
||||||
| ### Delegation | ||||||
|
|
||||||
| In the case of worker threads, sometimes short-lived is a feature, and in others it's an | ||||||
| inevitability. For extremely short-lived processes, it may be best for you to summarize the work | ||||||
| that was done in the worker and let the parent convert this information into the parent's own | ||||||
| statistics. This reduces the amount of aggregation that needs to be done by limiting the number of | ||||||
| processes that are being directly tracked. This is especially attractive in situations where the | ||||||
| worker thread is running computationally intensive tasks - these workers may not even respond in a | ||||||
| timely manner to messages sent to them because they are saturating the event loop with long, | ||||||
| synchronous tasks. | ||||||
|
|
||||||
| ### Graceful shutdown | ||||||
|
|
||||||
| However, if your workers are loading modules that are in common with the rest of your stack, then | ||||||
| it may be that some of these modules expect telemetry to be running wherever they are running, in | ||||||
| which case you will want to do graceful shutdowns in the case of errors or orderly shutdown to | ||||||
| ensure that the aggregator sees this data in between scrape intervals. For this we have the | ||||||
| `shutdown()` function. | ||||||
|
|
||||||
| When a worker or cluster worker knows it is terminating, it can flush its latest telemetry to the | ||||||
| aggregator. This orderly shutdown is the most memory efficient option, as the prometheus client | ||||||
| can aggregate the data from all dead workers into a single data structure. | ||||||
|
|
||||||
| ```javascript | ||||||
| // In worker bootstrapping code: | ||||||
|
|
||||||
| ['SIGHUP', 'SIGINT', 'SIGQUIT', 'SIGTERM'].forEach(sig => { | ||||||
| process.on(sig, async () => { | ||||||
| await registry.shutdown(); | ||||||
| process.exit(0); | ||||||
| }); | ||||||
| }); | ||||||
| ``` | ||||||
|
|
||||||
| See [the example](examples/workerTest.js) for a complete rundown, including the parent process | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. typo
Suggested change
|
||||||
| signalling workers to shut themselves down. | ||||||
|
|
||||||
| #### Space Complexity | ||||||
|
|
||||||
| The `shutdown()` function causes the main or the 'primary' process to aggregate all the 'sum' | ||||||
| metrics from all defunct workers that ran the shutdown to completion. The space needed in the | ||||||
| aggregator thread is proportional to the union of the cardinality of the stats from all of the | ||||||
| defunct workers. Therefore, so long as the cardinality of statistics is relatively common across | ||||||
| all workers (eg, workers do not label their own stats with threadId), then the space needed in the | ||||||
| aggregator thread is less than what the most prolific worker required - since the data is stored | ||||||
| as a snapshot instead of bringing forward the storage structure that underlies active Metrics. | ||||||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.