Repository navigation
Conversation
Contributor
|
@charzl Pre-commit is failing |
twangboy
previously approved these changes
Oct 29, 2026
twangboy
left a comment
Contributor
There was a problem hiding this comment.
Does this still work when multiprocessing is False?
Collaborator
Author
Yes. With multiprocessing: False, minion jobs run as threads in the same process. Added one more test to validate it. |
dwoz
approved these changes
Oct 30, 2026
twangboy
approved these changes
Oct 30, 2026
With `metrics.exporter: prometheus` only the process that bound the port was visible, so the counters of the MWorkers were lost. Use prometheus_client's multiprocess mode for this exporter. Every process writes its values to a shared directory and the main process adds them up on each scrape: one series per metric and label set, with no per-process label. Observable gauges are evaluated at scrape time in the serving process. The OpenTelemetry SDK is not used for this exporter; metric names stay the same as before. Refs saltstack#70248
Add a metrics_exporter input to the nightly stress workflow. With prometheus, the master serves its own metrics on :9464, prometheus scrapes them, and analyze_stats.py checks that the MWorkers' counter is visible on the one endpoint and never goes down.
Pre-create the bind mount owned by uid 65534, as the master branch does. Without it prometheus does not start and the analysis cannot query it.
Rebuild backend, instrument, and prometheus_client locks after fork while preserving cached instrument wrappers. Hold an OS lock before clearing a configured multiprocess directory, and isolate Salt from previously initialized multiprocess value caches. Add regression coverage for held locks at fork, competing directory owners, restart, and pre-existing prometheus_client metrics. All 46 related tests and the repository-wide Black check pass.
This branch is being deployed
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
What does this PR do?
Makes
metrics.exporter: prometheusreport all master processes on one/metricsendpoint.The exporter now uses
prometheus_clientin multiprocess mode instead of the OpenTelemetry SDK. Every process (master, MWorkers, minion job processes) writes its values to a shared directory, and the process that serves/metricsadds them up on each scrape. Observable gauges stay callbacks and are evaluated at scrape time in the serving process. OTLP and console exporters are not touched.What issues does this PR fix or reference?
Fixes #70365
Refs #70248 (the OTLP side is #70360)
Previous Behavior
Only the process that bound the port was visible. Processes forked from it could not bind the same port, so what the MWorkers counted was never exported.
New Behavior
One series per metric and label set, with the total over all master processes. No per-process label, nothing to
sum. Counts of a worker that exited stay in the total until the master stops, so counters do not go down.Behaviour to be aware of:
service_name/resource_attributesare still exposed ontarget_info, but theotel_scope_*labels are no longer added to each series. Metric names are unchanged.metrics.prometheus.multiproc_dir, whose*.dbfiles are removed at start). IfPROMETHEUS_MULTIPROC_DIRis already set in the environment, Salt logs a warning and uses its own directory.get_meter()returnsNonewith this exporter.Known limitations:
prometheus_clienthas no compaction for counters and histograms.PROMETHEUS_MULTIPROC_DIRin its own processes, so a Python program started by Salt (for example withcmd.run) that usesprometheus_clientinherits it.fire_eventlatency.Merge requirements satisfied?
Tests:
tests/pytests/unit/utils/test_metrics_prometheus.py(names, labels, threads writing while scraping, stale files, bad config, environment variable, bind failure) andtests/pytests/functional/utils/test_metrics_prometheus_multiprocess.py(three forked workers plus the parent, real HTTP scrape). They passed on Ubuntu 24.04/26.04 and Rocky 9 in CI on my fork, where the only failures areTest Package / downgrade(test_libyaml.py) andssh/test_saltext.py, which also fail on unmodified 3008.x.Run on a real master
I also ran this branch on a real master with a real Prometheus server: the
tests/monitoringDocker Compose setup, in my fork, with the stress load for 10 minutes, 5 MWorkers andmetrics.exporter: prometheus. The workflow changes needed for that are in the last two commits: ametrics_exporterinput for the nightly stress workflow, a scrape target for the master's own metrics, three checks inanalyze_stats.pythat only run withmetrics_exporter: prometheus, and the ownership of the prometheus data directory (as onmaster). With the default inputs the stress test behaves as before.salt_master_requests_handled_total, which is only incremented inside the MWorkers, was 7032 with one series percmdand no per-process label.resets()of that counter over the run was 0, so the values did not go down between scrapes.Runs: prometheus, metrics disabled.
How the stress test checks it
Run "Nightly Stress Test" by hand (
workflow_dispatch) withenable_metrics: trueandmetrics_exporter: prometheus. The scheduled nightly run keepsenable_metrics: false, so it does not exercise this exporter.The workflow adds a
metrics:block withexporter: prometheusandhost: 0.0.0.0tomaster.conf, restarts the master, runs the stress load, and the existing Prometheus container scrapessalt-master:9464(newsalt-metricsjob).analyze_stats.pythen checks, only in this mode:salt-metricstarget is up;salt_master_requests_handled_totalis above 0 (it is only incremented in the MWorkers, so this shows their values reach the one endpoint);resets()of that counter over the run is 0.The workflow also saves the master's
/metricsoutput and the listing of the shared directory as artifacts. The existing memory, FD and process-count checks run as before.Limits: the load is a loop of commands, so the checks are about presence and trend, not exact totals (the functional test covers those). The slope checks look at the last 30 minutes, so runs shorter than that are dominated by start-up.
Commits signed with GPG?
No